summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2017-02-01 10:36:08 +0800
committerGitHub <noreply@github.com>2017-02-01 10:36:08 +0800
commit081485ecfddc88a05fdea0b0230672271658c086 (patch)
treebbaaa55ede02f311056f5df6c8b56301be09982d
parent10644d6dd7574b031118bf01b2bd737017230ffd (diff)
downloadgitea-081485ecfddc88a05fdea0b0230672271658c086.tar.gz
gitea-081485ecfddc88a05fdea0b0230672271658c086.zip
add milestone changed traker on issue view (#804)
-rw-r--r--models/issue.go29
-rw-r--r--models/issue_comment.go81
-rw-r--r--models/pull.go2
-rw-r--r--options/locale/locale_en-US.ini3
-rw-r--r--options/locale/locale_zh-CN.ini3
-rw-r--r--public/js/index.js6
-rw-r--r--routers/api/v1/repo/issue.go2
-rw-r--r--routers/api/v1/repo/pull.go2
-rw-r--r--routers/repo/issue.go35
-rw-r--r--templates/repo/issue/view_content.tmpl11
10 files changed, 134 insertions, 40 deletions
diff --git a/models/issue.go b/models/issue.go
index 1727da1d50..05b17e4da5 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -739,7 +739,7 @@ type NewIssueOptions struct {
IsPull bool
}
-func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) {
+func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {
opts.Issue.Title = strings.TrimSpace(opts.Issue.Title)
opts.Issue.Index = opts.Repo.NextIssueIndex()
@@ -754,9 +754,6 @@ func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) {
if milestone != nil {
opts.Issue.MilestoneID = milestone.ID
opts.Issue.Milestone = milestone
- if err = changeMilestoneAssign(e, opts.Issue, -1); err != nil {
- return err
- }
}
}
@@ -785,6 +782,12 @@ func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) {
return err
}
+ if opts.Issue.MilestoneID > 0 {
+ if err = changeMilestoneAssign(e, doer, opts.Issue, -1); err != nil {
+ return err
+ }
+ }
+
if opts.IsPull {
_, err = e.Exec("UPDATE `repository` SET num_pulls = num_pulls + 1 WHERE id = ?", opts.Issue.RepoID)
} else {
@@ -849,7 +852,7 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
return err
}
- if err = newIssue(sess, NewIssueOptions{
+ if err = newIssue(sess, issue.Poster, NewIssueOptions{
Repo: repo,
Issue: issue,
LableIDs: labelIDs,
@@ -1773,7 +1776,7 @@ func ChangeMilestoneIssueStats(issue *Issue) (err error) {
return sess.Commit()
}
-func changeMilestoneAssign(e *xorm.Session, issue *Issue, oldMilestoneID int64) error {
+func changeMilestoneAssign(e *xorm.Session, doer *User, issue *Issue, oldMilestoneID int64) error {
if oldMilestoneID > 0 {
m, err := getMilestoneByRepoID(e, issue.RepoID, oldMilestoneID)
if err != nil {
@@ -1810,18 +1813,28 @@ func changeMilestoneAssign(e *xorm.Session, issue *Issue, oldMilestoneID int64)
}
}
+ if err := issue.loadRepo(e); err != nil {
+ return err
+ }
+
+ if oldMilestoneID > 0 || issue.MilestoneID > 0 {
+ if _, err := createMilestoneComment(e, doer, issue.Repo, issue, oldMilestoneID, issue.MilestoneID); err != nil {
+ return err
+ }
+ }
+
return updateIssue(e, issue)
}
// ChangeMilestoneAssign changes assignment of milestone for issue.
-func ChangeMilestoneAssign(issue *Issue, oldMilestoneID int64) (err error) {
+func ChangeMilestoneAssign(issue *Issue, doer *User, oldMilestoneID int64) (err error) {
sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
}
- if err = changeMilestoneAssign(sess, issue, oldMilestoneID); err != nil {
+ if err = changeMilestoneAssign(sess, doer, issue, oldMilestoneID); err != nil {
return err
}
return sess.Commit()
diff --git a/models/issue_comment.go b/models/issue_comment.go
index be7044a8e7..d128e2ebab 100644
--- a/models/issue_comment.go
+++ b/models/issue_comment.go
@@ -38,6 +38,8 @@ const (
CommentTypePullRef
// Labels changed
CommentTypeLabel
+ // Milestone changed
+ CommentTypeMilestone
)
// CommentTag defines comment tag type
@@ -58,9 +60,13 @@ type Comment struct {
PosterID int64 `xorm:"INDEX"`
Poster *User `xorm:"-"`
IssueID int64 `xorm:"INDEX"`
- CommitID int64
LabelID int64
Label *Label `xorm:"-"`
+ OldMilestoneID int64
+ MilestoneID int64
+ OldMilestone *Milestone `xorm:"-"`
+ Milestone *Milestone `xorm:"-"`
+ CommitID int64
Line int64
Content string `xorm:"TEXT"`
RenderedContent string `xorm:"-"`
@@ -204,6 +210,36 @@ func (c *Comment) LoadLabel() error {
return nil
}
+// LoadMilestone if comment.Type is CommentTypeMilestone, then load milestone
+func (c *Comment) LoadMilestone() error {
+ if c.OldMilestoneID > 0 {
+ var oldMilestone Milestone
+ has, err := x.ID(c.OldMilestoneID).Get(&oldMilestone)
+ if err != nil {
+ return err
+ } else if !has {
+ return ErrMilestoneNotExist{
+ ID: c.OldMilestoneID,
+ }
+ }
+ c.OldMilestone = &oldMilestone
+ }
+
+ if c.MilestoneID > 0 {
+ var milestone Milestone
+ has, err := x.ID(c.MilestoneID).Get(&milestone)
+ if err != nil {
+ return err
+ } else if !has {
+ return ErrMilestoneNotExist{
+ ID: c.MilestoneID,
+ }
+ }
+ c.Milestone = &milestone
+ }
+ return nil
+}
+
// MailParticipants sends new comment emails to repository watchers
// and mentioned people.
func (c *Comment) MailParticipants(e Engine, opType ActionType, issue *Issue) (err error) {
@@ -233,15 +269,17 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err
LabelID = opts.Label.ID
}
comment := &Comment{
- Type: opts.Type,
- PosterID: opts.Doer.ID,
- Poster: opts.Doer,
- IssueID: opts.Issue.ID,
- LabelID: LabelID,
- CommitID: opts.CommitID,
- CommitSHA: opts.CommitSHA,
- Line: opts.LineNum,
- Content: opts.Content,
+ Type: opts.Type,
+ PosterID: opts.Doer.ID,
+ Poster: opts.Doer,
+ IssueID: opts.Issue.ID,
+ LabelID: LabelID,
+ OldMilestoneID: opts.OldMilestoneID,
+ MilestoneID: opts.MilestoneID,
+ CommitID: opts.CommitID,
+ CommitSHA: opts.CommitSHA,
+ Line: opts.LineNum,
+ Content: opts.Content,
}
if _, err = e.Insert(comment); err != nil {
return nil, err
@@ -367,6 +405,17 @@ func createLabelComment(e *xorm.Session, doer *User, repo *Repository, issue *Is
})
}
+func createMilestoneComment(e *xorm.Session, doer *User, repo *Repository, issue *Issue, oldMilestoneID, milestoneID int64) (*Comment, error) {
+ return createComment(e, &CreateCommentOptions{
+ Type: CommentTypeMilestone,
+ Doer: doer,
+ Repo: repo,
+ Issue: issue,
+ OldMilestoneID: oldMilestoneID,
+ MilestoneID: milestoneID,
+ })
+}
+
// CreateCommentOptions defines options for creating comment
type CreateCommentOptions struct {
Type CommentType
@@ -375,11 +424,13 @@ type CreateCommentOptions struct {
Issue *Issue
Label *Label
- CommitID int64
- CommitSHA string
- LineNum int64
- Content string
- Attachments []string // UUIDs of attachments
+ OldMilestoneID int64
+ MilestoneID int64
+ CommitID int64
+ CommitSHA string
+ LineNum int64
+ Content string
+ Attachments []string // UUIDs of attachments
}
// CreateComment creates comment of issue or commit.
diff --git a/models/pull.go b/models/pull.go
index 382738bf29..e680480978 100644
--- a/models/pull.go
+++ b/models/pull.go
@@ -470,7 +470,7 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
return err
}
- if err = newIssue(sess, NewIssueOptions{
+ if err = newIssue(sess, pull.Poster, NewIssueOptions{
Repo: repo,
Issue: pull,
LableIDs: labelIDs,
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 546b9489b1..cd2b67f8da 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -543,6 +543,9 @@ issues.label_templates.use = Use this label set
issues.label_templates.fail_to_load_file = Failed to load label template file '%s': %v
issues.add_label_at = `added the <div class="ui label" style="color: %s; background-color: %s">%s</div> label %s`
issues.remove_label_at = `removed the <div class="ui label" style="color: %s; background-color: %s">%s</div> label %s`
+issues.add_milestone_at = `added this to the <b>%s</b> milestone %s`
+issues.change_milestone_at = `modified the milestone from <b>%s</b> to <b>%s</b> %s`
+issues.remove_milestone_at = `removed this from the <b>%s</b> milestone %s`
issues.open_tab = %d Open
issues.close_tab = %d Closed
issues.filter_label = Label
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index 840ff36b5f..dfb9bbb172 100644
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -503,6 +503,9 @@ issues.label_templates.use=加载标签模板
issues.label_templates.fail_to_load_file=加载标签模板文件 '%s' 时发生错误:%v
issues.add_label_at = ` %[4]s 添加了标签 <div class="ui label" style="color: %[1]s; background-color: %[2]s">%[3]s</div>`
issues.remove_label_at = ` %[4]s 删除了标签 <div class="ui label" style="color: %[1]s; background-color: %[2]s">%[3]s</div>`
+issues.add_milestone_at = ` %[2]s 添加了里程碑 <b>%[1]s</b>`
+issues.change_milestone_at = `%[3]s 修改了里程碑从 <b>%[1]s</b> 到 <b>%[2]s</b>`
+issues.remove_milestone_at = `%[2]s 删除了里程碑 <b>%[1]s</b>`
issues.open_tab=%d 个开启中
issues.close_tab=%d 个已关闭
issues.filter_label=标签筛选
diff --git a/public/js/index.js b/public/js/index.js
index e52da6e5ba..086ec7656f 100644
--- a/public/js/index.js
+++ b/public/js/index.js
@@ -168,6 +168,12 @@ function initCommentForm() {
var $list = $('.ui' + select_id + '.list');
var hasUpdateAction = $menu.data('action') == 'update';
+ $(select_id).dropdown('setting', 'onHide', function(){
+ if (hasUpdateAction) {
+ location.reload();
+ }
+ });
+
$menu.find('.item:not(.no-select)').click(function () {
$(this).parent().find('.item').each(function () {
$(this).removeClass('selected active')
diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go
index ac0289c412..c65f4b7063 100644
--- a/routers/api/v1/repo/issue.go
+++ b/routers/api/v1/repo/issue.go
@@ -168,7 +168,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
issue.MilestoneID != *form.Milestone {
oldMilestoneID := issue.MilestoneID
issue.MilestoneID = *form.Milestone
- if err = models.ChangeMilestoneAssign(issue, oldMilestoneID); err != nil {
+ if err = models.ChangeMilestoneAssign(issue, ctx.User, oldMilestoneID); err != nil {
ctx.Error(500, "ChangeMilestoneAssign", err)
return
}
diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go
index 4c10024bfb..9a38d37528 100644
--- a/routers/api/v1/repo/pull.go
+++ b/routers/api/v1/repo/pull.go
@@ -241,7 +241,7 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) {
issue.MilestoneID != form.Milestone {
oldMilestoneID := issue.MilestoneID
issue.MilestoneID = form.Milestone
- if err = models.ChangeMilestoneAssign(issue, oldMilestoneID); err != nil {
+ if err = models.ChangeMilestoneAssign(issue, ctx.User, oldMilestoneID); err != nil {
ctx.Error(500, "ChangeMilestoneAssign", err)
return
}
diff --git a/routers/repo/issue.go b/routers/repo/issue.go
index b2490e242a..76440359ef 100644
--- a/routers/repo/issue.go
+++ b/routers/repo/issue.go
@@ -384,22 +384,27 @@ func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm) ([]int64
return nil, 0, 0
}
- // Check labels.
- labelIDs, err := base.StringsToInt64s(strings.Split(form.LabelIDs, ","))
- if err != nil {
- return nil, 0, 0
- }
- labelIDMark := base.Int64sToMap(labelIDs)
+ var labelIDs []int64
hasSelected := false
- for i := range labels {
- if labelIDMark[labels[i].ID] {
- labels[i].IsChecked = true
- hasSelected = true
+ // Check labels.
+ if len(form.LabelIDs) > 0 {
+ labelIDs, err = base.StringsToInt64s(strings.Split(form.LabelIDs, ","))
+ if err != nil {
+ return nil, 0, 0
+ }
+ labelIDMark := base.Int64sToMap(labelIDs)
+
+ for i := range labels {
+ if labelIDMark[labels[i].ID] {
+ labels[i].IsChecked = true
+ hasSelected = true
+ }
}
}
+
+ ctx.Data["Labels"] = labels
ctx.Data["HasSelectedLabel"] = hasSelected
ctx.Data["label_ids"] = form.LabelIDs
- ctx.Data["Labels"] = labels
// Check milestone.
milestoneID := form.MilestoneID
@@ -617,6 +622,11 @@ func ViewIssue(ctx *context.Context) {
ctx.Handle(500, "LoadLabel", err)
return
}
+ } else if comment.Type == models.CommentTypeMilestone {
+ if err = comment.LoadMilestone(); err != nil {
+ ctx.Handle(500, "LoadMilestone", err)
+ return
+ }
}
}
@@ -625,7 +635,6 @@ func ViewIssue(ctx *context.Context) {
canDelete := false
if ctx.IsSigned && pull.HeadBranch != "master" {
-
if err := pull.GetHeadRepo(); err != nil {
log.Error(4, "GetHeadRepo: %v", err)
} else if ctx.User.IsWriterOfRepo(pull.HeadRepo) {
@@ -729,7 +738,7 @@ func UpdateIssueMilestone(ctx *context.Context) {
// Not check for invalid milestone id and give responsibility to owners.
issue.MilestoneID = milestoneID
- if err := models.ChangeMilestoneAssign(issue, oldMilestoneID); err != nil {
+ if err := models.ChangeMilestoneAssign(issue, ctx.User, oldMilestoneID); err != nil {
ctx.Handle(500, "ChangeMilestoneAssign", err)
return
}
diff --git a/templates/repo/issue/view_content.tmpl b/templates/repo/issue/view_content.tmpl
index ef32d0ba1e..39e0587d94 100644
--- a/templates/repo/issue/view_content.tmpl
+++ b/templates/repo/issue/view_content.tmpl
@@ -151,7 +151,16 @@
<img src="{{.Poster.RelAvatarLink}}">
</a>
<span class="text grey"><a href="{{.Poster.HomeLink}}">{{.Poster.Name}}</a>
- {{if .Content}}{{$.i18n.Tr "repo.issues.add_label_at" .Label.ForegroundColor .Label.Color .Label.Name $createdStr | Safe}}{{else}}{{$.i18n.Tr "repo.issues.remove_label_at" .Label.ForegroundColor .Label.Color .Label.Name $createdStr | Safe}}{{end}}</span>
+ {{if .Content}}{{$.i18n.Tr "repo.issues.add_label_at" .Label.ForegroundColor .Label.Color .Label.Name $createdStr | Safe}}{{else}}{{$.i18n.Tr "repo.issues.remove_label_at" .Label.ForegroundColor .Label.Color .Label.Name $createdStr | Safe}}{{end}}</span>
+ </div>
+ {{else if eq .Type 8}}
+ <div class="event">
+ <span class="octicon octicon-primitive-dot"></span>
+ <a class="ui avatar image" href="{{.Poster.HomeLink}}">
+ <img src="{{.Poster.RelAvatarLink}}">
+ </a>
+ <span class="text grey"><a href="{{.Poster.HomeLink}}">{{.Poster.Name}}</a>
+ {{if gt .OldMilestoneID 0}}{{if gt .MilestoneID 0}}{{$.i18n.Tr "repo.issues.change_milestone_at" .OldMilestone.Name .Milestone.Name $createdStr | Safe}}{{else}}{{$.i18n.Tr "repo.issues.remove_milestone_at" .OldMilestone.Name $createdStr | Safe}}{{end}}{{else if gt .MilestoneID 0}}{{$.i18n.Tr "repo.issues.add_milestone_at" .Milestone.Name $createdStr | Safe}}{{end}}</span>
</div>
{{end}}