Add task filter for labels (#747)

Update docs

Add task filter for labels

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/747
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
This commit is contained in:
konrad 2020-12-20 12:41:36 +00:00
parent 18325e964d
commit 03e4bf30c2
6 changed files with 48 additions and 24 deletions

View file

@ -91,7 +91,7 @@ func validateTaskField(fieldName string) error {
// @Param s query string false "Search tasks by task text." // @Param s query string false "Search tasks by task text."
// @Param sort_by query string false "The sorting parameter. You can pass this multiple times to get the tasks ordered by multiple different parametes, along with `order_by`. Possible values to sort by are `id`, `title`, `description`, `done`, `done_at`, `due_date`, `created_by_id`, `list_id`, `repeat_after`, `priority`, `start_date`, `end_date`, `hex_color`, `percent_done`, `uid`, `created`, `updated`. Default is `id`." // @Param sort_by query string false "The sorting parameter. You can pass this multiple times to get the tasks ordered by multiple different parametes, along with `order_by`. Possible values to sort by are `id`, `title`, `description`, `done`, `done_at`, `due_date`, `created_by_id`, `list_id`, `repeat_after`, `priority`, `start_date`, `end_date`, `hex_color`, `percent_done`, `uid`, `created`, `updated`. Default is `id`."
// @Param order_by query string false "The ordering parameter. Possible values to order by are `asc` or `desc`. Default is `asc`." // @Param order_by query string false "The ordering parameter. Possible values to order by are `asc` or `desc`. Default is `asc`."
// @Param filter_by query string false "The name of the field to filter by. Allowed values are all task properties except `labels`, `list` and `namespace`. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match." // @Param filter_by query string false "The name of the field to filter by. Allowed values are all task properties except `list` and `namespace`. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match."
// @Param filter_value query string false "The value to filter for." // @Param filter_value query string false "The value to filter for."
// @Param filter_comparator query string false "The comparator to use for a filter. Available values are `equals`, `greater`, `greater_equals`, `less`, `less_equals`, `like` and `in`. `in` expects comma-separated values in `filter_value`. Defaults to `equals`" // @Param filter_comparator query string false "The comparator to use for a filter. Available values are `equals`, `greater`, `greater_equals`, `less`, `less_equals`, `like` and `in`. `in` expects comma-separated values in `filter_value`. Defaults to `equals`"
// @Param filter_concat query string false "The concatinator to use for filters. Available values are `and` or `or`. Defaults to `or`." // @Param filter_concat query string false "The concatinator to use for filters. Available values are `and` or `or`. Defaults to `or`."

View file

@ -62,6 +62,15 @@ func TestTaskCollection_ReadAll(t *testing.T) {
loc := config.GetTimeZone() loc := config.GetTimeZone()
label4 := &Label{
ID: 4,
Title: "Label #4 - visible via other task",
CreatedByID: 2,
CreatedBy: user2,
Created: testCreatedTime,
Updated: testUpdatedTime,
}
// We use individual variables for the tasks here to be able to rearrange or remove ones more easily // We use individual variables for the tasks here to be able to rearrange or remove ones more easily
task1 := &Task{ task1 := &Task{
ID: 1, ID: 1,
@ -75,14 +84,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
BucketID: 1, BucketID: 1,
IsFavorite: true, IsFavorite: true,
Labels: []*Label{ Labels: []*Label{
{ label4,
ID: 4,
Title: "Label #4 - visible via other task",
CreatedByID: 2,
CreatedBy: user2,
Created: testCreatedTime,
Updated: testUpdatedTime,
},
}, },
RelatedTasks: map[RelationKind][]*Task{ RelatedTasks: map[RelationKind][]*Task{
RelationKindSubtask: { RelationKindSubtask: {
@ -137,14 +139,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
ListID: 1, ListID: 1,
BucketID: 1, BucketID: 1,
Labels: []*Label{ Labels: []*Label{
{ label4,
ID: 4,
Title: "Label #4 - visible via other task",
CreatedByID: 2,
CreatedBy: user2,
Created: testCreatedTime,
Updated: testUpdatedTime,
},
}, },
RelatedTasks: map[RelationKind][]*Task{}, RelatedTasks: map[RelationKind][]*Task{},
Created: time.Unix(1543626724, 0).In(loc), Created: time.Unix(1543626724, 0).In(loc),
@ -932,6 +927,20 @@ func TestTaskCollection_ReadAll(t *testing.T) {
}, },
wantErr: false, wantErr: false,
}, },
{
name: "filter labels",
fields: fields{
FilterBy: []string{"labels"},
FilterValue: []string{"4"},
FilterComparator: []string{"equals"},
},
args: defaultArgs,
want: []*Task{
task1,
task2,
},
wantErr: false,
},
} }
for _, tt := range tests { for _, tt := range tests {

View file

@ -144,7 +144,7 @@ type taskOptions struct {
// @Param s query string false "Search tasks by task text." // @Param s query string false "Search tasks by task text."
// @Param sort_by query string false "The sorting parameter. You can pass this multiple times to get the tasks ordered by multiple different parametes, along with `order_by`. Possible values to sort by are `id`, `title`, `description`, `done`, `done_at`, `due_date`, `created_by_id`, `list_id`, `repeat_after`, `priority`, `start_date`, `end_date`, `hex_color`, `percent_done`, `uid`, `created`, `updated`. Default is `id`." // @Param sort_by query string false "The sorting parameter. You can pass this multiple times to get the tasks ordered by multiple different parametes, along with `order_by`. Possible values to sort by are `id`, `title`, `description`, `done`, `done_at`, `due_date`, `created_by_id`, `list_id`, `repeat_after`, `priority`, `start_date`, `end_date`, `hex_color`, `percent_done`, `uid`, `created`, `updated`. Default is `id`."
// @Param order_by query string false "The ordering parameter. Possible values to order by are `asc` or `desc`. Default is `asc`." // @Param order_by query string false "The ordering parameter. Possible values to order by are `asc` or `desc`. Default is `asc`."
// @Param filter_by query string false "The name of the field to filter by. Allowed values are all task properties except `labels`, `list` and `namespace`. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match." // @Param filter_by query string false "The name of the field to filter by. Allowed values are all task properties except `list` and `namespace`. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match."
// @Param filter_value query string false "The value to filter for." // @Param filter_value query string false "The value to filter for."
// @Param filter_comparator query string false "The comparator to use for a filter. Available values are `equals`, `greater`, `greater_equals`, `less`, `less_equals`, `like` and `in`. `in` expects comma-separated values in `filter_value`. Defaults to `equals`" // @Param filter_comparator query string false "The comparator to use for a filter. Available values are `equals`, `greater`, `greater_equals`, `less`, `less_equals`, `like` and `in`. `in` expects comma-separated values in `filter_value`. Defaults to `equals`"
// @Param filter_concat query string false "The concatinator to use for filters. Available values are `and` or `or`. Defaults to `or`." // @Param filter_concat query string false "The concatinator to use for filters. Available values are `and` or `or`. Defaults to `or`."
@ -270,6 +270,7 @@ func getRawTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks []
// Some filters need a special treatment since they are in a separate table // Some filters need a special treatment since they are in a separate table
reminderFilters := []builder.Cond{} reminderFilters := []builder.Cond{}
assigneeFilters := []builder.Cond{} assigneeFilters := []builder.Cond{}
labelFilters := []builder.Cond{}
var filters = make([]builder.Cond, 0, len(opts.filters)) var filters = make([]builder.Cond, 0, len(opts.filters))
// To still find tasks with nil values, we exclude 0s when comparing with >/< values. // To still find tasks with nil values, we exclude 0s when comparing with >/< values.
@ -294,6 +295,16 @@ func getRawTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks []
continue continue
} }
if f.field == "labels" {
f.field = "label_id"
filter, err := getFilterCond(f, opts.filterIncludeNulls)
if err != nil {
return nil, 0, 0, err
}
labelFilters = append(labelFilters, filter)
continue
}
filter, err := getFilterCond(f, opts.filterIncludeNulls) filter, err := getFilterCond(f, opts.filterIncludeNulls)
if err != nil { if err != nil {
return nil, 0, 0, err return nil, 0, 0, err
@ -354,6 +365,10 @@ func getRawTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks []
filters = append(filters, getFilterCondForSeparateTable("task_assignees", opts.filterConcat, assigneeFilters)) filters = append(filters, getFilterCondForSeparateTable("task_assignees", opts.filterConcat, assigneeFilters))
} }
if len(labelFilters) > 0 {
filters = append(filters, getFilterCondForSeparateTable("label_task", opts.filterConcat, labelFilters))
}
query = query.Where(listCond) query = query.Where(listCond)
queryCount = queryCount.Where(listCond) queryCount = queryCount.Where(listCond)

View file

@ -1892,7 +1892,7 @@ var doc = `{
}, },
{ {
"type": "string", "type": "string",
"description": "The name of the field to filter by. Allowed values are all task properties except ` + "`" + `labels` + "`" + `, ` + "`" + `list` + "`" + ` and ` + "`" + `namespace` + "`" + `. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match.", "description": "The name of the field to filter by. Allowed values are all task properties except ` + "`" + `list` + "`" + ` and ` + "`" + `namespace` + "`" + `. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match.",
"name": "filter_by", "name": "filter_by",
"in": "query" "in": "query"
}, },
@ -4006,7 +4006,7 @@ var doc = `{
}, },
{ {
"type": "string", "type": "string",
"description": "The name of the field to filter by. Allowed values are all task properties except ` + "`" + `labels` + "`" + `, ` + "`" + `list` + "`" + ` and ` + "`" + `namespace` + "`" + `. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match.", "description": "The name of the field to filter by. Allowed values are all task properties except ` + "`" + `list` + "`" + ` and ` + "`" + `namespace` + "`" + `. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match.",
"name": "filter_by", "name": "filter_by",
"in": "query" "in": "query"
}, },

View file

@ -1875,7 +1875,7 @@
}, },
{ {
"type": "string", "type": "string",
"description": "The name of the field to filter by. Allowed values are all task properties except `labels`, `list` and `namespace`. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match.", "description": "The name of the field to filter by. Allowed values are all task properties except `list` and `namespace`. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match.",
"name": "filter_by", "name": "filter_by",
"in": "query" "in": "query"
}, },
@ -3989,7 +3989,7 @@
}, },
{ {
"type": "string", "type": "string",
"description": "The name of the field to filter by. Allowed values are all task properties except `labels`, `list` and `namespace`. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match.", "description": "The name of the field to filter by. Allowed values are all task properties except `list` and `namespace`. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match.",
"name": "filter_by", "name": "filter_by",
"in": "query" "in": "query"
}, },

View file

@ -2443,7 +2443,7 @@ paths:
in: query in: query
name: order_by name: order_by
type: string type: string
- description: The name of the field to filter by. Allowed values are all task properties except `labels`, `list` and `namespace`. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match. - description: The name of the field to filter by. Allowed values are all task properties except `list` and `namespace`. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match.
in: query in: query
name: filter_by name: filter_by
type: string type: string
@ -4467,7 +4467,7 @@ paths:
in: query in: query
name: order_by name: order_by
type: string type: string
- description: The name of the field to filter by. Allowed values are all task properties except `labels`, `list` and `namespace`. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match. - description: The name of the field to filter by. Allowed values are all task properties except `list` and `namespace`. Task properties which are their own object require passing in the id of that entity. Accepts an array for multiple filters which will be chanied together, all supplied filter must match.
in: query in: query
name: filter_by name: filter_by
type: string type: string