···116116func (l *Label) SetArchived(isArchived bool) {
117117 if !isArchived {
118118 l.ArchivedUnix = timeutil.TimeStamp(0)
119119- } else if isArchived && l.ArchivedUnix.IsZero() {
119119+ } else if isArchived && !l.IsArchived() {
120120 // Only change the date when it is newly archived.
121121 l.ArchivedUnix = timeutil.TimeStampNow()
122122 }
123123+}
124124+125125+// IsArchived returns true if label is an archived
126126+func (l *Label) IsArchived() bool {
127127+ return !l.ArchivedUnix.IsZero()
123128}
124129125130// CalOpenOrgIssues calculates the open issues of a label for a specific repo
···164169// BelongsToOrg returns true if label is an organization label
165170func (l *Label) BelongsToOrg() bool {
166171 return l.OrgID > 0
167167-}
168168-169169-// IsArchived returns true if label is an archived
170170-func (l *Label) IsArchived() bool {
171171- return l.ArchivedUnix > 0
172172}
173173174174// BelongsToRepo returns true if label is a repository label
+39-11
modules/templates/util_render.go
···2020 "code.gitea.io/gitea/modules/markup"
2121 "code.gitea.io/gitea/modules/markup/markdown"
2222 "code.gitea.io/gitea/modules/setting"
2323+ "code.gitea.io/gitea/modules/translation"
2324 "code.gitea.io/gitea/modules/util"
2425)
2526···104105 return template.HTML(htmlWithCodeTags)
105106}
106107108108+const (
109109+ activeLabelOpacity = uint8(255)
110110+ archivedLabelOpacity = uint8(127)
111111+)
112112+113113+func GetLabelOpacityByte(isArchived bool) uint8 {
114114+ if isArchived {
115115+ return archivedLabelOpacity
116116+ }
117117+ return activeLabelOpacity
118118+}
119119+107120// RenderIssueTitle renders issue/pull title with defined post processors
108121func RenderIssueTitle(ctx context.Context, text string, metas map[string]string) template.HTML {
109122 renderedText, err := markup.RenderIssueTitle(&markup.RenderContext{
···118131}
119132120133// RenderLabel renders a label
121121-func RenderLabel(ctx context.Context, label *issues_model.Label) template.HTML {
122122- labelScope := label.ExclusiveScope()
123123-124124- textColor := "#111"
134134+// locale is needed due to an import cycle with our context providing the `Tr` function
135135+func RenderLabel(ctx context.Context, locale translation.Locale, label *issues_model.Label) template.HTML {
136136+ var (
137137+ archivedCSSClass string
138138+ textColor = "#111"
139139+ labelScope = label.ExclusiveScope()
140140+ )
125141 r, g, b := util.HexToRBGColor(label.Color)
142142+126143 // Determine if label text should be light or dark to be readable on background color
144144+ // this doesn't account for saturation or transparency
127145 if util.UseLightTextOnBackground(r, g, b) {
128146 textColor = "#eee"
129147 }
130148131149 description := emoji.ReplaceAliases(template.HTMLEscapeString(label.Description))
132150151151+ if label.IsArchived() {
152152+ archivedCSSClass = "archived-label"
153153+ description = locale.TrString("repo.issues.archived_label_description", description)
154154+ }
155155+133156 if labelScope == "" {
134157 // Regular label
135135- s := fmt.Sprintf("<div class='ui label' style='color: %s !important; background-color: %s !important' data-tooltip-content title='%s'>%s</div>",
136136- textColor, label.Color, description, RenderEmoji(ctx, label.Name))
158158+159159+ labelColor := label.Color + hex.EncodeToString([]byte{GetLabelOpacityByte(label.IsArchived())})
160160+ s := fmt.Sprintf("<div class='ui label %s' style='color: %s !important; background-color: %s !important;' data-tooltip-content title='%s'>%s</div>",
161161+ archivedCSSClass, textColor, labelColor, description, RenderEmoji(ctx, label.Name))
137162 return template.HTML(s)
138163 }
139164···152177 darkenFactor := math.Max(luminance-darken, 0.0) / math.Max(luminance, 1.0/255.0)
153178 lightenFactor := math.Min(luminance+lighten, 1.0) / math.Max(luminance, 1.0/255.0)
154179180180+ opacity := GetLabelOpacityByte(label.IsArchived())
155181 scopeBytes := []byte{
156182 uint8(math.Min(math.Round(r*darkenFactor), 255)),
157183 uint8(math.Min(math.Round(g*darkenFactor), 255)),
158184 uint8(math.Min(math.Round(b*darkenFactor), 255)),
185185+ opacity,
159186 }
160187 itemBytes := []byte{
161188 uint8(math.Min(math.Round(r*lightenFactor), 255)),
162189 uint8(math.Min(math.Round(g*lightenFactor), 255)),
163190 uint8(math.Min(math.Round(b*lightenFactor), 255)),
191191+ opacity,
164192 }
165193166166- itemColor := "#" + hex.EncodeToString(itemBytes)
167194 scopeColor := "#" + hex.EncodeToString(scopeBytes)
195195+ itemColor := "#" + hex.EncodeToString(itemBytes)
168196169169- s := fmt.Sprintf("<span class='ui label scope-parent' data-tooltip-content title='%s'>"+
197197+ s := fmt.Sprintf("<span class='ui label %s scope-parent' data-tooltip-content title='%s'>"+
170198 "<div class='ui label scope-left' style='color: %s !important; background-color: %s !important'>%s</div>"+
171199 "<div class='ui label scope-right' style='color: %s !important; background-color: %s !important'>%s</div>"+
172200 "</span>",
173173- description,
201201+ archivedCSSClass, description,
174202 textColor, scopeColor, scopeText,
175203 textColor, itemColor, itemText)
176204 return template.HTML(s)
···211239 return output
212240}
213241214214-func RenderLabels(ctx context.Context, labels []*issues_model.Label, repoLink string) template.HTML {
242242+func RenderLabels(ctx context.Context, locale translation.Locale, labels []*issues_model.Label, repoLink string) template.HTML {
215243 htmlCode := `<span class="labels-list">`
216244 for _, label := range labels {
217245 // Protect against nil value in labels - shouldn't happen but would cause a panic if so
···219247 continue
220248 }
221249 htmlCode += fmt.Sprintf("<a href='%s/issues?labels=%d'>%s</a> ",
222222- repoLink, label.ID, RenderLabel(ctx, label))
250250+ repoLink, label.ID, RenderLabel(ctx, locale, label))
223251 }
224252 htmlCode += "</span>"
225253 return template.HTML(htmlCode)
+1
options/locale/locale_en-US.ini
···16281628issues.label_deletion = Delete label
16291629issues.label_deletion_desc = Deleting a label removes it from all issues. Continue?
16301630issues.label_deletion_success = The label has been deleted.
16311631+issues.archived_label_description = (Archived) %s
16311632issues.label.filter_sort.alphabetically = Alphabetically
16321633issues.label.filter_sort.reverse_alphabetically = Reverse alphabetically
16331634issues.label.filter_sort.by_size = Smallest size