You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

notification.go 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package user
  5. import (
  6. "errors"
  7. "fmt"
  8. "net/http"
  9. "strings"
  10. "code.gitea.io/gitea/models"
  11. "code.gitea.io/gitea/modules/base"
  12. "code.gitea.io/gitea/modules/context"
  13. "code.gitea.io/gitea/modules/setting"
  14. )
  15. const (
  16. tplNotification base.TplName = "user/notification/notification"
  17. tplNotificationDiv base.TplName = "user/notification/notification_div"
  18. )
  19. // GetNotificationCount is the middleware that sets the notification count in the context
  20. func GetNotificationCount(c *context.Context) {
  21. if strings.HasPrefix(c.Req.URL.Path, "/api") {
  22. return
  23. }
  24. if !c.IsSigned {
  25. return
  26. }
  27. c.Data["NotificationUnreadCount"] = func() int64 {
  28. count, err := models.GetNotificationCount(c.User, models.NotificationStatusUnread)
  29. if err != nil {
  30. c.ServerError("GetNotificationCount", err)
  31. return -1
  32. }
  33. return count
  34. }
  35. }
  36. // Notifications is the notifications page
  37. func Notifications(c *context.Context) {
  38. getNotifications(c)
  39. if c.Written() {
  40. return
  41. }
  42. if c.FormBool("div-only") {
  43. c.Data["SequenceNumber"] = c.FormString("sequence-number")
  44. c.HTML(http.StatusOK, tplNotificationDiv)
  45. return
  46. }
  47. c.HTML(http.StatusOK, tplNotification)
  48. }
  49. func getNotifications(c *context.Context) {
  50. var (
  51. keyword = c.FormTrim("q")
  52. status models.NotificationStatus
  53. page = c.FormInt("page")
  54. perPage = c.FormInt("perPage")
  55. )
  56. if page < 1 {
  57. page = 1
  58. }
  59. if perPage < 1 {
  60. perPage = 20
  61. }
  62. switch keyword {
  63. case "read":
  64. status = models.NotificationStatusRead
  65. default:
  66. status = models.NotificationStatusUnread
  67. }
  68. total, err := models.GetNotificationCount(c.User, status)
  69. if err != nil {
  70. c.ServerError("ErrGetNotificationCount", err)
  71. return
  72. }
  73. // redirect to last page if request page is more than total pages
  74. pager := context.NewPagination(int(total), perPage, page, 5)
  75. if pager.Paginater.Current() < page {
  76. c.Redirect(fmt.Sprintf("/notifications?q=%s&page=%d", c.FormString("q"), pager.Paginater.Current()))
  77. return
  78. }
  79. statuses := []models.NotificationStatus{status, models.NotificationStatusPinned}
  80. notifications, err := models.NotificationsForUser(c.User, statuses, page, perPage)
  81. if err != nil {
  82. c.ServerError("ErrNotificationsForUser", err)
  83. return
  84. }
  85. failCount := 0
  86. repos, failures, err := notifications.LoadRepos()
  87. if err != nil {
  88. c.ServerError("LoadRepos", err)
  89. return
  90. }
  91. notifications = notifications.Without(failures)
  92. if err := repos.LoadAttributes(); err != nil {
  93. c.ServerError("LoadAttributes", err)
  94. return
  95. }
  96. failCount += len(failures)
  97. failures, err = notifications.LoadIssues()
  98. if err != nil {
  99. c.ServerError("LoadIssues", err)
  100. return
  101. }
  102. notifications = notifications.Without(failures)
  103. failCount += len(failures)
  104. failures, err = notifications.LoadComments()
  105. if err != nil {
  106. c.ServerError("LoadComments", err)
  107. return
  108. }
  109. notifications = notifications.Without(failures)
  110. failCount += len(failures)
  111. if failCount > 0 {
  112. c.Flash.Error(fmt.Sprintf("ERROR: %d notifications were removed due to missing parts - check the logs", failCount))
  113. }
  114. c.Data["Title"] = c.Tr("notifications")
  115. c.Data["Keyword"] = keyword
  116. c.Data["Status"] = status
  117. c.Data["Notifications"] = notifications
  118. pager.SetDefaultParams(c)
  119. c.Data["Page"] = pager
  120. }
  121. // NotificationStatusPost is a route for changing the status of a notification
  122. func NotificationStatusPost(c *context.Context) {
  123. var (
  124. notificationID = c.FormInt64("notification_id")
  125. statusStr = c.FormString("status")
  126. status models.NotificationStatus
  127. )
  128. switch statusStr {
  129. case "read":
  130. status = models.NotificationStatusRead
  131. case "unread":
  132. status = models.NotificationStatusUnread
  133. case "pinned":
  134. status = models.NotificationStatusPinned
  135. default:
  136. c.ServerError("InvalidNotificationStatus", errors.New("Invalid notification status"))
  137. return
  138. }
  139. if _, err := models.SetNotificationStatus(notificationID, c.User, status); err != nil {
  140. c.ServerError("SetNotificationStatus", err)
  141. return
  142. }
  143. if !c.FormBool("noredirect") {
  144. url := fmt.Sprintf("%s/notifications?page=%s", setting.AppSubURL, c.FormString("page"))
  145. c.Redirect(url, http.StatusSeeOther)
  146. }
  147. getNotifications(c)
  148. if c.Written() {
  149. return
  150. }
  151. c.Data["Link"] = setting.AppURL + "notifications"
  152. c.Data["SequenceNumber"] = c.Req.PostFormValue("sequence-number")
  153. c.HTML(http.StatusOK, tplNotificationDiv)
  154. }
  155. // NotificationPurgePost is a route for 'purging' the list of notifications - marking all unread as read
  156. func NotificationPurgePost(c *context.Context) {
  157. err := models.UpdateNotificationStatuses(c.User, models.NotificationStatusUnread, models.NotificationStatusRead)
  158. if err != nil {
  159. c.ServerError("ErrUpdateNotificationStatuses", err)
  160. return
  161. }
  162. url := fmt.Sprintf("%s/notifications", setting.AppSubURL)
  163. c.Redirect(url, http.StatusSeeOther)
  164. }