Add option to control which repositories are included in the digest.

This commit is contained in:
Mihai Parparita 2014-08-31 15:22:19 -07:00
parent 7852b128df
commit 1cb55cfe6a
5 changed files with 70 additions and 24 deletions

View file

@ -19,6 +19,7 @@ type Account struct {
OAuthToken oauth.Token `datastore:"-,"` OAuthToken oauth.Token `datastore:"-,"`
TimezoneName string `datastore:",noindex"` TimezoneName string `datastore:",noindex"`
TimezoneLocation *time.Location `datastore:"-,"` TimezoneLocation *time.Location `datastore:"-,"`
ExcludedRepoIds []int `datastore:",noindex"`
} }
func getAccount(c appengine.Context, githubUserId int) (*Account, error) { func getAccount(c appengine.Context, githubUserId int) (*Account, error) {
@ -66,6 +67,15 @@ func getAllAccountGithubUserIds(c appengine.Context) ([]int, error) {
return result, nil return result, nil
} }
func (account *Account) IsRepoIdExcluded(repoId int) bool {
for i := range account.ExcludedRepoIds {
if account.ExcludedRepoIds[i] == repoId {
return true
}
}
return false
}
func (account *Account) put(c appengine.Context) error { func (account *Account) put(c appengine.Context) error {
w := new(bytes.Buffer) w := new(bytes.Buffer)
err := gob.NewEncoder(w).Encode(&account.OAuthToken) err := gob.NewEncoder(w).Encode(&account.OAuthToken)

View file

@ -133,7 +133,7 @@ func newDigest(c appengine.Context, githubClient *github.Client, account *Accoun
return nil, err return nil, err
} }
repos, err := getRepos(c, githubClient, user) repos, err := getRepos(c, githubClient, account, user)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -151,7 +151,7 @@ func newDigest(c appengine.Context, githubClient *github.Client, account *Accoun
// Only look at repos that may have activity in the digest interval. // Only look at repos that may have activity in the digest interval.
var intervalRepos []*Repo var intervalRepos []*Repo
for _, repo := range repos.AllRepos { for _, repo := range repos.AllRepos {
if repo.Vintage.Before(digestEndTime) && repo.PushedAt != nil && if repo.IncludeInDigest && repo.Vintage.Before(digestEndTime) && repo.PushedAt != nil &&
repo.PushedAt.After(digestStartTime) { repo.PushedAt.After(digestStartTime) {
intervalRepos = append(intervalRepos, repo) intervalRepos = append(intervalRepos, repo)
} }

View file

@ -49,8 +49,8 @@ func init() {
router.HandleFunc("/digest/send", sendDigestHandler).Name("send-digest").Methods("POST") router.HandleFunc("/digest/send", sendDigestHandler).Name("send-digest").Methods("POST")
router.HandleFunc("/digest/cron", digestCronHandler) router.HandleFunc("/digest/cron", digestCronHandler)
router.HandleFunc("/account/settings", settingsHandler).Name("settings") router.HandleFunc("/account/settings", settingsHandler).Name("settings").Methods("GET")
router.HandleFunc("/account/set-timezone", setTimezoneHandler).Name("set-timezone").Methods("POST") router.HandleFunc("/account/settings", saveSettingsHandler).Name("save-settings").Methods("POST")
router.HandleFunc("/admin/digest", digestAdminHandler) router.HandleFunc("/admin/digest", digestAdminHandler)
http.Handle("/", router) http.Handle("/", router)
@ -374,7 +374,7 @@ func settingsHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
repos, err := getRepos(c, githubClient, user) repos, err := getRepos(c, githubClient, account, user)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
@ -391,7 +391,7 @@ func settingsHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
func setTimezoneHandler(w http.ResponseWriter, r *http.Request) { func saveSettingsHandler(w http.ResponseWriter, r *http.Request) {
session, _ := sessionStore.Get(r, sessionConfig.CookieName) session, _ := sessionStore.Get(r, sessionConfig.CookieName)
userId := session.Values[sessionConfig.UserIdKey].(int) userId := session.Values[sessionConfig.UserIdKey].(int)
c := appengine.NewContext(r) c := appengine.NewContext(r)
@ -400,6 +400,21 @@ func setTimezoneHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
oauthTransport := githubOAuthTransport(c)
oauthTransport.Token = &account.OAuthToken
githubClient := github.NewClient(oauthTransport.Client())
user, _, err := githubClient.Users.Get("")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
repos, err := getRepos(c, githubClient, account, user)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
timezoneName := r.FormValue("timezone_name") timezoneName := r.FormValue("timezone_name")
_, err = time.LoadLocation(timezoneName) _, err = time.LoadLocation(timezoneName)
@ -407,16 +422,25 @@ func setTimezoneHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest) http.Error(w, err.Error(), http.StatusBadRequest)
return return
} }
account.TimezoneName = timezoneName account.TimezoneName = timezoneName
account.ExcludedRepoIds = make([]int, 0)
for _, repo := range repos.AllRepos {
repoId := *repo.ID
_, included := r.Form[fmt.Sprintf("repo-%d", repoId)]
if !included {
account.ExcludedRepoIds = append(account.ExcludedRepoIds, repoId)
}
}
err = account.put(c) err = account.put(c)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
indexUrl, _ := router.Get("index").URL() settingsUrl, _ := router.Get("settings").URL()
http.Redirect(w, r, indexUrl.String(), http.StatusFound) http.Redirect(w, r, settingsUrl.String(), http.StatusFound)
} }
func digestAdminHandler(w http.ResponseWriter, r *http.Request) { func digestAdminHandler(w http.ResponseWriter, r *http.Request) {

View file

@ -159,11 +159,16 @@ type Repos struct {
type Repo struct { type Repo struct {
*github.Repository *github.Repository
Vintage time.Time Vintage time.Time
IncludeInDigest bool
} }
func newRepo(githubRepo *github.Repository) *Repo { func newRepo(githubRepo *github.Repository, account *Account) *Repo {
return &Repo{githubRepo, githubRepo.CreatedAt.UTC()} return &Repo{
Repository: githubRepo,
Vintage: githubRepo.CreatedAt.UTC(),
IncludeInDigest: !account.IsRepoIdExcluded(*githubRepo.ID),
}
} }
func (repo *Repo) TypeAsOcticonName() string { func (repo *Repo) TypeAsOcticonName() string {
@ -200,7 +205,7 @@ type OrgRepos struct {
Repos []*Repo Repos []*Repo
} }
func getRepos(c appengine.Context, githubClient *github.Client, user *github.User) (*Repos, error) { func getRepos(c appengine.Context, githubClient *github.Client, account *Account, user *github.User) (*Repos, error) {
// The username parameter must be left blank so that we can get all of the // The username parameter must be left blank so that we can get all of the
// repositories the user has access to, not just ones that they own. // repositories the user has access to, not just ones that they own.
clientUserRepos, _, err := githubClient.Repositories.List("", nil) clientUserRepos, _, err := githubClient.Repositories.List("", nil)
@ -215,7 +220,7 @@ func getRepos(c appengine.Context, githubClient *github.Client, user *github.Use
for i := range clientUserRepos { for i := range clientUserRepos {
ownerID := *clientUserRepos[i].Owner.ID ownerID := *clientUserRepos[i].Owner.ID
if ownerID == *user.ID { if ownerID == *user.ID {
repos.UserRepos = append(repos.UserRepos, newRepo(&clientUserRepos[i])) repos.UserRepos = append(repos.UserRepos, newRepo(&clientUserRepos[i], account))
} else { } else {
var userRepos *UserRepos var userRepos *UserRepos
for j := range repos.OtherUserRepos { for j := range repos.OtherUserRepos {
@ -231,7 +236,7 @@ func getRepos(c appengine.Context, githubClient *github.Client, user *github.Use
} }
repos.OtherUserRepos = append(repos.OtherUserRepos, userRepos) repos.OtherUserRepos = append(repos.OtherUserRepos, userRepos)
} }
userRepos.Repos = append(userRepos.Repos, newRepo(&clientUserRepos[i])) userRepos.Repos = append(userRepos.Repos, newRepo(&clientUserRepos[i], account))
} }
} }
@ -251,7 +256,7 @@ func getRepos(c appengine.Context, githubClient *github.Client, user *github.Use
orgRepos := make([]*Repo, 0, len(clientOrgRepos)) orgRepos := make([]*Repo, 0, len(clientOrgRepos))
allRepoCount += len(clientOrgRepos) allRepoCount += len(clientOrgRepos)
for j := range clientOrgRepos { for j := range clientOrgRepos {
orgRepos = append(orgRepos, newRepo(&clientOrgRepos[j])) orgRepos = append(orgRepos, newRepo(&clientOrgRepos[j], account))
} }
repos.OrgRepos = append(repos.OrgRepos, &OrgRepos{org, orgRepos}) repos.OrgRepos = append(repos.OrgRepos, &OrgRepos{org, orgRepos})
} }

View file

@ -2,16 +2,22 @@
{{define "repo"}} {{define "repo"}}
<li class="repo {{.TypeAsClassName}}"> <li class="repo {{.TypeAsClassName}}">
<span class="glyph octicon octicon-{{.TypeAsOcticonName}}"></span> <label>
<a href="{{.HTMLURL}}">{{.FullName}}</a> <input type="checkbox" name="repo-{{.ID}}" value="include" {{if .IncludeInDigest}}checked{{end}}>
<span class="vintage">{{.DisplayVintage}}</span> <span class="glyph octicon octicon-{{.TypeAsOcticonName}}"></span>
<a href="{{.HTMLURL}}">{{.FullName}}</a>
<span class="vintage">{{.DisplayVintage}}</span>
</label>
</li> </li>
{{end}} {{end}}
{{define "body"}} {{define "body"}}
<form method="POST" action="{{routeUrl "save-settings"}}">
<p> <p>
<form method="POST" action="{{routeUrl "set-timezone"}}"> <label>
Timezone for digest day boundaries:
<select name="timezone_name"> <select name="timezone_name">
{{$accountTimezoneName := .Account.TimezoneName}} {{$accountTimezoneName := .Account.TimezoneName}}
{{range .Timezones}} {{range .Timezones}}
@ -22,13 +28,11 @@
{{end}} {{end}}
{{end}} {{end}}
</select> </select>
</label>
<input type="submit" value="Set Timezone">
</form>
</p> </p>
<p> <p>
You have {{len .Repos.AllRepos}} repositories: You have {{len .Repos.AllRepos}} repositories. Select which you would like to include in your digest:
</p> </p>
<div class="repos"> <div class="repos">
@ -71,5 +75,8 @@
</div> </div>
{{end}} {{end}}
<input type="submit" value="Save Settings">
</form>
{{end}} {{end}}