diff --git a/src/frontend/src/hooks/UseFilter.tsx b/src/frontend/src/hooks/UseFilter.tsx index 2ae5399c04f7..b10a151082f6 100644 --- a/src/frontend/src/hooks/UseFilter.tsx +++ b/src/frontend/src/hooks/UseFilter.tsx @@ -44,7 +44,15 @@ export function useFilters(props: UseFilterProps) { }); const choices: TableFilterChoice[] = useMemo(() => { - return query.data?.map(props.transform) ?? []; + let opts = query.data?.map(props.transform) ?? []; + + // Ensure stringiness + return opts.map((opt: any) => { + return { + value: opt.value.toString(), + label: opt?.label?.toString() ?? opt.value.toString() + }; + }); }, [props.transform, query.data]); const refresh = useCallback(() => { diff --git a/src/frontend/src/tables/ColumnSelect.tsx b/src/frontend/src/tables/ColumnSelect.tsx index f0d83f8ecde9..cf858111058e 100644 --- a/src/frontend/src/tables/ColumnSelect.tsx +++ b/src/frontend/src/tables/ColumnSelect.tsx @@ -12,7 +12,7 @@ export function TableColumnSelect({ return ( - + diff --git a/src/frontend/src/tables/Filter.tsx b/src/frontend/src/tables/Filter.tsx index cf6d7aabe987..948ef95634df 100644 --- a/src/frontend/src/tables/Filter.tsx +++ b/src/frontend/src/tables/Filter.tsx @@ -72,8 +72,8 @@ export function StatusFilterOptions( return Object.keys(codes).map((key) => { const entry = codes[key]; return { - value: entry.key, - label: entry.label ?? entry.key + value: entry.key.toString(), + label: entry.label?.toString() ?? entry.key.toString() }; }); } diff --git a/src/frontend/src/tables/FilterSelectDrawer.tsx b/src/frontend/src/tables/FilterSelectDrawer.tsx index c159a6c59a42..2b79e30956b6 100644 --- a/src/frontend/src/tables/FilterSelectDrawer.tsx +++ b/src/frontend/src/tables/FilterSelectDrawer.tsx @@ -57,12 +57,6 @@ function FilterItem({ ); } -interface FilterProps extends React.ComponentPropsWithoutRef<'div'> { - name: string; - label: string; - description?: string; -} - function FilterAddGroup({ tableState, availableFilters @@ -182,6 +176,9 @@ export function FilterSelectDrawer({ withCloseButton={true} opened={opened} onClose={onClose} + closeButtonProps={{ + 'aria-label': 'filter-drawer-close' + }} title={{t`Table Filters`}} > diff --git a/src/frontend/src/tables/InvenTreeTable.tsx b/src/frontend/src/tables/InvenTreeTable.tsx index c372153d40ae..ef77ec65c5be 100644 --- a/src/frontend/src/tables/InvenTreeTable.tsx +++ b/src/frontend/src/tables/InvenTreeTable.tsx @@ -626,7 +626,7 @@ export function InvenTreeTable({ /> )} {tableProps.enableRefresh && ( - + refetch()} /> @@ -644,7 +644,10 @@ export function InvenTreeTable({ label={tableState.activeFilters?.length ?? 0} disabled={tableState.activeFilters?.length == 0} > - + setFiltersVisible(!filtersVisible)} diff --git a/src/frontend/tests/pui_tables.spec.ts b/src/frontend/tests/pui_tables.spec.ts new file mode 100644 index 000000000000..07ac23284749 --- /dev/null +++ b/src/frontend/tests/pui_tables.spec.ts @@ -0,0 +1,67 @@ +import { test } from './baseFixtures.js'; +import { baseUrl } from './defaults.js'; +import { doQuickLogin } from './login.js'; + +// Helper function to set the value of a specific table filter +const setFilter = async (page, name: string, value: string) => { + await page.getByLabel('table-select-filters').click(); + await page.getByRole('button', { name: 'Add Filter' }).click(); + await page.getByPlaceholder('Select filter').click(); + await page.getByRole('option', { name: name, exact: true }).click(); + await page.getByPlaceholder('Select filter value').click(); + await page.getByRole('option', { name: value, exact: true }).click(); + await page.getByLabel('filter-drawer-close').click(); +}; + +// Helper function to clear table filters +const clearFilters = async (page) => { + await page.getByLabel('table-select-filters').click(); + await page.getByRole('button', { name: 'Clear Filters' }).click(); + await page.getByLabel('filter-drawer-close').click(); +}; + +test('PUI - Tables - Filters', async ({ page }) => { + await doQuickLogin(page); + + // Head to the "build order list" page + await page.goto(`${baseUrl}/build/`); + + await setFilter(page, 'Status', 'Complete'); + await setFilter(page, 'Responsible', 'allaccess'); + await setFilter(page, 'Project Code', 'PRJ-NIM'); + + await clearFilters(page); + + // Head to the "part list" page + await page.goto(`${baseUrl}/part/category/index/parts/`); + + await setFilter(page, 'Assembly', 'Yes'); + + await clearFilters(page); + + // Head to the "purchase order list" page + await page.goto(`${baseUrl}/purchasing/index/purchaseorders/`); + + await setFilter(page, 'Status', 'Complete'); + await setFilter(page, 'Responsible', 'readers'); + await setFilter(page, 'Assigned to me', 'No'); + await setFilter(page, 'Project Code', 'PRO-ZEN'); + + await clearFilters(page); +}); + +test('PUI - Tables - Columns', async ({ page }) => { + await doQuickLogin(page); + + // Go to the "stock list" page + await page.goto(`${baseUrl}/stock/location/index/stock-items`); + + // Open column selector + await page.getByLabel('table-select-columns').click(); + + // De-select some items + await page.getByRole('menuitem', { name: 'Description' }).click(); + await page.getByRole('menuitem', { name: 'Stocktake' }).click(); + + await page.waitForTimeout(2500); +});