Add workflow column filtering to cards (#2787)

This commit is contained in:
Rob Zolkos
2026-04-14 13:14:14 -04:00
committed by GitHub
parent dd42f0a098
commit bb54b859dc
6 changed files with 42 additions and 1 deletions
+1
View File
@@ -35,6 +35,7 @@ class Filter < ApplicationRecord
result = terms.reduce(result) do |result, term| result = terms.reduce(result) do |result, term|
result.mentioning(term, user: creator) result.mentioning(term, user: creator)
end end
result = result.where(column_id: column_ids) if column_ids.present?
result.distinct result.distinct
end end
+9 -1
View File
@@ -31,7 +31,7 @@ module Filter::Fields
included do included do
store_accessor :fields, :assignment_status, :indexed_by, :sorted_by, :terms, store_accessor :fields, :assignment_status, :indexed_by, :sorted_by, :terms,
:card_ids, :creation, :closure :card_ids, :creation, :closure, :column_ids
def assignment_status def assignment_status
super.to_s.inquiry super.to_s.inquiry
@@ -60,6 +60,14 @@ module Filter::Fields
def terms=(value) def terms=(value)
super(Array(value).filter(&:present?)) super(Array(value).filter(&:present?))
end end
def column_ids
Array(super).filter(&:present?).uniq
end
def column_ids=(value)
super(Array(value).filter(&:present?).uniq)
end
end end
def with(**fields) def with(**fields)
+1
View File
@@ -8,6 +8,7 @@ module Filter::Params
:creation, :creation,
:closure, :closure,
card_ids: [], card_ids: [],
column_ids: [],
assignee_ids: [], assignee_ids: [],
creator_ids: [], creator_ids: [],
closer_ids: [], closer_ids: [],
+6
View File
@@ -16,6 +16,7 @@ __Query Parameters:__
| `creator_ids[]` | Filter by card creator ID(s) | | `creator_ids[]` | Filter by card creator ID(s) |
| `closer_ids[]` | Filter by user ID(s) who closed the cards | | `closer_ids[]` | Filter by user ID(s) who closed the cards |
| `card_ids[]` | Filter to specific card ID(s) | | `card_ids[]` | Filter to specific card ID(s) |
| `column_ids[]` | Filter by workflow column ID(s) |
| `indexed_by` | Filter by: `all` (default), `closed`, `not_now`, `stalled`, `postponing_soon`, `golden` | | `indexed_by` | Filter by: `all` (default), `closed`, `not_now`, `stalled`, `postponing_soon`, `golden` |
| `sorted_by` | Sort order: `latest` (default), `newest`, `oldest` | | `sorted_by` | Sort order: `latest` (default), `newest`, `oldest` |
| `assignment_status` | Filter by assignment status: `unassigned` | | `assignment_status` | Filter by assignment status: `unassigned` |
@@ -23,6 +24,11 @@ __Query Parameters:__
| `closure` | Filter by closure date: `today`, `yesterday`, `thisweek`, `lastweek`, `thismonth`, `lastmonth`, `thisyear`, `lastyear` | | `closure` | Filter by closure date: `today`, `yesterday`, `thisweek`, `lastweek`, `thismonth`, `lastmonth`, `thisyear`, `lastyear` |
| `terms[]` | Search terms to filter cards | | `terms[]` | Search terms to filter cards |
Repeated `column_ids[]` values are ORed together. Other filters combine with AND.
Example:
- `column_ids[]=03f...` — cards in a workflow column by ID
__Response:__ __Response:__
```json ```json
+14
View File
@@ -15,6 +15,20 @@ class CardsControllerTest < ActionDispatch::IntegrationTest
assert_response :success assert_response :success
end end
test "index as JSON can filter by workflow column id" do
get cards_path(format: :json), params: { column_ids: [ columns(:writebook_in_progress).id ] }
assert_response :success
assert_equal [ cards(:text).number ], @response.parsed_body.pluck("number")
end
test "index as JSON can OR multiple workflow column ids" do
get cards_path(format: :json), params: { column_ids: [ columns(:writebook_triage).id, columns(:writebook_in_progress).id ] }
assert_response :success
assert_equal [ cards(:logo).number, cards(:layout).number, cards(:text).number ].sort, @response.parsed_body.pluck("number").sort
end
test "create a new draft" do test "create a new draft" do
assert_difference -> { Card.count }, 1 do assert_difference -> { Card.count }, 1 do
post board_cards_path(boards(:writebook)) post board_cards_path(boards(:writebook))
+11
View File
@@ -166,6 +166,17 @@ class FilterTest < ActiveSupport::TestCase
assert_not users(:david).filters.new(board_ids: [ boards(:writebook).id ]).used?(ignore_boards: true) assert_not users(:david).filters.new(board_ids: [ boards(:writebook).id ]).used?(ignore_boards: true)
end end
test "column ids filter cards by workflow columns" do
assert_equal [ cards(:text) ], users(:david).filters.new(column_ids: [ columns(:writebook_in_progress).id ]).cards.to_a
assert_equal [ cards(:logo), cards(:layout) ].sort_by(&:id), users(:david).filters.new(column_ids: [ columns(:writebook_triage).id ]).cards.to_a.sort_by(&:id)
end
test "column ids are ORed together" do
filter = users(:david).filters.new(column_ids: [ columns(:writebook_triage).id, columns(:writebook_in_progress).id ])
assert_equal [ cards(:logo), cards(:layout), cards(:text) ].sort_by(&:id), filter.cards.to_a.sort_by(&:id)
end
test "board titles are scoped to creator's account" do test "board titles are scoped to creator's account" do
# Give mike (initech) access to the board in his account # Give mike (initech) access to the board in his account
boards(:miltons_wish_list).accesses.grant_to(users(:mike)) boards(:miltons_wish_list).accesses.grant_to(users(:mike))