From 1830e2547373279c88231966e4f0b64548b0af6f Mon Sep 17 00:00:00 2001 From: Kemal Zebari Date: Fri, 6 Jun 2025 10:33:37 -0700 Subject: [PATCH 01/11] Validate hex colors when creating/editing labels --- templates/repo/issue/labels/label_edit_modal.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/issue/labels/label_edit_modal.tmpl b/templates/repo/issue/labels/label_edit_modal.tmpl index 364fc508f1975..2f93dc038ca0a 100644 --- a/templates/repo/issue/labels/label_edit_modal.tmpl +++ b/templates/repo/issue/labels/label_edit_modal.tmpl @@ -50,7 +50,7 @@
- + {{template "repo/issue/label_precolors"}}
From 3d39baf1048e08ad693c606c873aa92b225654d0 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 6 Jun 2025 10:41:27 -0700 Subject: [PATCH 02/11] Fix new label validation --- modules/label/label.go | 17 ++++++++++++++++- routers/web/org/org_labels.go | 14 ++++++++++++-- routers/web/repo/issue_label.go | 14 ++++++++++++-- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/modules/label/label.go b/modules/label/label.go index ce028aa9f3b25..8e6f659fa782c 100644 --- a/modules/label/label.go +++ b/modules/label/label.go @@ -21,6 +21,19 @@ type Label struct { ExclusiveOrder int `yaml:"exclusive_order,omitempty"` } +type ErrInvalidLabelColor struct { + Color string +} + +func (e *ErrInvalidLabelColor) Error() string { + return fmt.Sprintf("invalid label color: %s", e.Color) +} + +func IsErrInvalidLabelColor(err error) bool { + _, ok := err.(*ErrInvalidLabelColor) + return ok +} + // NormalizeColor normalizes a color string to a 6-character hex code func NormalizeColor(color string) (string, error) { // normalize case @@ -32,7 +45,9 @@ func NormalizeColor(color string) (string, error) { } if !colorPattern.MatchString(color) { - return "", fmt.Errorf("bad color code: %s", color) + return "", &ErrInvalidLabelColor{ + Color: color, + } } // convert 3-character shorthand into 6-character version diff --git a/routers/web/org/org_labels.go b/routers/web/org/org_labels.go index 456ed3f01ed3b..a68b6cf9703dd 100644 --- a/routers/web/org/org_labels.go +++ b/routers/web/org/org_labels.go @@ -52,7 +52,12 @@ func NewLabel(ctx *context.Context) { ExclusiveOrder: form.ExclusiveOrder, } if err := issues_model.NewLabel(ctx, l); err != nil { - ctx.ServerError("NewLabel", err) + if label.IsErrInvalidLabelColor(err) { + ctx.Flash.Error(err.Error()) + ctx.Redirect(ctx.Org.OrgLink + "/settings/labels") + } else { + ctx.ServerError("NewLabel", err) + } return } ctx.Redirect(ctx.Org.OrgLink + "/settings/labels") @@ -79,7 +84,12 @@ func UpdateLabel(ctx *context.Context) { l.Color = form.Color l.SetArchived(form.IsArchived) if err := issues_model.UpdateLabel(ctx, l); err != nil { - ctx.ServerError("UpdateLabel", err) + if label.IsErrInvalidLabelColor(err) { + ctx.Flash.Error(err.Error()) + ctx.Redirect(ctx.Org.OrgLink + "/settings/labels") + } else { + ctx.ServerError("UpdateLabel", err) + } return } ctx.Redirect(ctx.Org.OrgLink + "/settings/labels") diff --git a/routers/web/repo/issue_label.go b/routers/web/repo/issue_label.go index f9c41adbcfd33..21c2d77c0a1b9 100644 --- a/routers/web/repo/issue_label.go +++ b/routers/web/repo/issue_label.go @@ -119,7 +119,12 @@ func NewLabel(ctx *context.Context) { Color: form.Color, } if err := issues_model.NewLabel(ctx, l); err != nil { - ctx.ServerError("NewLabel", err) + if label.IsErrInvalidLabelColor(err) { + ctx.Flash.Error(err.Error()) + ctx.Redirect(ctx.Repo.RepoLink + "/labels") + } else { + ctx.ServerError("NewLabel", err) + } return } ctx.Redirect(ctx.Repo.RepoLink + "/labels") @@ -146,7 +151,12 @@ func UpdateLabel(ctx *context.Context) { l.SetArchived(form.IsArchived) if err := issues_model.UpdateLabel(ctx, l); err != nil { - ctx.ServerError("UpdateLabel", err) + if label.IsErrInvalidLabelColor(err) { + ctx.Flash.Error(err.Error()) + ctx.Redirect(ctx.Repo.RepoLink + "/labels") + } else { + ctx.ServerError("UpdateLabel", err) + } return } ctx.Redirect(ctx.Repo.RepoLink + "/labels") From 10bd974bbfb14bae76f54d12a8c5046dba396b18 Mon Sep 17 00:00:00 2001 From: Kemal Zebari Date: Fri, 6 Jun 2025 13:43:37 -0700 Subject: [PATCH 03/11] Update backend changes + add web route tests --- modules/label/label.go | 2 +- routers/web/repo/issue_label.go | 10 +++---- routers/web/repo/issue_label_test.go | 40 ++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/modules/label/label.go b/modules/label/label.go index 8e6f659fa782c..c4957aba0707d 100644 --- a/modules/label/label.go +++ b/modules/label/label.go @@ -26,7 +26,7 @@ type ErrInvalidLabelColor struct { } func (e *ErrInvalidLabelColor) Error() string { - return fmt.Sprintf("invalid label color: %s", e.Color) + return "invalid label color: " + e.Color } func IsErrInvalidLabelColor(err error) bool { diff --git a/routers/web/repo/issue_label.go b/routers/web/repo/issue_label.go index 21c2d77c0a1b9..5620bcf07f9c8 100644 --- a/routers/web/repo/issue_label.go +++ b/routers/web/repo/issue_label.go @@ -120,12 +120,11 @@ func NewLabel(ctx *context.Context) { } if err := issues_model.NewLabel(ctx, l); err != nil { if label.IsErrInvalidLabelColor(err) { - ctx.Flash.Error(err.Error()) - ctx.Redirect(ctx.Repo.RepoLink + "/labels") + ctx.Flash.Error("NewLabel: " + err.Error()) } else { ctx.ServerError("NewLabel", err) + return } - return } ctx.Redirect(ctx.Repo.RepoLink + "/labels") } @@ -152,12 +151,11 @@ func UpdateLabel(ctx *context.Context) { l.SetArchived(form.IsArchived) if err := issues_model.UpdateLabel(ctx, l); err != nil { if label.IsErrInvalidLabelColor(err) { - ctx.Flash.Error(err.Error()) - ctx.Redirect(ctx.Repo.RepoLink + "/labels") + ctx.Flash.Error("UpdateLabel: " + err.Error()) } else { ctx.ServerError("UpdateLabel", err) + return } - return } ctx.Redirect(ctx.Repo.RepoLink + "/labels") } diff --git a/routers/web/repo/issue_label_test.go b/routers/web/repo/issue_label_test.go index c3fba07034bb5..4c8e6abc0f821 100644 --- a/routers/web/repo/issue_label_test.go +++ b/routers/web/repo/issue_label_test.go @@ -92,6 +92,23 @@ func TestNewLabel(t *testing.T) { assert.Equal(t, "/user2/repo1/labels", test.RedirectURL(ctx.Resp)) } +func TestNewLabelGivenInvalidLabelCode(t *testing.T) { + unittest.PrepareTestEnv(t) + ctx, _ := contexttest.MockContext(t, "user2/repo1/labels/edit") + contexttest.LoadUser(t, ctx, 2) + contexttest.LoadRepo(t, ctx, 1) + web.SetForm(ctx, &forms.CreateLabelForm{ + Title: "newlabel", + Color: "bad-label-code", + }) + NewLabel(ctx) + assert.Equal(t, http.StatusSeeOther, ctx.Resp.WrittenStatus()) + assert.True(t, ctx.Flash.Has("error")) + unittest.AssertNotExistsBean(t, &issues_model.Label{ + Name: "newlabel", + }) +} + func TestUpdateLabel(t *testing.T) { unittest.PrepareTestEnv(t) ctx, _ := contexttest.MockContext(t, "user2/repo1/labels/edit") @@ -113,6 +130,29 @@ func TestUpdateLabel(t *testing.T) { assert.Equal(t, "/user2/repo1/labels", test.RedirectURL(ctx.Resp)) } +func TestUpdateLabelGivenInvalidLabelCode(t *testing.T) { + unittest.PrepareTestEnv(t) + ctx, _ := contexttest.MockContext(t, "user2/repo1/labels/edit") + contexttest.LoadUser(t, ctx, 2) + contexttest.LoadRepo(t, ctx, 1) + web.SetForm(ctx, &forms.CreateLabelForm{ + ID: 1, + Title: "label1", + Color: "bad-label-code", + }) + + UpdateLabel(ctx) + + assert.Equal(t, http.StatusSeeOther, ctx.Resp.WrittenStatus()) + assert.Equal(t, "/user2/repo1/labels", test.RedirectURL(ctx.Resp)) + assert.True(t, ctx.Flash.Has("error")) + unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ + ID: 1, + Name: "label1", + Color: "#abcdef", + }) +} + func TestDeleteLabel(t *testing.T) { unittest.PrepareTestEnv(t) ctx, _ := contexttest.MockContext(t, "user2/repo1/labels/delete") From 6c3aa9be4d5742b58a582f3aa12d65f686e98c03 Mon Sep 17 00:00:00 2001 From: Kemal Zebari Date: Fri, 6 Jun 2025 14:06:58 -0700 Subject: [PATCH 04/11] Make regex more strict --- templates/repo/issue/labels/label_edit_modal.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/issue/labels/label_edit_modal.tmpl b/templates/repo/issue/labels/label_edit_modal.tmpl index 2f93dc038ca0a..bfe37fa3bfffd 100644 --- a/templates/repo/issue/labels/label_edit_modal.tmpl +++ b/templates/repo/issue/labels/label_edit_modal.tmpl @@ -50,7 +50,7 @@
- + {{template "repo/issue/label_precolors"}}
From e76508a584ccdb973793079344b13f90fb7514b6 Mon Sep 17 00:00:00 2001 From: Kemal Zebari Date: Fri, 6 Jun 2025 14:14:38 -0700 Subject: [PATCH 05/11] Simplify org labels route changes --- routers/web/org/org_labels.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/routers/web/org/org_labels.go b/routers/web/org/org_labels.go index a68b6cf9703dd..741713f51257d 100644 --- a/routers/web/org/org_labels.go +++ b/routers/web/org/org_labels.go @@ -54,11 +54,11 @@ func NewLabel(ctx *context.Context) { if err := issues_model.NewLabel(ctx, l); err != nil { if label.IsErrInvalidLabelColor(err) { ctx.Flash.Error(err.Error()) - ctx.Redirect(ctx.Org.OrgLink + "/settings/labels") } else { ctx.ServerError("NewLabel", err) + return } - return + } ctx.Redirect(ctx.Org.OrgLink + "/settings/labels") } @@ -86,11 +86,11 @@ func UpdateLabel(ctx *context.Context) { if err := issues_model.UpdateLabel(ctx, l); err != nil { if label.IsErrInvalidLabelColor(err) { ctx.Flash.Error(err.Error()) - ctx.Redirect(ctx.Org.OrgLink + "/settings/labels") } else { ctx.ServerError("UpdateLabel", err) + return } - return + } ctx.Redirect(ctx.Org.OrgLink + "/settings/labels") } From fda7476ef3117a5c12a18a541a2474b87a88e966 Mon Sep 17 00:00:00 2001 From: Kemal Zebari Date: Fri, 6 Jun 2025 14:30:00 -0700 Subject: [PATCH 06/11] Update error messages for org labels + add missing assertion in test --- routers/web/org/org_labels.go | 4 ++-- routers/web/repo/issue_label_test.go | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/routers/web/org/org_labels.go b/routers/web/org/org_labels.go index 741713f51257d..d98c86db962cf 100644 --- a/routers/web/org/org_labels.go +++ b/routers/web/org/org_labels.go @@ -53,7 +53,7 @@ func NewLabel(ctx *context.Context) { } if err := issues_model.NewLabel(ctx, l); err != nil { if label.IsErrInvalidLabelColor(err) { - ctx.Flash.Error(err.Error()) + ctx.Flash.Error("NewLabel: " + err.Error()) } else { ctx.ServerError("NewLabel", err) return @@ -85,7 +85,7 @@ func UpdateLabel(ctx *context.Context) { l.SetArchived(form.IsArchived) if err := issues_model.UpdateLabel(ctx, l); err != nil { if label.IsErrInvalidLabelColor(err) { - ctx.Flash.Error(err.Error()) + ctx.Flash.Error("UpdateLabel: " + err.Error()) } else { ctx.ServerError("UpdateLabel", err) return diff --git a/routers/web/repo/issue_label_test.go b/routers/web/repo/issue_label_test.go index 4c8e6abc0f821..d3730e5d1171f 100644 --- a/routers/web/repo/issue_label_test.go +++ b/routers/web/repo/issue_label_test.go @@ -103,6 +103,7 @@ func TestNewLabelGivenInvalidLabelCode(t *testing.T) { }) NewLabel(ctx) assert.Equal(t, http.StatusSeeOther, ctx.Resp.WrittenStatus()) + assert.Equal(t, "/user2/repo1/labels", test.RedirectURL(ctx.Resp)) assert.True(t, ctx.Flash.Has("error")) unittest.AssertNotExistsBean(t, &issues_model.Label{ Name: "newlabel", From 5ab2729bbc066c6f2e555f5e7df1f70004e393c7 Mon Sep 17 00:00:00 2001 From: Kemal Zebari Date: Fri, 6 Jun 2025 14:45:15 -0700 Subject: [PATCH 07/11] PR backend linter feedback --- routers/web/org/org_labels.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/routers/web/org/org_labels.go b/routers/web/org/org_labels.go index d98c86db962cf..ef94949cae881 100644 --- a/routers/web/org/org_labels.go +++ b/routers/web/org/org_labels.go @@ -58,7 +58,6 @@ func NewLabel(ctx *context.Context) { ctx.ServerError("NewLabel", err) return } - } ctx.Redirect(ctx.Org.OrgLink + "/settings/labels") } @@ -90,7 +89,6 @@ func UpdateLabel(ctx *context.Context) { ctx.ServerError("UpdateLabel", err) return } - } ctx.Redirect(ctx.Org.OrgLink + "/settings/labels") } From 76eaa999c7436d81e640abce2af1ee1fc2a923cf Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sat, 7 Jun 2025 12:34:52 +0800 Subject: [PATCH 08/11] fix --- modules/label/label.go | 27 +++------- routers/web/org/org_labels.go | 52 ++++++++----------- routers/web/repo/issue_label.go | 52 ++++++++----------- routers/web/shared/label/label.go | 26 ++++++++++ .../repo/issue/labels/label_edit_modal.tmpl | 4 +- web_src/js/features/comp/LabelEdit.ts | 2 +- 6 files changed, 80 insertions(+), 83 deletions(-) create mode 100644 routers/web/shared/label/label.go diff --git a/modules/label/label.go b/modules/label/label.go index c4957aba0707d..3e68c4d26e4cd 100644 --- a/modules/label/label.go +++ b/modules/label/label.go @@ -7,10 +7,10 @@ import ( "fmt" "regexp" "strings" -) + "sync" -// colorPattern is a regexp which can validate label color -var colorPattern = regexp.MustCompile("^#?(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})$") + "code.gitea.io/gitea/modules/util" +) // Label represents label information loaded from template type Label struct { @@ -21,18 +21,9 @@ type Label struct { ExclusiveOrder int `yaml:"exclusive_order,omitempty"` } -type ErrInvalidLabelColor struct { - Color string -} - -func (e *ErrInvalidLabelColor) Error() string { - return "invalid label color: " + e.Color -} - -func IsErrInvalidLabelColor(err error) bool { - _, ok := err.(*ErrInvalidLabelColor) - return ok -} +var colorPattern = sync.OnceValue(func() *regexp.Regexp { + return regexp.MustCompile(`^#([\da-fA-F]{3}|[\da-fA-F]{6})$`) +}) // NormalizeColor normalizes a color string to a 6-character hex code func NormalizeColor(color string) (string, error) { @@ -44,10 +35,8 @@ func NormalizeColor(color string) (string, error) { color = "#" + color } - if !colorPattern.MatchString(color) { - return "", &ErrInvalidLabelColor{ - Color: color, - } + if !colorPattern().MatchString(color) { + return "", util.NewInvalidArgumentErrorf("invalid color: %s", color) } // convert 3-character shorthand into 6-character version diff --git a/routers/web/org/org_labels.go b/routers/web/org/org_labels.go index ef94949cae881..2a4aa7f557d86 100644 --- a/routers/web/org/org_labels.go +++ b/routers/web/org/org_labels.go @@ -4,13 +4,15 @@ package org import ( - "net/http" + "errors" "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/label" repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" + shared_label "code.gitea.io/gitea/routers/web/shared/label" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/forms" ) @@ -32,14 +34,8 @@ func RetrieveLabels(ctx *context.Context) { // NewLabel create new label for organization func NewLabel(ctx *context.Context) { - form := web.GetForm(ctx).(*forms.CreateLabelForm) - ctx.Data["Title"] = ctx.Tr("repo.labels") - ctx.Data["PageIsLabels"] = true - ctx.Data["PageIsOrgSettings"] = true - - if ctx.HasError() { - ctx.Flash.Error(ctx.Data["ErrorMsg"].(string)) - ctx.Redirect(ctx.Org.OrgLink + "/settings/labels") + form := shared_label.GetLabelEditForm(ctx) + if ctx.Written() { return } @@ -52,27 +48,25 @@ func NewLabel(ctx *context.Context) { ExclusiveOrder: form.ExclusiveOrder, } if err := issues_model.NewLabel(ctx, l); err != nil { - if label.IsErrInvalidLabelColor(err) { - ctx.Flash.Error("NewLabel: " + err.Error()) - } else { - ctx.ServerError("NewLabel", err) - return - } + ctx.ServerError("NewLabel", err) + return } - ctx.Redirect(ctx.Org.OrgLink + "/settings/labels") + ctx.JSONRedirect(ctx.Org.OrgLink + "/settings/labels") } // UpdateLabel update a label's name and color func UpdateLabel(ctx *context.Context) { - form := web.GetForm(ctx).(*forms.CreateLabelForm) + form := shared_label.GetLabelEditForm(ctx) + if ctx.Written() { + return + } + l, err := issues_model.GetLabelInOrgByID(ctx, ctx.Org.Organization.ID, form.ID) - if err != nil { - switch { - case issues_model.IsErrOrgLabelNotExist(err): - ctx.HTTPError(http.StatusNotFound) - default: - ctx.ServerError("UpdateLabel", err) - } + if errors.Is(err, util.ErrNotExist) { + ctx.JSONErrorNotFound() + return + } else if err != nil { + ctx.ServerError("GetLabelInOrgByID", err) return } @@ -83,14 +77,10 @@ func UpdateLabel(ctx *context.Context) { l.Color = form.Color l.SetArchived(form.IsArchived) if err := issues_model.UpdateLabel(ctx, l); err != nil { - if label.IsErrInvalidLabelColor(err) { - ctx.Flash.Error("UpdateLabel: " + err.Error()) - } else { - ctx.ServerError("UpdateLabel", err) - return - } + ctx.ServerError("UpdateLabel", err) + return } - ctx.Redirect(ctx.Org.OrgLink + "/settings/labels") + ctx.JSONRedirect(ctx.Org.OrgLink + "/settings/labels") } // DeleteLabel delete a label diff --git a/routers/web/repo/issue_label.go b/routers/web/repo/issue_label.go index 5620bcf07f9c8..72a316e98ddbf 100644 --- a/routers/web/repo/issue_label.go +++ b/routers/web/repo/issue_label.go @@ -4,6 +4,7 @@ package repo import ( + "errors" "net/http" "code.gitea.io/gitea/models/db" @@ -13,7 +14,9 @@ import ( "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/templates" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" + shared_label "code.gitea.io/gitea/routers/web/shared/label" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/forms" issue_service "code.gitea.io/gitea/services/issue" @@ -100,13 +103,8 @@ func RetrieveLabelsForList(ctx *context.Context) { // NewLabel create new label for repository func NewLabel(ctx *context.Context) { - form := web.GetForm(ctx).(*forms.CreateLabelForm) - ctx.Data["Title"] = ctx.Tr("repo.labels") - ctx.Data["PageIsLabels"] = true - - if ctx.HasError() { - ctx.Flash.Error(ctx.Data["ErrorMsg"].(string)) - ctx.Redirect(ctx.Repo.RepoLink + "/labels") + form := shared_label.GetLabelEditForm(ctx) + if ctx.Written() { return } @@ -119,45 +117,39 @@ func NewLabel(ctx *context.Context) { Color: form.Color, } if err := issues_model.NewLabel(ctx, l); err != nil { - if label.IsErrInvalidLabelColor(err) { - ctx.Flash.Error("NewLabel: " + err.Error()) - } else { - ctx.ServerError("NewLabel", err) - return - } + ctx.ServerError("NewLabel", err) + return } - ctx.Redirect(ctx.Repo.RepoLink + "/labels") + ctx.JSONRedirect(ctx.Repo.RepoLink + "/labels") } // UpdateLabel update a label's name and color func UpdateLabel(ctx *context.Context) { - form := web.GetForm(ctx).(*forms.CreateLabelForm) + form := shared_label.GetLabelEditForm(ctx) + if ctx.Written() { + return + } + l, err := issues_model.GetLabelInRepoByID(ctx, ctx.Repo.Repository.ID, form.ID) - if err != nil { - switch { - case issues_model.IsErrRepoLabelNotExist(err): - ctx.HTTPError(http.StatusNotFound) - default: - ctx.ServerError("UpdateLabel", err) - } + if errors.Is(err, util.ErrNotExist) { + ctx.JSONErrorNotFound() + return + } else if err != nil { + ctx.ServerError("GetLabelInRepoByID", err) return } + l.Name = form.Title l.Exclusive = form.Exclusive l.ExclusiveOrder = form.ExclusiveOrder l.Description = form.Description l.Color = form.Color - l.SetArchived(form.IsArchived) if err := issues_model.UpdateLabel(ctx, l); err != nil { - if label.IsErrInvalidLabelColor(err) { - ctx.Flash.Error("UpdateLabel: " + err.Error()) - } else { - ctx.ServerError("UpdateLabel", err) - return - } + ctx.ServerError("UpdateLabel", err) + return } - ctx.Redirect(ctx.Repo.RepoLink + "/labels") + ctx.JSONRedirect(ctx.Repo.RepoLink + "/labels") } // DeleteLabel delete a label diff --git a/routers/web/shared/label/label.go b/routers/web/shared/label/label.go new file mode 100644 index 0000000000000..e542726ec0482 --- /dev/null +++ b/routers/web/shared/label/label.go @@ -0,0 +1,26 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package label + +import ( + "code.gitea.io/gitea/modules/label" + "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/services/context" + "code.gitea.io/gitea/services/forms" +) + +func GetLabelEditForm(ctx *context.Context) *forms.CreateLabelForm { + form := web.GetForm(ctx).(*forms.CreateLabelForm) + if ctx.HasError() { + ctx.JSONError(ctx.Data["ErrorMsg"].(string)) + return nil + } + var err error + form.Color, err = label.NormalizeColor(form.Color) + if err != nil { + ctx.JSONError(".....") // TODO: translate + return nil + } + return form +} diff --git a/templates/repo/issue/labels/label_edit_modal.tmpl b/templates/repo/issue/labels/label_edit_modal.tmpl index bfe37fa3bfffd..1193cbca7b126 100644 --- a/templates/repo/issue/labels/label_edit_modal.tmpl +++ b/templates/repo/issue/labels/label_edit_modal.tmpl @@ -5,7 +5,7 @@ >
-
+ {{.CsrfTokenHtml}}
@@ -50,7 +50,7 @@
- + {{template "repo/issue/label_precolors"}}
diff --git a/web_src/js/features/comp/LabelEdit.ts b/web_src/js/features/comp/LabelEdit.ts index 55351cd900bb9..a5bb750cdbe85 100644 --- a/web_src/js/features/comp/LabelEdit.ts +++ b/web_src/js/features/comp/LabelEdit.ts @@ -70,7 +70,7 @@ export function initCompLabelEdit(pageSelector: string) { form.reportValidity(); return false; } - form.submit(); + form.dispatchEvent(new Event('submit', {bubbles: true})); }, }).modal('show'); }; From e43f28234ef7578462051e0b95657452c2ed4e69 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sat, 7 Jun 2025 12:56:21 +0800 Subject: [PATCH 09/11] fix --- modules/test/utils.go | 10 ++++ options/locale/locale_en-US.ini | 2 +- routers/web/repo/issue_label_test.go | 81 +++++++++++++--------------- routers/web/shared/label/label.go | 2 +- 4 files changed, 50 insertions(+), 45 deletions(-) diff --git a/modules/test/utils.go b/modules/test/utils.go index 3051d3d286b9c..53c6a3ed52e61 100644 --- a/modules/test/utils.go +++ b/modules/test/utils.go @@ -17,6 +17,7 @@ import ( // RedirectURL returns the redirect URL of a http response. // It also works for JSONRedirect: `{"redirect": "..."}` +// FIXME: it should separate the logic of checking from header and JSON body func RedirectURL(resp http.ResponseWriter) string { loc := resp.Header().Get("Location") if loc != "" { @@ -34,6 +35,15 @@ func RedirectURL(resp http.ResponseWriter) string { return "" } +func ParseJSONError(buf []byte) (ret struct { + ErrorMessage string `json:"errorMessage"` + RenderFormat string `json:"renderFormat"` +}, +) { + _ = json.Unmarshal(buf, &ret) + return ret +} + func IsNormalPageCompleted(s string) bool { return strings.Contains(s, `