aboutsummaryrefslogtreecommitdiff
path: root/models
diff options
context:
space:
mode:
authorLauris BH2023-03-02 01:44:23 +0200
committerGitHub2023-03-02 01:44:23 +0200
commit58b414380371a4419f909491700673d43ae6b4ff (patch)
tree9d994ac5afecdf2109fe93d9ba97a12c201bd27e /models
parentde6c718b46ebd3b7f6362c766eed328044d95ec7 (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.go115
-rw-r--r--models/issues/label_test.go2
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})