Merge pull request #1142 from nowcommunity/fix/1137-localities-default-sort-name

Localities table: default sort by name
This commit is contained in:
Kari Lintulaakso
2026-04-22 12:37:40 +03:00
committed by GitHub
3 changed files with 76 additions and 11 deletions
@@ -435,6 +435,7 @@ export const LocalityTable = ({ selectorFn }: { selectorFn?: (newObject: Localit
selectorFn={selectorFn}
checkRowRestriction={checkRowRestriction}
idFieldName="lid"
defaultSorting={[{ id: 'loc_name', desc: false }]}
columns={columns}
isFetching={localitiesQueryIsFetching}
isError={localitiesQueryIsError}
@@ -21,11 +21,11 @@ jest.mock('@/hooks/user', () => ({
useUser: jest.fn(),
}))
const reactRouterDom = jest.requireActual<typeof import('react-router-dom')>('react-router-dom')
let mockLocationSearch = ''
jest.mock('react-router-dom', () => ({
...reactRouterDom,
useLocation: () => ({ search: '', pathname: '/table' }),
...jest.requireActual<typeof import('react-router-dom')>('react-router-dom'),
useLocation: () => ({ search: mockLocationSearch, pathname: '/table' }),
useNavigate: () => jest.fn(),
}))
@@ -44,6 +44,7 @@ const mockUseUser = useUser as jest.Mock
describe('TableView table help integration', () => {
beforeEach(() => {
mockLocationSearch = ''
mockUsePageContext.mockReturnValue({
editRights: {},
idList: [],
@@ -74,6 +75,55 @@ describe('TableView table help integration', () => {
})
})
it('uses defaultSorting when URL sorting is explicitly empty', () => {
mockLocationSearch = '?&columnfilters=[]&sorting=[]&pagination={"pageIndex":0,"pageSize":25}'
const setSqlOrderBy = jest.fn()
mockUsePageContext.mockReturnValue({
editRights: {},
idList: [],
idFieldName: 'id',
viewName: 'test',
previousTableUrls: [],
createTitle: () => '',
createSubtitle: () => '',
sqlLimit: 25,
sqlOffset: 0,
sqlColumnFilters: [],
sqlOrderBy: [],
setIdList: jest.fn(),
setSqlLimit: jest.fn(),
setSqlOffset: jest.fn(),
setSqlColumnFilters: jest.fn(),
setSqlOrderBy,
setPreviousTableUrls: jest.fn(),
})
render(
<TableView<TestRow>
title="Test Table"
idFieldName="id"
columns={[
{ header: 'Name', accessorKey: 'name' },
{ header: 'Id', accessorKey: 'id' },
]}
visibleColumns={{ name: true, id: true }}
data={[
{
id: '1',
name: 'Alpha',
full_count: 1,
},
]}
url="test"
isFetching={false}
defaultSorting={[{ id: 'name', desc: false }]}
/>
)
expect(setSqlOrderBy).toHaveBeenCalledWith([{ id: 'name', desc: false }])
})
it('shows help with multi-sort guidance for regular tables', () => {
const { getByRole, getByText } = render(
<TableView<TestRow>
@@ -69,6 +69,7 @@ export const TableView = <T extends MRT_RowData>({
columns,
visibleColumns,
idFieldName,
defaultSorting,
checkRowRestriction,
selectorFn,
tableRowAction,
@@ -93,6 +94,7 @@ export const TableView = <T extends MRT_RowData>({
columns: MRT_ColumnDef<T>[]
visibleColumns: MRT_VisibilityState
idFieldName: keyof T
defaultSorting?: MRT_SortingState
checkRowRestriction?: (row: T) => boolean
selectorFn?: (id: T) => void
tableRowAction?: (row: T) => void
@@ -124,7 +126,7 @@ export const TableView = <T extends MRT_RowData>({
setPreviousTableUrls,
} = usePageContext()
const [columnFilters, setColumnFilters] = useState<MRT_ColumnFiltersState>([])
const [sorting, setSorting] = useState<MRT_SortingState>([])
const [sorting, setSorting] = useState<MRT_SortingState>(defaultSorting ?? [])
const navigate = useNavigate()
const [pagination, setPagination] = useState<MRT_PaginationState>(
selectorFn ? defaultPaginationSmall : defaultPagination
@@ -185,7 +187,10 @@ export const TableView = <T extends MRT_RowData>({
return typeof candidate.pageIndex === 'number' && typeof candidate.pageSize === 'number'
}
const loadStateFromUrl = (state: TableStateInUrl, defaultState: [] | MRT_PaginationState) => {
const loadStateFromUrl = <TState extends MRT_ColumnFiltersState | MRT_SortingState | MRT_PaginationState>(
state: TableStateInUrl,
defaultState: TState
): TState => {
const searchParams = new URLSearchParams(location.search)
const stateFromUrl = searchParams.get(state)
if (!stateFromUrl) return defaultState
@@ -208,14 +213,23 @@ export const TableView = <T extends MRT_RowData>({
}
return columnFilter
})
return normalizedFilters
return normalizedFilters as unknown as TState
}
if (state === 'sorting') {
return isSortingState(parsed) ? parsed : defaultState
if (!isSortingState(parsed)) {
return defaultState
}
const fallback = defaultState as unknown as MRT_SortingState
if (parsed.length === 0 && fallback.length > 0) {
return defaultState
}
return parsed as unknown as TState
}
if (state === 'pagination') {
return isPaginationState(parsed) ? parsed : defaultState
return (isPaginationState(parsed) ? parsed : defaultState) as TState
}
return defaultState
@@ -440,9 +454,9 @@ export const TableView = <T extends MRT_RowData>({
// Load state from url only on first render
useEffect(() => {
if (selectorFn) return
setColumnFilters(loadStateFromUrl('columnfilters', []) as MRT_ColumnFiltersState)
setSorting(loadStateFromUrl('sorting', []) as MRT_SortingState)
setPagination(loadStateFromUrl('pagination', defaultPagination) as MRT_PaginationState)
setColumnFilters(loadStateFromUrl('columnfilters', []))
setSorting(loadStateFromUrl('sorting', defaultSorting ?? []))
setPagination(loadStateFromUrl('pagination', defaultPagination))
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])