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.6KB

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