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 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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. issue_service "code.gitea.io/gitea/services/issue"
  12. )
  13. const (
  14. tplLabels base.TplName = "repo/issue/labels"
  15. )
  16. // Labels render issue's labels page
  17. func Labels(ctx *context.Context) {
  18. ctx.Data["Title"] = ctx.Tr("repo.labels")
  19. ctx.Data["PageIsIssueList"] = true
  20. ctx.Data["PageIsLabels"] = true
  21. ctx.Data["RequireMinicolors"] = true
  22. ctx.Data["RequireTribute"] = true
  23. ctx.Data["LabelTemplates"] = models.LabelTemplates
  24. ctx.HTML(200, tplLabels)
  25. }
  26. // InitializeLabels init labels for a repository
  27. func InitializeLabels(ctx *context.Context, form auth.InitializeLabelsForm) {
  28. if ctx.HasError() {
  29. ctx.Redirect(ctx.Repo.RepoLink + "/labels")
  30. return
  31. }
  32. if err := models.InitalizeLabels(ctx.Repo.Repository.ID, form.TemplateName); err != nil {
  33. if models.IsErrIssueLabelTemplateLoad(err) {
  34. originalErr := err.(models.ErrIssueLabelTemplateLoad).OriginalError
  35. ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, originalErr))
  36. ctx.Redirect(ctx.Repo.RepoLink + "/labels")
  37. return
  38. }
  39. ctx.ServerError("InitalizeLabels", err)
  40. return
  41. }
  42. ctx.Redirect(ctx.Repo.RepoLink + "/labels")
  43. }
  44. // RetrieveLabels find all the labels of a repository
  45. func RetrieveLabels(ctx *context.Context) {
  46. labels, err := models.GetLabelsByRepoID(ctx.Repo.Repository.ID, ctx.Query("sort"))
  47. if err != nil {
  48. ctx.ServerError("RetrieveLabels.GetLabels", err)
  49. return
  50. }
  51. for _, l := range labels {
  52. l.CalOpenIssues()
  53. }
  54. ctx.Data["Labels"] = labels
  55. ctx.Data["NumLabels"] = len(labels)
  56. ctx.Data["SortType"] = ctx.Query("sort")
  57. }
  58. // NewLabel create new label for repository
  59. func NewLabel(ctx *context.Context, form auth.CreateLabelForm) {
  60. ctx.Data["Title"] = ctx.Tr("repo.labels")
  61. ctx.Data["PageIsLabels"] = true
  62. if ctx.HasError() {
  63. ctx.Flash.Error(ctx.Data["ErrorMsg"].(string))
  64. ctx.Redirect(ctx.Repo.RepoLink + "/labels")
  65. return
  66. }
  67. l := &models.Label{
  68. RepoID: ctx.Repo.Repository.ID,
  69. Name: form.Title,
  70. Description: form.Description,
  71. Color: form.Color,
  72. }
  73. if err := models.NewLabel(l); err != nil {
  74. ctx.ServerError("NewLabel", err)
  75. return
  76. }
  77. ctx.Redirect(ctx.Repo.RepoLink + "/labels")
  78. }
  79. // UpdateLabel update a label's name and color
  80. func UpdateLabel(ctx *context.Context, form auth.CreateLabelForm) {
  81. l, err := models.GetLabelByID(form.ID)
  82. if err != nil {
  83. switch {
  84. case models.IsErrLabelNotExist(err):
  85. ctx.Error(404)
  86. default:
  87. ctx.ServerError("UpdateLabel", err)
  88. }
  89. return
  90. }
  91. l.Name = form.Title
  92. l.Description = form.Description
  93. l.Color = form.Color
  94. if err := models.UpdateLabel(l); err != nil {
  95. ctx.ServerError("UpdateLabel", err)
  96. return
  97. }
  98. ctx.Redirect(ctx.Repo.RepoLink + "/labels")
  99. }
  100. // DeleteLabel delete a label
  101. func DeleteLabel(ctx *context.Context) {
  102. if err := models.DeleteLabel(ctx.Repo.Repository.ID, ctx.QueryInt64("id")); err != nil {
  103. ctx.Flash.Error("DeleteLabel: " + err.Error())
  104. } else {
  105. ctx.Flash.Success(ctx.Tr("repo.issues.label_deletion_success"))
  106. }
  107. ctx.JSON(200, map[string]interface{}{
  108. "redirect": ctx.Repo.RepoLink + "/labels",
  109. })
  110. }
  111. // UpdateIssueLabel change issue's labels
  112. func UpdateIssueLabel(ctx *context.Context) {
  113. issues := getActionIssues(ctx)
  114. if ctx.Written() {
  115. return
  116. }
  117. switch action := ctx.Query("action"); action {
  118. case "clear":
  119. for _, issue := range issues {
  120. if err := issue_service.ClearLabels(issue, ctx.User); err != nil {
  121. ctx.ServerError("ClearLabels", err)
  122. return
  123. }
  124. }
  125. case "attach", "detach", "toggle":
  126. label, err := models.GetLabelByID(ctx.QueryInt64("id"))
  127. if err != nil {
  128. if models.IsErrLabelNotExist(err) {
  129. ctx.Error(404, "GetLabelByID")
  130. } else {
  131. ctx.ServerError("GetLabelByID", err)
  132. }
  133. return
  134. }
  135. if action == "toggle" {
  136. // detach if any issues already have label, otherwise attach
  137. action = "attach"
  138. for _, issue := range issues {
  139. if issue.HasLabel(label.ID) {
  140. action = "detach"
  141. break
  142. }
  143. }
  144. }
  145. if action == "attach" {
  146. for _, issue := range issues {
  147. if err = issue_service.AddLabel(issue, ctx.User, label); err != nil {
  148. ctx.ServerError("AddLabel", err)
  149. return
  150. }
  151. }
  152. } else {
  153. for _, issue := range issues {
  154. if err = issue_service.RemoveLabel(issue, ctx.User, label); err != nil {
  155. ctx.ServerError("RemoveLabel", err)
  156. return
  157. }
  158. }
  159. }
  160. default:
  161. log.Warn("Unrecognized action: %s", action)
  162. ctx.Error(500)
  163. return
  164. }
  165. ctx.JSON(200, map[string]interface{}{
  166. "ok": true,
  167. })
  168. }