Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add notification interface and refactor UI notifications #5085

Merged
merged 3 commits into from
Oct 18, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
add notification interface and refactor UI notifications
  • Loading branch information
lunny committed Oct 18, 2018
commit 00539b2ab7a1cbff9cb1f2435cb838c94543ea54
41 changes: 41 additions & 0 deletions modules/notification/base/base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2018 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.

package base

import (
"code.gitea.io/git"
"code.gitea.io/gitea/models"
)

// Notifier defines an interface to notify receiver
type Notifier interface {
Run()

NotifyCreateRepository(doer *models.User, u *models.User, repo *models.Repository)
NotifyMigrateRepository(doer *models.User, u *models.User, repo *models.Repository)
NotifyDeleteRepository(doer *models.User, repo *models.Repository)
NotifyForkRepository(doer *models.User, oldRepo, repo *models.Repository)

NotifyNewIssue(*models.Issue)
NotifyIssueChangeStatus(*models.User, *models.Issue, bool)
NotifyIssueChangeMilestone(doer *models.User, issue *models.Issue)
NotifyIssueChangeAssignee(doer *models.User, issue *models.Issue, removed bool)
NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string)
NotifyIssueClearLabels(doer *models.User, issue *models.Issue)
NotifyIssueChangeTitle(doer *models.User, issue *models.Issue, oldTitle string)
NotifyIssueChangeLabels(doer *models.User, issue *models.Issue,
addedLabels []*models.Label, removedLabels []*models.Label)
NotifyNewPullRequest(*models.PullRequest)
NotifyMergePullRequest(*models.PullRequest, *models.User, *git.Repository)
jonasfranz marked this conversation as resolved.
Show resolved Hide resolved

NotifyCreateIssueComment(*models.User, *models.Repository,
*models.Issue, *models.Comment)
NotifyUpdateComment(*models.User, *models.Comment, string)
NotifyDeleteComment(*models.User, *models.Comment)

NotifyNewRelease(rel *models.Release)
NotifyUpdateRelease(doer *models.User, rel *models.Release)
NotifyDeleteRelease(doer *models.User, rel *models.Release)
}
174 changes: 146 additions & 28 deletions modules/notification/notification.go
Original file line number Diff line number Diff line change
@@ -1,50 +1,168 @@
// Copyright 2016 The Gitea Authors. All rights reserved.
// Copyright 2018 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.

package notification

import (
"code.gitea.io/git"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/notification/base"
"code.gitea.io/gitea/modules/notification/ui"
)

