You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

issue_label.go 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package repo
  5. import (
  6. "code.gitea.io/gitea/models"
  7. "code.gitea.io/gitea/modules/auth"
  8. "code.gitea.io/gitea/modules/base"
  9. "code.gitea.io/gitea/modules/context"
  10. "code.gitea.io/gitea/modules/log"
  11. "code.gitea.io/gitea/modules/setting"
  12. issue_service "code.gitea.io/gitea/services/issue"
  13. )
  14. const (
  15. tplLabels base.TplName = "repo/issue/labels"
  16. )
  17. // Labels render issue's labels page
  18. func Labels(ctx *context.Context) {
  19. ctx.Data["Title"] = ctx.Tr("repo.labels")
  20. ctx.Data["PageIsIssueList"] = true
  21. ctx.Data["PageIsLabels"] = true
  22. ctx.Data["RequireMinicolors"] = true
  23. ctx.Data["RequireTribute"] = true
  24. ctx.Data["LabelTemplates"] = models.LabelTemplates
  25. ctx.HTML(200, tplLabels)
  26. }
  27. // InitializeLabels init labels for a repository
  28. func InitializeLabels(ctx *context.Context, form auth.InitializeLabelsForm) {
  29. if ctx.HasError() {
  30. ctx.Redirect(ctx.Repo.RepoLink + "/labels")
  31. return
  32. }
  33. if err := models.InitializeLabels(models.DefaultDBContext(), ctx.Repo.Repository.ID, form.TemplateName, false); err != nil {
  34. if models.IsErrIssueLabelTemplateLoad(err) {
  35. originalErr := err.(models.ErrIssueLabelTemplateLoad).OriginalError
  36. ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, originalErr))
  37. ctx.Redirect(ctx.Repo.RepoLink + "/labels")
  38. return
  39. }
  40. ctx.ServerError("InitializeLabels", err)
  41. return
  42. }
  43. ctx.Redirect(ctx.Repo.RepoLink + "/labels")
  44. }
  45. // RetrieveLabels find all the labels of a repository and organization
  46. func RetrieveLabels(ctx *context.Context) {
  47. labels, err := models.GetLabelsByRepoID(ctx.Repo.Repository.ID, ctx.Query("sort"), models.ListOptions{})
  48. if err != nil {
  49. ctx.ServerError("RetrieveLabels.GetLabels", err)
  50. return
  51. }
  52. for _, l := range labels {
  53. l.CalOpenIssues()
  54. }
  55. ctx.Data["Labels"] = labels
  56. if ctx.Repo.Owner.IsOrganization() {
  57. orgLabels, err := models.GetLabelsByOrgID(ctx.Repo.Owner.ID, ctx.Query("sort"), models.ListOptions{})
  58. if err != nil {
  59. ctx.ServerError("GetLabelsByOrgID", err)
  60. return
  61. }
  62. for _, l := range orgLabels {
  63. l.CalOpenOrgIssues(ctx.Repo.Repository.ID, l.ID)
  64. }
  65. ctx.Data["OrgLabels"] = orgLabels
  66. org, err := models.GetOrgByName(ctx.Repo.Owner.LowerName)
  67. if err != nil {
  68. ctx.ServerError("GetOrgByName", err)
  69. return
  70. }
  71. if ctx.User != nil {
  72. ctx.Org.IsOwner, err = org.IsOwnedBy(ctx.User.ID)
  73. if err != nil {
  74. ctx.ServerError("org.IsOwnedBy", err)
  75. return
  76. }
  77. ctx.Org.OrgLink = setting.AppSubURL + "/org/" + org.LowerName
  78. ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner
  79. ctx.Data["OrganizationLink"] = ctx.Org.OrgLink
  80. }
  81. }
  82. ctx.Data["NumLabels"] = len(labels)
  83. ctx.Data["SortType"] = ctx.Query("sort")
  84. }
  85. // NewLabel create new label for repository
  86. func NewLabel(ctx *context.Context, form auth.CreateLabelForm) {
  87. ctx.Data["Title"] = ctx.Tr("repo.labels")
  88. ctx.Data["PageIsLabels"] = true
  89. if ctx.HasError() {
  90. ctx.Flash.Error(ctx.Data["ErrorMsg"].(string))
  91. ctx.Redirect(ctx.Repo.RepoLink + "/labels")
  92. return
  93. }
  94. l := &models.Label{
  95. RepoID: ctx.Repo.Repository.ID,
  96. Name: form.Title,
  97. Description: form.Description,
  98. Color: form.Color,
  99. }
  100. if err := models.NewLabel(l); err != nil {
  101. ctx.ServerError("NewLabel", err)
  102. return
  103. }
  104. ctx.Redirect(ctx.Repo.RepoLink + "/labels")
  105. }
  106. // UpdateLabel update a label's name and color
  107. func UpdateLabel(ctx *context.Context, form auth.CreateLabelForm) {
  108. l, err := models.GetLabelInRepoByID(ctx.Repo.Repository.ID, form.ID)
  109. if err != nil {
  110. switch {
  111. case models.IsErrRepoLabelNotExist(err):
  112. ctx.Error(404)
  113. default:
  114. ctx.ServerError("UpdateLabel", err)
  115. }
  116. return
  117. }
  118. l.Name = form.Title
  119. l.Description = form.Description
  120. l.Color = form.Color
  121. if err := models.UpdateLabel(l); err != nil {
  122. ctx.ServerError("UpdateLabel", err)
  123. return
  124. }
  125. ctx.Redirect(ctx.Repo.RepoLink + "/labels")
  126. }
  127. // DeleteLabel delete a label
  128. func DeleteLabel(ctx *context.Context) {
  129. if err := models.DeleteLabel(ctx.Repo.Repository.ID, ctx.QueryInt64("id")); err != nil {
  130. ctx.Flash.Error("DeleteLabel: " + err.Error())
  131. } else {
  132. ctx.Flash.Success(ctx.Tr("repo.issues.label_deletion_success"))
  133. }
  134. ctx.JSON(200, map[string]interface{}{
  135. "redirect": ctx.Repo.RepoLink + "/labels",
  136. })
  137. }
  138. // UpdateIssueLabel change issue's labels
  139. func UpdateIssueLabel(ctx *context.Context) {
  140. issues := getActionIssues(ctx)
  141. if ctx.Written() {
  142. return
  143. }
  144. switch action := ctx.Query("action"); action {
  145. case "clear":
  146. for _, issue := range issues {
  147. if err := issue_service.ClearLabels(issue, ctx.User); err != nil {
  148. ctx.ServerError("ClearLabels", err)
  149. return
  150. }
  151. }
  152. case "attach", "detach", "toggle":
  153. label, err := models.GetLabelByID(ctx.QueryInt64("id"))
  154. if err != nil {
  155. if models.IsErrRepoLabelNotExist(err) {
  156. ctx.Error(404, "GetLabelByID")
  157. } else {
  158. ctx.ServerError("GetLabelByID", err)
  159. }
  160. return
  161. }
  162. if action == "toggle" {
  163. // detach if any issues already have label, otherwise attach
  164. action = "attach"
  165. for _, issue := range issues {
  166. if issue.HasLabel(label.ID) {
  167. action = "detach"
  168. break
  169. }
  170. }
  171. }
  172. if action == "attach" {
  173. for _, issue := range issues {
  174. if err = issue_service.AddLabel(issue, ctx.User, label); err != nil {
  175. ctx.ServerError("AddLabel", err)
  176. return
  177. }
  178. }
  179. } else {
  180. for _, issue := range issues {
  181. if err = issue_service.RemoveLabel(issue, ctx.User, label); err != nil {
  182. ctx.ServerError("RemoveLabel", err)
  183. return
  184. }
  185. }
  186. }
  187. default:
  188. log.Warn("Unrecognized action: %s", action)
  189. ctx.Error(500)
  190. return
  191. }
  192. ctx.JSON(200, map[string]interface{}{
  193. "ok": true,
  194. })
  195. }