mirror of
https://github.com/samsonjs/retrogit.git
synced 2026-03-25 09:25:49 +00:00
Weekly digest option.
This commit is contained in:
parent
71ef392cfa
commit
40540fd91f
5 changed files with 122 additions and 31 deletions
|
|
@ -23,6 +23,8 @@ type Account struct {
|
|||
TimezoneLocation *time.Location `datastore:"-,"`
|
||||
ExcludedRepoIds []int `datastore:",noindex"`
|
||||
DigestEmailAddress string
|
||||
Frequency string
|
||||
WeeklyDay time.Weekday
|
||||
}
|
||||
|
||||
func getAccount(c appengine.Context, githubUserId int) (*Account, error) {
|
||||
|
|
@ -49,6 +51,9 @@ func initAccount(account *Account) error {
|
|||
if len(account.TimezoneName) == 0 {
|
||||
account.TimezoneName = "America/Los_Angeles"
|
||||
}
|
||||
if len(account.Frequency) == 0 {
|
||||
account.Frequency = "daily"
|
||||
}
|
||||
account.TimezoneLocation, err = time.LoadLocation(account.TimezoneName)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -56,18 +61,20 @@ func initAccount(account *Account) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func getAllAccountGithubUserIds(c appengine.Context) ([]int, error) {
|
||||
func getAllAccounts(c appengine.Context) ([]Account, error) {
|
||||
q := datastore.NewQuery("Account")
|
||||
var accounts []Account
|
||||
_, err := q.GetAll(c, &accounts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]int, len(accounts))
|
||||
for i := range accounts {
|
||||
result[i] = accounts[i].GitHubUserId
|
||||
err = initAccount(&accounts[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
return accounts, nil
|
||||
}
|
||||
|
||||
func (account *Account) IsRepoIdExcluded(repoId int) bool {
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
CommitDisplayDateFormat = "3:04pm"
|
||||
CommitDisplayDateTooltipFormat = "Monday January 2 3:04pm"
|
||||
DigestDisplayDateFormat = "January 2, 2006"
|
||||
DigestDisplayDayOfWeekFormat = "Monday"
|
||||
CommitDisplayDateFormat = "3:04pm"
|
||||
CommitDisplayDateFullFormat = "Monday January 2 3:04pm"
|
||||
DigestDisplayDateFormat = "January 2, 2006"
|
||||
DigestDisplayShortDateFormat = "January 2"
|
||||
DigestDisplayDayOfWeekFormat = "Monday"
|
||||
)
|
||||
|
||||
type DigestCommit struct {
|
||||
|
|
@ -52,12 +53,16 @@ func (commit DigestCommit) DisplayDate() string {
|
|||
return commit.PushDate.Format(CommitDisplayDateFormat)
|
||||
}
|
||||
|
||||
func (commit DigestCommit) WeeklyDisplayDate() string {
|
||||
return commit.PushDate.Format(CommitDisplayDateFullFormat)
|
||||
}
|
||||
|
||||
func (commit DigestCommit) DisplayDateTooltip() string {
|
||||
// But show the full details in a tooltip
|
||||
return fmt.Sprintf(
|
||||
"Pushed at %s\nCommited at %s",
|
||||
commit.PushDate.Format(CommitDisplayDateTooltipFormat),
|
||||
commit.CommitDate.Format(CommitDisplayDateTooltipFormat))
|
||||
commit.PushDate.Format(CommitDisplayDateFullFormat),
|
||||
commit.CommitDate.Format(CommitDisplayDateFullFormat))
|
||||
}
|
||||
|
||||
type RepoDigest struct {
|
||||
|
|
@ -76,6 +81,7 @@ type IntervalDigest struct {
|
|||
yearDelta int
|
||||
StartTime time.Time
|
||||
EndTime time.Time
|
||||
Weekly bool
|
||||
RepoDigests []*RepoDigest
|
||||
repos []*Repo
|
||||
}
|
||||
|
|
@ -116,15 +122,33 @@ func (digest *IntervalDigest) Description() string {
|
|||
} else {
|
||||
formattedRepoCount = fmt.Sprintf("%d repositories", repoCount)
|
||||
}
|
||||
dayOfWeek := digest.StartTime.Format(DigestDisplayDayOfWeekFormat)
|
||||
// Insert a zero-width space inside the day of the week so that Gmail's
|
||||
// event detection doesn't pick it up.
|
||||
dayOfWeek = fmt.Sprintf("%s\u200B%s", dayOfWeek[:1], dayOfWeek[1:])
|
||||
return fmt.Sprintf("%s was a %s. You had %s in %s that day.",
|
||||
digest.StartTime.Format(DigestDisplayDateFormat),
|
||||
dayOfWeek,
|
||||
|
||||
if !digest.Weekly {
|
||||
dayOfWeek := digest.StartTime.Format(DigestDisplayDayOfWeekFormat)
|
||||
// Insert a zero-width space inside the day of the week so that Gmail's
|
||||
// event detection doesn't pick it up.
|
||||
dayOfWeek = fmt.Sprintf("%s\u200B%s", dayOfWeek[:1], dayOfWeek[1:])
|
||||
return fmt.Sprintf("%s was a %s. You had %s in %s that day.",
|
||||
digest.StartTime.Format(DigestDisplayDateFormat),
|
||||
dayOfWeek,
|
||||
formattedCommitCount,
|
||||
formattedRepoCount)
|
||||
}
|
||||
|
||||
formattedEndTime := digest.EndTime.Format(DigestDisplayDateFormat)
|
||||
var formattedStartTime string
|
||||
if digest.StartTime.Year() == digest.EndTime.Year() {
|
||||
formattedStartTime = digest.StartTime.Format(DigestDisplayShortDateFormat)
|
||||
} else {
|
||||
formattedStartTime = digest.StartTime.Format(DigestDisplayDateFormat)
|
||||
}
|
||||
formattedStartTime = fmt.Sprintf("%s\u200B%s", formattedStartTime[:1], formattedStartTime[1:])
|
||||
formattedEndTime = fmt.Sprintf("%s\u200B%s", formattedEndTime[:1], formattedEndTime[1:])
|
||||
return fmt.Sprintf("You had %s in %s the week of %s to %s.",
|
||||
formattedCommitCount,
|
||||
formattedRepoCount)
|
||||
formattedRepoCount,
|
||||
formattedStartTime,
|
||||
formattedEndTime)
|
||||
}
|
||||
|
||||
type Digest struct {
|
||||
|
|
@ -152,7 +176,11 @@ func newDigest(c appengine.Context, githubClient *github.Client, account *Accoun
|
|||
if digestStartTime.Before(oldestDigestTime) {
|
||||
break
|
||||
}
|
||||
digestEndTime := digestStartTime.AddDate(0, 0, 1)
|
||||
daysInDigest := 1
|
||||
if account.Frequency == "weekly" {
|
||||
daysInDigest = 7
|
||||
}
|
||||
digestEndTime := digestStartTime.AddDate(0, 0, daysInDigest)
|
||||
|
||||
// Only look at repos that may have activity in the digest interval.
|
||||
var intervalRepos []*Repo
|
||||
|
|
@ -169,6 +197,7 @@ func newDigest(c appengine.Context, githubClient *github.Client, account *Accoun
|
|||
RepoDigests: make([]*RepoDigest, 0, len(intervalRepos)),
|
||||
StartTime: digestStartTime,
|
||||
EndTime: digestEndTime,
|
||||
Weekly: account.Frequency == "weekly",
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -238,15 +238,23 @@ func sendDigestHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func digestCronHandler(w http.ResponseWriter, r *http.Request) {
|
||||
c := appengine.NewContext(r)
|
||||
githubUserIds, err := getAllAccountGithubUserIds(c)
|
||||
accounts, err := getAllAccounts(c)
|
||||
if err != nil {
|
||||
c.Errorf("Error looking up accounts: %s", err.Error())
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
for _, githubUserId := range githubUserIds {
|
||||
c.Infof("Enqueing task for %d...", githubUserId)
|
||||
sendDigestForAccountFunc.Call(c, githubUserId)
|
||||
for _, account := range accounts {
|
||||
if account.Frequency == "weekly" {
|
||||
now := time.Now().In(account.TimezoneLocation)
|
||||
if now.Weekday() != account.WeeklyDay {
|
||||
c.Infof("Skipping %d, since it wants weekly digests on %ss and today is a %s.",
|
||||
account.GitHubUserId, account.WeeklyDay, now.Weekday())
|
||||
continue
|
||||
}
|
||||
}
|
||||
c.Infof("Enqueing task for %d...", account.GitHubUserId)
|
||||
sendDigestForAccountFunc.Call(c, account.GitHubUserId)
|
||||
}
|
||||
fmt.Fprint(w, "Done")
|
||||
}
|
||||
|
|
@ -421,6 +429,14 @@ func saveSettingsHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
account.Frequency = r.FormValue("frequency")
|
||||
weeklyDay, err := strconv.Atoi(r.FormValue("weekly_day"))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
account.WeeklyDay = time.Weekday(weeklyDay)
|
||||
|
||||
timezoneName := r.FormValue("timezone_name")
|
||||
_, err = time.LoadLocation(timezoneName)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -15,18 +15,43 @@
|
|||
|
||||
<form method="POST" action="{{routeUrl "save-settings"}}">
|
||||
|
||||
<div class="setting">
|
||||
<label>
|
||||
Frequency:
|
||||
<select name="frequency" id="frequency" onchange="updateWeeklyDayContainer()">
|
||||
<option value="daily" {{if eq "daily" .Account.Frequency}}selected{{end}}>Daily</option>
|
||||
<option value="weekly" {{if eq "weekly" .Account.Frequency}}selected{{end}}>Weekly</option>
|
||||
</select>
|
||||
<span id="weekly-day-container">
|
||||
on
|
||||
<select name="weekly_day">
|
||||
<option value="0" {{if eq 0 .Account.WeeklyDay}}selected{{end}}>Sundays</option>
|
||||
<option value="1" {{if eq 1 .Account.WeeklyDay}}selected{{end}}>Mondays</option>
|
||||
<option value="2" {{if eq 2 .Account.WeeklyDay}}selected{{end}}>Tuesdays</option>
|
||||
<option value="3" {{if eq 3 .Account.WeeklyDay}}selected{{end}}>Wednesdays</option>
|
||||
<option value="4" {{if eq 4 .Account.WeeklyDay}}selected{{end}}>Thursdays</option>
|
||||
<option value="5" {{if eq 5 .Account.WeeklyDay}}selected{{end}}>Fridays</option>
|
||||
<option value="6" {{if eq 6 .Account.WeeklyDay}}selected{{end}}>Saturdays</option>
|
||||
</select>
|
||||
</span>
|
||||
<div class="explanation">
|
||||
How often you'd like to get digests. If there is no activity on that day or week, then no email will be sent.
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="setting">
|
||||
<label>
|
||||
Timezone:
|
||||
<select name="timezone_name">
|
||||
{{$accountTimezoneName := .Account.TimezoneName}}
|
||||
{{range .Timezones}}
|
||||
{{if .LocationName}}
|
||||
<option value="{{.LocationName}}" {{if eq .LocationName $accountTimezoneName}}selected{{end}}>{{.LocationName}} (GMT {{.DisplayUTCOffset}})</option>
|
||||
{{else}}
|
||||
<option disabled></option>
|
||||
{{end}}
|
||||
{{$accountTimezoneName := .Account.TimezoneName}}
|
||||
{{range .Timezones}}
|
||||
{{if .LocationName}}
|
||||
<option value="{{.LocationName}}" {{if eq .LocationName $accountTimezoneName}}selected{{end}}>{{.LocationName}} (GMT {{.DisplayUTCOffset}})</option>
|
||||
{{else}}
|
||||
<option disabled></option>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</select>
|
||||
<div class="explanation">
|
||||
Used for determining day boundaries and timestamps in emails.
|
||||
|
|
@ -96,5 +121,18 @@
|
|||
<input type="submit" value="Save Settings">
|
||||
</form>
|
||||
|
||||
<script>
|
||||
function updateWeeklyDayContainer() {
|
||||
var frequencyNode = document.getElementById("frequency");
|
||||
var weeklyDayContainerNode = document.getElementById("weekly-day-container");
|
||||
if (frequencyNode.value == "weekly") {
|
||||
weeklyDayContainerNode.style.display = "inline";
|
||||
} else {
|
||||
weeklyDayContainerNode.style.display = "none";
|
||||
}
|
||||
}
|
||||
updateWeeklyDayContainer();
|
||||
</script>
|
||||
|
||||
{{end}}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
</p>
|
||||
|
||||
{{range .IntervalDigests }}
|
||||
{{$interval := .}}
|
||||
<h1 style="{{style "interval-header"}}">{{.Header}}</h1>
|
||||
|
||||
<p>{{.Description}}</p>
|
||||
|
|
@ -36,7 +37,7 @@
|
|||
<a href="{{.URL}}"
|
||||
style="{{style "link" "commit.footer.link"}}">{{.DisplaySHA}}</a>
|
||||
<i title={{.DisplayDateTooltip}}
|
||||
style="{{style "commit.footer.date"}}">{{.DisplayDate}}</i>
|
||||
style="{{style "commit.footer.date"}}">{{if $interval.Weekly}}{{.WeeklyDisplayDate}}{{else}}{{.DisplayDate}}{{end}}</i>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
|
|||
Loading…
Reference in a new issue