type (
notificationService struct {
issueQueue chan issueNotificationOpts
var (
notifiers []base.Notifier
)

// RegisterNotifier providers method to receive notify messages
func RegisterNotifier(notifier base.Notifier) {
go notifier.Run()
notifiers = append(notifiers, notifier)
}

func init() {
RegisterNotifier(ui.NewNotifier())
}

// NotifyCreateIssueComment notifies issue comment related message to notifiers
func NotifyCreateIssueComment(doer *models.User, repo *models.Repository,
issue *models.Issue, comment *models.Comment) {
for _, notifier := range notifiers {
notifier.NotifyCreateIssueComment(doer, repo, issue, comment)
}
}

issueNotificationOpts struct {
issue *models.Issue
notificationAuthorID int64
// NotifyNewIssue notifies new issue to notifiers
func NotifyNewIssue(issue *models.Issue) {
for _, notifier := range notifiers {
notifier.NotifyNewIssue(issue)
}
)
}

var (
// Service is the notification service
Service = &notificationService{
issueQueue: make(chan issueNotificationOpts, 100),
// NotifyIssueChangeStatus notifies close or reopen issue to notifiers
func NotifyIssueChangeStatus(doer *models.User, issue *models.Issue, closeOrReopen bool) {
for _, notifier := range notifiers {
notifier.NotifyIssueChangeStatus(doer, issue, closeOrReopen)
}
)
}

func init() {
go Service.Run()
// NotifyMergePullRequest notifies merge pull request to notifiers
func NotifyMergePullRequest(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repository) {
for _, notifier := range notifiers {
notifier.NotifyMergePullRequest(pr, doer, baseGitRepo)
jonasfranz marked this conversation as resolved.
Show resolved Hide resolved
}
}

// NotifyNewPullRequest notifies new pull request to notifiers
func NotifyNewPullRequest(pr *models.PullRequest) {
for _, notifier := range notifiers {
notifier.NotifyNewPullRequest(pr)
}
}

// NotifyUpdateComment notifies update comment to notifiers
func NotifyUpdateComment(doer *models.User, c *models.Comment, oldContent string) {
for _, notifier := range notifiers {
notifier.NotifyUpdateComment(doer, c, oldContent)
}
}

// NotifyDeleteComment notifies delete comment to notifiers
func NotifyDeleteComment(doer *models.User, c *models.Comment) {
for _, notifier := range notifiers {
notifier.NotifyDeleteComment(doer, c)
}
}

// NotifyDeleteRepository notifies delete repository to notifiers
func NotifyDeleteRepository(doer *models.User, repo *models.Repository) {
for _, notifier := range notifiers {
notifier.NotifyDeleteRepository(doer, repo)
}
}

// NotifyForkRepository notifies fork repository to notifiers
func NotifyForkRepository(doer *models.User, oldRepo, repo *models.Repository) {
for _, notifier := range notifiers {
notifier.NotifyForkRepository(doer, oldRepo, repo)
}
}

// NotifyNewRelease notifies new release to notifiers
func NotifyNewRelease(rel *models.Release) {
for _, notifier := range notifiers {
notifier.NotifyNewRelease(rel)
}
}

// NotifyUpdateRelease notifies update release to notifiers
func NotifyUpdateRelease(doer *models.User, rel *models.Release) {
for _, notifier := range notifiers {
notifier.NotifyUpdateRelease(doer, rel)
}
}

// NotifyDeleteRelease notifies delete release to notifiers
func NotifyDeleteRelease(doer *models.User, rel *models.Release) {
for _, notifier := range notifiers {
notifier.NotifyDeleteRelease(doer, rel)
}
}

// NotifyIssueChangeMilestone notifies change milestone to notifiers
func NotifyIssueChangeMilestone(doer *models.User, issue *models.Issue) {
for _, notifier := range notifiers {
notifier.NotifyIssueChangeMilestone(doer, issue)
}
}

// NotifyIssueChangeContent notifies change content to notifiers
func NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string) {
for _, notifier := range notifiers {
notifier.NotifyIssueChangeContent(doer, issue, oldContent)
}
}

// NotifyIssueChangeAssignee notifies change content to notifiers
func NotifyIssueChangeAssignee(doer *models.User, issue *models.Issue, removed bool) {
for _, notifier := range notifiers {
notifier.NotifyIssueChangeAssignee(doer, issue, removed)
}
}

// NotifyIssueClearLabels notifies clear labels to notifiers
func NotifyIssueClearLabels(doer *models.User, issue *models.Issue) {
for _, notifier := range notifiers {
notifier.NotifyIssueClearLabels(doer, issue)
}
}

// NotifyIssueChangeTitle notifies change title to notifiers
func NotifyIssueChangeTitle(doer *models.User, issue *models.Issue, oldTitle string) {
for _, notifier := range notifiers {
notifier.NotifyIssueChangeTitle(doer, issue, oldTitle)
}
}

// NotifyIssueChangeLabels notifies change labels to notifiers
func NotifyIssueChangeLabels(doer *models.User, issue *models.Issue,
addedLabels []*models.Label, removedLabels []*models.Label) {
for _, notifier := range notifiers {
notifier.NotifyIssueChangeLabels(doer, issue, addedLabels, removedLabels)
}
}

func (ns *notificationService) Run() {
for {
select {
case opts := <-ns.issueQueue:
if err := models.CreateOrUpdateIssueNotifications(opts.issue, opts.notificationAuthorID); err != nil {
log.Error(4, "Was unable to create issue notification: %v", err)
}
}
// NotifyCreateRepository notifies create repository to notifiers
func NotifyCreateRepository(doer *models.User, u *models.User, repo *models.Repository) {
for _, notifier := range notifiers {
notifier.NotifyCreateRepository(doer, u, repo)
}
}

func (ns *notificationService) NotifyIssue(issue *models.Issue, notificationAuthorID int64) {
ns.issueQueue <- issueNotificationOpts{
issue,
notificationAuthorID,
// NotifyMigrateRepository notifies create repository to notifiers
func NotifyMigrateRepository(doer *models.User, u *models.User, repo *models.Repository) {
for _, notifier := range notifiers {
notifier.NotifyMigrateRepository(doer, u, repo)
}
}
127 changes: 127 additions & 0 deletions modules/notification/ui/ui.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright 2018 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.

package ui

import (
"code.gitea.io/git"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/notification/base"
)

type (
notificationService struct {
issueQueue chan issueNotificationOpts
}

issueNotificationOpts struct {
issue *models.Issue
notificationAuthorID int64
}
)

var (
_ base.Notifier = &notificationService{}
)

// NewNotifier create a new notificationService notifier
func NewNotifier() base.Notifier {
return &notificationService{
issueQueue: make(chan issueNotificationOpts, 100),
}
}

func (ns *notificationService) Run() {
for {
select {
case opts := <-ns.issueQueue:
if err := models.CreateOrUpdateIssueNotifications(opts.issue, opts.notificationAuthorID); err != nil {
log.Error(4, "Was unable to create issue notification: %v", err)
}
}
}
}

func (ns *notificationService) NotifyCreateIssueComment(doer *models.User, repo *models.Repository,
issue *models.Issue, comment *models.Comment) {
ns.issueQueue <- issueNotificationOpts{
issue,
doer.ID,
}
}

func (ns *notificationService) NotifyNewIssue(issue *models.Issue) {
ns.issueQueue <- issueNotificationOpts{
issue,
issue.Poster.ID,
}
}

func (ns *notificationService) NotifyIssueChangeStatus(doer *models.User, issue *models.Issue, isClosed bool) {
ns.issueQueue <- issueNotificationOpts{
issue,
doer.ID,
}
}

func (ns *notificationService) NotifyMergePullRequest(pr *models.PullRequest, doer *models.User, gitRepo *git.Repository) {
ns.issueQueue <- issueNotificationOpts{
pr.Issue,
doer.ID,
}
}

func (ns *notificationService) NotifyNewPullRequest(pr *models.PullRequest) {
ns.issueQueue <- issueNotificationOpts{
pr.Issue,
pr.Issue.PosterID,
}
}

func (ns *notificationService) NotifyUpdateComment(doer *models.User, c *models.Comment, oldContent string) {
}

func (ns *notificationService) NotifyDeleteComment(doer *models.User, c *models.Comment) {
}

func (ns *notificationService) NotifyDeleteRepository(doer *models.User, repo *models.Repository) {
}

func (ns *notificationService) NotifyForkRepository(doer *models.User, oldRepo, repo *models.Repository) {
}

func (ns *notificationService) NotifyNewRelease(rel *models.Release) {
}

func (ns *notificationService) NotifyUpdateRelease(doer *models.User, rel *models.Release) {
}

func (ns *notificationService) NotifyDeleteRelease(doer *models.User, rel *models.Release) {
}

func (ns *notificationService) NotifyIssueChangeMilestone(doer *models.User, issue *models.Issue) {
}

func (ns *notificationService) NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string) {
}

func (ns *notificationService) NotifyIssueChangeAssignee(doer *models.User, issue *models.Issue, removed bool) {
}

func (ns *notificationService) NotifyIssueClearLabels(doer *models.User, issue *models.Issue) {
}

func (ns *notificationService) NotifyIssueChangeTitle(doer *models.User, issue *models.Issue, oldTitle string) {
}

func (ns *notificationService) NotifyIssueChangeLabels(doer *models.User, issue *models.Issue,
addedLabels []*models.Label, removedLabels []*models.Label) {
}

func (ns *notificationService) NotifyCreateRepository(doer *models.User, u *models.User, repo *models.Repository) {
}

func (ns *notificationService) NotifyMigrateRepository(doer *models.User, u *models.User, repo *models.Repository) {
}
5 changes: 5 additions & 0 deletions routers/api/v1/repo/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/indexer"
"code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"

Expand Down Expand Up @@ -207,6 +208,8 @@ func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) {
return
}

notification.NotifyNewIssue(issue)

if form.Closed {
if err := issue.ChangeStatus(ctx.User, ctx.Repo.Repository, true); err != nil {
if models.IsErrDependenciesLeft(err) {
Expand Down Expand Up @@ -337,6 +340,8 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
ctx.Error(500, "ChangeStatus", err)
return
}

notification.NotifyIssueChangeStatus(ctx.User, issue, api.StateClosed == api.StateType(*form.State))
}

// Refetch from database to assign some automatic values
Expand Down
Loading