mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-18 23:43:56 +09:00
11de54dd41
Backport #38893 by @HsukqiLee Closes #38872 Labels in the label selection dropdown (issue/PR sidebar, new issue form) were always listed alphabetically, so a scoped set like the default Priority labels showed up as Critical, High, Low, Medium even though each label carries an exclusive order. This adds `CompareLabelForDisplay`/`SortLabelsForDisplay` in `models/issues`: labels are grouped by their exclusive scope and sorted by exclusive order within a scope (unordered ones last), falling back to name order. The sorting is applied to the issue page sidebar data and the shared label filter data, so the filter dropdown on the issue list gets the same ordering. Unscoped labels are unaffected and still sort by name. Includes a unit test covering the default Priority label set. Co-authored-by: Hsukqi Lee <team@tsinbei.com>
79 lines
2.3 KiB
Go
79 lines
2.3 KiB
Go
// Copyright 2024 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package issue
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"gitea.dev/models/db"
|
|
issues_model "gitea.dev/models/issues"
|
|
user_model "gitea.dev/models/user"
|
|
"gitea.dev/modules/base"
|
|
"gitea.dev/services/context"
|
|
)
|
|
|
|
// PrepareFilterIssueLabels reads the "labels" query parameter, sets `ctx.Data["Labels"]` and `ctx.Data["SelectLabels"]`
|
|
func PrepareFilterIssueLabels(ctx *context.Context, repoID int64, owner *user_model.User) (ret struct {
|
|
AllLabels []*issues_model.Label
|
|
SelectedLabelIDs []int64
|
|
},
|
|
) {
|
|
// 1,-2 means including label 1 and excluding label 2
|
|
// 0 means issues with no label
|
|
// blank means labels will not be filtered for issues
|
|
selectLabels := ctx.FormString("labels")
|
|
if selectLabels != "" {
|
|
var err error
|
|
ret.SelectedLabelIDs, err = base.StringsToInt64s(strings.Split(selectLabels, ","))
|
|
if err != nil {
|
|
ctx.Flash.Error(ctx.Tr("invalid_data", selectLabels), true)
|
|
}
|
|
}
|
|
|
|
var allLabels []*issues_model.Label
|
|
if repoID != 0 {
|
|
repoLabels, err := issues_model.GetLabelsByRepoID(ctx, repoID, "", db.ListOptions{})
|
|
if err != nil {
|
|
ctx.ServerError("GetLabelsByRepoID", err)
|
|
return ret
|
|
}
|
|
issues_model.SortLabelsForDisplay(repoLabels)
|
|
allLabels = append(allLabels, repoLabels...)
|
|
}
|
|
|
|
if owner != nil && owner.IsOrganization() {
|
|
orgLabels, err := issues_model.GetLabelsByOrgID(ctx, owner.ID, "", db.ListOptions{})
|
|
if err != nil {
|
|
ctx.ServerError("GetLabelsByOrgID", err)
|
|
return ret
|
|
}
|
|
issues_model.SortLabelsForDisplay(orgLabels)
|
|
allLabels = append(allLabels, orgLabels...)
|
|
}
|
|
|
|
// Get the exclusive scope for every label ID
|
|
labelExclusiveScopes := make([]string, 0, len(ret.SelectedLabelIDs))
|
|
for _, labelID := range ret.SelectedLabelIDs {
|
|
foundExclusiveScope := false
|
|
for _, label := range allLabels {
|
|
if label.ID == labelID || label.ID == -labelID {
|
|
labelExclusiveScopes = append(labelExclusiveScopes, label.ExclusiveScope())
|
|
foundExclusiveScope = true
|
|
break
|
|
}
|
|
}
|
|
if !foundExclusiveScope {
|
|
labelExclusiveScopes = append(labelExclusiveScopes, "")
|
|
}
|
|
}
|
|
|
|
for _, l := range allLabels {
|
|
l.LoadSelectedLabelsAfterClick(ret.SelectedLabelIDs, labelExclusiveScopes)
|
|
}
|
|
ctx.Data["Labels"] = allLabels
|
|
ctx.Data["SelectLabels"] = selectLabels
|
|
ret.AllLabels = allLabels
|
|
return ret
|
|
}
|