From 18325e964d097adba1b463c105bf9563caafe879 Mon Sep 17 00:00:00 2001 From: konrad Date: Sat, 19 Dec 2020 21:39:11 +0000 Subject: [PATCH] Add task filter for assignees (#746) Update docs Add filter by assignee Fix string values Update docs Update docs Make "in" task filter actually work Add "in" filter type Co-authored-by: kolaente Reviewed-on: https://kolaente.dev/vikunja/api/pulls/746 Co-Authored-By: konrad Co-Committed-By: konrad --- pkg/db/fixtures/list.yml | 1 + pkg/models/task_collection.go | 4 +- pkg/models/task_collection_filter.go | 74 +++++++++++++++++++++------- pkg/models/task_collection_test.go | 40 +++++++++++++++ pkg/models/tasks.go | 59 +++++++++++++++------- pkg/swagger/docs.go | 16 ++++-- pkg/swagger/swagger.json | 16 ++++-- pkg/swagger/swagger.yaml | 14 ++++-- 8 files changed, 169 insertions(+), 55 deletions(-) diff --git a/pkg/db/fixtures/list.yml b/pkg/db/fixtures/list.yml index 20ea7b6eec..7cbfadc8b9 100644 --- a/pkg/db/fixtures/list.yml +++ b/pkg/db/fixtures/list.yml @@ -171,6 +171,7 @@ namespace_id: 14 updated: 2018-12-02 15:13:12 created: 2018-12-01 15:13:12 +# User 1 does not have access to this list - id: 20 title: Test20 diff --git a/pkg/models/task_collection.go b/pkg/models/task_collection.go index 3b3985b53a..0aedeb30b7 100644 --- a/pkg/models/task_collection.go +++ b/pkg/models/task_collection.go @@ -91,9 +91,9 @@ func validateTaskField(fieldName string) error { // @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 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`, `assignees`, `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 `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_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` and `like`. 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_include_nulls query string false "If set to true the result will include filtered fields whose value is set to `null`. Available values are `true` or `false`. Defaults to `false`." // @Security JWTKeyAuth diff --git a/pkg/models/task_collection_filter.go b/pkg/models/task_collection_filter.go index d0022fbfd0..09b73556ff 100644 --- a/pkg/models/task_collection_filter.go +++ b/pkg/models/task_collection_filter.go @@ -21,6 +21,7 @@ import ( "fmt" "reflect" "strconv" + "strings" "time" "code.vikunja.io/api/pkg/config" @@ -40,6 +41,7 @@ const ( taskFilterComparatorLessEquals taskFilterComparator = "<=" taskFilterComparatorNotEquals taskFilterComparator = "!=" taskFilterComparatorLike taskFilterComparator = "like" + taskFilterComparatorIn taskFilterComparator = "in" ) type taskFilter struct { @@ -89,7 +91,7 @@ func getTaskFiltersByCollections(c *TaskCollection) (filters []*taskFilter, err // Cast the field value to its native type if len(c.FilterValue) > i { - filter.value, err = getNativeValueForTaskField(filter.field, c.FilterValue[i]) + filter.value, err = getNativeValueForTaskField(filter.field, filter.comparator, c.FilterValue[i]) if err != nil { return nil, ErrInvalidTaskFilterValue{ Value: filter.field, @@ -113,7 +115,8 @@ func validateTaskFieldComparator(comparator taskFilterComparator) error { taskFilterComparatorLess, taskFilterComparatorLessEquals, taskFilterComparatorNotEquals, - taskFilterComparatorLike: + taskFilterComparatorLike, + taskFilterComparatorIn: return nil case taskFilterComparatorInvalid: fallthrough @@ -138,42 +141,75 @@ func getFilterComparatorFromString(comparator string) (taskFilterComparator, err return taskFilterComparatorNotEquals, nil case "like": return taskFilterComparatorLike, nil + case "in": + return taskFilterComparatorIn, nil default: return taskFilterComparatorInvalid, ErrInvalidTaskFilterComparator{Comparator: taskFilterComparator(comparator)} } } -func getNativeValueForTaskField(fieldName, value string) (nativeValue interface{}, err error) { - field, ok := reflect.TypeOf(&Task{}).Elem().FieldByName(strcase.ToCamel(fieldName)) - if !ok { - return nil, ErrInvalidTaskField{TaskField: fieldName} - } - +func getValueForField(field reflect.StructField, rawValue string) (value interface{}, err error) { switch field.Type.Kind() { case reflect.Int64: - nativeValue, err = strconv.ParseInt(value, 10, 64) + value, err = strconv.ParseInt(rawValue, 10, 64) case reflect.Float64: - nativeValue, err = strconv.ParseFloat(value, 64) + value, err = strconv.ParseFloat(rawValue, 64) case reflect.String: - nativeValue = value + value = rawValue case reflect.Bool: - nativeValue, err = strconv.ParseBool(value) + value, err = strconv.ParseBool(rawValue) case reflect.Struct: if field.Type == schemas.TimeType { - nativeValue, err = time.Parse(time.RFC3339, value) - nativeValue = nativeValue.(time.Time).In(config.GetTimeZone()) + value, err = time.Parse(time.RFC3339, rawValue) + value = value.(time.Time).In(config.GetTimeZone()) } case reflect.Slice: - t := reflect.SliceOf(schemas.TimeType) - if t != nil { - nativeValue, err = time.Parse(time.RFC3339, value) - nativeValue = nativeValue.(time.Time).In(config.GetTimeZone()) + // If this is a slice of pointers we're dealing with some property which is a relation + // In that case we don't really care about what the actual type is, we just cast the value to an + // int64 since we need the id - yes, this assumes we only ever have int64 IDs, but this is fine. + if field.Type.Elem().Kind() == reflect.Ptr { + value, err = strconv.ParseInt(rawValue, 10, 64) + return + } + + // There are probably better ways to do this - please let me know if you have one. + if field.Type.Elem().String() == "time.Time" { + value, err = time.Parse(time.RFC3339, rawValue) + value = value.(time.Time).In(config.GetTimeZone()) return } fallthrough default: - panic(fmt.Errorf("unrecognized filter type %s for field %s, value %s", field.Type.String(), fieldName, value)) + panic(fmt.Errorf("unrecognized filter type %s for field %s, value %s", field.Type.String(), field.Name, value)) } return } + +func getNativeValueForTaskField(fieldName string, comparator taskFilterComparator, value string) (nativeValue interface{}, err error) { + + var realFieldName = strcase.ToCamel(fieldName) + if strings.ToLower(fieldName) == "id" { + realFieldName = "ID" + } + + field, ok := reflect.TypeOf(&Task{}).Elem().FieldByName(realFieldName) + if !ok { + return nil, ErrInvalidTaskField{TaskField: fieldName} + } + + if comparator == taskFilterComparatorIn { + vals := strings.Split(value, ",") + valueSlice := []interface{}{} + for _, val := range vals { + v, err := getValueForField(field, val) + if err != nil { + return nil, err + } + valueSlice = append(valueSlice, v) + } + return valueSlice, nil + } + + return getValueForField(field, value) +} diff --git a/pkg/models/task_collection_test.go b/pkg/models/task_collection_test.go index c68f2d67d3..3a3623d839 100644 --- a/pkg/models/task_collection_test.go +++ b/pkg/models/task_collection_test.go @@ -892,6 +892,46 @@ func TestTaskCollection_ReadAll(t *testing.T) { }, wantErr: false, }, + { + name: "filter in", + fields: fields{ + FilterBy: []string{"id"}, + FilterValue: []string{"1,2,34"}, // Task 34 is forbidden for user 1 + FilterComparator: []string{"in"}, + }, + args: defaultArgs, + want: []*Task{ + task1, + task2, + }, + wantErr: false, + }, + { + name: "filter assignees", + fields: fields{ + FilterBy: []string{"assignees"}, + FilterValue: []string{"1"}, + FilterComparator: []string{"equals"}, + }, + args: defaultArgs, + want: []*Task{ + task30, + }, + wantErr: false, + }, + { + name: "filter assignees in", + fields: fields{ + FilterBy: []string{"assignees"}, + FilterValue: []string{"1,2"}, + FilterComparator: []string{"in"}, + }, + args: defaultArgs, + want: []*Task{ + task30, + }, + wantErr: false, + }, } for _, tt := range tests { diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index 03489b12c8..f52352d6fa 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -142,12 +142,13 @@ type taskOptions struct { // @Param page query int false "The page number. Used for pagination. If not provided, the first page of results is returned." // @Param per_page query int false "The maximum number of items per page. Note this parameter is limited by the configured maximum of items per page." // @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`, `text`, `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 filter_by query string false "The name of the field to filter by. 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 `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_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` and `less_equals`. 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_include_nulls query string false "If set to true the result will include filtered fields whose value is set to `null`. Available values are `true` or `false`. Defaults to `false`." // @Security JWTKeyAuth // @Success 200 {array} models.Task "The tasks" // @Failure 500 {object} models.Message "Internal error" @@ -176,6 +177,8 @@ func getFilterCond(f *taskFilter, includeNulls bool) (cond builder.Cond, err err return nil, ErrInvalidTaskFilterValue{Field: f.field, Value: f.value} } cond = &builder.Like{f.field, "%" + val + "%"} + case taskFilterComparatorIn: + cond = builder.In(f.field, f.value) case taskFilterComparatorInvalid: // Nothing to do } @@ -187,6 +190,24 @@ func getFilterCond(f *taskFilter, includeNulls bool) (cond builder.Cond, err err return } +func getFilterCondForSeparateTable(table string, concat taskFilterConcatinator, conds []builder.Cond) builder.Cond { + var filtercond builder.Cond + if concat == filterConcatOr { + filtercond = builder.Or(conds...) + } + if concat == filterConcatAnd { + filtercond = builder.And(conds...) + } + + return builder.In( + "id", + builder. + Select("task_id"). + From(table). + Where(filtercond), + ) +} + //nolint:gocyclo func getRawTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks []*Task, resultCount int, totalItems int64, err error) { @@ -246,8 +267,9 @@ func getRawTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks [] } } - // Reminder filters need a special treatment since they are in a separate database + // Some filters need a special treatment since they are in a separate table reminderFilters := []builder.Cond{} + assigneeFilters := []builder.Cond{} var filters = make([]builder.Cond, 0, len(opts.filters)) // To still find tasks with nil values, we exclude 0s when comparing with >/< values. @@ -262,6 +284,16 @@ func getRawTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks [] continue } + if f.field == "assignees" { + f.field = "user_id" + filter, err := getFilterCond(f, opts.filterIncludeNulls) + if err != nil { + return nil, 0, 0, err + } + assigneeFilters = append(assigneeFilters, filter) + continue + } + filter, err := getFilterCond(f, opts.filterIncludeNulls) if err != nil { return nil, 0, 0, err @@ -315,22 +347,11 @@ func getRawTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks [] } if len(reminderFilters) > 0 { - var filtercond builder.Cond - if opts.filterConcat == filterConcatOr { - filtercond = builder.Or(reminderFilters...) - } - if opts.filterConcat == filterConcatAnd { - filtercond = builder.And(reminderFilters...) - } - reminderFilter := builder.In( - "id", - builder. - Select("task_id"). - From("task_reminders"). - Where(filtercond), - ) + filters = append(filters, getFilterCondForSeparateTable("task_reminders", opts.filterConcat, reminderFilters)) + } - filters = append(filters, reminderFilter) + if len(assigneeFilters) > 0 { + filters = append(filters, getFilterCondForSeparateTable("task_assignees", opts.filterConcat, assigneeFilters)) } query = query.Where(listCond) diff --git a/pkg/swagger/docs.go b/pkg/swagger/docs.go index d76499811f..734509c237 100644 --- a/pkg/swagger/docs.go +++ b/pkg/swagger/docs.go @@ -1892,7 +1892,7 @@ var doc = `{ }, { "type": "string", - "description": "The name of the field to filter by. Allowed values are all task properties except ` + "`" + `labels` + "`" + `, ` + "`" + `assignees` + "`" + `, ` + "`" + `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 ` + "`" + `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.", "name": "filter_by", "in": "query" }, @@ -1904,7 +1904,7 @@ var doc = `{ }, { "type": "string", - "description": "The comparator to use for a filter. Available values are ` + "`" + `equals` + "`" + `, ` + "`" + `greater` + "`" + `, ` + "`" + `greater_equals` + "`" + `, ` + "`" + `less` + "`" + `, ` + "`" + `less_equals` + "`" + ` and ` + "`" + `like` + "`" + `. Defaults to ` + "`" + `equals` + "`" + `", + "description": "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` + "`" + `", "name": "filter_comparator", "in": "query" }, @@ -3994,7 +3994,7 @@ var doc = `{ }, { "type": "string", - "description": "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` + "`" + `, ` + "`" + `text` + "`" + `, ` + "`" + `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` + "`" + `.", + "description": "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` + "`" + `.", "name": "sort_by", "in": "query" }, @@ -4006,7 +4006,7 @@ var doc = `{ }, { "type": "string", - "description": "The name of the field to filter by. 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 ` + "`" + `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.", "name": "filter_by", "in": "query" }, @@ -4018,7 +4018,7 @@ var doc = `{ }, { "type": "string", - "description": "The comparator to use for a filter. Available values are ` + "`" + `equals` + "`" + `, ` + "`" + `greater` + "`" + `, ` + "`" + `greater_equals` + "`" + `, ` + "`" + `less` + "`" + ` and ` + "`" + `less_equals` + "`" + `. Defaults to ` + "`" + `equals` + "`" + `", + "description": "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` + "`" + `", "name": "filter_comparator", "in": "query" }, @@ -4027,6 +4027,12 @@ var doc = `{ "description": "The concatinator to use for filters. Available values are ` + "`" + `and` + "`" + ` or ` + "`" + `or` + "`" + `. Defaults to ` + "`" + `or` + "`" + `.", "name": "filter_concat", "in": "query" + }, + { + "type": "string", + "description": "If set to true the result will include filtered fields whose value is set to ` + "`" + `null` + "`" + `. Available values are ` + "`" + `true` + "`" + ` or ` + "`" + `false` + "`" + `. Defaults to ` + "`" + `false` + "`" + `.", + "name": "filter_include_nulls", + "in": "query" } ], "responses": { diff --git a/pkg/swagger/swagger.json b/pkg/swagger/swagger.json index f9fb78832d..f1579ca9be 100644 --- a/pkg/swagger/swagger.json +++ b/pkg/swagger/swagger.json @@ -1875,7 +1875,7 @@ }, { "type": "string", - "description": "The name of the field to filter by. Allowed values are all task properties except `labels`, `assignees`, `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 `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.", "name": "filter_by", "in": "query" }, @@ -1887,7 +1887,7 @@ }, { "type": "string", - "description": "The comparator to use for a filter. Available values are `equals`, `greater`, `greater_equals`, `less`, `less_equals` and `like`. Defaults to `equals`", + "description": "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`", "name": "filter_comparator", "in": "query" }, @@ -3977,7 +3977,7 @@ }, { "type": "string", - "description": "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`, `text`, `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`.", + "description": "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`.", "name": "sort_by", "in": "query" }, @@ -3989,7 +3989,7 @@ }, { "type": "string", - "description": "The name of the field to filter by. 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 `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.", "name": "filter_by", "in": "query" }, @@ -4001,7 +4001,7 @@ }, { "type": "string", - "description": "The comparator to use for a filter. Available values are `equals`, `greater`, `greater_equals`, `less` and `less_equals`. Defaults to `equals`", + "description": "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`", "name": "filter_comparator", "in": "query" }, @@ -4010,6 +4010,12 @@ "description": "The concatinator to use for filters. Available values are `and` or `or`. Defaults to `or`.", "name": "filter_concat", "in": "query" + }, + { + "type": "string", + "description": "If set to true the result will include filtered fields whose value is set to `null`. Available values are `true` or `false`. Defaults to `false`.", + "name": "filter_include_nulls", + "in": "query" } ], "responses": { diff --git a/pkg/swagger/swagger.yaml b/pkg/swagger/swagger.yaml index 87300dd661..ab165aa2e1 100644 --- a/pkg/swagger/swagger.yaml +++ b/pkg/swagger/swagger.yaml @@ -2443,7 +2443,7 @@ paths: in: query name: order_by type: string - - description: The name of the field to filter by. Allowed values are all task properties except `labels`, `assignees`, `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 `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. in: query name: filter_by type: string @@ -2451,7 +2451,7 @@ paths: in: query name: filter_value type: string - - description: The comparator to use for a filter. Available values are `equals`, `greater`, `greater_equals`, `less`, `less_equals` and `like`. Defaults to `equals` + - description: 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` in: query name: filter_comparator type: string @@ -4459,7 +4459,7 @@ paths: in: query name: s type: string - - description: 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`, `text`, `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`. + - description: 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`. in: query name: sort_by type: string @@ -4467,7 +4467,7 @@ paths: in: query name: order_by type: string - - description: The name of the field to filter by. 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 `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. in: query name: filter_by type: string @@ -4475,7 +4475,7 @@ paths: in: query name: filter_value type: string - - description: The comparator to use for a filter. Available values are `equals`, `greater`, `greater_equals`, `less` and `less_equals`. Defaults to `equals` + - description: 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` in: query name: filter_comparator type: string @@ -4483,6 +4483,10 @@ paths: in: query name: filter_concat type: string + - description: If set to true the result will include filtered fields whose value is set to `null`. Available values are `true` or `false`. Defaults to `false`. + in: query + name: filter_include_nulls + type: string produces: - application/json responses: