Add pages to view watched repos and subscribed issues/PRs (#17156)
Adds GitHub-like pages to view watched repos and subscribed issues/PRs This is my second try to fix this, but it is better than the first since it doesn't uses a filter option which could be slow when accessing `/issues` or `/pulls` and it shows both pulls and issues (the first try is #17053). Closes #16111 Replaces and closes #17053  Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
parent
3b6a7e5c8a
commit
08609d439d
6 changed files with 334 additions and 2 deletions
|
@ -13,16 +13,23 @@ import (
|
|||
"strings"
|
||||
|
||||
activities_model "code.gitea.io/gitea/models/activities"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
issue_service "code.gitea.io/gitea/services/issue"
|
||||
pull_service "code.gitea.io/gitea/services/pull"
|
||||
)
|
||||
|
||||
const (
|
||||
tplNotification base.TplName = "user/notification/notification"
|
||||
tplNotificationDiv base.TplName = "user/notification/notification_div"
|
||||
tplNotification base.TplName = "user/notification/notification"
|
||||
tplNotificationDiv base.TplName = "user/notification/notification_div"
|
||||
tplNotificationSubscriptions base.TplName = "user/notification/notification_subscriptions"
|
||||
)
|
||||
|
||||
// GetNotificationCount is the middleware that sets the notification count in the context
|
||||
|
@ -197,6 +204,208 @@ func NotificationPurgePost(c *context.Context) {
|
|||
c.Redirect(setting.AppSubURL+"/notifications", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// NotificationSubscriptions returns the list of subscribed issues
|
||||
func NotificationSubscriptions(c *context.Context) {
|
||||
page := c.FormInt("page")
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
sortType := c.FormString("sort")
|
||||
c.Data["SortType"] = sortType
|
||||
|
||||
state := c.FormString("state")
|
||||
if !util.IsStringInSlice(state, []string{"all", "open", "closed"}, true) {
|
||||
state = "all"
|
||||
}
|
||||
c.Data["State"] = state
|
||||
var showClosed util.OptionalBool
|
||||
switch state {
|
||||
case "all":
|
||||
showClosed = util.OptionalBoolNone
|
||||
case "closed":
|
||||
showClosed = util.OptionalBoolTrue
|
||||
case "open":
|
||||
showClosed = util.OptionalBoolFalse
|
||||
}
|
||||
|
||||
var issueTypeBool util.OptionalBool
|
||||
issueType := c.FormString("issueType")
|
||||
switch issueType {
|
||||
case "issues":
|
||||
issueTypeBool = util.OptionalBoolFalse
|
||||
case "pulls":
|
||||
issueTypeBool = util.OptionalBoolTrue
|
||||
default:
|
||||
issueTypeBool = util.OptionalBoolNone
|
||||
}
|
||||
c.Data["IssueType"] = issueType
|
||||
|
||||
var labelIDs []int64
|
||||
selectedLabels := c.FormString("labels")
|
||||
c.Data["Labels"] = selectedLabels
|
||||
if len(selectedLabels) > 0 && selectedLabels != "0" {
|
||||
var err error
|
||||
labelIDs, err = base.StringsToInt64s(strings.Split(selectedLabels, ","))
|
||||
if err != nil {
|
||||
c.ServerError("StringsToInt64s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
count, err := issues_model.CountIssues(&issues_model.IssuesOptions{
|
||||
SubscriberID: c.Doer.ID,
|
||||
IsClosed: showClosed,
|
||||
IsPull: issueTypeBool,
|
||||
LabelIDs: labelIDs,
|
||||
})
|
||||
if err != nil {
|
||||
c.ServerError("CountIssues", err)
|
||||
return
|
||||
}
|
||||
issues, err := issues_model.Issues(&issues_model.IssuesOptions{
|
||||
ListOptions: db.ListOptions{
|
||||
PageSize: setting.UI.IssuePagingNum,
|
||||
Page: page,
|
||||
},
|
||||
SubscriberID: c.Doer.ID,
|
||||
SortType: sortType,
|
||||
IsClosed: showClosed,
|
||||
IsPull: issueTypeBool,
|
||||
LabelIDs: labelIDs,
|
||||
})
|
||||
if err != nil {
|
||||
c.ServerError("Issues", err)
|
||||
return
|
||||
}
|
||||
|
||||
commitStatuses, lastStatus, err := pull_service.GetIssuesAllCommitStatus(c, issues)
|
||||
if err != nil {
|
||||
c.ServerError("GetIssuesAllCommitStatus", err)
|
||||
return
|
||||
}
|
||||
c.Data["CommitLastStatus"] = lastStatus
|
||||
c.Data["CommitStatuses"] = commitStatuses
|
||||
c.Data["Issues"] = issues
|
||||
|
||||
c.Data["IssueRefEndNames"], c.Data["IssueRefURLs"] = issue_service.GetRefEndNamesAndURLs(issues, "")
|
||||
|
||||
commitStatus, err := pull_service.GetIssuesLastCommitStatus(c, issues)
|
||||
if err != nil {
|
||||
c.ServerError("GetIssuesLastCommitStatus", err)
|
||||
return
|
||||
}
|
||||
c.Data["CommitStatus"] = commitStatus
|
||||
|
||||
issueList := issues_model.IssueList(issues)
|
||||
approvalCounts, err := issueList.GetApprovalCounts(c)
|
||||
if err != nil {
|
||||
c.ServerError("ApprovalCounts", err)
|
||||
return
|
||||
}
|
||||
c.Data["ApprovalCounts"] = func(issueID int64, typ string) int64 {
|
||||
counts, ok := approvalCounts[issueID]
|
||||
if !ok || len(counts) == 0 {
|
||||
return 0
|
||||
}
|
||||
reviewTyp := issues_model.ReviewTypeApprove
|
||||
if typ == "reject" {
|
||||
reviewTyp = issues_model.ReviewTypeReject
|
||||
} else if typ == "waiting" {
|
||||
reviewTyp = issues_model.ReviewTypeRequest
|
||||
}
|
||||
for _, count := range counts {
|
||||
if count.Type == reviewTyp {
|
||||
return count.Count
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
c.Data["Status"] = 1
|
||||
c.Data["Title"] = c.Tr("notification.subscriptions")
|
||||
|
||||
// redirect to last page if request page is more than total pages
|
||||
pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5)
|
||||
if pager.Paginater.Current() < page {
|
||||
c.Redirect(fmt.Sprintf("/notifications/subscriptions?page=%d", pager.Paginater.Current()))
|
||||
return
|
||||
}
|
||||
pager.AddParam(c, "sort", "SortType")
|
||||
pager.AddParam(c, "state", "State")
|
||||
c.Data["Page"] = pager
|
||||
|
||||
c.HTML(http.StatusOK, tplNotificationSubscriptions)
|
||||
}
|
||||
|
||||
// NotificationWatching returns the list of watching repos
|
||||
func NotificationWatching(c *context.Context) {
|
||||
page := c.FormInt("page")
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
var orderBy db.SearchOrderBy
|
||||
c.Data["SortType"] = c.FormString("sort")
|
||||
switch c.FormString("sort") {
|
||||
case "newest":
|
||||
orderBy = db.SearchOrderByNewest
|
||||
case "oldest":
|
||||
orderBy = db.SearchOrderByOldest
|
||||
case "recentupdate":
|
||||
orderBy = db.SearchOrderByRecentUpdated
|
||||
case "leastupdate":
|
||||
orderBy = db.SearchOrderByLeastUpdated
|
||||
case "reversealphabetically":
|
||||
orderBy = db.SearchOrderByAlphabeticallyReverse
|
||||
case "alphabetically":
|
||||
orderBy = db.SearchOrderByAlphabetically
|
||||
case "moststars":
|
||||
orderBy = db.SearchOrderByStarsReverse
|
||||
case "feweststars":
|
||||
orderBy = db.SearchOrderByStars
|
||||
case "mostforks":
|
||||
orderBy = db.SearchOrderByForksReverse
|
||||
case "fewestforks":
|
||||
orderBy = db.SearchOrderByForks
|
||||
default:
|
||||
c.Data["SortType"] = "recentupdate"
|
||||
orderBy = db.SearchOrderByRecentUpdated
|
||||
}
|
||||
|
||||
repos, count, err := repo_model.SearchRepository(&repo_model.SearchRepoOptions{
|
||||
ListOptions: db.ListOptions{
|
||||
PageSize: setting.UI.User.RepoPagingNum,
|
||||
Page: page,
|
||||
},
|
||||
Actor: c.Doer,
|
||||
Keyword: c.FormTrim("q"),
|
||||
OrderBy: orderBy,
|
||||
Private: c.IsSigned,
|
||||
WatchedByID: c.Doer.ID,
|
||||
Collaborate: util.OptionalBoolFalse,
|
||||
TopicOnly: c.FormBool("topic"),
|
||||
IncludeDescription: setting.UI.SearchRepoDescription,
|
||||
})
|
||||
if err != nil {
|
||||
c.ServerError("ErrSearchRepository", err)
|
||||
return
|
||||
}
|
||||
total := int(count)
|
||||
c.Data["Total"] = total
|
||||
c.Data["Repos"] = repos
|
||||
|
||||
// redirect to last page if request page is more than total pages
|
||||
pager := context.NewPagination(total, setting.UI.User.RepoPagingNum, page, 5)
|
||||
pager.SetDefaultParams(c)
|
||||
c.Data["Page"] = pager
|
||||
|
||||
c.Data["Status"] = 2
|
||||
c.Data["Title"] = c.Tr("notification.watching")
|
||||
|
||||
c.HTML(http.StatusOK, tplNotificationSubscriptions)
|
||||
}
|
||||
|
||||
// NewAvailable returns the notification counts
|
||||
func NewAvailable(ctx *context.Context) {
|
||||
ctx.JSON(http.StatusOK, structs.NotificationCount{New: activities_model.CountUnread(ctx, ctx.Doer.ID)})
|
||||
|
|
|
@ -1269,6 +1269,8 @@ func RegisterRoutes(m *web.Route) {
|
|||
|
||||
m.Group("/notifications", func() {
|
||||
m.Get("", user.Notifications)
|
||||
m.Get("/subscriptions", user.NotificationSubscriptions)
|
||||
m.Get("/watching", user.NotificationWatching)
|
||||
m.Post("/status", user.NotificationStatusPost)
|
||||
m.Post("/purge", user.NotificationPurgePost)
|
||||
m.Get("/new", user.NewAvailable)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue