code.gitea.io/gitea@v1.22.3/routers/web/repo/issue_label.go (about) 1 // Copyright 2017 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package repo 5 6 import ( 7 "net/http" 8 9 "code.gitea.io/gitea/models/db" 10 issues_model "code.gitea.io/gitea/models/issues" 11 "code.gitea.io/gitea/models/organization" 12 "code.gitea.io/gitea/modules/base" 13 "code.gitea.io/gitea/modules/label" 14 "code.gitea.io/gitea/modules/log" 15 repo_module "code.gitea.io/gitea/modules/repository" 16 "code.gitea.io/gitea/modules/web" 17 "code.gitea.io/gitea/services/context" 18 "code.gitea.io/gitea/services/forms" 19 issue_service "code.gitea.io/gitea/services/issue" 20 ) 21 22 const ( 23 tplLabels base.TplName = "repo/issue/labels" 24 ) 25 26 // Labels render issue's labels page 27 func Labels(ctx *context.Context) { 28 ctx.Data["Title"] = ctx.Tr("repo.labels") 29 ctx.Data["PageIsIssueList"] = true 30 ctx.Data["PageIsLabels"] = true 31 ctx.Data["LabelTemplateFiles"] = repo_module.LabelTemplateFiles 32 ctx.HTML(http.StatusOK, tplLabels) 33 } 34 35 // InitializeLabels init labels for a repository 36 func InitializeLabels(ctx *context.Context) { 37 form := web.GetForm(ctx).(*forms.InitializeLabelsForm) 38 if ctx.HasError() { 39 ctx.Redirect(ctx.Repo.RepoLink + "/labels") 40 return 41 } 42 43 if err := repo_module.InitializeLabels(ctx, ctx.Repo.Repository.ID, form.TemplateName, false); err != nil { 44 if label.IsErrTemplateLoad(err) { 45 originalErr := err.(label.ErrTemplateLoad).OriginalError 46 ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, originalErr)) 47 ctx.Redirect(ctx.Repo.RepoLink + "/labels") 48 return 49 } 50 ctx.ServerError("InitializeLabels", err) 51 return 52 } 53 ctx.Redirect(ctx.Repo.RepoLink + "/labels") 54 } 55 56 // RetrieveLabels find all the labels of a repository and organization 57 func RetrieveLabels(ctx *context.Context) { 58 labels, err := issues_model.GetLabelsByRepoID(ctx, ctx.Repo.Repository.ID, ctx.FormString("sort"), db.ListOptions{}) 59 if err != nil { 60 ctx.ServerError("RetrieveLabels.GetLabels", err) 61 return 62 } 63 64 for _, l := range labels { 65 l.CalOpenIssues() 66 } 67 68 ctx.Data["Labels"] = labels 69 70 if ctx.Repo.Owner.IsOrganization() { 71 orgLabels, err := issues_model.GetLabelsByOrgID(ctx, ctx.Repo.Owner.ID, ctx.FormString("sort"), db.ListOptions{}) 72 if err != nil { 73 ctx.ServerError("GetLabelsByOrgID", err) 74 return 75 } 76 for _, l := range orgLabels { 77 l.CalOpenOrgIssues(ctx, ctx.Repo.Repository.ID, l.ID) 78 } 79 ctx.Data["OrgLabels"] = orgLabels 80 81 org, err := organization.GetOrgByName(ctx, ctx.Repo.Owner.LowerName) 82 if err != nil { 83 ctx.ServerError("GetOrgByName", err) 84 return 85 } 86 if ctx.Doer != nil { 87 ctx.Org.IsOwner, err = org.IsOwnedBy(ctx, ctx.Doer.ID) 88 if err != nil { 89 ctx.ServerError("org.IsOwnedBy", err) 90 return 91 } 92 ctx.Org.OrgLink = org.AsUser().OrganisationLink() 93 ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner 94 ctx.Data["OrganizationLink"] = ctx.Org.OrgLink 95 } 96 } 97 ctx.Data["NumLabels"] = len(labels) 98 ctx.Data["SortType"] = ctx.FormString("sort") 99 } 100 101 // NewLabel create new label for repository 102 func NewLabel(ctx *context.Context) { 103 form := web.GetForm(ctx).(*forms.CreateLabelForm) 104 ctx.Data["Title"] = ctx.Tr("repo.labels") 105 ctx.Data["PageIsLabels"] = true 106 107 if ctx.HasError() { 108 ctx.Flash.Error(ctx.Data["ErrorMsg"].(string)) 109 ctx.Redirect(ctx.Repo.RepoLink + "/labels") 110 return 111 } 112 113 l := &issues_model.Label{ 114 RepoID: ctx.Repo.Repository.ID, 115 Name: form.Title, 116 Exclusive: form.Exclusive, 117 Description: form.Description, 118 Color: form.Color, 119 } 120 if err := issues_model.NewLabel(ctx, l); err != nil { 121 ctx.ServerError("NewLabel", err) 122 return 123 } 124 ctx.Redirect(ctx.Repo.RepoLink + "/labels") 125 } 126 127 // UpdateLabel update a label's name and color 128 func UpdateLabel(ctx *context.Context) { 129 form := web.GetForm(ctx).(*forms.CreateLabelForm) 130 l, err := issues_model.GetLabelInRepoByID(ctx, ctx.Repo.Repository.ID, form.ID) 131 if err != nil { 132 switch { 133 case issues_model.IsErrRepoLabelNotExist(err): 134 ctx.Error(http.StatusNotFound) 135 default: 136 ctx.ServerError("UpdateLabel", err) 137 } 138 return 139 } 140 l.Name = form.Title 141 l.Exclusive = form.Exclusive 142 l.Description = form.Description 143 l.Color = form.Color 144 145 l.SetArchived(form.IsArchived) 146 if err := issues_model.UpdateLabel(ctx, l); err != nil { 147 ctx.ServerError("UpdateLabel", err) 148 return 149 } 150 ctx.Redirect(ctx.Repo.RepoLink + "/labels") 151 } 152 153 // DeleteLabel delete a label 154 func DeleteLabel(ctx *context.Context) { 155 if err := issues_model.DeleteLabel(ctx, ctx.Repo.Repository.ID, ctx.FormInt64("id")); err != nil { 156 ctx.Flash.Error("DeleteLabel: " + err.Error()) 157 } else { 158 ctx.Flash.Success(ctx.Tr("repo.issues.label_deletion_success")) 159 } 160 161 ctx.JSONRedirect(ctx.Repo.RepoLink + "/labels") 162 } 163 164 // UpdateIssueLabel change issue's labels 165 func UpdateIssueLabel(ctx *context.Context) { 166 issues := getActionIssues(ctx) 167 if ctx.Written() { 168 return 169 } 170 171 switch action := ctx.FormString("action"); action { 172 case "clear": 173 for _, issue := range issues { 174 if err := issue_service.ClearLabels(ctx, issue, ctx.Doer); err != nil { 175 ctx.ServerError("ClearLabels", err) 176 return 177 } 178 } 179 case "attach", "detach", "toggle", "toggle-alt": 180 label, err := issues_model.GetLabelByID(ctx, ctx.FormInt64("id")) 181 if err != nil { 182 if issues_model.IsErrRepoLabelNotExist(err) { 183 ctx.Error(http.StatusNotFound, "GetLabelByID") 184 } else { 185 ctx.ServerError("GetLabelByID", err) 186 } 187 return 188 } 189 190 if action == "toggle" { 191 // detach if any issues already have label, otherwise attach 192 action = "attach" 193 if label.ExclusiveScope() == "" { 194 for _, issue := range issues { 195 if issues_model.HasIssueLabel(ctx, issue.ID, label.ID) { 196 action = "detach" 197 break 198 } 199 } 200 } 201 } else if action == "toggle-alt" { 202 // always detach with alt key pressed, to be able to remove 203 // scoped labels 204 action = "detach" 205 } 206 207 if action == "attach" { 208 for _, issue := range issues { 209 if err = issue_service.AddLabel(ctx, issue, ctx.Doer, label); err != nil { 210 ctx.ServerError("AddLabel", err) 211 return 212 } 213 } 214 } else { 215 for _, issue := range issues { 216 if err = issue_service.RemoveLabel(ctx, issue, ctx.Doer, label); err != nil { 217 ctx.ServerError("RemoveLabel", err) 218 return 219 } 220 } 221 } 222 default: 223 log.Warn("Unrecognized action: %s", action) 224 ctx.Error(http.StatusInternalServerError) 225 return 226 } 227 228 ctx.JSONOK() 229 }