mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-03 21:08:25 +00:00 
			
		
		
		
	Notifications - Step 2
This commit is contained in:
		@@ -168,6 +168,8 @@ func runWeb(ctx *cli.Context) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	bindIgnErr := binding.BindIgnErr
 | 
						bindIgnErr := binding.BindIgnErr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m.Use(user.GetNotificationCount)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// FIXME: not all routes need go through same middlewares.
 | 
						// FIXME: not all routes need go through same middlewares.
 | 
				
			||||||
	// Especially some AJAX requests, we can reduce middleware number to improve performance.
 | 
						// Especially some AJAX requests, we can reduce middleware number to improve performance.
 | 
				
			||||||
	// Routers.
 | 
						// Routers.
 | 
				
			||||||
@@ -578,6 +580,8 @@ func runWeb(ctx *cli.Context) error {
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
	// ***** END: Repository *****
 | 
						// ***** END: Repository *****
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m.Get("/notifications", reqSignIn, user.Notifications)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m.Group("/api", func() {
 | 
						m.Group("/api", func() {
 | 
				
			||||||
		apiv1.RegisterRoutes(m)
 | 
							apiv1.RegisterRoutes(m)
 | 
				
			||||||
	}, ignSignIn)
 | 
						}, ignSignIn)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,6 +13,7 @@ version = Version
 | 
				
			|||||||
page = Page
 | 
					page = Page
 | 
				
			||||||
template = Template
 | 
					template = Template
 | 
				
			||||||
language = Language
 | 
					language = Language
 | 
				
			||||||
 | 
					notifications = Notifications
 | 
				
			||||||
create_new = Create...
 | 
					create_new = Create...
 | 
				
			||||||
user_profile_and_more = User profile and more
 | 
					user_profile_and_more = User profile and more
 | 
				
			||||||
signed_in_as = Signed in as
 | 
					signed_in_as = Signed in as
 | 
				
			||||||
@@ -1230,3 +1231,10 @@ default_message = Drop files here or click to upload.
 | 
				
			|||||||
invalid_input_type = You can't upload files of this type.
 | 
					invalid_input_type = You can't upload files of this type.
 | 
				
			||||||
file_too_big = File size ({{filesize}} MB) exceeds maximum size ({{maxFilesize}} MB).
 | 
					file_too_big = File size ({{filesize}} MB) exceeds maximum size ({{maxFilesize}} MB).
 | 
				
			||||||
remove_file = Remove file
 | 
					remove_file = Remove file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[notification]
 | 
				
			||||||
 | 
					notifications = Notifications
 | 
				
			||||||
 | 
					unread = Unread
 | 
				
			||||||
 | 
					read = Read
 | 
				
			||||||
 | 
					no_unread = You have no unread notifications.
 | 
				
			||||||
 | 
					no_read = You have no read notifications.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,6 +13,7 @@ version=Versão
 | 
				
			|||||||
page=Página
 | 
					page=Página
 | 
				
			||||||
template=Template
 | 
					template=Template
 | 
				
			||||||
language=Idioma
 | 
					language=Idioma
 | 
				
			||||||
 | 
					notifications = Notificações
 | 
				
			||||||
create_new=Criar...
 | 
					create_new=Criar...
 | 
				
			||||||
user_profile_and_more=Perfil do usuário e configurações
 | 
					user_profile_and_more=Perfil do usuário e configurações
 | 
				
			||||||
signed_in_as=Logado como
 | 
					signed_in_as=Logado como
 | 
				
			||||||
@@ -1197,3 +1198,10 @@ default_message=Arraste e solte arquivos aqui, ou clique para selecioná-los.
 | 
				
			|||||||
invalid_input_type=Você não pode enviar arquivos deste tipo.
 | 
					invalid_input_type=Você não pode enviar arquivos deste tipo.
 | 
				
			||||||
file_too_big=O tamanho do arquivo ({{filesize}} MB) excede o limite máximo ({{maxFilesize}} MB).
 | 
					file_too_big=O tamanho do arquivo ({{filesize}} MB) excede o limite máximo ({{maxFilesize}} MB).
 | 
				
			||||||
remove_file=Remover
 | 
					remove_file=Remover
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[notification]
 | 
				
			||||||
 | 
					notifications = Notificações
 | 
				
			||||||
 | 
					unread = Não lidas
 | 
				
			||||||
 | 
					read = Lidas
 | 
				
			||||||
 | 
					no_unread = Você não possui notificações não lidas.
 | 
				
			||||||
 | 
					no_read = Você não possui notificações lidas.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2694,6 +2694,24 @@ footer .ui.language .menu {
 | 
				
			|||||||
.user.followers .follow .ui.button {
 | 
					.user.followers .follow .ui.button {
 | 
				
			||||||
  padding: 8px 15px;
 | 
					  padding: 8px 15px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					.user.notification .octicon {
 | 
				
			||||||
 | 
					  float: left;
 | 
				
			||||||
 | 
					  font-size: 2em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.user.notification .content {
 | 
				
			||||||
 | 
					  float: left;
 | 
				
			||||||
 | 
					  margin-left: 7px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.user.notification .octicon-issue-opened,
 | 
				
			||||||
 | 
					.user.notification .octicon-git-pull-request {
 | 
				
			||||||
 | 
					  color: green;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.user.notification .octicon-issue-closed {
 | 
				
			||||||
 | 
					  color: red;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.user.notification .octicon-git-merge {
 | 
				
			||||||
 | 
					  color: purple;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
.dashboard {
 | 
					.dashboard {
 | 
				
			||||||
  padding-top: 15px;
 | 
					  padding-top: 15px;
 | 
				
			||||||
  padding-bottom: 80px;
 | 
					  padding-bottom: 80px;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -74,4 +74,25 @@
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    &.notification {
 | 
				
			||||||
 | 
					        .octicon {
 | 
				
			||||||
 | 
					            float: left;
 | 
				
			||||||
 | 
					            font-size: 2em;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        .content {
 | 
				
			||||||
 | 
					            float: left;
 | 
				
			||||||
 | 
					            margin-left: 7px;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        .octicon-issue-opened, .octicon-git-pull-request {
 | 
				
			||||||
 | 
					            color: green;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        .octicon-issue-closed {
 | 
				
			||||||
 | 
					            color: red;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        .octicon-git-merge {
 | 
				
			||||||
 | 
					            color: purple;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										54
									
								
								routers/user/notification.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								routers/user/notification.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					package user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/base"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/context"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						tplNotification base.TplName = "user/notification/notification"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetNotificationCount is the middleware that sets the notification count in the context
 | 
				
			||||||
 | 
					func GetNotificationCount(c *context.Context) {
 | 
				
			||||||
 | 
						if !c.IsSigned {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, err := models.GetNotificationUnreadCount(c.User)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							c.Handle(500, "GetNotificationCount", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c.Data["NotificationUnreadCount"] = count
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Notifications is the notifications page
 | 
				
			||||||
 | 
					func Notifications(c *context.Context) {
 | 
				
			||||||
 | 
						var status models.NotificationStatus
 | 
				
			||||||
 | 
						switch c.Query("status") {
 | 
				
			||||||
 | 
						case "read":
 | 
				
			||||||
 | 
							status = models.NotificationStatusRead
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							status = models.NotificationStatusUnread
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						notifications, err := models.NotificationsForUser(c.User, status)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							c.Handle(500, "ErrNotificationsForUser", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						title := "Notifications"
 | 
				
			||||||
 | 
						if count := len(notifications); count > 0 {
 | 
				
			||||||
 | 
							title = fmt.Sprintf("(%d) %s", count, title)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.Data["Title"] = title
 | 
				
			||||||
 | 
						c.Data["Status"] = status
 | 
				
			||||||
 | 
						c.Data["Notifications"] = notifications
 | 
				
			||||||
 | 
						c.HTML(200, tplNotification)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -29,7 +29,6 @@ const (
 | 
				
			|||||||
	tplSettingsSocial       base.TplName = "user/settings/social"
 | 
						tplSettingsSocial       base.TplName = "user/settings/social"
 | 
				
			||||||
	tplSettingsApplications base.TplName = "user/settings/applications"
 | 
						tplSettingsApplications base.TplName = "user/settings/applications"
 | 
				
			||||||
	tplSettingsDelete       base.TplName = "user/settings/delete"
 | 
						tplSettingsDelete       base.TplName = "user/settings/delete"
 | 
				
			||||||
	tplNotification         base.TplName = "user/notification"
 | 
					 | 
				
			||||||
	tplSecurity             base.TplName = "user/security"
 | 
						tplSecurity             base.TplName = "user/security"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,6 +82,18 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
								{{if .IsSigned}}
 | 
													{{if .IsSigned}}
 | 
				
			||||||
									<div class="right menu">
 | 
														<div class="right menu">
 | 
				
			||||||
 | 
															<a href="/notifications" class="ui head link jump item poping up" data-content='{{.i18n.Tr "notifications"}}' data-variation="tiny inverted">
 | 
				
			||||||
 | 
																<span class="text">
 | 
				
			||||||
 | 
																	<i class="octicon octicon-inbox"><span class="sr-only">{{.i18n.Tr "notifications"}}</span></i>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
																	{{if .NotificationUnreadCount}}
 | 
				
			||||||
 | 
																		<span class="ui red label">
 | 
				
			||||||
 | 
																			{{.NotificationUnreadCount}}
 | 
				
			||||||
 | 
																		</span>
 | 
				
			||||||
 | 
																	{{end}}
 | 
				
			||||||
 | 
																</span>
 | 
				
			||||||
 | 
															</a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
										<div class="ui dropdown head link jump item poping up" data-content="{{.i18n.Tr "create_new"}}" data-variation="tiny inverted">
 | 
															<div class="ui dropdown head link jump item poping up" data-content="{{.i18n.Tr "create_new"}}" data-variation="tiny inverted">
 | 
				
			||||||
											<span class="text">
 | 
																<span class="text">
 | 
				
			||||||
												<i class="octicon octicon-plus"><span class="sr-only">{{.i18n.Tr "create_new"}}</span></i>
 | 
																	<i class="octicon octicon-plus"><span class="sr-only">{{.i18n.Tr "create_new"}}</span></i>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										68
									
								
								templates/user/notification/notification.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								templates/user/notification/notification.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					{{template "base/head" .}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="user notification">
 | 
				
			||||||
 | 
						<div class="ui container">
 | 
				
			||||||
 | 
							<h1 class="ui header">{{.i18n.Tr "notification.notifications"}}</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<div class="ui top attached tabular menu">
 | 
				
			||||||
 | 
								<a href="/notifications?status=unread">
 | 
				
			||||||
 | 
									<div class="{{if eq .Status 1}}active{{end}} item">
 | 
				
			||||||
 | 
										{{.i18n.Tr "notification.unread"}}
 | 
				
			||||||
 | 
										{{if eq .Status 1}}
 | 
				
			||||||
 | 
											<div class="ui label">{{len .Notifications}}</div>
 | 
				
			||||||
 | 
										{{end}}
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</a>
 | 
				
			||||||
 | 
								<a href="/notifications?status=read">
 | 
				
			||||||
 | 
									<div class="{{if eq .Status 2}}active{{end}} item">
 | 
				
			||||||
 | 
										{{.i18n.Tr "notification.read"}}
 | 
				
			||||||
 | 
										{{if eq .Status 2}}
 | 
				
			||||||
 | 
											<div class="ui label">{{len .Notifications}}</div>
 | 
				
			||||||
 | 
										{{end}}
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</a>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div class="ui bottom attached active tab segment">
 | 
				
			||||||
 | 
								{{if eq (len .Notifications) 0}}
 | 
				
			||||||
 | 
									{{if eq .Status 1}}
 | 
				
			||||||
 | 
										{{.i18n.Tr "notification.no_unread"}}
 | 
				
			||||||
 | 
									{{else}}
 | 
				
			||||||
 | 
										{{.i18n.Tr "notification.no_read"}}
 | 
				
			||||||
 | 
									{{end}}
 | 
				
			||||||
 | 
								{{else}}
 | 
				
			||||||
 | 
									<div class="ui relaxed divided list">
 | 
				
			||||||
 | 
										{{range $notification := .Notifications}}
 | 
				
			||||||
 | 
											{{$issue := $notification.GetIssue}}
 | 
				
			||||||
 | 
											{{$repo := $notification.GetRepo}}
 | 
				
			||||||
 | 
											{{$repoOwner := $repo.MustOwner}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											<div class="item">
 | 
				
			||||||
 | 
												<a href="{{$.AppSubUrl}}/{{$repoOwner.Name}}/{{$repo.Name}}/issues/{{$issue.Index}}">
 | 
				
			||||||
 | 
													{{if and $issue.IsPull}}
 | 
				
			||||||
 | 
														{{if $issue.IsClosed}}
 | 
				
			||||||
 | 
															<i class="octicon octicon-git-merge"></i>
 | 
				
			||||||
 | 
														{{else}}
 | 
				
			||||||
 | 
															<i class="octicon octicon-git-pull-request"></i>
 | 
				
			||||||
 | 
														{{end}}
 | 
				
			||||||
 | 
													{{else}}
 | 
				
			||||||
 | 
														{{if $issue.IsClosed}}
 | 
				
			||||||
 | 
															<i class="octicon octicon-issue-closed"></i>
 | 
				
			||||||
 | 
														{{else}}
 | 
				
			||||||
 | 
															<i class="octicon octicon-issue-opened"></i>
 | 
				
			||||||
 | 
														{{end}}
 | 
				
			||||||
 | 
													{{end}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
													<div class="content">
 | 
				
			||||||
 | 
														<div class="header">{{$repoOwner.Name}}/{{$repo.Name}}</div>
 | 
				
			||||||
 | 
														<div class="description">{{$issue.Title}}</div>
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												</a>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										{{end}}
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								{{end}}
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{template "base/footer" .}}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user