2019-04-20 06:15:19 +02:00
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
2016-12-30 16:49:54 -02:00
package user
import (
2017-01-12 02:27:09 -02:00
"errors"
2016-12-30 16:49:54 -02:00
"fmt"
2020-04-24 04:57:38 +01:00
"net/http"
2017-01-12 02:27:09 -02:00
"strconv"
2017-01-02 16:31:50 -02:00
"strings"
2016-12-30 16:49:54 -02:00
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
2017-01-12 02:27:09 -02:00
"code.gitea.io/gitea/modules/setting"
2016-12-30 16:49:54 -02:00
)
const (
2020-04-24 04:57:38 +01:00
tplNotification base . TplName = "user/notification/notification"
tplNotificationDiv base . TplName = "user/notification/notification_div"
2016-12-30 16:49:54 -02:00
)
// GetNotificationCount is the middleware that sets the notification count in the context
func GetNotificationCount ( c * context . Context ) {
2017-01-02 16:31:50 -02:00
if strings . HasPrefix ( c . Req . URL . Path , "/api" ) {
return
}
2016-12-30 16:49:54 -02:00
if ! c . IsSigned {
return
}
2020-04-24 04:57:38 +01:00
c . Data [ "NotificationUnreadCount" ] = func ( ) int64 {
count , err := models . GetNotificationCount ( c . User , models . NotificationStatusUnread )
if err != nil {
c . ServerError ( "GetNotificationCount" , err )
return - 1
}
2016-12-30 16:49:54 -02:00
2020-04-24 04:57:38 +01:00
return count
}
2016-12-30 16:49:54 -02:00
}
// Notifications is the notifications page
func Notifications ( c * context . Context ) {
2020-04-24 04:57:38 +01:00
getNotifications ( c )
if c . Written ( ) {
return
}
if c . QueryBool ( "div-only" ) {
c . HTML ( http . StatusOK , tplNotificationDiv )
return
}
c . HTML ( http . StatusOK , tplNotification )
}
func getNotifications ( c * context . Context ) {
2017-01-03 17:09:36 -02:00
var (
2017-02-11 12:00:01 +08:00
keyword = strings . Trim ( c . Query ( "q" ) , " " )
2017-01-03 17:09:36 -02:00
status models . NotificationStatus
page = c . QueryInt ( "page" )
perPage = c . QueryInt ( "perPage" )
)
if page < 1 {
page = 1
}
if perPage < 1 {
perPage = 20
}
switch keyword {
2016-12-30 16:49:54 -02:00
case "read" :
status = models . NotificationStatusRead
default :
status = models . NotificationStatusUnread
}
2020-01-18 02:31:26 +08:00
total , err := models . GetNotificationCount ( c . User , status )
if err != nil {
c . ServerError ( "ErrGetNotificationCount" , err )
return
}
// redirect to last page if request page is more than total pages
pager := context . NewPagination ( int ( total ) , perPage , page , 5 )
if pager . Paginater . Current ( ) < page {
c . Redirect ( fmt . Sprintf ( "/notifications?q=%s&page=%d" , c . Query ( "q" ) , pager . Paginater . Current ( ) ) )
return
}
2017-01-12 02:27:09 -02:00
statuses := [ ] models . NotificationStatus { status , models . NotificationStatusPinned }
notifications , err := models . NotificationsForUser ( c . User , statuses , page , perPage )
2016-12-30 16:49:54 -02:00
if err != nil {
2018-01-10 22:34:17 +01:00
c . ServerError ( "ErrNotificationsForUser" , err )
2016-12-30 16:49:54 -02:00
return
}
2020-03-29 20:51:14 +01:00
failCount := 0
repos , failures , err := notifications . LoadRepos ( )
2019-11-12 16:33:34 +08:00
if err != nil {
c . ServerError ( "LoadRepos" , err )
return
}
2020-03-29 20:51:14 +01:00
notifications = notifications . Without ( failures )
2019-11-12 16:33:34 +08:00
if err := repos . LoadAttributes ( ) ; err != nil {
c . ServerError ( "LoadAttributes" , err )
return
}
2020-03-29 20:51:14 +01:00
failCount += len ( failures )
2019-11-12 16:33:34 +08:00
2020-03-29 20:51:14 +01:00
failures , err = notifications . LoadIssues ( )
if err != nil {
2019-11-12 16:33:34 +08:00
c . ServerError ( "LoadIssues" , err )
return
}
2020-03-29 20:51:14 +01:00
notifications = notifications . Without ( failures )
failCount += len ( failures )
failures , err = notifications . LoadComments ( )
if err != nil {
2019-11-12 16:33:34 +08:00
c . ServerError ( "LoadComments" , err )
return
}
2020-03-29 20:51:14 +01:00
notifications = notifications . Without ( failures )
failCount += len ( failures )
if failCount > 0 {
c . Flash . Error ( fmt . Sprintf ( "ERROR: %d notifications were removed due to missing parts - check the logs" , failCount ) )
}
2019-11-12 16:33:34 +08:00
2020-04-24 04:57:38 +01:00
c . Data [ "Title" ] = c . Tr ( "notifications" )
2017-01-03 17:09:36 -02:00
c . Data [ "Keyword" ] = keyword
2016-12-30 16:49:54 -02:00
c . Data [ "Status" ] = status
c . Data [ "Notifications" ] = notifications
2019-04-20 06:15:19 +02:00
pager . SetDefaultParams ( c )
c . Data [ "Page" ] = pager
2016-12-30 16:49:54 -02:00
}
2017-01-12 02:27:09 -02:00
// NotificationStatusPost is a route for changing the status of a notification
func NotificationStatusPost ( c * context . Context ) {
var (
notificationID , _ = strconv . ParseInt ( c . Req . PostFormValue ( "notification_id" ) , 10 , 64 )
statusStr = c . Req . PostFormValue ( "status" )
status models . NotificationStatus
)
switch statusStr {
case "read" :
status = models . NotificationStatusRead
case "unread" :
status = models . NotificationStatusUnread
case "pinned" :
status = models . NotificationStatusPinned
default :
2018-01-10 22:34:17 +01:00
c . ServerError ( "InvalidNotificationStatus" , errors . New ( "Invalid notification status" ) )
2017-01-12 02:27:09 -02:00
return
}
if err := models . SetNotificationStatus ( notificationID , c . User , status ) ; err != nil {
2018-01-10 22:34:17 +01:00
c . ServerError ( "SetNotificationStatus" , err )
2017-01-12 02:27:09 -02:00
return
}
2020-04-24 04:57:38 +01:00
if ! c . QueryBool ( "noredirect" ) {
url := fmt . Sprintf ( "%s/notifications?page=%s" , setting . AppSubURL , c . Query ( "page" ) )
c . Redirect ( url , http . StatusSeeOther )
}
getNotifications ( c )
if c . Written ( ) {
return
}
c . HTML ( http . StatusOK , tplNotificationDiv )
2017-01-12 02:27:09 -02:00
}
2017-12-07 12:52:57 +07:00
// NotificationPurgePost is a route for 'purging' the list of notifications - marking all unread as read
func NotificationPurgePost ( c * context . Context ) {
err := models . UpdateNotificationStatuses ( c . User , models . NotificationStatusUnread , models . NotificationStatusRead )
if err != nil {
2018-01-10 22:34:17 +01:00
c . ServerError ( "ErrUpdateNotificationStatuses" , err )
2017-12-07 12:52:57 +07:00
return
}
url := fmt . Sprintf ( "%s/notifications" , setting . AppSubURL )
2020-04-24 04:57:38 +01:00
c . Redirect ( url , http . StatusSeeOther )
2017-12-07 12:52:57 +07:00
}