From 7d21c7bdddc5bf5f9188fd43945116373b4d3669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tao=20Bojl=C3=A9n?= Date: Tue, 18 Aug 2026 10:34:33 +0100 Subject: [PATCH 1/2] Handle filters for removed table columns Co-authored-by: Amp Amp-Thread-ID: https://ampcode.com/threads/T-019fec69-19ab-77e8-b6f0-85af1ed67eed --- .../dashboard/components/table/Table.test.tsx | 48 +++++++++++++++++++ .../components/table/TableFilter.tsx | 20 +++++--- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/client/src/webpages/dashboard/components/table/Table.test.tsx b/client/src/webpages/dashboard/components/table/Table.test.tsx index 74ce24e4..cd76c782 100644 --- a/client/src/webpages/dashboard/components/table/Table.test.tsx +++ b/client/src/webpages/dashboard/components/table/Table.test.tsx @@ -349,6 +349,54 @@ describe('Table behavior', () => { expectAllRowsVisible(); }); + it('prunes staged filters when their columns are removed', () => { + const nameColumn = { + ...columns[0], + meta: { filter: filterFor('name', 'Filter names') }, + filterFn: 'text', + } satisfies TableColumnDef; + const statusColumn = { + ...columns[1], + meta: { filter: filterFor('status', 'Filter statuses') }, + filterFn: 'text', + } satisfies TableColumnDef; + const { rerender } = renderTable([nameColumn, statusColumn]); + + fireEvent.click(screen.getByRole('button', { name: /filter/i })); + const filterMenu = screen + .getByRole('button', { name: 'Save' }) + .closest('.absolute'); + expect(filterMenu).not.toBeNull(); + fireEvent.click(within(filterMenu!).getByText('Name')); + fireEvent.change(screen.getByPlaceholderText('Filter names'), { + target: { value: 'alp' }, + }); + + rerender( + + + , + ); + fireEvent.click(screen.getByRole('button', { name: 'Save' })); + + rerender( + +
+ , + ); + fireEvent.click(screen.getByRole('button', { name: /filter/i })); + const restoredFilterMenu = screen + .getByRole('button', { name: 'Save' }) + .closest('.absolute'); + expect(restoredFilterMenu).not.toBeNull(); + if (!screen.queryByPlaceholderText('Filter names')) { + fireEvent.click(within(restoredFilterMenu!).getByText('Name')); + } + expect( + (screen.getByPlaceholderText('Filter names') as HTMLInputElement).value, + ).toBe(''); + }); + it('renders links and selects a clicked row using its raw data', () => { const onSelectRow = vi.fn(); renderTable(columns, { diff --git a/client/src/webpages/dashboard/components/table/TableFilter.tsx b/client/src/webpages/dashboard/components/table/TableFilter.tsx index 9598e62c..0be78b41 100644 --- a/client/src/webpages/dashboard/components/table/TableFilter.tsx +++ b/client/src/webpages/dashboard/components/table/TableFilter.tsx @@ -72,10 +72,17 @@ export default function TableFilter(props: { }; const onSave = () => { + const missingColumnIds: string[] = []; for (const [columnId, value] of Object.entries(unsavedFilterValues)) { - filterColumns - .find((column) => column.id === columnId)! - .setFilterValue(value); + const column = filterColumns.find((column) => column.id === columnId); + if (!column) { + missingColumnIds.push(columnId); + continue; + } + column.setFilterValue(value); + } + if (missingColumnIds.length > 0) { + setUnsavedFilterValues(omit(unsavedFilterValues, missingColumnIds)); } setMenuVisible(false); }; @@ -92,9 +99,10 @@ export default function TableFilter(props: { const removeFilter = (columnId: string) => { setUnsavedFilterValues(omit(unsavedFilterValues, columnId)); - filterColumns - .find((column) => column.id === columnId)! - .setFilterValue(undefined); + const column = filterColumns.find((column) => column.id === columnId); + if (column) { + column.setFilterValue(undefined); + } }; const activeFilters = filterColumns.filter((column) => From c2f7e9f5da9a4f2c248dcb687d7f0ee615e149d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tao=20Bojl=C3=A9n?= Date: Tue, 18 Aug 2026 12:35:17 +0100 Subject: [PATCH 2/2] Fix table filter test lint Co-authored-by: Amp Amp-Thread-ID: https://ampcode.com/threads/T-019fec69-19ab-77e8-b6f0-85af1ed67eed --- client/src/webpages/dashboard/components/table/Table.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/webpages/dashboard/components/table/Table.test.tsx b/client/src/webpages/dashboard/components/table/Table.test.tsx index cd76c782..5f7c6c85 100644 --- a/client/src/webpages/dashboard/components/table/Table.test.tsx +++ b/client/src/webpages/dashboard/components/table/Table.test.tsx @@ -393,7 +393,7 @@ describe('Table behavior', () => { fireEvent.click(within(restoredFilterMenu!).getByText('Name')); } expect( - (screen.getByPlaceholderText('Filter names') as HTMLInputElement).value, + screen.getByPlaceholderText('Filter names').value, ).toBe(''); });