fix(kanban): make loading tasks for a bucket work

This fixes two closely-related bugs:
1. When loading tasks from a bucket of a saved filter, the saved filter query would override the user-supplied filter, which would cause to only tasks matching the saved filter query to be returned.
2. When a filter query for a bucket was specified, the function would only check if one of the top level filters was a filter for tasks in a specific bucket. That means a filter like "bucket_id = 42 && labels = foo" would return the expected result, while a filter like "labels = foo && (bucket_id = 42 && priority = 1)" would fail with an error 500 because the task_buckets table was not joined to the sql query. The fix from the first bug caused such filter queries.
This commit is contained in:
kolaente 2024-10-02 10:41:38 +02:00
parent b6806acda0
commit 425f6378c6
No known key found for this signature in database
GPG Key ID: F40E70337AB24C9B
2 changed files with 27 additions and 11 deletions

View File

@ -262,6 +262,10 @@ func (tf *TaskCollection) ReadAll(s *xorm.Session, a web.Auth, search string, pa
tc.ProjectID = tf.ProjectID
tc.isSavedFilter = true
if tf.Filter != "" {
tc.Filter = "(" + tf.Filter + ") && (" + tc.Filter + ")"
}
return tc.ReadAll(s, a, search, page, perPage)
}
@ -281,11 +285,13 @@ func (tf *TaskCollection) ReadAll(s *xorm.Session, a web.Auth, search string, pa
}
}
if view.BucketConfigurationMode == BucketConfigurationModeFilter && strings.Contains(tf.Filter, "bucket_id") {
if strings.Contains(tf.Filter, "bucket_id") {
filteringForBucket = true
tf.Filter, err = getFilterValueForBucketFilter(tf.Filter, view)
if err != nil {
return nil, 0, 0, err
if view.BucketConfigurationMode == BucketConfigurationModeFilter {
tf.Filter, err = getFilterValueForBucketFilter(tf.Filter, view)
if err != nil {
return nil, 0, 0, err
}
}
}
}

View File

@ -206,6 +206,22 @@ func convertFiltersToDBFilterCond(rawFilters []*taskFilter, includeNulls bool) (
return filterCond, nil
}
func hasBucketIDInParsedFilter(filters []*taskFilter) bool {
for _, filter := range filters {
if subfilters, is := filter.value.([]*taskFilter); is {
has := hasBucketIDInParsedFilter(subfilters)
if has {
return true
}
}
if filter.field == taskPropertyBucketID {
return true
}
}
return false
}
//nolint:gocyclo
func (d *dbTaskSearcher) Search(opts *taskSearchOptions) (tasks []*Task, totalCount int64, err error) {
@ -214,13 +230,7 @@ func (d *dbTaskSearcher) Search(opts *taskSearchOptions) (tasks []*Task, totalCo
return nil, 0, err
}
var joinTaskBuckets bool
for _, filter := range opts.parsedFilters {
if filter.field == taskPropertyBucketID {
joinTaskBuckets = true
break
}
}
joinTaskBuckets := hasBucketIDInParsedFilter(opts.parsedFilters)
filterCond, err := convertFiltersToDBFilterCond(opts.parsedFilters, opts.filterIncludeNulls)
if err != nil {