diff --git a/models/issue_comment.go b/models/issue_comment.go
index 5c053ec02a..63256ddc99 100644
--- a/models/issue_comment.go
+++ b/models/issue_comment.go
@@ -124,7 +124,9 @@ type Comment struct {
IssueID int64 `xorm:"INDEX"`
Issue *Issue `xorm:"-"`
LabelID int64
- Label *Label `xorm:"-"`
+ Label *Label `xorm:"-"`
+ AddedLabels []*Label `xorm:"-"`
+ RemovedLabels []*Label `xorm:"-"`
OldProjectID int64
ProjectID int64
OldProject *Project `xorm:"-"`
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index 63be27d987..03ec80f99c 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -343,6 +343,16 @@ func NewFuncMap() []template.FuncMap {
// the table is NOT sorted with this header
return ""
},
+ "RenderLabels": func(labels []*models.Label) template.HTML {
+ html := ""
+
+ for _, label := range labels {
+ html = fmt.Sprintf("%s
%s
",
+ html, label.ForegroundColor(), label.Color, RenderEmoji(label.Name))
+ }
+
+ return template.HTML(html)
+ },
}}
}
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 9864346bac..60557aea76 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -979,8 +979,11 @@ issues.label_templates.info = No labels exist yet. Create a label with 'New Labe
issues.label_templates.helper = Select a label set
issues.label_templates.use = Use Label Set
issues.label_templates.fail_to_load_file = Failed to load label template file '%s': %v
-issues.add_label_at = added the %s
label %s
-issues.remove_label_at = removed the %s
label %s
+issues.add_label = added the %s label %s
+issues.add_labels = added the %s labels %s
+issues.remove_label = removed the %s label %s
+issues.remove_labels = removed the %s labels %s
+issues.add_remove_labels = added %s and removed %s labels %s
issues.add_milestone_at = `added this to the %s milestone %s`
issues.add_project_at = `added this to the %s project %s`
issues.change_milestone_at = `modified the milestone from %s to %s %s`
diff --git a/routers/repo/issue.go b/routers/repo/issue.go
index 835a952e5e..1763b1c1a2 100644
--- a/routers/repo/issue.go
+++ b/routers/repo/issue.go
@@ -1354,6 +1354,9 @@ func ViewIssue(ctx *context.Context) {
}
}
+ // Combine multiple label assignments into a single comment
+ combineLabelComments(issue)
+
getBranchData(ctx, issue)
if issue.IsPull {
pull := issue.PullRequest
@@ -2385,3 +2388,46 @@ func attachmentsHTML(ctx *context.Context, attachments []*models.Attachment) str
}
return attachHTML
}
+
+func combineLabelComments(issue *models.Issue) {
+ for i := 0; i < len(issue.Comments); {
+ c := issue.Comments[i]
+ var shouldMerge bool
+ var removingCur bool
+ var prev *models.Comment
+
+ if i == 0 {
+ shouldMerge = false
+ } else {
+ prev = issue.Comments[i-1]
+ removingCur = c.Content != "1"
+
+ shouldMerge = prev.PosterID == c.PosterID && c.CreatedUnix-prev.CreatedUnix < 60 &&
+ c.Type == prev.Type
+ }
+
+ if c.Type == models.CommentTypeLabel {
+ if !shouldMerge {
+ if removingCur {
+ c.RemovedLabels = make([]*models.Label, 1)
+ c.AddedLabels = make([]*models.Label, 0)
+ c.RemovedLabels[0] = c.Label
+ } else {
+ c.RemovedLabels = make([]*models.Label, 0)
+ c.AddedLabels = make([]*models.Label, 1)
+ c.AddedLabels[0] = c.Label
+ }
+ } else {
+ if removingCur {
+ prev.RemovedLabels = append(prev.RemovedLabels, c.Label)
+ } else {
+ prev.AddedLabels = append(prev.AddedLabels, c.Label)
+ }
+ prev.CreatedUnix = c.CreatedUnix
+ issue.Comments = append(issue.Comments[:i], issue.Comments[i+1:]...)
+ continue
+ }
+ }
+ i++
+ }
+}
diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl
index 68bb2d49f7..e37c7e7fdd 100644
--- a/templates/repo/issue/view_content/comments.tmpl
+++ b/templates/repo/issue/view_content/comments.tmpl
@@ -161,7 +161,7 @@
{{else if eq .Type 7}}
- {{if .Label}}
+ {{if or .AddedLabels .RemovedLabels}}
{{svg "octicon-tag"}}
@@ -169,7 +169,13 @@
{{.Poster.GetDisplayName}}
- {{if .Content}}{{$.i18n.Tr "repo.issues.add_label_at" .Label.ForegroundColor .Label.Color (.Label.Name|RenderEmoji) $createdStr | Safe}}{{else}}{{$.i18n.Tr "repo.issues.remove_label_at" .Label.ForegroundColor .Label.Color (.Label.Name|RenderEmoji) $createdStr | Safe}}{{end}}
+ {{if and .AddedLabels (not .RemovedLabels)}}
+ {{$.i18n.Tr (TrN $.i18n.Lang (len .AddedLabels) "repo.issues.add_label" "repo.issues.add_labels") (RenderLabels .AddedLabels) $createdStr | Safe}}
+ {{else if and (not .AddedLabels) .RemovedLabels}}
+ {{$.i18n.Tr (TrN $.i18n.Lang (len .RemovedLabels) "repo.issues.remove_label" "repo.issues.remove_labels") (RenderLabels .RemovedLabels) $createdStr | Safe}}
+ {{else}}
+ {{$.i18n.Tr "repo.issues.add_remove_labels" (RenderLabels .AddedLabels) (RenderLabels .RemovedLabels) $createdStr | Safe}}
+ {{end}}
{{end}}