Skip to content

Commit 58c634b

Browse files
authored
Refactor sidebar label selector (#32460)
Introduce `issueSidebarLabelsData` to handle all sidebar labels related data.
1 parent b55a31e commit 58c634b

22 files changed

+275
-232
lines changed

routers/web/repo/compare.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -788,14 +788,22 @@ func CompareDiff(ctx *context.Context) {
788788

789789
if !nothingToCompare {
790790
// Setup information for new form.
791-
RetrieveRepoMetas(ctx, ctx.Repo.Repository, true)
791+
retrieveRepoMetasForIssueWriter(ctx, ctx.Repo.Repository, true)
792+
if ctx.Written() {
793+
return
794+
}
795+
labelsData := retrieveRepoLabels(ctx, ctx.Repo.Repository, 0, true)
792796
if ctx.Written() {
793797
return
794798
}
795799
RetrieveRepoReviewers(ctx, ctx.Repo.Repository, nil, true)
796800
if ctx.Written() {
797801
return
798802
}
803+
_, templateErrs := setTemplateIfExists(ctx, pullRequestTemplateKey, pullRequestTemplateCandidates, labelsData)
804+
if len(templateErrs) > 0 {
805+
ctx.Flash.Warning(renderErrorOfTemplates(ctx, templateErrs), true)
806+
}
799807
}
800808
}
801809
beforeCommitID := ctx.Data["BeforeCommitID"].(string)
@@ -808,11 +816,6 @@ func CompareDiff(ctx *context.Context) {
808816
ctx.Data["Title"] = "Comparing " + base.ShortSha(beforeCommitID) + separator + base.ShortSha(afterCommitID)
809817

810818
ctx.Data["IsDiffCompare"] = true
811-
_, templateErrs := setTemplateIfExists(ctx, pullRequestTemplateKey, pullRequestTemplateCandidates)
812-
813-
if len(templateErrs) > 0 {
814-
ctx.Flash.Warning(renderErrorOfTemplates(ctx, templateErrs), true)
815-
}
816819

817820
if content, ok := ctx.Data["content"].(string); ok && content != "" {
818821
// If a template content is set, prepend the "content". In this case that's only

routers/web/repo/issue.go

Lines changed: 99 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -870,51 +870,112 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is
870870
ctx.Data["IssueSidebarReviewersData"] = data
871871
}
872872

873-
// RetrieveRepoMetas find all the meta information of a repository
874-
func RetrieveRepoMetas(ctx *context.Context, repo *repo_model.Repository, isPull bool) []*issues_model.Label {
875-
if !ctx.Repo.CanWriteIssuesOrPulls(isPull) {
876-
return nil
873+
type issueSidebarLabelsData struct {
874+
Repository *repo_model.Repository
875+
RepoLink string
876+
IssueID int64
877+
IsPullRequest bool
878+
AllLabels []*issues_model.Label
879+
RepoLabels []*issues_model.Label
880+
OrgLabels []*issues_model.Label
881+
SelectedLabelIDs string
882+
}
883+
884+
func makeSelectedStringIDs[KeyType, ItemType comparable](
885+
allLabels []*issues_model.Label, candidateKey func(candidate *issues_model.Label) KeyType,
886+
selectedItems []ItemType, selectedKey func(selected ItemType) KeyType,
887+
) string {
888+
selectedIDSet := make(container.Set[string])
889+
allLabelMap := map[KeyType]*issues_model.Label{}
890+
for _, label := range allLabels {
891+
allLabelMap[candidateKey(label)] = label
892+
}
893+
for _, item := range selectedItems {
894+
if label, ok := allLabelMap[selectedKey(item)]; ok {
895+
label.IsChecked = true
896+
selectedIDSet.Add(strconv.FormatInt(label.ID, 10))
897+
}
898+
}
899+
ids := selectedIDSet.Values()
900+
sort.Strings(ids)
901+
return strings.Join(ids, ",")
902+
}
903+
904+
func (d *issueSidebarLabelsData) SetSelectedLabels(labels []*issues_model.Label) {
905+
d.SelectedLabelIDs = makeSelectedStringIDs(
906+
d.AllLabels, func(label *issues_model.Label) int64 { return label.ID },
907+
labels, func(label *issues_model.Label) int64 { return label.ID },
908+
)
909+
}
910+
911+
func (d *issueSidebarLabelsData) SetSelectedLabelNames(labelNames []string) {
912+
d.SelectedLabelIDs = makeSelectedStringIDs(
913+
d.AllLabels, func(label *issues_model.Label) string { return strings.ToLower(label.Name) },
914+
labelNames, strings.ToLower,
915+
)
916+
}
917+
918+
func (d *issueSidebarLabelsData) SetSelectedLabelIDs(labelIDs []int64) {
919+
d.SelectedLabelIDs = makeSelectedStringIDs(
920+
d.AllLabels, func(label *issues_model.Label) int64 { return label.ID },
921+
labelIDs, func(labelID int64) int64 { return labelID },
922+
)
923+
}
924+
925+
func retrieveRepoLabels(ctx *context.Context, repo *repo_model.Repository, issueID int64, isPull bool) *issueSidebarLabelsData {
926+
labelsData := &issueSidebarLabelsData{
927+
Repository: repo,
928+
RepoLink: ctx.Repo.RepoLink,
929+
IssueID: issueID,
930+
IsPullRequest: isPull,
877931
}
932+
ctx.Data["IssueSidebarLabelsData"] = labelsData
878933

879934
labels, err := issues_model.GetLabelsByRepoID(ctx, repo.ID, "", db.ListOptions{})
880935
if err != nil {
881936
ctx.ServerError("GetLabelsByRepoID", err)
882937
return nil
883938
}
884-
ctx.Data["Labels"] = labels
939+
labelsData.RepoLabels = labels
940+
885941
if repo.Owner.IsOrganization() {
886942
orgLabels, err := issues_model.GetLabelsByOrgID(ctx, repo.Owner.ID, ctx.FormString("sort"), db.ListOptions{})
887943
if err != nil {
888944
return nil
889945
}
946+
labelsData.OrgLabels = orgLabels
947+
}
948+
labelsData.AllLabels = append(labelsData.AllLabels, labelsData.RepoLabels...)
949+
labelsData.AllLabels = append(labelsData.AllLabels, labelsData.OrgLabels...)
950+
return labelsData
951+
}
890952

891-
ctx.Data["OrgLabels"] = orgLabels
892-
labels = append(labels, orgLabels...)
953+
// retrieveRepoMetasForIssueWriter finds some the meta information of a repository for an issue/pr writer
954+
func retrieveRepoMetasForIssueWriter(ctx *context.Context, repo *repo_model.Repository, isPull bool) {
955+
if !ctx.Repo.CanWriteIssuesOrPulls(isPull) {
956+
return
893957
}
894958

895959
RetrieveRepoMilestonesAndAssignees(ctx, repo)
896960
if ctx.Written() {
897-
return nil
961+
return
898962
}
899963

900964
retrieveProjects(ctx, repo)
901965
if ctx.Written() {
902-
return nil
966+
return
903967
}
904968

905969
PrepareBranchList(ctx)
906970
if ctx.Written() {
907-
return nil
971+
return
908972
}
909-
910973
// Contains true if the user can create issue dependencies
911974
ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx, ctx.Doer, isPull)
912-
913-
return labels
914975
}
915976

916977
// Tries to load and set an issue template. The first return value indicates if a template was loaded.
917-
func setTemplateIfExists(ctx *context.Context, ctxDataKey string, possibleFiles []string) (bool, map[string]error) {
978+
func setTemplateIfExists(ctx *context.Context, ctxDataKey string, possibleFiles []string, labelsData *issueSidebarLabelsData) (bool, map[string]error) {
918979
commit, err := ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultBranch)
919980
if err != nil {
920981
return false, nil
@@ -951,26 +1012,9 @@ func setTemplateIfExists(ctx *context.Context, ctxDataKey string, possibleFiles
9511012
ctx.Data["Fields"] = template.Fields
9521013
ctx.Data["TemplateFile"] = template.FileName
9531014
}
954-
labelIDs := make([]string, 0, len(template.Labels))
955-
if repoLabels, err := issues_model.GetLabelsByRepoID(ctx, ctx.Repo.Repository.ID, "", db.ListOptions{}); err == nil {
956-
ctx.Data["Labels"] = repoLabels
957-
if ctx.Repo.Owner.IsOrganization() {
958-
if orgLabels, err := issues_model.GetLabelsByOrgID(ctx, ctx.Repo.Owner.ID, ctx.FormString("sort"), db.ListOptions{}); err == nil {
959-
ctx.Data["OrgLabels"] = orgLabels
960-
repoLabels = append(repoLabels, orgLabels...)
961-
}
962-
}
9631015

964-
for _, metaLabel := range template.Labels {
965-
for _, repoLabel := range repoLabels {
966-
if strings.EqualFold(repoLabel.Name, metaLabel) {
967-
repoLabel.IsChecked = true
968-
labelIDs = append(labelIDs, strconv.FormatInt(repoLabel.ID, 10))
969-
break
970-
}
971-
}
972-
}
973-
}
1016+
labelsData.SetSelectedLabelNames(template.Labels)
1017+
9741018
selectedAssigneeIDs := make([]int64, 0, len(template.Assignees))
9751019
selectedAssigneeIDStrings := make([]string, 0, len(template.Assignees))
9761020
if userIDs, err := user_model.GetUserIDsByNames(ctx, template.Assignees, false); err == nil {
@@ -983,8 +1027,7 @@ func setTemplateIfExists(ctx *context.Context, ctxDataKey string, possibleFiles
9831027
if template.Ref != "" && !strings.HasPrefix(template.Ref, "refs/") { // Assume that the ref intended is always a branch - for tags users should use refs/tags/<ref>
9841028
template.Ref = git.BranchPrefix + template.Ref
9851029
}
986-
ctx.Data["HasSelectedLabel"] = len(labelIDs) > 0
987-
ctx.Data["label_ids"] = strings.Join(labelIDs, ",")
1030+
9881031
ctx.Data["HasSelectedAssignee"] = len(selectedAssigneeIDs) > 0
9891032
ctx.Data["assignee_ids"] = strings.Join(selectedAssigneeIDStrings, ",")
9901033
ctx.Data["SelectedAssigneeIDs"] = selectedAssigneeIDs
@@ -1042,8 +1085,14 @@ func NewIssue(ctx *context.Context) {
10421085
}
10431086
}
10441087

1045-
RetrieveRepoMetas(ctx, ctx.Repo.Repository, false)
1046-
1088+
retrieveRepoMetasForIssueWriter(ctx, ctx.Repo.Repository, false)
1089+
if ctx.Written() {
1090+
return
1091+
}
1092+
labelsData := retrieveRepoLabels(ctx, ctx.Repo.Repository, 0, false)
1093+
if ctx.Written() {
1094+
return
1095+
}
10471096
tags, err := repo_model.GetTagNamesByRepoID(ctx, ctx.Repo.Repository.ID)
10481097
if err != nil {
10491098
ctx.ServerError("GetTagNamesByRepoID", err)
@@ -1052,7 +1101,7 @@ func NewIssue(ctx *context.Context) {
10521101
ctx.Data["Tags"] = tags
10531102

10541103
ret := issue_service.ParseTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
1055-
templateLoaded, errs := setTemplateIfExists(ctx, issueTemplateKey, IssueTemplateCandidates)
1104+
templateLoaded, errs := setTemplateIfExists(ctx, issueTemplateKey, IssueTemplateCandidates, labelsData)
10561105
for k, v := range errs {
10571106
ret.TemplateErrors[k] = v
10581107
}
@@ -1161,34 +1210,25 @@ func ValidateRepoMetas(ctx *context.Context, form forms.CreateIssueForm, isPull
11611210
err error
11621211
)
11631212

1164-
labels := RetrieveRepoMetas(ctx, ctx.Repo.Repository, isPull)
1213+
retrieveRepoMetasForIssueWriter(ctx, ctx.Repo.Repository, isPull)
1214+
if ctx.Written() {
1215+
return ret
1216+
}
1217+
labelsData := retrieveRepoLabels(ctx, ctx.Repo.Repository, 0, isPull)
11651218
if ctx.Written() {
11661219
return ret
11671220
}
11681221

11691222
var labelIDs []int64
1170-
hasSelected := false
11711223
// Check labels.
11721224
if len(form.LabelIDs) > 0 {
11731225
labelIDs, err = base.StringsToInt64s(strings.Split(form.LabelIDs, ","))
11741226
if err != nil {
11751227
return ret
11761228
}
1177-
labelIDMark := make(container.Set[int64])
1178-
labelIDMark.AddMultiple(labelIDs...)
1179-
1180-
for i := range labels {
1181-
if labelIDMark.Contains(labels[i].ID) {
1182-
labels[i].IsChecked = true
1183-
hasSelected = true
1184-
}
1185-
}
1229+
labelsData.SetSelectedLabelIDs(labelIDs)
11861230
}
11871231

1188-
ctx.Data["Labels"] = labels
1189-
ctx.Data["HasSelectedLabel"] = hasSelected
1190-
ctx.Data["label_ids"] = form.LabelIDs
1191-
11921232
// Check milestone.
11931233
milestoneID := form.MilestoneID
11941234
if milestoneID > 0 {
@@ -1579,38 +1619,15 @@ func ViewIssue(ctx *context.Context) {
15791619
}
15801620
}
15811621

1582-
// Metas.
1583-
// Check labels.
1584-
labelIDMark := make(container.Set[int64])
1585-
for _, label := range issue.Labels {
1586-
labelIDMark.Add(label.ID)
1587-
}
1588-
labels, err := issues_model.GetLabelsByRepoID(ctx, repo.ID, "", db.ListOptions{})
1589-
if err != nil {
1590-
ctx.ServerError("GetLabelsByRepoID", err)
1622+
retrieveRepoMetasForIssueWriter(ctx, repo, issue.IsPull)
1623+
if ctx.Written() {
15911624
return
15921625
}
1593-
ctx.Data["Labels"] = labels
1594-
1595-
if repo.Owner.IsOrganization() {
1596-
orgLabels, err := issues_model.GetLabelsByOrgID(ctx, repo.Owner.ID, ctx.FormString("sort"), db.ListOptions{})
1597-
if err != nil {
1598-
ctx.ServerError("GetLabelsByOrgID", err)
1599-
return
1600-
}
1601-
ctx.Data["OrgLabels"] = orgLabels
1602-
1603-
labels = append(labels, orgLabels...)
1604-
}
1605-
1606-
hasSelected := false
1607-
for i := range labels {
1608-
if labelIDMark.Contains(labels[i].ID) {
1609-
labels[i].IsChecked = true
1610-
hasSelected = true
1611-
}
1626+
labelsData := retrieveRepoLabels(ctx, repo, issue.ID, issue.IsPull)
1627+
if ctx.Written() {
1628+
return
16121629
}
1613-
ctx.Data["HasSelectedLabel"] = hasSelected
1630+
labelsData.SetSelectedLabels(issue.Labels)
16141631

16151632
// Check milestone and assignee.
16161633
if ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {

routers/web/repo/issue_label.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ func InitializeLabels(ctx *context.Context) {
5353
ctx.Redirect(ctx.Repo.RepoLink + "/labels")
5454
}
5555

56-
// RetrieveLabels find all the labels of a repository and organization
57-
func RetrieveLabels(ctx *context.Context) {
56+
// RetrieveLabelsForList find all the labels of a repository and organization, it is only used by "/labels" page to list all labels
57+
func RetrieveLabelsForList(ctx *context.Context) {
5858
labels, err := issues_model.GetLabelsByRepoID(ctx, ctx.Repo.Repository.ID, ctx.FormString("sort"), db.ListOptions{})
5959
if err != nil {
60-
ctx.ServerError("RetrieveLabels.GetLabels", err)
60+
ctx.ServerError("RetrieveLabelsForList.GetLabels", err)
6161
return
6262
}
6363

routers/web/repo/issue_label_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func TestRetrieveLabels(t *testing.T) {
6262
contexttest.LoadUser(t, ctx, 2)
6363
contexttest.LoadRepo(t, ctx, testCase.RepoID)
6464
ctx.Req.Form.Set("sort", testCase.Sort)
65-
RetrieveLabels(ctx)
65+
RetrieveLabelsForList(ctx)
6666
assert.False(t, ctx.Written())
6767
labels, ok := ctx.Data["Labels"].([]*issues_model.Label)
6868
assert.True(t, ok)

routers/web/web.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1163,7 +1163,7 @@ func registerRoutes(m *web.Router) {
11631163
m.Get("/issues/posters", repo.IssuePosters) // it can't use {type:issues|pulls} because it would conflict with other routes like "/pulls/{index}"
11641164
m.Get("/pulls/posters", repo.PullPosters)
11651165
m.Get("/comments/{id}/attachments", repo.GetCommentAttachments)
1166-
m.Get("/labels", repo.RetrieveLabels, repo.Labels)
1166+
m.Get("/labels", repo.RetrieveLabelsForList, repo.Labels)
11671167
m.Get("/milestones", repo.Milestones)
11681168
m.Get("/milestone/{id}", context.RepoRef(), repo.MilestoneIssuesAndPulls)
11691169
m.Group("/{type:issues|pulls}", func() {

templates/repo/issue/labels/label.tmpl

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)