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.

200 lines
4.7 KiB

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