1
0

Saved filters (#655)

Fix updating saved filters

Fix filter not loadable because of missing param declaration

Add fancy special cases for postgres exists in db

Add special case for postgrs json

Add read one test

Add rights tests

Fix lint

Fixed getting a single saved filter from db

Add tests for the usual crud methods

Add test stubs and TODOs

Add test for converting saved filter ids to list ids and vice versa

Add test fixture for saved filters and fix existing tests

Fix exposed json variables of filters

Fix creating saved filters table for tests

Add getting saved filters as pseudo namespace

Cleanup

Refactor getting all namespaces to use a map for easier handling of pseudo namespaces

Add custom erros for saved filters

Swagger docs

Fix lint

Add routes for saved filters

Add alias for mage build

Add method to get a saved filter from the lists endpoint

Add getting tasks from a saved filter

Add create, update, delete, read one methods

Add rights methods for saved filters

Fix docs minLength

Add saved filters column

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/655
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
This commit is contained in:
konrad
2020-09-26 21:02:17 +00:00
parent a6fdf114d1
commit 0fb2edf051
26 changed files with 1650 additions and 119 deletions

View File

@ -172,6 +172,201 @@ var doc = `{
}
}
},
"/filters": {
"put": {
"security": [
{
"JWTKeyAuth": []
}
],
"description": "Creates a new saved filter",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"filter"
],
"summary": "Creates a new saved filter",
"responses": {
"200": {
"description": "The Saved Filter",
"schema": {
"$ref": "#/definitions/models.SavedFilter"
}
},
"403": {
"description": "The user does not have access to that saved filter.",
"schema": {
"$ref": "#/definitions/web.HTTPError"
}
},
"500": {
"description": "Internal error",
"schema": {
"$ref": "#/definitions/models.Message"
}
}
}
}
},
"/filters/{id}": {
"get": {
"security": [
{
"JWTKeyAuth": []
}
],
"description": "Returns a saved filter by its ID.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"filter"
],
"summary": "Gets one saved filter",
"parameters": [
{
"type": "integer",
"description": "Filter ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "The Saved Filter",
"schema": {
"$ref": "#/definitions/models.SavedFilter"
}
},
"403": {
"description": "The user does not have access to that saved filter.",
"schema": {
"$ref": "#/definitions/web.HTTPError"
}
},
"500": {
"description": "Internal error",
"schema": {
"$ref": "#/definitions/models.Message"
}
}
}
},
"post": {
"security": [
{
"JWTKeyAuth": []
}
],
"description": "Updates a saved filter by its ID.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"filter"
],
"summary": "Updates a saved filter",
"parameters": [
{
"type": "integer",
"description": "Filter ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "The Saved Filter",
"schema": {
"$ref": "#/definitions/models.SavedFilter"
}
},
"403": {
"description": "The user does not have access to that saved filter.",
"schema": {
"$ref": "#/definitions/web.HTTPError"
}
},
"404": {
"description": "The saved filter does not exist.",
"schema": {
"$ref": "#/definitions/web.HTTPError"
}
},
"500": {
"description": "Internal error",
"schema": {
"$ref": "#/definitions/models.Message"
}
}
}
},
"delete": {
"security": [
{
"JWTKeyAuth": []
}
],
"description": "Removes a saved filter by its ID.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"filter"
],
"summary": "Removes a saved filter",
"parameters": [
{
"type": "integer",
"description": "Filter ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "The Saved Filter",
"schema": {
"$ref": "#/definitions/models.SavedFilter"
}
},
"403": {
"description": "The user does not have access to that saved filter.",
"schema": {
"$ref": "#/definitions/web.HTTPError"
}
},
"404": {
"description": "The saved filter does not exist.",
"schema": {
"$ref": "#/definitions/web.HTTPError"
}
},
"500": {
"description": "Internal error",
"schema": {
"$ref": "#/definitions/models.Message"
}
}
}
}
},
"/info": {
"get": {
"description": "Returns the version, frontendurl, motd and various settings of Vikunja",
@ -6403,7 +6598,7 @@ var doc = `{
"description": "The task text. This is what you'll see in the list.",
"type": "string",
"maxLength": 250,
"minLength": 3
"minLength": 1
},
"updated": {
"description": "A timestamp when this task was last updated. You cannot change this value.",
@ -6440,7 +6635,7 @@ var doc = `{
"description": "The title of the lable. You'll see this one on tasks associated with it.",
"type": "string",
"maxLength": 250,
"minLength": 3
"minLength": 1
},
"updated": {
"description": "A timestamp when this label was last updated. You cannot change this value.",
@ -6561,7 +6756,7 @@ var doc = `{
"description": "The title of the list. You'll see this in the namespace overview.",
"type": "string",
"maxLength": 250,
"minLength": 3
"minLength": 1
},
"updated": {
"description": "A timestamp when this list was last updated. You cannot change this value.",
@ -6652,7 +6847,7 @@ var doc = `{
"description": "The name of this namespace.",
"type": "string",
"maxLength": 250,
"minLength": 5
"minLength": 1
},
"updated": {
"description": "A timestamp when this namespace was last updated. You cannot change this value.",
@ -6726,7 +6921,7 @@ var doc = `{
"description": "The name of this namespace.",
"type": "string",
"maxLength": 250,
"minLength": 5
"minLength": 1
},
"updated": {
"description": "A timestamp when this namespace was last updated. You cannot change this value.",
@ -6743,6 +6938,43 @@ var doc = `{
}
}
},
"models.SavedFilter": {
"type": "object",
"properties": {
"created": {
"description": "A timestamp when this filter was created. You cannot change this value.",
"type": "string"
},
"description": {
"description": "The description of the filter",
"type": "string"
},
"filters": {
"description": "The actual filters this filter contains",
"type": "object",
"$ref": "#/definitions/models.TaskCollection"
},
"id": {
"description": "The unique numeric id of this saved filter",
"type": "integer"
},
"owner": {
"description": "The user who owns this filter",
"type": "object",
"$ref": "#/definitions/user.User"
},
"title": {
"description": "The title of the filter.",
"type": "string",
"maxLength": 250,
"minLength": 1
},
"updated": {
"description": "A timestamp when this filter was last updated. You cannot change this value.",
"type": "string"
}
}
},
"models.Task": {
"type": "object",
"properties": {
@ -6865,7 +7097,7 @@ var doc = `{
"description": "The task text. This is what you'll see in the list.",
"type": "string",
"maxLength": 250,
"minLength": 3
"minLength": 1
},
"updated": {
"description": "A timestamp when this task was last updated. You cannot change this value.",
@ -6906,6 +7138,54 @@ var doc = `{
}
}
},
"models.TaskCollection": {
"type": "object",
"properties": {
"filter_by": {
"description": "The field name of the field to filter by",
"type": "array",
"items": {
"type": "string"
}
},
"filter_comparator": {
"description": "The comparator for field and value",
"type": "array",
"items": {
"type": "string"
}
},
"filter_concat": {
"description": "The way all filter conditions are concatenated together, can be either \"and\" or \"or\".,",
"type": "string"
},
"filter_include_nulls": {
"description": "If set to true, the result will also include null values",
"type": "boolean"
},
"filter_value": {
"description": "The value of the field name to filter by",
"type": "array",
"items": {
"type": "string"
}
},
"order_by": {
"description": "The query parameter to order the items by. This can be either asc or desc, with asc being the default.",
"type": "array",
"items": {
"type": "string"
}
},
"sort_by": {
"description": "The query parameter to sort by. This is for ex. done, priority, etc.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
"models.TaskComment": {
"type": "object",
"properties": {
@ -6984,7 +7264,7 @@ var doc = `{
"description": "The name of this team.",
"type": "string",
"maxLength": 250,
"minLength": 5
"minLength": 1
},
"updated": {
"description": "A timestamp when this relation was last updated. You cannot change this value.",
@ -7095,7 +7375,7 @@ var doc = `{
"description": "The username of the user. Is always unique.",
"type": "string",
"maxLength": 250,
"minLength": 3
"minLength": 1
}
}
},
@ -7130,7 +7410,7 @@ var doc = `{
"description": "The name of this team.",
"type": "string",
"maxLength": 250,
"minLength": 5
"minLength": 1
},
"right": {
"type": "integer"
@ -7168,7 +7448,7 @@ var doc = `{
"description": "The username of the user. Is always unique.",
"type": "string",
"maxLength": 250,
"minLength": 3
"minLength": 1
}
}
},
@ -7315,7 +7595,7 @@ var doc = `{
"description": "The username of the user. Is always unique.",
"type": "string",
"maxLength": 250,
"minLength": 3
"minLength": 1
}
}
},

View File

@ -155,6 +155,201 @@
}
}
},
"/filters": {
"put": {
"security": [
{
"JWTKeyAuth": []
}
],
"description": "Creates a new saved filter",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"filter"
],
"summary": "Creates a new saved filter",
"responses": {
"200": {
"description": "The Saved Filter",
"schema": {
"$ref": "#/definitions/models.SavedFilter"
}
},
"403": {
"description": "The user does not have access to that saved filter.",
"schema": {
"$ref": "#/definitions/web.HTTPError"
}
},
"500": {
"description": "Internal error",
"schema": {
"$ref": "#/definitions/models.Message"
}
}
}
}
},
"/filters/{id}": {
"get": {
"security": [
{
"JWTKeyAuth": []
}
],
"description": "Returns a saved filter by its ID.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"filter"
],
"summary": "Gets one saved filter",
"parameters": [
{
"type": "integer",
"description": "Filter ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "The Saved Filter",
"schema": {
"$ref": "#/definitions/models.SavedFilter"
}
},
"403": {
"description": "The user does not have access to that saved filter.",
"schema": {
"$ref": "#/definitions/web.HTTPError"
}
},
"500": {
"description": "Internal error",
"schema": {
"$ref": "#/definitions/models.Message"
}
}
}
},
"post": {
"security": [
{
"JWTKeyAuth": []
}
],
"description": "Updates a saved filter by its ID.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"filter"
],
"summary": "Updates a saved filter",
"parameters": [
{
"type": "integer",
"description": "Filter ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "The Saved Filter",
"schema": {
"$ref": "#/definitions/models.SavedFilter"
}
},
"403": {
"description": "The user does not have access to that saved filter.",
"schema": {
"$ref": "#/definitions/web.HTTPError"
}
},
"404": {
"description": "The saved filter does not exist.",
"schema": {
"$ref": "#/definitions/web.HTTPError"
}
},
"500": {
"description": "Internal error",
"schema": {
"$ref": "#/definitions/models.Message"
}
}
}
},
"delete": {
"security": [
{
"JWTKeyAuth": []
}
],
"description": "Removes a saved filter by its ID.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"filter"
],
"summary": "Removes a saved filter",
"parameters": [
{
"type": "integer",
"description": "Filter ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "The Saved Filter",
"schema": {
"$ref": "#/definitions/models.SavedFilter"
}
},
"403": {
"description": "The user does not have access to that saved filter.",
"schema": {
"$ref": "#/definitions/web.HTTPError"
}
},
"404": {
"description": "The saved filter does not exist.",
"schema": {
"$ref": "#/definitions/web.HTTPError"
}
},
"500": {
"description": "Internal error",
"schema": {
"$ref": "#/definitions/models.Message"
}
}
}
}
},
"/info": {
"get": {
"description": "Returns the version, frontendurl, motd and various settings of Vikunja",
@ -6386,7 +6581,7 @@
"description": "The task text. This is what you'll see in the list.",
"type": "string",
"maxLength": 250,
"minLength": 3
"minLength": 1
},
"updated": {
"description": "A timestamp when this task was last updated. You cannot change this value.",
@ -6423,7 +6618,7 @@
"description": "The title of the lable. You'll see this one on tasks associated with it.",
"type": "string",
"maxLength": 250,
"minLength": 3
"minLength": 1
},
"updated": {
"description": "A timestamp when this label was last updated. You cannot change this value.",
@ -6544,7 +6739,7 @@
"description": "The title of the list. You'll see this in the namespace overview.",
"type": "string",
"maxLength": 250,
"minLength": 3
"minLength": 1
},
"updated": {
"description": "A timestamp when this list was last updated. You cannot change this value.",
@ -6635,7 +6830,7 @@
"description": "The name of this namespace.",
"type": "string",
"maxLength": 250,
"minLength": 5
"minLength": 1
},
"updated": {
"description": "A timestamp when this namespace was last updated. You cannot change this value.",
@ -6709,7 +6904,7 @@
"description": "The name of this namespace.",
"type": "string",
"maxLength": 250,
"minLength": 5
"minLength": 1
},
"updated": {
"description": "A timestamp when this namespace was last updated. You cannot change this value.",
@ -6726,6 +6921,43 @@
}
}
},
"models.SavedFilter": {
"type": "object",
"properties": {
"created": {
"description": "A timestamp when this filter was created. You cannot change this value.",
"type": "string"
},
"description": {
"description": "The description of the filter",
"type": "string"
},
"filters": {
"description": "The actual filters this filter contains",
"type": "object",
"$ref": "#/definitions/models.TaskCollection"
},
"id": {
"description": "The unique numeric id of this saved filter",
"type": "integer"
},
"owner": {
"description": "The user who owns this filter",
"type": "object",
"$ref": "#/definitions/user.User"
},
"title": {
"description": "The title of the filter.",
"type": "string",
"maxLength": 250,
"minLength": 1
},
"updated": {
"description": "A timestamp when this filter was last updated. You cannot change this value.",
"type": "string"
}
}
},
"models.Task": {
"type": "object",
"properties": {
@ -6848,7 +7080,7 @@
"description": "The task text. This is what you'll see in the list.",
"type": "string",
"maxLength": 250,
"minLength": 3
"minLength": 1
},
"updated": {
"description": "A timestamp when this task was last updated. You cannot change this value.",
@ -6889,6 +7121,54 @@
}
}
},
"models.TaskCollection": {
"type": "object",
"properties": {
"filter_by": {
"description": "The field name of the field to filter by",
"type": "array",
"items": {
"type": "string"
}
},
"filter_comparator": {
"description": "The comparator for field and value",
"type": "array",
"items": {
"type": "string"
}
},
"filter_concat": {
"description": "The way all filter conditions are concatenated together, can be either \"and\" or \"or\".,",
"type": "string"
},
"filter_include_nulls": {
"description": "If set to true, the result will also include null values",
"type": "boolean"
},
"filter_value": {
"description": "The value of the field name to filter by",
"type": "array",
"items": {
"type": "string"
}
},
"order_by": {
"description": "The query parameter to order the items by. This can be either asc or desc, with asc being the default.",
"type": "array",
"items": {
"type": "string"
}
},
"sort_by": {
"description": "The query parameter to sort by. This is for ex. done, priority, etc.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
"models.TaskComment": {
"type": "object",
"properties": {
@ -6967,7 +7247,7 @@
"description": "The name of this team.",
"type": "string",
"maxLength": 250,
"minLength": 5
"minLength": 1
},
"updated": {
"description": "A timestamp when this relation was last updated. You cannot change this value.",
@ -7078,7 +7358,7 @@
"description": "The username of the user. Is always unique.",
"type": "string",
"maxLength": 250,
"minLength": 3
"minLength": 1
}
}
},
@ -7113,7 +7393,7 @@
"description": "The name of this team.",
"type": "string",
"maxLength": 250,
"minLength": 5
"minLength": 1
},
"right": {
"type": "integer"
@ -7151,7 +7431,7 @@
"description": "The username of the user. Is always unique.",
"type": "string",
"maxLength": 250,
"minLength": 3
"minLength": 1
}
}
},
@ -7298,7 +7578,7 @@
"description": "The username of the user. Is always unique.",
"type": "string",
"maxLength": 250,
"minLength": 3
"minLength": 1
}
}
},

