2019-12-12 05:23:05 +01:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2022-11-27 13:20:29 -05:00
// SPDX-License-Identifier: MIT
2019-12-12 05:23:05 +01:00
package repo
import (
2020-03-08 17:46:24 +00:00
"errors"
2019-12-20 18:07:12 +01:00
"net/http"
2022-06-13 17:37:59 +08:00
issues_model "code.gitea.io/gitea/models/issues"
2019-12-12 05:23:05 +01:00
"code.gitea.io/gitea/modules/context"
2020-01-24 19:00:29 +00:00
"code.gitea.io/gitea/routers/api/v1/utils"
2022-12-29 03:57:15 +01:00
"code.gitea.io/gitea/services/convert"
2019-12-12 05:23:05 +01:00
)
// StartIssueStopwatch creates a stopwatch for the given issue.
func StartIssueStopwatch ( ctx * context . APIContext ) {
// swagger:operation POST /repos/{owner}/{repo}/issues/{index}/stopwatch/start issue issueStartStopWatch
// ---
// summary: Start stopwatch on an issue.
// consumes:
// - application/json
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// - name: index
// in: path
// description: index of the issue to create the stopwatch on
// type: integer
// format: int64
// required: true
// responses:
// "201":
// "$ref": "#/responses/empty"
// "403":
// description: Not repo writer, user does not have rights to toggle stopwatch
// "404":
2019-12-20 18:07:12 +01:00
// "$ref": "#/responses/notFound"
2019-12-12 05:23:05 +01:00
// "409":
// description: Cannot start a stopwatch again if it already exists
2019-12-20 18:07:12 +01:00
2019-12-12 05:23:05 +01:00
issue , err := prepareIssueStopwatch ( ctx , false )
if err != nil {
return
}
2022-06-13 17:37:59 +08:00
if err := issues_model . CreateIssueStopwatch ( ctx , ctx . Doer , issue ) ; err != nil {
2019-12-20 18:07:12 +01:00
ctx . Error ( http . StatusInternalServerError , "CreateOrStopIssueStopwatch" , err )
2019-12-12 05:23:05 +01:00
return
}
2019-12-20 18:07:12 +01:00
ctx . Status ( http . StatusCreated )
2019-12-12 05:23:05 +01:00
}
// StopIssueStopwatch stops a stopwatch for the given issue.
func StopIssueStopwatch ( ctx * context . APIContext ) {
// swagger:operation POST /repos/{owner}/{repo}/issues/{index}/stopwatch/stop issue issueStopStopWatch
// ---
// summary: Stop an issue's existing stopwatch.
// consumes:
// - application/json
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// - name: index
// in: path
// description: index of the issue to stop the stopwatch on
// type: integer
// format: int64
// required: true
// responses:
// "201":
// "$ref": "#/responses/empty"
// "403":
// description: Not repo writer, user does not have rights to toggle stopwatch
// "404":
2019-12-20 18:07:12 +01:00
// "$ref": "#/responses/notFound"
2019-12-12 05:23:05 +01:00
// "409":
// description: Cannot stop a non existent stopwatch
2019-12-20 18:07:12 +01:00
2019-12-12 05:23:05 +01:00
issue , err := prepareIssueStopwatch ( ctx , true )
if err != nil {
return
}
2022-06-13 17:37:59 +08:00
if err := issues_model . FinishIssueStopwatch ( ctx , ctx . Doer , issue ) ; err != nil {
2019-12-20 18:07:12 +01:00
ctx . Error ( http . StatusInternalServerError , "CreateOrStopIssueStopwatch" , err )
2019-12-12 05:23:05 +01:00
return
}
2019-12-20 18:07:12 +01:00
ctx . Status ( http . StatusCreated )
2019-12-12 05:23:05 +01:00
}
// DeleteIssueStopwatch delete a specific stopwatch
func DeleteIssueStopwatch ( ctx * context . APIContext ) {
// swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/stopwatch/delete issue issueDeleteStopWatch
// ---
// summary: Delete an issue's existing stopwatch.
// consumes:
// - application/json
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// - name: index
// in: path
// description: index of the issue to stop the stopwatch on
// type: integer
// format: int64
// required: true
// responses:
// "204":
// "$ref": "#/responses/empty"
// "403":
// description: Not repo writer, user does not have rights to toggle stopwatch
// "404":
2019-12-20 18:07:12 +01:00
// "$ref": "#/responses/notFound"
2019-12-12 05:23:05 +01:00
// "409":
// description: Cannot cancel a non existent stopwatch
2019-12-20 18:07:12 +01:00
2019-12-12 05:23:05 +01:00
issue , err := prepareIssueStopwatch ( ctx , true )
if err != nil {
return
}
2023-09-16 16:39:12 +02:00
if err := issues_model . CancelStopwatch ( ctx , ctx . Doer , issue ) ; err != nil {
2019-12-20 18:07:12 +01:00
ctx . Error ( http . StatusInternalServerError , "CancelStopwatch" , err )
2019-12-12 05:23:05 +01:00
return
}
2019-12-20 18:07:12 +01:00
ctx . Status ( http . StatusNoContent )
2019-12-12 05:23:05 +01:00
}
2022-06-13 17:37:59 +08:00
func prepareIssueStopwatch ( ctx * context . APIContext , shouldExist bool ) ( * issues_model . Issue , error ) {
2023-07-22 22:14:27 +08:00
issue , err := issues_model . GetIssueByIndex ( ctx , ctx . Repo . Repository . ID , ctx . ParamsInt64 ( ":index" ) )
2019-12-12 05:23:05 +01:00
if err != nil {
2022-06-13 17:37:59 +08:00
if issues_model . IsErrIssueNotExist ( err ) {
2019-12-12 05:23:05 +01:00
ctx . NotFound ( )
} else {
2019-12-20 18:07:12 +01:00
ctx . Error ( http . StatusInternalServerError , "GetIssueByIndex" , err )
2019-12-12 05:23:05 +01:00
}
return nil , err
}
2020-01-20 20:00:32 +08:00
if ! ctx . Repo . CanWriteIssuesOrPulls ( issue . IsPull ) {
2019-12-20 18:07:12 +01:00
ctx . Status ( http . StatusForbidden )
2020-03-08 17:46:24 +00:00
return nil , errors . New ( "Unable to write to PRs" )
2019-12-12 05:23:05 +01:00
}
2023-10-14 10:37:24 +02:00
if ! ctx . Repo . CanUseTimetracker ( ctx , issue , ctx . Doer ) {
2019-12-20 18:07:12 +01:00
ctx . Status ( http . StatusForbidden )
2020-03-08 17:46:24 +00:00
return nil , errors . New ( "Cannot use time tracker" )
2019-12-12 05:23:05 +01:00
}
2023-09-16 16:39:12 +02:00
if issues_model . StopwatchExists ( ctx , ctx . Doer . ID , issue . ID ) != shouldExist {
2019-12-12 05:23:05 +01:00
if shouldExist {
2019-12-20 18:07:12 +01:00
ctx . Error ( http . StatusConflict , "StopwatchExists" , "cannot stop/cancel a non existent stopwatch" )
2020-03-08 17:46:24 +00:00
err = errors . New ( "cannot stop/cancel a non existent stopwatch" )
2019-12-12 05:23:05 +01:00
} else {
2019-12-20 18:07:12 +01:00
ctx . Error ( http . StatusConflict , "StopwatchExists" , "cannot start a stopwatch again if it already exists" )
2020-03-08 17:46:24 +00:00
err = errors . New ( "cannot start a stopwatch again if it already exists" )
2019-12-12 05:23:05 +01:00
}
return nil , err
}
return issue , nil
}
// GetStopwatches get all stopwatches
func GetStopwatches ( ctx * context . APIContext ) {
// swagger:operation GET /user/stopwatches user userGetStopWatches
// ---
// summary: Get list of all existing stopwatches
2020-01-24 19:00:29 +00:00
// parameters:
// - name: page
// in: query
// description: page number of results to return (1-based)
// type: integer
// - name: limit
// in: query
2020-06-09 06:57:38 +02:00
// description: page size of results
2020-01-24 19:00:29 +00:00
// type: integer
2019-12-12 05:23:05 +01:00
// consumes:
// - application/json
// produces:
// - application/json
// responses:
// "200":
// "$ref": "#/responses/StopWatchList"
2023-09-16 16:39:12 +02:00
sws , err := issues_model . GetUserStopwatches ( ctx , ctx . Doer . ID , utils . GetListOptions ( ctx ) )
2019-12-12 05:23:05 +01:00
if err != nil {
2019-12-20 18:07:12 +01:00
ctx . Error ( http . StatusInternalServerError , "GetUserStopwatches" , err )
2019-12-12 05:23:05 +01:00
return
}
2023-09-16 16:39:12 +02:00
count , err := issues_model . CountUserStopwatches ( ctx , ctx . Doer . ID )
2021-08-12 14:43:08 +02:00
if err != nil {
ctx . InternalServerError ( err )
return
}
2023-10-14 10:37:24 +02:00
apiSWs , err := convert . ToStopWatches ( ctx , sws )
2019-12-12 05:23:05 +01:00
if err != nil {
2019-12-20 18:07:12 +01:00
ctx . Error ( http . StatusInternalServerError , "APIFormat" , err )
2019-12-12 05:23:05 +01:00
return
}
2021-08-12 14:43:08 +02:00
ctx . SetTotalCountHeader ( count )
2019-12-20 18:07:12 +01:00
ctx . JSON ( http . StatusOK , apiSWs )
2019-12-12 05:23:05 +01:00
}