Skip to content

Commit cafce3b

Browse files
puni9869delvhwxiaoguang
authored
Allow to archive labels (#26478)
## Archived labels This adds the structure to allow for archived labels. Archived labels are, just like closed milestones or projects, a medium to hide information without deleting it. It is especially useful if there are outdated labels that should no longer be used without deleting the label entirely. ## Changes 1. UI and API have been equipped with the support to mark a label as archived 2. The time when a label has been archived will be stored in the DB ## Outsourced for the future There's no special handling for archived labels at the moment. This will be done in the future. ## Screenshots ![image](https://github.com/go-gitea/gitea/assets/80308335/208f95cd-42e4-4ed7-9a1f-cd2050a645d4) ![image](https://github.com/go-gitea/gitea/assets/80308335/746428e0-40bb-45b3-b992-85602feb371d) Part of #25237 --------- Co-authored-by: delvh <[email protected]> Co-authored-by: wxiaoguang <[email protected]>
1 parent db7b0a1 commit cafce3b

File tree

18 files changed

+111
-20
lines changed

18 files changed

+111
-20
lines changed

models/fixtures/label.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
exclusive: false
88
num_issues: 2
99
num_closed_issues: 0
10+
archived_unix: 0
1011

1112
-
1213
id: 2
@@ -17,6 +18,7 @@
1718
exclusive: false
1819
num_issues: 1
1920
num_closed_issues: 1
21+
archived_unix: 0
2022

2123
-
2224
id: 3
@@ -27,6 +29,7 @@
2729
exclusive: false
2830
num_issues: 0
2931
num_closed_issues: 0
32+
archived_unix: 0
3033

3134
-
3235
id: 4
@@ -37,6 +40,7 @@
3740
exclusive: false
3841
num_issues: 1
3942
num_closed_issues: 0
43+
archived_unix: 0
4044

4145
-
4246
id: 5
@@ -47,6 +51,7 @@
4751
exclusive: false
4852
num_issues: 0
4953
num_closed_issues: 0
54+
archived_unix: 0
5055

5156
-
5257
id: 6
@@ -57,6 +62,7 @@
5762
exclusive: false
5863
num_issues: 0
5964
num_closed_issues: 0
65+
archived_unix: 0
6066

6167
-
6268
id: 7
@@ -67,6 +73,7 @@
6773
exclusive: true
6874
num_issues: 0
6975
num_closed_issues: 0
76+
archived_unix: 0
7077

7178
-
7279
id: 8
@@ -77,6 +84,7 @@
7784
exclusive: true
7885
num_issues: 0
7986
num_closed_issues: 0
87+
archived_unix: 0
8088

8189
-
8290
id: 9
@@ -87,3 +95,4 @@
8795
exclusive: true
8896
num_issues: 0
8997
num_closed_issues: 0
98+
archived_unix: 0

models/issues/label.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ type Label struct {
9797
QueryString string `xorm:"-"`
9898
IsSelected bool `xorm:"-"`
9999
IsExcluded bool `xorm:"-"`
100+
101+
ArchivedUnix timeutil.TimeStamp `xorm:"DEFAULT NULL"`
100102
}
101103

102104
func init() {
@@ -109,6 +111,15 @@ func (l *Label) CalOpenIssues() {
109111
l.NumOpenIssues = l.NumIssues - l.NumClosedIssues
110112
}
111113

114+
// SetArchived set the label as archived
115+
func (l *Label) SetArchived(isArchived bool) {
116+
if isArchived && l.ArchivedUnix.IsZero() {
117+
l.ArchivedUnix = timeutil.TimeStampNow()
118+
} else {
119+
l.ArchivedUnix = timeutil.TimeStamp(0)
120+
}
121+
}
122+
112123
// CalOpenOrgIssues calculates the open issues of a label for a specific repo
113124
func (l *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64) {
114125
counts, _ := CountIssuesByRepo(ctx, &IssuesOptions{
@@ -153,6 +164,11 @@ func (l *Label) BelongsToOrg() bool {
153164
return l.OrgID > 0
154165
}
155166

167+
// IsArchived returns true if label is an archived
168+
func (l *Label) IsArchived() bool {
169+
return l.ArchivedUnix > 0
170+
}
171+
156172
// BelongsToRepo returns true if label is a repository label
157173
func (l *Label) BelongsToRepo() bool {
158174
return l.RepoID > 0
@@ -211,7 +227,7 @@ func UpdateLabel(l *Label) error {
211227
}
212228
l.Color = color
213229

214-
return updateLabelCols(db.DefaultContext, l, "name", "description", "color", "exclusive")
230+
return updateLabelCols(db.DefaultContext, l, "name", "description", "color", "exclusive", "archived_unix")
215231
}
216232

217233
// DeleteLabel delete a label

models/issues/label_test.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
repo_model "code.gitea.io/gitea/models/repo"
1212
"code.gitea.io/gitea/models/unittest"
1313
user_model "code.gitea.io/gitea/models/user"
14+
"code.gitea.io/gitea/modules/timeutil"
1415

1516
"github.com/stretchr/testify/assert"
1617
)
@@ -259,11 +260,12 @@ func TestUpdateLabel(t *testing.T) {
259260
label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
260261
// make sure update wont overwrite it
261262
update := &issues_model.Label{
262-
ID: label.ID,
263-
Color: "#ffff00",
264-
Name: "newLabelName",
265-
Description: label.Description,
266-
Exclusive: false,
263+
ID: label.ID,
264+
Color: "#ffff00",
265+
Name: "newLabelName",
266+
Description: label.Description,
267+
Exclusive: false,
268+
ArchivedUnix: timeutil.TimeStamp(0),
267269
}
268270
label.Color = update.Color
269271
label.Name = update.Name
@@ -273,6 +275,7 @@ func TestUpdateLabel(t *testing.T) {
273275
assert.EqualValues(t, label.Color, newLabel.Color)
274276
assert.EqualValues(t, label.Name, newLabel.Name)
275277
assert.EqualValues(t, label.Description, newLabel.Description)
278+
assert.EqualValues(t, newLabel.ArchivedUnix, 0)
276279
unittest.CheckConsistencyFor(t, &issues_model.Label{}, &repo_model.Repository{})
277280
}
278281

models/migrations/migrations.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,8 @@ var migrations = []Migration{
522522
NewMigration("Drop deleted branch table", v1_21.DropDeletedBranchTable),
523523
// v270 -> v271
524524
NewMigration("Fix PackageProperty typo", v1_21.FixPackagePropertyTypo),
525+
// v271 -> v272
526+
NewMigration("Allow archiving labels", v1_21.AddArchivedUnixColumInLabelTable),
525527
}
526528

527529
// GetCurrentDBVersion returns the current db version

models/migrations/v1_21/v271.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package v1_21 //nolint
5+
import (
6+
"code.gitea.io/gitea/modules/timeutil"
7+
8+
"xorm.io/xorm"
9+
)
10+
11+
func AddArchivedUnixColumInLabelTable(x *xorm.Engine) error {
12+
type Label struct {
13+
ArchivedUnix timeutil.TimeStamp `xorm:"DEFAULT NULL"`
14+
}
15+
return x.Sync(new(Label))
16+
}

modules/structs/issue_label.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ type Label struct {
1111
Name string `json:"name"`
1212
// example: false
1313
Exclusive bool `json:"exclusive"`
14+
// example: false
15+
IsArchived bool `json:"is_archived"`
1416
// example: 00aabb
1517
Color string `json:"color"`
1618
Description string `json:"description"`
@@ -27,6 +29,8 @@ type CreateLabelOption struct {
2729
// example: #00aabb
2830
Color string `json:"color" binding:"Required"`
2931
Description string `json:"description"`
32+
// example: false
33+
IsArchived bool `json:"is_archived"`
3034
}
3135

3236
// EditLabelOption options for editing a label
@@ -37,6 +41,8 @@ type EditLabelOption struct {
3741
// example: #00aabb
3842
Color *string `json:"color"`
3943
Description *string `json:"description"`
44+
// example: false
45+
IsArchived *bool `json:"is_archived"`
4046
}
4147

4248
// IssueLabelsOption a collection of labels

options/locale/locale_en-US.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,6 +1491,8 @@ issues.label_title = Name
14911491
issues.label_description = Description
14921492
issues.label_color = Color
14931493
issues.label_exclusive = Exclusive
1494+
issues.label_archive = Archive Label
1495+
issues.label_archive_tooltip= Archived labels are excluded from the label search when applying labels to an issue. Existing labels on issues remain unaffected, allowing you to retire obsolete labels without losing information.
14941496
issues.label_exclusive_desc = Name the label <code>scope/item</code> to make it mutually exclusive with other <code>scope/</code> labels.
14951497
issues.label_exclusive_warning = Any conflicting scoped labels will be removed when editing the labels of an issue or pull request.
14961498
issues.label_count = %d labels

routers/api/v1/org/label.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ func EditLabel(ctx *context.APIContext) {
209209
if form.Description != nil {
210210
l.Description = *form.Description
211211
}
212+
l.SetArchived(form.IsArchived != nil && *form.IsArchived)
212213
if err := issues_model.UpdateLabel(l); err != nil {
213214
ctx.Error(http.StatusInternalServerError, "UpdateLabel", err)
214215
return

routers/api/v1/repo/label.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,14 @@ func CreateLabel(ctx *context.APIContext) {
151151
return
152152
}
153153
form.Color = color
154-
155154
l := &issues_model.Label{
156155
Name: form.Name,
157156
Exclusive: form.Exclusive,
158157
Color: form.Color,
159158
RepoID: ctx.Repo.Repository.ID,
160159
Description: form.Description,
161160
}
161+
l.SetArchived(form.IsArchived)
162162
if err := issues_model.NewLabel(ctx, l); err != nil {
163163
ctx.Error(http.StatusInternalServerError, "NewLabel", err)
164164
return
@@ -231,6 +231,7 @@ func EditLabel(ctx *context.APIContext) {
231231
if form.Description != nil {
232232
l.Description = *form.Description
233233
}
234+
l.SetArchived(form.IsArchived != nil && *form.IsArchived)
234235
if err := issues_model.UpdateLabel(l); err != nil {
235236
ctx.Error(http.StatusInternalServerError, "UpdateLabel", err)
236237
return

routers/web/org/org_labels.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ func UpdateLabel(ctx *context.Context) {
7575
l.Exclusive = form.Exclusive
7676
l.Description = form.Description
7777
l.Color = form.Color
78+
l.SetArchived(form.IsArchived)
7879
if err := issues_model.UpdateLabel(l); err != nil {
7980
ctx.ServerError("UpdateLabel", err)
8081
return

routers/web/repo/issue_label.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"code.gitea.io/gitea/modules/label"
1515
"code.gitea.io/gitea/modules/log"
1616
repo_module "code.gitea.io/gitea/modules/repository"
17+
"code.gitea.io/gitea/modules/timeutil"
1718
"code.gitea.io/gitea/modules/web"
1819
"code.gitea.io/gitea/services/forms"
1920
issue_service "code.gitea.io/gitea/services/issue"
@@ -111,11 +112,12 @@ func NewLabel(ctx *context.Context) {
111112
}
112113

113114
l := &issues_model.Label{
114-
RepoID: ctx.Repo.Repository.ID,
115-
Name: form.Title,
116-
Exclusive: form.Exclusive,
117-
Description: form.Description,
118-
Color: form.Color,
115+
RepoID: ctx.Repo.Repository.ID,
116+
Name: form.Title,
117+
Exclusive: form.Exclusive,
118+
Description: form.Description,
119+
Color: form.Color,
120+
ArchivedUnix: timeutil.TimeStamp(0),
119121
}
120122
if err := issues_model.NewLabel(ctx, l); err != nil {
121123
ctx.ServerError("NewLabel", err)
@@ -137,11 +139,12 @@ func UpdateLabel(ctx *context.Context) {
137139
}
138140
return
139141
}
140-
141142
l.Name = form.Title
142143
l.Exclusive = form.Exclusive
143144
l.Description = form.Description
144145
l.Color = form.Color
146+
147+
l.SetArchived(form.IsArchived)
145148
if err := issues_model.UpdateLabel(l); err != nil {
146149
ctx.ServerError("UpdateLabel", err)
147150
return

routers/web/repo/issue_label_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ func TestUpdateLabel(t *testing.T) {
9797
test.LoadUser(t, ctx, 2)
9898
test.LoadRepo(t, ctx, 1)
9999
web.SetForm(ctx, &forms.CreateLabelForm{
100-
ID: 2,
101-
Title: "newnameforlabel",
102-
Color: "#abcdef",
100+
ID: 2,
101+
Title: "newnameforlabel",
102+
Color: "#abcdef",
103+
IsArchived: true,
103104
})
104105
UpdateLabel(ctx)
105106
assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status())

services/convert/issue.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ func ToLabel(label *issues_model.Label, repo *repo_model.Repository, org *user_m
208208
Exclusive: label.Exclusive,
209209
Color: strings.TrimLeft(label.Color, "#"),
210210
Description: label.Description,
211+
IsArchived: label.IsArchived(),
211212
}
212213

213214
// calculate URL

services/forms/repo_form.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,7 @@ type CreateLabelForm struct {
569569
ID int64
570570
Title string `binding:"Required;MaxSize(50)" locale:"repo.issues.label_title"`
571571
Exclusive bool `form:"exclusive"`
572+
IsArchived bool `form:"is_archived"`
572573
Description string `binding:"MaxSize(200)" locale:"repo.issues.label_description"`
573574
Color string `binding:"Required;MaxSize(7)" locale:"repo.issues.label_color"`
574575
}

templates/repo/issue/labels/edit_delete_label.tmpl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@
3333
<div class="desc gt-ml-2 gt-mt-3 gt-hidden label-exclusive-warning">
3434
{{svg "octicon-alert"}} {{.locale.Tr "repo.issues.label_exclusive_warning" | Safe}}
3535
</div>
36+
<br>
37+
</div>
38+
<div class="field label-is-archived-input-field">
39+
<div class="ui checkbox">
40+
<input class="label-is-archived-input" name="is_archived" type="checkbox">
41+
<label>{{.locale.Tr "repo.issues.label_archive"}}</label>
42+
</div>
43+
<i class="gt-ml-2" data-tooltip-content={{.locale.Tr "repo.issues.label_archive_tooltip"}}>
44+
{{svg "octicon-info"}}
45+
</i>
3646
</div>
3747
<div class="field">
3848
<label for="description">{{.locale.Tr "repo.issues.label_description"}}</label>

templates/repo/issue/labels/label_list.tmpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@
4444
</div>
4545
<div class="label-operation">
4646
{{if and (not $.PageIsOrgSettingsLabels) (not $.Repository.IsArchived) (or $.CanWriteIssues $.CanWritePulls)}}
47-
<a class="edit-label-button" href="#" data-id="{{.ID}}" data-title="{{.Name}}" {{if .Exclusive}}data-exclusive{{end}} data-num-issues="{{.NumIssues}}" data-description="{{.Description}}" data-color={{.Color}}>{{svg "octicon-pencil"}} {{$.locale.Tr "repo.issues.label_edit"}}</a>
47+
<a class="edit-label-button" href="#" data-id="{{.ID}}" data-title="{{.Name}}" {{if .Exclusive}}data-exclusive{{end}} {{if gt .ArchivedUnix 0}}data-is-archived{{end}} data-num-issues="{{.NumIssues}}" data-description="{{.Description}}" data-color={{.Color}}>{{svg "octicon-pencil"}} {{$.locale.Tr "repo.issues.label_edit"}}</a>
4848
<a class="delete-button" href="#" data-url="{{$.Link}}/delete" data-id="{{.ID}}">{{svg "octicon-trash"}} {{$.locale.Tr "repo.issues.label_delete"}}</a>
4949
{{else if $.PageIsOrgSettingsLabels}}
50-
<a class="edit-label-button" href="#" data-id="{{.ID}}" data-title="{{.Name}}" {{if .Exclusive}}data-exclusive{{end}} data-num-issues="{{.NumIssues}}" data-description="{{.Description}}" data-color={{.Color}}>{{svg "octicon-pencil"}} {{$.locale.Tr "repo.issues.label_edit"}}</a>
50+
<a class="edit-label-button" href="#" data-id="{{.ID}}" data-title="{{.Name}}" {{if .Exclusive}}data-exclusive{{end}} {{if gt .ArchivedUnix 0}}data-is-archived{{end}} data-num-issues="{{.NumIssues}}" data-description="{{.Description}}" data-color={{.Color}}>{{svg "octicon-pencil"}} {{$.locale.Tr "repo.issues.label_edit"}}</a>
5151
<a class="delete-button" href="#" data-url="{{$.Link}}/delete" data-id="{{.ID}}">{{svg "octicon-trash"}} {{$.locale.Tr "repo.issues.label_delete"}}</a>
5252
{{end}}
5353
</div>

templates/swagger/v1_json.tmpl

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)