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

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