diff --git a/pkg/models/label_task.go b/pkg/models/label_task.go index 00dc8fc9e..1a23fc8d6 100644 --- a/pkg/models/label_task.go +++ b/pkg/models/label_task.go @@ -330,9 +330,18 @@ type LabelTaskBulk struct { // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{taskID}/labels/bulk [post] func (ltb *LabelTaskBulk) Create(a web.Auth) (err error) { - task, err := GetTaskByID(ltb.TaskID) + task, err := GetTaskByIDSimple(ltb.TaskID) if err != nil { return } + labels, _, _, err := getLabelsByTaskIDs(&LabelByTaskIDsOptions{ + TaskIDs: []int64{ltb.TaskID}, + }) + if err != nil { + return err + } + for _, l := range labels { + task.Labels = append(task.Labels, &l.Label) + } return task.updateTaskLabels(a, ltb.Labels) } diff --git a/pkg/models/task_assignees.go b/pkg/models/task_assignees.go index e7de9af1e..1b0f28bec 100644 --- a/pkg/models/task_assignees.go +++ b/pkg/models/task_assignees.go @@ -284,9 +284,17 @@ type BulkAssignees struct { // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{taskID}/assignees/bulk [post] func (ba *BulkAssignees) Create(a web.Auth) (err error) { - task, err := GetTaskByID(ba.TaskID) // We need to use the full method here because we need all current assignees. + task, err := GetTaskByIDSimple(ba.TaskID) if err != nil { return } + assignees, err := getRawTaskAssigneesForTasks([]int64{task.ID}) + if err != nil { + return err + } + for _, a := range assignees { + task.Assignees = append(task.Assignees, &a.User) + } + return task.updateTaskAssignees(ba.Assignees) } diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index fb47cf5e0..137df073c 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -339,44 +339,6 @@ func GetTaskSimple(t *Task) (task Task, err error) { return } -// GetTaskByID returns all tasks a list has -func GetTaskByID(listTaskID int64) (listTask Task, err error) { - listTask, err = GetTaskByIDSimple(listTaskID) - if err != nil { - return - } - - u, err := GetUserByID(listTask.CreatedByID) - if err != nil { - return - } - listTask.CreatedBy = u - - // Get assignees - taskAssignees, err := getRawTaskAssigneesForTasks([]int64{listTaskID}) - if err != nil { - return - } - for _, u := range taskAssignees { - if u != nil { - listTask.Assignees = append(listTask.Assignees, &u.User) - } - } - - // Get task labels - taskLabels, _, _, err := getLabelsByTaskIDs(&LabelByTaskIDsOptions{ - TaskIDs: []int64{listTaskID}, - }) - if err != nil { - return - } - for _, label := range taskLabels { - listTask.Labels = append(listTask.Labels, &label.Label) - } - - return -} - // GetTasksByIDs returns all tasks for a list of ids func (bt *BulkTask) GetTasksByIDs() (err error) { for _, id := range bt.IDs { @@ -636,7 +598,7 @@ func (t *Task) Create(a web.Auth) (err error) { // @Router /tasks/{id} [post] func (t *Task) Update() (err error) { // Check if the task exists - ot, err := GetTaskByID(t.ID) + ot, err := GetTaskByIDSimple(t.ID) if err != nil { return } @@ -854,12 +816,6 @@ func (t *Task) updateReminders(reminders []int64) (err error) { // @Router /tasks/{id} [delete] func (t *Task) Delete() (err error) { - // Check if it exists - _, err = GetTaskByID(t.ID) - if err != nil { - return - } - if _, err = x.ID(t.ID).Delete(Task{}); err != nil { return err } @@ -874,3 +830,38 @@ func (t *Task) Delete() (err error) { err = updateListLastUpdated(&List{ID: t.ListID}) return } + +// ReadOne gets one task by its ID +// @Summary Get one task +// @Description Returns one task by its ID +// @tags task +// @Accept json +// @Produce json +// @Param ID path int true "The task ID" +// @Security JWTKeyAuth +// @Success 200 {object} models.Task "The task" +// @Failure 404 {object} models.Message "Task not found" +// @Failure 500 {object} models.Message "Internal error" +// @Router /tasks/all [get] +func (t *Task) ReadOne() (err error) { + + taskMap := make(map[int64]*Task, 1) + taskMap[t.ID] = &Task{} + *taskMap[t.ID], err = GetTaskByIDSimple(t.ID) + if err != nil { + return + } + + tasks, err := addMoreInfoToTasks(taskMap) + if err != nil { + return + } + + if len(tasks) == 0 { + return ErrTaskDoesNotExist{t.ID} + } + + *t = *tasks[0] + + return +} diff --git a/pkg/models/tasks_test.go b/pkg/models/tasks_test.go index 2baed4e0c..ffc06d682 100644 --- a/pkg/models/tasks_test.go +++ b/pkg/models/tasks_test.go @@ -24,6 +24,8 @@ import ( func TestTask_Create(t *testing.T) { //assert.NoError(t, LoadFixtures()) + // TODO: This test needs refactoring + // Fake list task listtask := Task{ Text: "Lorem", @@ -48,11 +50,6 @@ func TestTask_Create(t *testing.T) { err = listtask.Update() assert.NoError(t, err) - // Check if it was updated - li, err := GetTaskByID(listtask.ID) - assert.NoError(t, err) - assert.Equal(t, li.Text, "Test34") - // Delete the task allowed, _ = listtask.CanDelete(doer) assert.True(t, allowed) @@ -61,7 +58,7 @@ func TestTask_Create(t *testing.T) { // Delete a nonexistant task listtask.ID = 0 - err = listtask.Delete() + _, err = listtask.CanDelete(doer) // The check if the task exists happens in CanDelete assert.Error(t, err) assert.True(t, IsErrTaskDoesNotExist(err)) @@ -106,3 +103,18 @@ func TestUpdateDone(t *testing.T) { assert.Equal(t, int64(0), oldTask.DoneAtUnix) }) } + +func TestTask_ReadOne(t *testing.T) { + t.Run("default", func(t *testing.T) { + task := &Task{ID: 1} + err := task.ReadOne() + assert.NoError(t, err) + assert.Equal(t, "task #1", task.Text) + }) + t.Run("nonexisting", func(t *testing.T) { + task := &Task{ID: 99999} + err := task.ReadOne() + assert.Error(t, err) + assert.True(t, IsErrTaskDoesNotExist(err)) + }) +} diff --git a/pkg/routes/routes.go b/pkg/routes/routes.go index d7bf3e89e..a01970a58 100644 --- a/pkg/routes/routes.go +++ b/pkg/routes/routes.go @@ -221,6 +221,7 @@ func registerAPIRoutes(a *echo.Group) { }, } a.PUT("/lists/:list", taskHandler.CreateWeb) + a.GET("/tasks/:listtask", taskHandler.ReadOneWeb) a.GET("/tasks/all", taskHandler.ReadAllWeb) a.DELETE("/tasks/:listtask", taskHandler.DeleteWeb) a.POST("/tasks/:listtask", taskHandler.UpdateWeb) diff --git a/pkg/swagger/docs.go b/pkg/swagger/docs.go index c3013fb17..4dcd470f6 100644 --- a/pkg/swagger/docs.go +++ b/pkg/swagger/docs.go @@ -1,6 +1,6 @@ // GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // This file was generated by swaggo/swag at -// 2019-10-23 23:00:23.451871583 +0200 CEST m=+0.120322599 +// 2019-11-02 21:06:44.848486087 +0100 CET m=+0.175638002 package swagger @@ -407,7 +407,7 @@ var doc = `{ "JWTKeyAuth": [] } ], - "description": "Returns a list by its ID.", + "description": "Returns a team by its ID.", "consumes": [ "application/json" ], @@ -415,13 +415,13 @@ var doc = `{ "application/json" ], "tags": [ - "list" + "team" ], - "summary": "Gets one list", + "summary": "Gets one team", "parameters": [ { "type": "integer", - "description": "List ID", + "description": "Team ID", "name": "id", "in": "path", "required": true @@ -429,13 +429,13 @@ var doc = `{ ], "responses": { "200": { - "description": "The list", + "description": "The team", "schema": { - "$ref": "#/definitions/models.List" + "$ref": "#/definitions/models.Team" } }, "403": { - "description": "The user does not have access to the list", + "description": "The user does not have access to the team", "schema": { "$ref": "#/definitions/code.vikunja.io.web.HTTPError" } @@ -2561,7 +2561,7 @@ var doc = `{ "JWTKeyAuth": [] } ], - "description": "Returns all tasks on any list the user has access to.", + "description": "Returns one task by its ID", "consumes": [ "application/json" ], @@ -2571,53 +2571,27 @@ var doc = `{ "tags": [ "task" ], - "summary": "Get tasks", + "summary": "Get one task", "parameters": [ { "type": "integer", - "description": "The page number. Used for pagination. If not provided, the first page of results is returned.", - "name": "page", - "in": "query" - }, - { - "type": "integer", - "description": "The maximum number of items per page. Note this parameter is limited by the configured maximum of items per page.", - "name": "per_page", - "in": "query" - }, - { - "type": "string", - "description": "Search tasks by task text.", - "name": "s", - "in": "query" - }, - { - "type": "string", - "description": "The sorting parameter. Possible values to sort by are priority, prioritydesc, priorityasc, duedate, duedatedesc, duedateasc.", - "name": "sort", - "in": "query" - }, - { - "type": "integer", - "description": "The start date parameter to filter by. Expects a unix timestamp. If no end date, but a start date is specified, the end date is set to the current time.", - "name": "startdate", - "in": "query" - }, - { - "type": "integer", - "description": "The end date parameter to filter by. Expects a unix timestamp. If no start date, but an end date is specified, the start date is set to the current time.", - "name": "enddate", - "in": "query" + "description": "The task ID", + "name": "ID", + "in": "path", + "required": true } ], "responses": { "200": { - "description": "The tasks", + "description": "The task", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Task" - } + "$ref": "#/definitions/models.Task" + } + }, + "404": { + "description": "Task not found", + "schema": { + "$ref": "#/definitions/models.Message" } }, "500": { diff --git a/pkg/swagger/swagger.json b/pkg/swagger/swagger.json index 88d2dd2c4..409218a25 100644 --- a/pkg/swagger/swagger.json +++ b/pkg/swagger/swagger.json @@ -389,7 +389,7 @@ "JWTKeyAuth": [] } ], - "description": "Returns a list by its ID.", + "description": "Returns a team by its ID.", "consumes": [ "application/json" ], @@ -397,13 +397,13 @@ "application/json" ], "tags": [ - "list" + "team" ], - "summary": "Gets one list", + "summary": "Gets one team", "parameters": [ { "type": "integer", - "description": "List ID", + "description": "Team ID", "name": "id", "in": "path", "required": true @@ -411,13 +411,13 @@ ], "responses": { "200": { - "description": "The list", + "description": "The team", "schema": { - "$ref": "#/definitions/models.List" + "$ref": "#/definitions/models.Team" } }, "403": { - "description": "The user does not have access to the list", + "description": "The user does not have access to the team", "schema": { "$ref": "#/definitions/code.vikunja.io/web.HTTPError" } @@ -2543,7 +2543,7 @@ "JWTKeyAuth": [] } ], - "description": "Returns all tasks on any list the user has access to.", + "description": "Returns one task by its ID", "consumes": [ "application/json" ], @@ -2553,53 +2553,27 @@ "tags": [ "task" ], - "summary": "Get tasks", + "summary": "Get one task", "parameters": [ { "type": "integer", - "description": "The page number. Used for pagination. If not provided, the first page of results is returned.", - "name": "page", - "in": "query" - }, - { - "type": "integer", - "description": "The maximum number of items per page. Note this parameter is limited by the configured maximum of items per page.", - "name": "per_page", - "in": "query" - }, - { - "type": "string", - "description": "Search tasks by task text.", - "name": "s", - "in": "query" - }, - { - "type": "string", - "description": "The sorting parameter. Possible values to sort by are priority, prioritydesc, priorityasc, duedate, duedatedesc, duedateasc.", - "name": "sort", - "in": "query" - }, - { - "type": "integer", - "description": "The start date parameter to filter by. Expects a unix timestamp. If no end date, but a start date is specified, the end date is set to the current time.", - "name": "startdate", - "in": "query" - }, - { - "type": "integer", - "description": "The end date parameter to filter by. Expects a unix timestamp. If no start date, but an end date is specified, the start date is set to the current time.", - "name": "enddate", - "in": "query" + "description": "The task ID", + "name": "ID", + "in": "path", + "required": true } ], "responses": { "200": { - "description": "The tasks", + "description": "The task", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Task" - } + "$ref": "#/definitions/models.Task" + } + }, + "404": { + "description": "Task not found", + "schema": { + "$ref": "#/definitions/models.Message" } }, "500": { diff --git a/pkg/swagger/swagger.yaml b/pkg/swagger/swagger.yaml index 4e82864b4..73da65cf0 100644 --- a/pkg/swagger/swagger.yaml +++ b/pkg/swagger/swagger.yaml @@ -1138,9 +1138,9 @@ paths: get: consumes: - application/json - description: Returns a list by its ID. + description: Returns a team by its ID. parameters: - - description: List ID + - description: Team ID in: path name: id required: true @@ -1149,11 +1149,11 @@ paths: - application/json responses: "200": - description: The list + description: The team schema: - $ref: '#/definitions/models.List' + $ref: '#/definitions/models.Team' "403": - description: The user does not have access to the list + description: The user does not have access to the team schema: $ref: '#/definitions/code.vikunja.io/web.HTTPError' "500": @@ -1162,9 +1162,9 @@ paths: $ref: '#/definitions/models.Message' security: - JWTKeyAuth: [] - summary: Gets one list + summary: Gets one team tags: - - list + - team post: consumes: - application/json @@ -3177,55 +3177,31 @@ paths: get: consumes: - application/json - description: Returns all tasks on any list the user has access to. + description: Returns one task by its ID parameters: - - description: The page number. Used for pagination. If not provided, the first - page of results is returned. - in: query - name: page - type: integer - - description: The maximum number of items per page. Note this parameter is - limited by the configured maximum of items per page. - in: query - name: per_page - type: integer - - description: Search tasks by task text. - in: query - name: s - type: string - - description: The sorting parameter. Possible values to sort by are priority, - prioritydesc, priorityasc, duedate, duedatedesc, duedateasc. - in: query - name: sort - type: string - - description: The start date parameter to filter by. Expects a unix timestamp. - If no end date, but a start date is specified, the end date is set to the - current time. - in: query - name: startdate - type: integer - - description: The end date parameter to filter by. Expects a unix timestamp. - If no start date, but an end date is specified, the start date is set to - the current time. - in: query - name: enddate + - description: The task ID + in: path + name: ID + required: true type: integer produces: - application/json responses: "200": - description: The tasks + description: The task schema: - items: - $ref: '#/definitions/models.Task' - type: array + $ref: '#/definitions/models.Task' + "404": + description: Task not found + schema: + $ref: '#/definitions/models.Message' "500": description: Internal error schema: $ref: '#/definitions/models.Message' security: - JWTKeyAuth: [] - summary: Get tasks + summary: Get one task tags: - task /tasks/bulk: