You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

issue_stopwatch.go 5.8 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // Copyright 2019 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/context"
  9. )
  10. // StartIssueStopwatch creates a stopwatch for the given issue.
  11. func StartIssueStopwatch(ctx *context.APIContext) {
  12. // swagger:operation POST /repos/{owner}/{repo}/issues/{index}/stopwatch/start issue issueStartStopWatch
  13. // ---
  14. // summary: Start stopwatch on an issue.
  15. // consumes:
  16. // - application/json
  17. // produces:
  18. // - application/json
  19. // parameters:
  20. // - name: owner
  21. // in: path
  22. // description: owner of the repo
  23. // type: string
  24. // required: true
  25. // - name: repo
  26. // in: path
  27. // description: name of the repo
  28. // type: string
  29. // required: true
  30. // - name: index
  31. // in: path
  32. // description: index of the issue to create the stopwatch on
  33. // type: integer
  34. // format: int64
  35. // required: true
  36. // responses:
  37. // "201":
  38. // "$ref": "#/responses/empty"
  39. // "403":
  40. // description: Not repo writer, user does not have rights to toggle stopwatch
  41. // "404":
  42. // "$ref": "#/responses/notFound"
  43. // "409":
  44. // description: Cannot start a stopwatch again if it already exists
  45. issue, err := prepareIssueStopwatch(ctx, false)
  46. if err != nil {
  47. return
  48. }
  49. if err := models.CreateOrStopIssueStopwatch(ctx.User, issue); err != nil {
  50. ctx.Error(http.StatusInternalServerError, "CreateOrStopIssueStopwatch", err)
  51. return
  52. }
  53. ctx.Status(http.StatusCreated)
  54. }
  55. // StopIssueStopwatch stops a stopwatch for the given issue.
  56. func StopIssueStopwatch(ctx *context.APIContext) {
  57. // swagger:operation POST /repos/{owner}/{repo}/issues/{index}/stopwatch/stop issue issueStopStopWatch
  58. // ---
  59. // summary: Stop an issue's existing stopwatch.
  60. // consumes:
  61. // - application/json
  62. // produces:
  63. // - application/json
  64. // parameters:
  65. // - name: owner
  66. // in: path
  67. // description: owner of the repo
  68. // type: string
  69. // required: true
  70. // - name: repo
  71. // in: path
  72. // description: name of the repo
  73. // type: string
  74. // required: true
  75. // - name: index
  76. // in: path
  77. // description: index of the issue to stop the stopwatch on
  78. // type: integer
  79. // format: int64
  80. // required: true
  81. // responses:
  82. // "201":
  83. // "$ref": "#/responses/empty"
  84. // "403":
  85. // description: Not repo writer, user does not have rights to toggle stopwatch
  86. // "404":
  87. // "$ref": "#/responses/notFound"
  88. // "409":
  89. // description: Cannot stop a non existent stopwatch
  90. issue, err := prepareIssueStopwatch(ctx, true)
  91. if err != nil {
  92. return
  93. }
  94. if err := models.CreateOrStopIssueStopwatch(ctx.User, issue); err != nil {
  95. ctx.Error(http.StatusInternalServerError, "CreateOrStopIssueStopwatch", err)
  96. return
  97. }
  98. ctx.Status(http.StatusCreated)
  99. }
  100. // DeleteIssueStopwatch delete a specific stopwatch
  101. func DeleteIssueStopwatch(ctx *context.APIContext) {
  102. // swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/stopwatch/delete issue issueDeleteStopWatch
  103. // ---
  104. // summary: Delete an issue's existing stopwatch.
  105. // consumes:
  106. // - application/json
  107. // produces:
  108. // - application/json
  109. // parameters:
  110. // - name: owner
  111. // in: path
  112. // description: owner of the repo
  113. // type: string
  114. // required: true
  115. // - name: repo
  116. // in: path
  117. // description: name of the repo
  118. // type: string
  119. // required: true
  120. // - name: index
  121. // in: path
  122. // description: index of the issue to stop the stopwatch on
  123. // type: integer
  124. // format: int64
  125. // required: true
  126. // responses:
  127. // "204":
  128. // "$ref": "#/responses/empty"
  129. // "403":
  130. // description: Not repo writer, user does not have rights to toggle stopwatch
  131. // "404":
  132. // "$ref": "#/responses/notFound"
  133. // "409":
  134. // description: Cannot cancel a non existent stopwatch
  135. issue, err := prepareIssueStopwatch(ctx, true)
  136. if err != nil {
  137. return
  138. }
  139. if err := models.CancelStopwatch(ctx.User, issue); err != nil {
  140. ctx.Error(http.StatusInternalServerError, "CancelStopwatch", err)
  141. return
  142. }
  143. ctx.Status(http.StatusNoContent)
  144. }
  145. func prepareIssueStopwatch(ctx *context.APIContext, shouldExist bool) (*models.Issue, error) {
  146. issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
  147. if err != nil {
  148. if models.IsErrIssueNotExist(err) {
  149. ctx.NotFound()
  150. } else {
  151. ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
  152. }
  153. return nil, err
  154. }
  155. if !ctx.Repo.CanWrite(models.UnitTypeIssues) {
  156. ctx.Status(http.StatusForbidden)
  157. return nil, err
  158. }
  159. if !ctx.Repo.CanUseTimetracker(issue, ctx.User) {
  160. ctx.Status(http.StatusForbidden)
  161. return nil, err
  162. }
  163. if models.StopwatchExists(ctx.User.ID, issue.ID) != shouldExist {
  164. if shouldExist {
  165. ctx.Error(http.StatusConflict, "StopwatchExists", "cannot stop/cancel a non existent stopwatch")
  166. } else {
  167. ctx.Error(http.StatusConflict, "StopwatchExists", "cannot start a stopwatch again if it already exists")
  168. }
  169. return nil, err
  170. }
  171. return issue, nil
  172. }
  173. // GetStopwatches get all stopwatches
  174. func GetStopwatches(ctx *context.APIContext) {
  175. // swagger:operation GET /user/stopwatches user userGetStopWatches
  176. // ---
  177. // summary: Get list of all existing stopwatches
  178. // consumes:
  179. // - application/json
  180. // produces:
  181. // - application/json
  182. // responses:
  183. // "200":
  184. // "$ref": "#/responses/StopWatchList"
  185. sws, err := models.GetUserStopwatches(ctx.User.ID)
  186. if err != nil {
  187. ctx.Error(http.StatusInternalServerError, "GetUserStopwatches", err)
  188. return
  189. }
  190. apiSWs, err := sws.APIFormat()
  191. if err != nil {
  192. ctx.Error(http.StatusInternalServerError, "APIFormat", err)
  193. return
  194. }
  195. ctx.JSON(http.StatusOK, apiSWs)
  196. }