diff options
author | Lauris BH | 2023-03-02 01:44:23 +0200 |
---|---|---|
committer | GitHub | 2023-03-02 01:44:23 +0200 |
commit | 58b414380371a4419f909491700673d43ae6b4ff (patch) | |
tree | 9d994ac5afecdf2109fe93d9ba97a12c201bd27e /models | |
parent | de6c718b46ebd3b7f6362c766eed328044d95ec7 (diff) |
Add loading yaml label template files (#22976)
Extract from #11669 and enhancement to #22585 to support exclusive
scoped labels in label templates
* Move label template functionality to label module
* Fix handling of color codes
* Add Advanced label template
Diffstat (limited to 'models')
-rw-r--r-- | models/issues/label.go | 115 | ||||
-rw-r--r-- | models/issues/label_test.go | 2 |
2 files changed, 52 insertions, 65 deletions
diff --git a/models/issues/label.go b/models/issues/label.go index 90e4eb458..35c649e8f 100644 --- a/models/issues/label.go +++ b/models/issues/label.go @@ -7,12 +7,12 @@ package issues import ( "context" "fmt" - "regexp" "strconv" "strings" "code.gitea.io/gitea/models/db" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/label" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" @@ -78,9 +78,6 @@ func (err ErrLabelNotExist) Unwrap() error { return util.ErrNotExist } -// LabelColorPattern is a regexp witch can validate LabelColor -var LabelColorPattern = regexp.MustCompile("^#?(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})$") - // Label represents a label of repository for issues. type Label struct { ID int64 `xorm:"pk autoincr"` @@ -109,12 +106,12 @@ func init() { } // CalOpenIssues sets the number of open issues of a label based on the already stored number of closed issues. -func (label *Label) CalOpenIssues() { - label.NumOpenIssues = label.NumIssues - label.NumClosedIssues +func (l *Label) CalOpenIssues() { + l.NumOpenIssues = l.NumIssues - l.NumClosedIssues } // CalOpenOrgIssues calculates the open issues of a label for a specific repo -func (label *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64) { +func (l *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64) { counts, _ := CountIssuesByRepo(ctx, &IssuesOptions{ RepoID: repoID, LabelIDs: []int64{labelID}, @@ -122,22 +119,22 @@ func (label *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64) }) for _, count := range counts { - label.NumOpenRepoIssues += count + l.NumOpenRepoIssues += count } } // LoadSelectedLabelsAfterClick calculates the set of selected labels when a label is clicked -func (label *Label) LoadSelectedLabelsAfterClick(currentSelectedLabels []int64, currentSelectedExclusiveScopes []string) { +func (l *Label) LoadSelectedLabelsAfterClick(currentSelectedLabels []int64, currentSelectedExclusiveScopes []string) { var labelQuerySlice []string labelSelected := false - labelID := strconv.FormatInt(label.ID, 10) - labelScope := label.ExclusiveScope() + labelID := strconv.FormatInt(l.ID, 10) + labelScope := l.ExclusiveScope() for i, s := range currentSelectedLabels { - if s == label.ID { + if s == l.ID { labelSelected = true - } else if -s == label.ID { + } else if -s == l.ID { labelSelected = true - label.IsExcluded = true + l.IsExcluded = true } else if s != 0 { // Exclude other labels in the same scope from selection if s < 0 || labelScope == "" || labelScope != currentSelectedExclusiveScopes[i] { @@ -148,23 +145,23 @@ func (label *Label) LoadSelectedLabelsAfterClick(currentSelectedLabels []int64, if !labelSelected { labelQuerySlice = append(labelQuerySlice, labelID) } - label.IsSelected = labelSelected - label.QueryString = strings.Join(labelQuerySlice, ",") + l.IsSelected = labelSelected + l.QueryString = strings.Join(labelQuerySlice, ",") } // BelongsToOrg returns true if label is an organization label -func (label *Label) BelongsToOrg() bool { - return label.OrgID > 0 +func (l *Label) BelongsToOrg() bool { + return l.OrgID > 0 } // BelongsToRepo returns true if label is a repository label -func (label *Label) BelongsToRepo() bool { - return label.RepoID > 0 +func (l *Label) BelongsToRepo() bool { + return l.RepoID > 0 } // Get color as RGB values in 0..255 range -func (label *Label) ColorRGB() (float64, float64, float64, error) { - color, err := strconv.ParseUint(label.Color[1:], 16, 64) +func (l *Label) ColorRGB() (float64, float64, float64, error) { + color, err := strconv.ParseUint(l.Color[1:], 16, 64) if err != nil { return 0, 0, 0, err } @@ -176,9 +173,9 @@ func (label *Label) ColorRGB() (float64, float64, float64, error) { } // Determine if label text should be light or dark to be readable on background color -func (label *Label) UseLightTextColor() bool { - if strings.HasPrefix(label.Color, "#") { - if r, g, b, err := label.ColorRGB(); err == nil { +func (l *Label) UseLightTextColor() bool { + if strings.HasPrefix(l.Color, "#") { + if r, g, b, err := l.ColorRGB(); err == nil { // Perceived brightness from: https://www.w3.org/TR/AERT/#color-contrast // In the future WCAG 3 APCA may be a better solution brightness := (0.299*r + 0.587*g + 0.114*b) / 255 @@ -190,40 +187,26 @@ func (label *Label) UseLightTextColor() bool { } // Return scope substring of label name, or empty string if none exists -func (label *Label) ExclusiveScope() string { - if !label.Exclusive { +func (l *Label) ExclusiveScope() string { + if !l.Exclusive { return "" } - lastIndex := strings.LastIndex(label.Name, "/") - if lastIndex == -1 || lastIndex == 0 || lastIndex == len(label.Name)-1 { + lastIndex := strings.LastIndex(l.Name, "/") + if lastIndex == -1 || lastIndex == 0 || lastIndex == len(l.Name)-1 { return "" } - return label.Name[:lastIndex] + return l.Name[:lastIndex] } // NewLabel creates a new label -func NewLabel(ctx context.Context, label *Label) error { - if !LabelColorPattern.MatchString(label.Color) { - return fmt.Errorf("bad color code: %s", label.Color) - } - - // normalize case - label.Color = strings.ToLower(label.Color) - - // add leading hash - if label.Color[0] != '#' { - label.Color = "#" + label.Color - } - - // convert 3-character shorthand into 6-character version - if len(label.Color) == 4 { - r := label.Color[1] - g := label.Color[2] - b := label.Color[3] - label.Color = fmt.Sprintf("#%c%c%c%c%c%c", r, r, g, g, b, b) +func NewLabel(ctx context.Context, l *Label) error { + color, err := label.NormalizeColor(l.Color) + if err != nil { + return err } + l.Color = color - return db.Insert(ctx, label) + return db.Insert(ctx, l) } // NewLabels creates new labels @@ -234,11 +217,14 @@ func NewLabels(labels ...*Label) error { } defer committer.Close() - for _, label := range labels { - if !LabelColorPattern.MatchString(label.Color) { - return fmt.Errorf("bad color code: %s", label.Color) + for _, l := range labels { + color, err := label.NormalizeColor(l.Color) + if err != nil { + return err } - if err := db.Insert(ctx, label); err != nil { + l.Color = color + + if err := db.Insert(ctx, l); err != nil { return err } } @@ -247,15 +233,18 @@ func NewLabels(labels ...*Label) error { // UpdateLabel updates label information. func UpdateLabel(l *Label) error { - if !LabelColorPattern.MatchString(l.Color) { - return fmt.Errorf("bad color code: %s", l.Color) + color, err := label.NormalizeColor(l.Color) + if err != nil { + return err } + l.Color = color + return updateLabelCols(db.DefaultContext, l, "name", "description", "color", "exclusive") } // DeleteLabel delete a label func DeleteLabel(id, labelID int64) error { - label, err := GetLabelByID(db.DefaultContext, labelID) + l, err := GetLabelByID(db.DefaultContext, labelID) if err != nil { if IsErrLabelNotExist(err) { return nil @@ -271,10 +260,10 @@ func DeleteLabel(id, labelID int64) error { sess := db.GetEngine(ctx) - if label.BelongsToOrg() && label.OrgID != id { + if l.BelongsToOrg() && l.OrgID != id { return nil } - if label.BelongsToRepo() && label.RepoID != id { + if l.BelongsToRepo() && l.RepoID != id { return nil } @@ -682,14 +671,14 @@ func newIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer *us if err = issue.LoadRepo(ctx); err != nil { return err } - for _, label := range labels { + for _, l := range labels { // Don't add already present labels and invalid labels - if HasIssueLabel(ctx, issue.ID, label.ID) || - (label.RepoID != issue.RepoID && label.OrgID != issue.Repo.OwnerID) { + if HasIssueLabel(ctx, issue.ID, l.ID) || + (l.RepoID != issue.RepoID && l.OrgID != issue.Repo.OwnerID) { continue } - if err = newIssueLabel(ctx, issue, label, doer); err != nil { + if err = newIssueLabel(ctx, issue, l, doer); err != nil { return fmt.Errorf("newIssueLabel: %w", err) } } diff --git a/models/issues/label_test.go b/models/issues/label_test.go index 0e45e0db0..1f6ce4f42 100644 --- a/models/issues/label_test.go +++ b/models/issues/label_test.go @@ -15,8 +15,6 @@ import ( "github.com/stretchr/testify/assert" ) -// TODO TestGetLabelTemplateFile - func TestLabel_CalOpenIssues(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1}) |