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_pin.go 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. // Copyright 2023 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package repo
  4. import (
  5. "net/http"
  6. issues_model "code.gitea.io/gitea/models/issues"
  7. "code.gitea.io/gitea/modules/context"
  8. api "code.gitea.io/gitea/modules/structs"
  9. "code.gitea.io/gitea/services/convert"
  10. )
  11. // PinIssue pins a issue
  12. func PinIssue(ctx *context.APIContext) {
  13. // swagger:operation POST /repos/{owner}/{repo}/issues/{index}/pin issue pinIssue
  14. // ---
  15. // summary: Pin an Issue
  16. // parameters:
  17. // - name: owner
  18. // in: path
  19. // description: owner of the repo
  20. // type: string
  21. // required: true
  22. // - name: repo
  23. // in: path
  24. // description: name of the repo
  25. // type: string
  26. // required: true
  27. // - name: index
  28. // in: path
  29. // description: index of issue to pin
  30. // type: integer
  31. // format: int64
  32. // required: true
  33. // responses:
  34. // "204":
  35. // "$ref": "#/responses/empty"
  36. // "403":
  37. // "$ref": "#/responses/forbidden"
  38. // "404":
  39. // "$ref": "#/responses/notFound"
  40. issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
  41. if err != nil {
  42. if issues_model.IsErrIssueNotExist(err) {
  43. ctx.NotFound()
  44. } else if issues_model.IsErrIssueMaxPinReached(err) {
  45. ctx.Error(http.StatusBadRequest, "MaxPinReached", err)
  46. } else {
  47. ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
  48. }
  49. return
  50. }
  51. // If we don't do this, it will crash when trying to add the pin event to the comment history
  52. err = issue.LoadRepo(ctx)
  53. if err != nil {
  54. ctx.Error(http.StatusInternalServerError, "LoadRepo", err)
  55. return
  56. }
  57. err = issue.Pin(ctx, ctx.Doer)
  58. if err != nil {
  59. ctx.Error(http.StatusInternalServerError, "PinIssue", err)
  60. return
  61. }
  62. ctx.Status(http.StatusNoContent)
  63. }
  64. // UnpinIssue unpins a Issue
  65. func UnpinIssue(ctx *context.APIContext) {
  66. // swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/pin issue unpinIssue
  67. // ---
  68. // summary: Unpin an Issue
  69. // parameters:
  70. // - name: owner
  71. // in: path
  72. // description: owner of the repo
  73. // type: string
  74. // required: true
  75. // - name: repo
  76. // in: path
  77. // description: name of the repo
  78. // type: string
  79. // required: true
  80. // - name: index
  81. // in: path
  82. // description: index of issue to unpin
  83. // type: integer
  84. // format: int64
  85. // required: true
  86. // responses:
  87. // "204":
  88. // "$ref": "#/responses/empty"
  89. // "403":
  90. // "$ref": "#/responses/forbidden"
  91. // "404":
  92. // "$ref": "#/responses/notFound"
  93. issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
  94. if err != nil {
  95. if issues_model.IsErrIssueNotExist(err) {
  96. ctx.NotFound()
  97. } else {
  98. ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
  99. }
  100. return
  101. }
  102. // If we don't do this, it will crash when trying to add the unpin event to the comment history
  103. err = issue.LoadRepo(ctx)
  104. if err != nil {
  105. ctx.Error(http.StatusInternalServerError, "LoadRepo", err)
  106. return
  107. }
  108. err = issue.Unpin(ctx, ctx.Doer)
  109. if err != nil {
  110. ctx.Error(http.StatusInternalServerError, "UnpinIssue", err)
  111. return
  112. }
  113. ctx.Status(http.StatusNoContent)
  114. }
  115. // MoveIssuePin moves a pinned Issue to a new Position
  116. func MoveIssuePin(ctx *context.APIContext) {
  117. // swagger:operation PATCH /repos/{owner}/{repo}/issues/{index}/pin/{position} issue moveIssuePin
  118. // ---
  119. // summary: Moves the Pin to the given Position
  120. // parameters:
  121. // - name: owner
  122. // in: path
  123. // description: owner of the repo
  124. // type: string
  125. // required: true
  126. // - name: repo
  127. // in: path
  128. // description: name of the repo
  129. // type: string
  130. // required: true
  131. // - name: index
  132. // in: path
  133. // description: index of issue
  134. // type: integer
  135. // format: int64
  136. // required: true
  137. // - name: position
  138. // in: path
  139. // description: the new position
  140. // type: integer
  141. // format: int64
  142. // required: true
  143. // responses:
  144. // "204":
  145. // "$ref": "#/responses/empty"
  146. // "403":
  147. // "$ref": "#/responses/forbidden"
  148. // "404":
  149. // "$ref": "#/responses/notFound"
  150. issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
  151. if err != nil {
  152. if issues_model.IsErrIssueNotExist(err) {
  153. ctx.NotFound()
  154. } else {
  155. ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
  156. }
  157. return
  158. }
  159. err = issue.MovePin(ctx, int(ctx.ParamsInt64(":position")))
  160. if err != nil {
  161. ctx.Error(http.StatusInternalServerError, "MovePin", err)
  162. return
  163. }
  164. ctx.Status(http.StatusNoContent)
  165. }
  166. // ListPinnedIssues returns a list of all pinned Issues
  167. func ListPinnedIssues(ctx *context.APIContext) {
  168. // swagger:operation GET /repos/{owner}/{repo}/issues/pinned repository repoListPinnedIssues
  169. // ---
  170. // summary: List a repo's pinned issues
  171. // produces:
  172. // - application/json
  173. // parameters:
  174. // - name: owner
  175. // in: path
  176. // description: owner of the repo
  177. // type: string
  178. // required: true
  179. // - name: repo
  180. // in: path
  181. // description: name of the repo
  182. // type: string
  183. // required: true
  184. // responses:
  185. // "200":
  186. // "$ref": "#/responses/IssueList"
  187. // "404":
  188. // "$ref": "#/responses/notFound"
  189. issues, err := issues_model.GetPinnedIssues(ctx, ctx.Repo.Repository.ID, false)
  190. if err != nil {
  191. ctx.Error(http.StatusInternalServerError, "LoadPinnedIssues", err)
  192. return
  193. }
  194. ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues))
  195. }
  196. // ListPinnedPullRequests returns a list of all pinned PRs
  197. func ListPinnedPullRequests(ctx *context.APIContext) {
  198. // swagger:operation GET /repos/{owner}/{repo}/pulls/pinned repository repoListPinnedPullRequests
  199. // ---
  200. // summary: List a repo's pinned pull requests
  201. // produces:
  202. // - application/json
  203. // parameters:
  204. // - name: owner
  205. // in: path
  206. // description: owner of the repo
  207. // type: string
  208. // required: true
  209. // - name: repo
  210. // in: path
  211. // description: name of the repo
  212. // type: string
  213. // required: true
  214. // responses:
  215. // "200":
  216. // "$ref": "#/responses/PullRequestList"
  217. // "404":
  218. // "$ref": "#/responses/notFound"
  219. issues, err := issues_model.GetPinnedIssues(ctx, ctx.Repo.Repository.ID, true)
  220. if err != nil {
  221. ctx.Error(http.StatusInternalServerError, "LoadPinnedPullRequests", err)
  222. return
  223. }
  224. apiPrs := make([]*api.PullRequest, len(issues))
  225. if err := issues.LoadPullRequests(ctx); err != nil {
  226. ctx.Error(http.StatusInternalServerError, "LoadPullRequests", err)
  227. return
  228. }
  229. for i, currentIssue := range issues {
  230. pr := currentIssue.PullRequest
  231. if err = pr.LoadAttributes(ctx); err != nil {
  232. ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
  233. return
  234. }
  235. if err = pr.LoadBaseRepo(ctx); err != nil {
  236. ctx.Error(http.StatusInternalServerError, "LoadBaseRepo", err)
  237. return
  238. }
  239. if err = pr.LoadHeadRepo(ctx); err != nil {
  240. ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err)
  241. return
  242. }
  243. apiPrs[i] = convert.ToAPIPullRequest(ctx, pr, ctx.Doer)
  244. }
  245. ctx.JSON(http.StatusOK, &apiPrs)
  246. }
  247. // AreNewIssuePinsAllowed returns if new issues pins are allowed
  248. func AreNewIssuePinsAllowed(ctx *context.APIContext) {
  249. // swagger:operation GET /repos/{owner}/{repo}/new_pin_allowed repository repoNewPinAllowed
  250. // ---
  251. // summary: Returns if new Issue Pins are allowed
  252. // produces:
  253. // - application/json
  254. // parameters:
  255. // - name: owner
  256. // in: path
  257. // description: owner of the repo
  258. // type: string
  259. // required: true
  260. // - name: repo
  261. // in: path
  262. // description: name of the repo
  263. // type: string
  264. // required: true
  265. // responses:
  266. // "200":
  267. // "$ref": "#/responses/RepoNewIssuePinsAllowed"
  268. // "404":
  269. // "$ref": "#/responses/notFound"
  270. pinsAllowed := api.NewIssuePinsAllowed{}
  271. var err error
  272. pinsAllowed.Issues, err = issues_model.IsNewPinAllowed(ctx, ctx.Repo.Repository.ID, false)
  273. if err != nil {
  274. ctx.Error(http.StatusInternalServerError, "IsNewIssuePinAllowed", err)
  275. return
  276. }
  277. pinsAllowed.PullRequests, err = issues_model.IsNewPinAllowed(ctx, ctx.Repo.Repository.ID, true)
  278. if err != nil {
  279. ctx.Error(http.StatusInternalServerError, "IsNewPullRequestPinAllowed", err)
  280. return
  281. }
  282. ctx.JSON(http.StatusOK, pinsAllowed)
  283. }