View File

@ -182,7 +182,7 @@ definitions:
title:
description: The task text. This is what you'll see in the list.
maxLength: 250
minLength: 3
minLength: 1
type: string
updated:
description: A timestamp when this task was last updated. You cannot change this value.
@ -210,7 +210,7 @@ definitions:
title:
description: The title of the lable. You'll see this one on tasks associated with it.
maxLength: 250
minLength: 3
minLength: 1
type: string
updated:
description: A timestamp when this label was last updated. You cannot change this value.
@ -300,7 +300,7 @@ definitions:
title:
description: The title of the list. You'll see this in the namespace overview.
maxLength: 250
minLength: 3
minLength: 1
type: string
updated:
description: A timestamp when this list was last updated. You cannot change this value.
@ -367,7 +367,7 @@ definitions:
title:
description: The name of this namespace.
maxLength: 250
minLength: 5
minLength: 1
type: string
updated:
description: A timestamp when this namespace was last updated. You cannot change this value.
@ -422,7 +422,7 @@ definitions:
title:
description: The name of this namespace.
maxLength: 250
minLength: 5
minLength: 1
type: string
updated:
description: A timestamp when this namespace was last updated. You cannot change this value.
@ -434,6 +434,34 @@ definitions:
$ref: '#/definitions/models.Task'
type: array
type: object
models.SavedFilter:
properties:
created:
description: A timestamp when this filter was created. You cannot change this value.
type: string
description:
description: The description of the filter
type: string
filters:
$ref: '#/definitions/models.TaskCollection'
description: The actual filters this filter contains
type: object
id:
description: The unique numeric id of this saved filter
type: integer
owner:
$ref: '#/definitions/user.User'
description: The user who owns this filter
type: object
title:
description: The title of the filter.
maxLength: 250
minLength: 1
type: string
updated:
description: A timestamp when this filter was last updated. You cannot change this value.
type: string
type: object
models.Task:
properties:
assignees:
@ -531,7 +559,7 @@ definitions:
title:
description: The task text. This is what you'll see in the list.
maxLength: 250
minLength: 3
minLength: 1
type: string
updated:
description: A timestamp when this task was last updated. You cannot change this value.
@ -559,6 +587,40 @@ definitions:
task_id:
type: integer
type: object
models.TaskCollection:
properties:
filter_by:
description: The field name of the field to filter by
items:
type: string
type: array
filter_comparator:
description: The comparator for field and value
items:
type: string
type: array
filter_concat:
description: The way all filter conditions are concatenated together, can be either "and" or "or".,
type: string
filter_include_nulls:
description: If set to true, the result will also include null values
type: boolean
filter_value:
description: The value of the field name to filter by
items:
type: string
type: array
order_by:
description: The query parameter to order the items by. This can be either asc or desc, with asc being the default.
items:
type: string
type: array
sort_by:
description: The query parameter to sort by. This is for ex. done, priority, etc.
items:
type: string
type: array
type: object
models.TaskComment:
properties:
author:
@ -615,7 +677,7 @@ definitions:
name:
description: The name of this team.
maxLength: 250
minLength: 5
minLength: 1
type: string
updated:
description: A timestamp when this relation was last updated. You cannot change this value.
@ -697,7 +759,7 @@ definitions:
username:
description: The username of the user. Is always unique.
maxLength: 250
minLength: 3
minLength: 1
type: string
type: object
models.TeamWithRight:
@ -723,7 +785,7 @@ definitions:
name:
description: The name of this team.
maxLength: 250
minLength: 5
minLength: 1
type: string
right:
type: integer
@ -751,7 +813,7 @@ definitions:
username:
description: The username of the user. Is always unique.
maxLength: 250
minLength: 3
minLength: 1
type: string
type: object
todoist.Migration:
@ -855,7 +917,7 @@ definitions:
username:
description: The username of the user. Is always unique.
maxLength: 250
minLength: 3
minLength: 1
type: string
type: object
v1.Token:
@ -1069,6 +1131,130 @@ paths:
summary: Search for a background from unsplash
tags:
- list
/filters:
put:
consumes:
- application/json
description: Creates a new saved filter
produces:
- application/json
responses:
"200":
description: The Saved Filter
schema:
$ref: '#/definitions/models.SavedFilter'
"403":
description: The user does not have access to that saved filter.
schema:
$ref: '#/definitions/web.HTTPError'
"500":
description: Internal error
schema:
$ref: '#/definitions/models.Message'
security:
- JWTKeyAuth: []
summary: Creates a new saved filter
tags:
- filter
/filters/{id}:
delete:
consumes:
- application/json
description: Removes a saved filter by its ID.
parameters:
- description: Filter ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: The Saved Filter
schema:
$ref: '#/definitions/models.SavedFilter'
"403":
description: The user does not have access to that saved filter.
schema:
$ref: '#/definitions/web.HTTPError'
"404":
description: The saved filter does not exist.
schema:
$ref: '#/definitions/web.HTTPError'
"500":
description: Internal error
schema:
$ref: '#/definitions/models.Message'
security:
- JWTKeyAuth: []
summary: Removes a saved filter
tags:
- filter
get:
consumes:
- application/json
description: Returns a saved filter by its ID.
parameters:
- description: Filter ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: The Saved Filter
schema:
$ref: '#/definitions/models.SavedFilter'
"403":
description: The user does not have access to that saved filter.
schema:
$ref: '#/definitions/web.HTTPError'
"500":
description: Internal error
schema:
$ref: '#/definitions/models.Message'
security:
- JWTKeyAuth: []
summary: Gets one saved filter
tags:
- filter
post:
consumes:
- application/json
description: Updates a saved filter by its ID.
parameters:
- description: Filter ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: The Saved Filter
schema:
$ref: '#/definitions/models.SavedFilter'
"403":
description: The user does not have access to that saved filter.
schema:
$ref: '#/definitions/web.HTTPError'
"404":
description: The saved filter does not exist.
schema:
$ref: '#/definitions/web.HTTPError'
"500":
description: Internal error
schema:
$ref: '#/definitions/models.Message'
security:
- JWTKeyAuth: []
summary: Updates a saved filter
tags:
- filter
/info:
get:
description: Returns the version, frontendurl, motd and various settings of Vikunja