Browse Source

Merge pull request #539 from andreynering/notifications-step-2

Notifications - Step 2
tags/v1.2.0-rc1
Andrey Nering GitHub 8 years ago
parent
commit
52ab3e2b15
10 changed files with 233 additions and 6 deletions
  1. +4
    -0
      cmd/web.go
  2. +11
    -5
      models/notification.go
  3. +8
    -0
      options/locale/locale_en-US.ini
  4. +8
    -0
      options/locale/locale_pt-BR.ini
  5. +18
    -0
      public/css/index.css
  6. +21
    -0
      public/less/_user.less
  7. +81
    -0
      routers/user/notification.go
  8. +0
    -1
      routers/user/setting.go
  9. +12
    -0
      templates/base/head.tmpl
  10. +70
    -0
      templates/user/notification/notification.tmpl

+ 4
- 0
cmd/web.go View File

@@ -167,6 +167,8 @@ func runWeb(ctx *cli.Context) error {

bindIgnErr := binding.BindIgnErr

m.Use(user.GetNotificationCount)

// FIXME: not all routes need go through same middlewares.
// Especially some AJAX requests, we can reduce middleware number to improve performance.
// Routers.
@@ -577,6 +579,8 @@ func runWeb(ctx *cli.Context) error {
})
// ***** END: Repository *****

m.Get("/notifications", reqSignIn, user.Notifications)

m.Group("/api", func() {
apiv1.RegisterRoutes(m)
}, ignSignIn)


+ 11
- 5
models/notification.go View File

@@ -182,14 +182,20 @@ func getIssueNotification(e Engine, userID, issueID int64) (*Notification, error
}

// NotificationsForUser returns notifications for a given user and status
func NotificationsForUser(user *User, status NotificationStatus) ([]*Notification, error) {
return notificationsForUser(x, user, status)
func NotificationsForUser(user *User, status NotificationStatus, page, perPage int) ([]*Notification, error) {
return notificationsForUser(x, user, status, page, perPage)
}
func notificationsForUser(e Engine, user *User, status NotificationStatus) (notifications []*Notification, err error) {
err = e.
func notificationsForUser(e Engine, user *User, status NotificationStatus, page, perPage int) (notifications []*Notification, err error) {
sess := e.
Where("user_id = ?", user.ID).
And("status = ?", status).
OrderBy("updated_unix DESC").
OrderBy("updated_unix DESC")

if page > 0 && perPage > 0 {
sess.Limit(perPage, (page-1)*perPage)
}

err = sess.
Find(&notifications)
return
}


+ 8
- 0
options/locale/locale_en-US.ini View File

@@ -13,6 +13,7 @@ version = Version
page = Page
template = Template
language = Language
notifications = Notifications
create_new = Create...
user_profile_and_more = User profile and more
signed_in_as = Signed in as
@@ -1232,3 +1233,10 @@ default_message = Drop files here or click to upload.
invalid_input_type = You can't upload files of this type.
file_too_big = File size ({{filesize}} MB) exceeds maximum size ({{maxFilesize}} MB).
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.

+ 8
- 0
options/locale/locale_pt-BR.ini View File

@@ -13,6 +13,7 @@ version=Versão
page=Página
template=Template
language=Idioma
notifications = Notificações
create_new=Criar...
user_profile_and_more=Perfil do usuário e configurações
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.
file_too_big=O tamanho do arquivo ({{filesize}} MB) excede o limite máximo ({{maxFilesize}} MB).
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.

+ 18
- 0
public/css/index.css View File

@@ -2704,6 +2704,24 @@ footer .ui.language .menu {
.user.followers .follow .ui.button {
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: #21ba45;
}
.user.notification .octicon-issue-closed {
color: #d01919;
}
.user.notification .octicon-git-merge {
color: #a333c8;
}
.dashboard {
padding-top: 15px;
padding-bottom: 80px;


+ 21
- 0
public/less/_user.less View File

@@ -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: #21ba45;
}
.octicon-issue-closed {
color: #d01919;
}
.octicon-git-merge {
color: #a333c8;
}
}
}

+ 81
- 0
routers/user/notification.go View File

@@ -0,0 +1,81 @@
package user

import (
"fmt"
"strings"

"github.com/Unknwon/paginater"

"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 strings.HasPrefix(c.Req.URL.Path, "/api") {
return
}

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 (
keyword = c.Query("q")
status models.NotificationStatus
page = c.QueryInt("page")
perPage = c.QueryInt("perPage")
)
if page < 1 {
page = 1
}
if perPage < 1 {
perPage = 20
}

switch keyword {
case "read":
status = models.NotificationStatusRead
default:
status = models.NotificationStatusUnread
}

notifications, err := models.NotificationsForUser(c.User, status, page, perPage)
if err != nil {
c.Handle(500, "ErrNotificationsForUser", err)
return
}

total, err := models.GetNotificationCount(c.User, status)
if err != nil {
c.Handle(500, "ErrGetNotificationCount", err)
return
}

title := "Notifications"
if count := len(notifications); count > 0 {
title = fmt.Sprintf("(%d) %s", count, title)
}
c.Data["Title"] = title
c.Data["Keyword"] = keyword
c.Data["Status"] = status
c.Data["Notifications"] = notifications
c.Data["Page"] = paginater.New(int(total), perPage, page, 5)
c.HTML(200, tplNotification)
}

+ 0
- 1
routers/user/setting.go View File

@@ -29,7 +29,6 @@ const (
tplSettingsSocial base.TplName = "user/settings/social"
tplSettingsApplications base.TplName = "user/settings/applications"
tplSettingsDelete base.TplName = "user/settings/delete"
tplNotification base.TplName = "user/notification"
tplSecurity base.TplName = "user/security"
)



+ 12
- 0
templates/base/head.tmpl View File

@@ -82,6 +82,18 @@

{{if .IsSigned}}
<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">
<span class="text">
<i class="octicon octicon-plus"><span class="sr-only">{{.i18n.Tr "create_new"}}</span></i>


+ 70
- 0
templates/user/notification/notification.tmpl View File

@@ -0,0 +1,70 @@
{{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?q=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?q=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.Index}} - {{$issue.Title}}</div>
</div>
</a>
</div>
{{end}}
</div>
{{end}}
</div>

{{template "base/paginate" .}}
</div>
</div>

{{template "base/footer" .}}

Loading…
Cancel
Save