Added method to bulk update assignees
the build was successful Details

This commit is contained in:
kolaente 2019-01-07 23:18:38 +01:00
parent 37ae1611a4
commit d0b14aa718
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
8 changed files with 308 additions and 50 deletions

View File

@ -160,3 +160,16 @@ GET http://localhost:8080/api/v1/tasks/3565/assignees
Authorization: Bearer {{auth_token}}
###
# Add a bunch of assignees
PUT http://localhost:8080/api/v1/tasks/3565/assignees/bulk
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{
"assignees": [
{"id": 17}
]
}
###

View File

@ -1,6 +1,6 @@
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// This file was generated by swaggo/swag at
// 2019-01-07 22:44:21.325472216 +0100 CET m=+0.109716359
// 2019-01-07 23:16:50.581590248 +0100 CET m=+0.121922055
package docs
@ -37,7 +37,7 @@ var doc = `{
"JWTKeyAuth": []
}
],
"description": "Returns an array with all assignees for this task.",
"description": "Returns all labels which are either created by the user or associated with a task the user has at least read-access to.",
"consumes": [
"application/json"
],
@ -45,9 +45,9 @@ var doc = `{
"application/json"
],
"tags": [
"assignees"
"labels"
],
"summary": "Get all assignees for a task",
"summary": "Get all labels a user has access to",
"parameters": [
{
"type": "integer",
@ -57,18 +57,18 @@ var doc = `{
},
{
"type": "string",
"description": "Search assignees by their username.",
"description": "Search labels by label text.",
"name": "s",
"in": "query"
}
],
"responses": {
"200": {
"description": "The assignees",
"description": "The labels",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/models.User"
"$ref": "#/definitions/models.Label"
}
}
},
@ -391,7 +391,7 @@ var doc = `{
"JWTKeyAuth": []
}
],
"description": "Returns a list by its ID.",
"description": "Returns a team by its ID.",
"consumes": [
"application/json"
],
@ -399,13 +399,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
@ -413,14 +413,14 @@ var doc = `{
],
"responses": {
"200": {
"description": "The list",
"description": "The team",
"schema": {
"type": "object",
"$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": {
"type": "object",
"$ref": "#/definitions/code.vikunja.io.web.HTTPError"
@ -2711,6 +2711,68 @@ var doc = `{
}
}
},
"/tasks/{taskID}/assignees/bulk": {
"put": {
"security": [
{
"JWTKeyAuth": []
}
],
"description": "Adds new assignees to a task. The assignee needs to have access to the list, the doer must be able to edit this task. Every user not in the list will be unassigned from the task, pass an empty array to unassign everyone.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"assignees"
],
"summary": "Add new assignees to a task",
"parameters": [
{
"description": "The array of assignees",
"name": "assignee",
"in": "body",
"required": true,
"schema": {
"type": "object",
"$ref": "#/definitions/models.BulkAssignees"
}
},
{
"type": "integer",
"description": "Task ID",
"name": "taskID",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "The created assingees object.",
"schema": {
"type": "object",
"$ref": "#/definitions/models.ListTaskAssginee"
}
},
"400": {
"description": "Invalid assignee object provided.",
"schema": {
"type": "object",
"$ref": "#/definitions/code.vikunja.io.web.HTTPError"
}
},
"500": {
"description": "Internal error",
"schema": {
"type": "object",
"$ref": "#/definitions/models.Message"
}
}
}
}
},
"/tasks/{taskID}/assignees/{userID}": {
"delete": {
"security": [
@ -2739,7 +2801,7 @@ var doc = `{
},
{
"type": "integer",
"description": "Assignee ID",
"description": "Assignee user ID",
"name": "userID",
"in": "path",
"required": true
@ -3638,6 +3700,18 @@ var doc = `{
}
}
},
"models.BulkAssignees": {
"type": "object",
"properties": {
"assignees": {
"description": "A list with all assignees",
"type": "array",
"items": {
"$ref": "#/definitions/models.User"
}
}
}
},
"models.BulkTask": {
"type": "object",
"properties": {

View File

@ -24,7 +24,7 @@
"JWTKeyAuth": []
}
],
"description": "Returns an array with all assignees for this task.",
"description": "Returns all labels which are either created by the user or associated with a task the user has at least read-access to.",
"consumes": [
"application/json"
],
@ -32,9 +32,9 @@
"application/json"
],
"tags": [
"assignees"
"labels"
],
"summary": "Get all assignees for a task",
"summary": "Get all labels a user has access to",
"parameters": [
{
"type": "integer",
@ -44,18 +44,18 @@
},
{
"type": "string",
"description": "Search assignees by their username.",
"description": "Search labels by label text.",
"name": "s",
"in": "query"
}
],
"responses": {
"200": {
"description": "The assignees",
"description": "The labels",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/models.User"
"$ref": "#/definitions/models.Label"
}
}
},
@ -378,7 +378,7 @@
"JWTKeyAuth": []
}
],
"description": "Returns a list by its ID.",
"description": "Returns a team by its ID.",
"consumes": [
"application/json"
],
@ -386,13 +386,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
@ -400,14 +400,14 @@
],
"responses": {
"200": {
"description": "The list",
"description": "The team",
"schema": {
"type": "object",
"$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": {
"type": "object",
"$ref": "#/definitions/code.vikunja.io/web.HTTPError"
@ -2698,6 +2698,68 @@
}
}
},
"/tasks/{taskID}/assignees/bulk": {
"put": {
"security": [
{
"JWTKeyAuth": []
}
],
"description": "Adds new assignees to a task. The assignee needs to have access to the list, the doer must be able to edit this task. Every user not in the list will be unassigned from the task, pass an empty array to unassign everyone.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"assignees"
],
"summary": "Add new assignees to a task",
"parameters": [
{
"description": "The array of assignees",
"name": "assignee",
"in": "body",
"required": true,
"schema": {
"type": "object",
"$ref": "#/definitions/models.BulkAssignees"
}
},
{
"type": "integer",
"description": "Task ID",
"name": "taskID",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "The created assingees object.",
"schema": {
"type": "object",
"$ref": "#/definitions/models.ListTaskAssginee"
}
},
"400": {
"description": "Invalid assignee object provided.",
"schema": {
"type": "object",
"$ref": "#/definitions/code.vikunja.io/web.HTTPError"
}
},
"500": {
"description": "Internal error",
"schema": {
"type": "object",
"$ref": "#/definitions/models.Message"
}
}
}
}
},
"/tasks/{taskID}/assignees/{userID}": {
"delete": {
"security": [
@ -2726,7 +2788,7 @@
},
{
"type": "integer",
"description": "Assignee ID",
"description": "Assignee user ID",
"name": "userID",
"in": "path",
"required": true
@ -3624,6 +3686,18 @@
}
}
},
"models.BulkAssignees": {
"type": "object",
"properties": {
"assignees": {
"description": "A list with all assignees",
"type": "array",
"items": {
"$ref": "#/definitions/models.User"
}
}
}
},
"models.BulkTask": {
"type": "object",
"properties": {

View File

@ -21,6 +21,14 @@ definitions:
minLength: 3
type: string
type: object
models.BulkAssignees:
properties:
assignees:
description: A list with all assignees
items:
$ref: '#/definitions/models.User'
type: array
type: object
models.BulkTask:
properties:
assignees:
@ -641,14 +649,15 @@ paths:
get:
consumes:
- application/json
description: Returns an array with all assignees for this task.
description: Returns all labels which are either created by the user or associated
with a task the user has at least read-access to.
parameters:
- description: The page number. Used for pagination. If not provided, the first
page of results is returned.
in: query
name: p
type: integer
- description: Search assignees by their username.
- description: Search labels by label text.
in: query
name: s
type: string
@ -656,10 +665,10 @@ paths:
- application/json
responses:
"200":
description: The assignees
description: The labels
schema:
items:
$ref: '#/definitions/models.User'
$ref: '#/definitions/models.Label'
type: array
"500":
description: Internal error
@ -668,9 +677,9 @@ paths:
type: object
security:
- JWTKeyAuth: []
summary: Get all assignees for a task
summary: Get all labels a user has access to
tags:
- assignees
- labels
put:
consumes:
- application/json
@ -914,9 +923,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
@ -925,12 +934,12 @@ paths:
- application/json
responses:
"200":
description: The list
description: The team
schema:
$ref: '#/definitions/models.List'
$ref: '#/definitions/models.Team'
type: object
"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'
type: object
@ -941,9 +950,9 @@ paths:
type: object
security:
- JWTKeyAuth: []
summary: Gets one list
summary: Gets one team
tags:
- list
- team
post:
consumes:
- application/json
@ -2404,7 +2413,7 @@ paths:
name: taskID
required: true
type: integer
- description: Assignee ID
- description: Assignee user ID
in: path
name: userID
required: true
@ -2432,6 +2441,49 @@ paths:
summary: Delete an assignee
tags:
- assignees
/tasks/{taskID}/assignees/bulk:
put:
consumes:
- application/json
description: Adds new assignees to a task. The assignee needs to have access
to the list, the doer must be able to edit this task. Every user not in the
list will be unassigned from the task, pass an empty array to unassign everyone.
parameters:
- description: The array of assignees
in: body
name: assignee
required: true
schema:
$ref: '#/definitions/models.BulkAssignees'
type: object
- description: Task ID
in: path
name: taskID
required: true
type: integer
produces:
- application/json
responses:
"200":
description: The created assingees object.
schema:
$ref: '#/definitions/models.ListTaskAssginee'
type: object
"400":
description: Invalid assignee object provided.
schema:
$ref: '#/definitions/code.vikunja.io/web.HTTPError'
type: object
"500":
description: Internal error
schema:
$ref: '#/definitions/models.Message'
type: object
security:
- JWTKeyAuth: []
summary: Add new assignees to a task
tags:
- assignees
/tasks/all:
get:
consumes:

View File

@ -155,11 +155,13 @@ func (l *List) GetSimpleByID() (err error) {
func GetListSimplByTaskID(taskID int64) (l *List, err error) {
// We need to re-init our list object, because otherwise xorm creates a "where for every item in that list object,
// leading to not finding anything if the id is good, but for example the title is different.
var list List
exists, err := x.
Select("lists.*").
Select("list.*").
Table(List{}).
Join("INNER", "tasks", "list.id = tasks.list_id").
Where("tasks.id = ?", taskID).
Get(l)
Get(&list)
if err != nil {
return
}
@ -168,7 +170,7 @@ func GetListSimplByTaskID(taskID int64) (l *List, err error) {
return &List{}, ErrListDoesNotExist{ID: l.ID}
}
return
return &list, nil
}
// Gets the lists only, without any tasks or so

View File

@ -211,3 +211,34 @@ func (la *ListTaskAssginee) ReadAll(search string, a web.Auth, page int) (interf
Find(&taskAssignees)
return taskAssignees, err
}
// BulkAssignees is a helper struct used to update multiple assignees at once.
type BulkAssignees struct {
// A list with all assignees
Assignees []*User `json:"assignees"`
TaskID int64 `json:"-" param:"listtask"`
web.CRUDable `json:"-"`
web.Rights `json:"-"`
}
// Create adds new assignees to a task
// @Summary Add multiple new assignees to a task
// @Description Adds multiple new assignees to a task. The assignee needs to have access to the list, the doer must be able to edit this task. Every user not in the list will be unassigned from the task, pass an empty array to unassign everyone.
// @tags assignees
// @Accept json
// @Produce json
// @Security JWTKeyAuth
// @Param assignee body models.BulkAssignees true "The array of assignees"
// @Param taskID path int true "Task ID"
// @Success 200 {object} models.ListTaskAssginee "The created assingees object."
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid assignee object provided."
// @Failure 500 {object} models.Message "Internal error"
// @Router /tasks/{taskID}/assignees/bulk [put]
func (ba *BulkAssignees) Create(a web.Auth) (err error) {
task, err := GetListTaskByID(ba.TaskID) // We need to use the full method here because we need all current assignees.
if err != nil {
return
}
return task.updateTaskAssignees(ba.Assignees)
}

View File

@ -23,17 +23,22 @@ import (
// CanCreate checks if a user can add a new assignee
func (la *ListTaskAssginee) CanCreate(a web.Auth) bool {
return la.canDoListTaskAssingee(a)
return canDoListTaskAssingee(la.TaskID, a)
}
// CanCreate checks if a user can add a new assignee
func (ba *BulkAssignees) CanCreate(a web.Auth) bool {
return canDoListTaskAssingee(ba.TaskID, a)
}
// CanDelete checks if a user can delete an assignee
func (la *ListTaskAssginee) CanDelete(a web.Auth) bool {
return la.canDoListTaskAssingee(a)
return canDoListTaskAssingee(la.TaskID, a)
}
func (la *ListTaskAssginee) canDoListTaskAssingee(a web.Auth) bool {
func canDoListTaskAssingee(taskID int64, a web.Auth) bool {
// Check if the current user can edit the list
list, err := GetListSimplByTaskID(la.TaskID)
list, err := GetListSimplByTaskID(taskID)
if err != nil {
log.Log.Errorf("Error during canDoListTaskAssingee for ListTaskAssginee: %v", err)
return false

View File

@ -250,6 +250,13 @@ func RegisterRoutes(e *echo.Echo) {
a.DELETE("/tasks/:listtask/assignees/:user", assigneeTaskHandler.DeleteWeb)
a.GET("/tasks/:listtask/assignees", assigneeTaskHandler.ReadAllWeb)
bulkAssigneeHandler := &handler.WebHandler{
EmptyStruct: func() handler.CObject {
return &models.BulkAssignees{}
},
}
a.PUT("/tasks/:listtask/assignees/bulk", bulkAssigneeHandler.CreateWeb)
labelTaskHandler := &handler.WebHandler{
EmptyStruct: func() handler.CObject {
return &models.LabelTask{}