Add endpoint to get a single task (#106)
This commit is contained in:
parent
ed4c17892e
commit
9be5ab248c
8 changed files with 136 additions and 191 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue