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.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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. "strconv"
  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. )
  18. // GetNotificationCount is the middleware that sets the notification count in the context
  19. func GetNotificationCount(c *context.Context) {
  20. if strings.HasPrefix(c.Req.URL.Path, "/api") {
  21. return
  22. }
  23. if !c.IsSigned {
  24. return
  25. }
  26. count, err := models.GetNotificationCount(c.User, models.NotificationStatusUnread)
  27. if err != nil {
  28. c.ServerError("GetNotificationCount", err)
  29. return
  30. }
  31. c.Data["NotificationUnreadCount"] = count
  32. }
  33. // Notifications is the notifications page
  34. func Notifications(c *context.Context) {
  35. var (
  36. keyword = strings.Trim(c.Query("q"), " ")
  37. status models.NotificationStatus
  38. page = c.QueryInt("page")
  39. perPage = c.QueryInt("perPage")
  40. )
  41. if page < 1 {
  42. page = 1
  43. }
  44. if perPage < 1 {
  45. perPage = 20
  46. }
  47. switch keyword {
  48. case "read":
  49. status = models.NotificationStatusRead
  50. default:
  51. status = models.NotificationStatusUnread
  52. }
  53. statuses := []models.NotificationStatus{status, models.NotificationStatusPinned}
  54. notifications, err := models.NotificationsForUser(c.User, statuses, page, perPage)
  55. if err != nil {
  56. c.ServerError("ErrNotificationsForUser", err)
  57. return
  58. }
  59. failCount := 0
  60. repos, failures, err := notifications.LoadRepos()
  61. if err != nil {
  62. c.ServerError("LoadRepos", err)
  63. return
  64. }
  65. notifications = notifications.Without(failures)
  66. if err := repos.LoadAttributes(); err != nil {
  67. c.ServerError("LoadAttributes", err)
  68. return
  69. }
  70. failCount += len(failures)
  71. failures, err = notifications.LoadIssues()
  72. if err != nil {
  73. c.ServerError("LoadIssues", err)
  74. return
  75. }
  76. notifications = notifications.Without(failures)
  77. failCount += len(failures)
  78. failures, err = notifications.LoadComments()
  79. if err != nil {
  80. c.ServerError("LoadComments", err)
  81. return
  82. }
  83. notifications = notifications.Without(failures)
  84. failCount += len(failures)
  85. if failCount > 0 {
  86. c.Flash.Error(fmt.Sprintf("ERROR: %d notifications were removed due to missing parts - check the logs", failCount))
  87. }
  88. total, err := models.GetNotificationCount(c.User, status)
  89. if err != nil {
  90. c.ServerError("ErrGetNotificationCount", err)
  91. return
  92. }
  93. title := c.Tr("notifications")
  94. if status == models.NotificationStatusUnread && total > 0 {
  95. title = fmt.Sprintf("(%d) %s", total, title)
  96. }
  97. c.Data["Title"] = title
  98. c.Data["Keyword"] = keyword
  99. c.Data["Status"] = status
  100. c.Data["Notifications"] = notifications
  101. pager := context.NewPagination(int(total), perPage, page, 5)
  102. pager.SetDefaultParams(c)
  103. c.Data["Page"] = pager
  104. c.HTML(200, tplNotification)
  105. }
  106. // NotificationStatusPost is a route for changing the status of a notification
  107. func NotificationStatusPost(c *context.Context) {
  108. var (
  109. notificationID, _ = strconv.ParseInt(c.Req.PostFormValue("notification_id"), 10, 64)
  110. statusStr = c.Req.PostFormValue("status")
  111. status models.NotificationStatus
  112. )
  113. switch statusStr {
  114. case "read":
  115. status = models.NotificationStatusRead
  116. case "unread":
  117. status = models.NotificationStatusUnread
  118. case "pinned":
  119. status = models.NotificationStatusPinned
  120. default:
  121. c.ServerError("InvalidNotificationStatus", errors.New("Invalid notification status"))
  122. return
  123. }
  124. if err := models.SetNotificationStatus(notificationID, c.User, status); err != nil {
  125. c.ServerError("SetNotificationStatus", err)
  126. return
  127. }
  128. url := fmt.Sprintf("%s/notifications", setting.AppSubURL)
  129. c.Redirect(url, 303)
  130. }
  131. // NotificationPurgePost is a route for 'purging' the list of notifications - marking all unread as read
  132. func NotificationPurgePost(c *context.Context) {
  133. err := models.UpdateNotificationStatuses(c.User, models.NotificationStatusUnread, models.NotificationStatusRead)
  134. if err != nil {
  135. c.ServerError("ErrUpdateNotificationStatuses", err)
  136. return
  137. }
  138. url := fmt.Sprintf("%s/notifications", setting.AppSubURL)
  139. c.Redirect(url, 303)
  140. }