feat: add support for custom field filters in task listing#286
Conversation
- Implemented parsing and handling of custom field filters in the task handler. - Added tests for various custom field filter scenarios including select, number range, and date range filters. - Enhanced error handling for invalid JSON and unknown field keys in custom field filters. - Introduced regression tests to ensure stability against invalid stored values and field key reuse scenarios. - Updated API documentation to reflect new query parameters for custom field filters and importance ranges.
|
Run failed. View the logs →
|
|
Important Two concrete issues need fixing before merge: the date cast guard in the repository is missing an end anchor, and custom-field date bounds are not validated in the handler. Reviewed changes — PR #286 adds custom field filtering for task listing (select, multi_select, boolean, number, date, text, url), plus built-in filters for start/due date, story points, importance buckets, and tags.
Inline findings
|
|
Note: I attempted to submit the above review through
|
|
@pullfrog[bot] cannot successfully call
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — this run covered the one new fix commit and the incremental delta it introduces.
- End-anchored
customFieldDateExprregex — suffix-laden values like2024-01-01T...no longer pass the guard and crash on::date. - Capped importance bucket max at
2147483647— prevents an integer-overflow error whengetImportanceBucketBoundsis bound directly into SQLBETWEEN.
ℹ️ Custom-field date filter inputs remain unvalidated at the API boundary
The handler checks that custom_field_filters is valid JSON, but it does not validate that each date field's after/before strings are well-formed dates. The repository-level regex guard now prevents the previous SQLSTATE 22007 crash, so malformed requests silently return an empty result set instead of a 400. Consider aligning this with start_date_*/due_date_*, which already return CodeBadRequest.
ℹ️ Built-in date filters compare timestamp columns against midnight date bounds
start_date and due_date are stored as timestamps, while the new *_after and *_before params accept YYYY-MM-DD. A task due at mid-day on June 15 will be excluded by due_date_before=2024-06-15 because the comparison is against midnight. Decide whether "before the 15th" should mean before midnight at the start or end of the day.
Kimi K2 (free via Pullfrog for OSS) | 𝕏

Summary
Adds filtering by custom fields and several built-in task fields to view settings, available across every view type (Table/Board/Roadmap/Plugin — they share one settings panel and one filter-resolution path). Also fixes a filtering crash bug and removes two non-functional UI stubs.
What's new
Filtering (
apps/web,services/api)select/multi_select/booleanget a checklist selector,number/dateget an inclusive min/max or after/before range,text/urlget a debounced substring search. Sent as a single JSON query param (custom_field_filters) since fields are dynamic per project.GET /projects/:id/tasks:start_date_after/start_date_before,due_date_after/due_date_before,story_points_min/story_points_max,importance_ranges(JSON array of{min,max}, OR'd together),tags(comma-separated).Bug fix: custom-field filter crash (
SQLSTATE 22007)Reported repro: create a
selectfield, set a task's value to a string, delete the field, then create a new field reusing the samefield_keybut adatetype — filtering on it crashed the whole query instead of just excluding the bad row.DeleteCustomFieldDefinitionnow purges the field's stray values from every task in the project in the same transaction, so a later field reusing the key can no longer inherit incompatible data.custom_fieldsvalues through a regex-guardedCASE WHENinstead of a bare::numeric/::datecast, so any remaining invalid value is excluded (treated as no-match) rather than aborting the query — this closes the same latent crash class in the pre-existing custom-field sort and field-sum code paths too, not just the new filter code.Removed
onClick, no data). Time tracking should go through a plugin; Linked Tasks already covers relationships.Minor
newAttachmentRouter) caught by lint while working in that area.Test plan
go build ./... && go vet ./... && golangci-lint run ./...— clean.go test ./internal/... ./test/integration/...— full suite passes.services/api/test/e2e/task_filter_test.go— 15 test functions / 35 subtests against a real Postgres, covering all 7 custom-field types, all 5 built-in filters (including the non-contiguous importance-range OR case), multi-dimension AND composition,total_count/field_sumrespecting active filters, and validation-error paths (malformed dates, non-numeric story points,min > max). RanPACA_E2E=1 go test ./test/e2e/...for the full suite — all green, no regressions.apps/web:tsc -b,biome check ., and the fullvitestsuite all pass.