Skip to content

Commit 25d8bc0

Browse files
committed
Datatables: Clear all type errors
1 parent 4a6a34f commit 25d8bc0

File tree

11 files changed

+504
-492
lines changed

11 files changed

+504
-492
lines changed

src/components/tables/DataTable/DataTable.stories.tsx

Lines changed: 0 additions & 98 deletions
This file was deleted.

src/components/tables/DataTable/DataTableEager.stories.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { delay } from '../util/async_util.ts';
1010
import { type User, generateData } from '../util/generateData.ts';
1111
import { useEffectAsync } from '../util/hooks.ts';
1212
import * as Filtering from './filtering/Filtering.ts';
13+
import type { Fields, FilterQuery } from '../MultiSearch/filterQuery.ts';
1314

1415
import { Panel } from '../../containers/Panel/Panel.tsx';
1516
import * as DataTablePlugins from './plugins/useRowSelectColumn.tsx';
@@ -50,7 +51,7 @@ const columns = [
5051
},
5152
];
5253

53-
const fields = {
54+
const fields: Fields = {
5455
name: {
5556
type: 'text',
5657
operators: ['$text'],
@@ -80,11 +81,12 @@ const fields = {
8081
operators: ['$eq', '$ne', '$lt', '$lte', '$gt', '$gte'],
8182
label: 'Days active',
8283
placeholder: 'Number of days active',
83-
accessor: (user: User) => differenceInDays(new Date(), user.joinDate),
84+
accessor: (item: unknown) => differenceInDays(new Date(), (item as User).joinDate),
8485
},
8586
};
8687

8788
type dataTeableEagerTemplateProps = DataTableEager.TableProviderEagerProps<User> & { delay: number };
89+
8890
const DataTableEagerTemplate = (props: dataTeableEagerTemplateProps) => {
8991
const memoizedColumns = React.useMemo(() => props.columns, [props.columns]);
9092
const memoizedItems = React.useMemo(() => props.items, [props.items]);
@@ -117,13 +119,18 @@ const DataTableEagerTemplate = (props: dataTeableEagerTemplateProps) => {
117119
const DataTableEagerWithFilterTemplate = (props: dataTeableEagerTemplateProps) => {
118120
const memoizedColumns = React.useMemo(() => props.columns, [props.columns]);
119121

120-
const [filters, setFilters] = React.useState([]);
121-
const [filteredItems, setFilteredItems] = React.useState(props.items);
122+
const [filters, setFilters] = React.useState<FilterQuery>([]);
123+
const [filteredItems, setFilteredItems] = React.useState<User[]>(props.items as User[]);
122124

125+
// Convert items array into a record
126+
const itemsAsRecord = React.useMemo(() => {
127+
return Object.fromEntries(props.items.map(item => [item.id, item])) as Record<string, User>;
128+
}, [props.items]);
129+
123130
React.useEffect(() => {
124-
const filtered = Filtering.filterByQuery(fields, props.items, filters);
125-
setFilteredItems(Object.values(filtered));
126-
}, [filters, props.items]);
131+
const filtered = Filtering.filterByQuery(fields, itemsAsRecord, filters);
132+
setFilteredItems(Object.values(filtered) as User[]);
133+
}, [filters, itemsAsRecord]);
127134

128135
return (
129136
<Panel>

src/components/tables/DataTable/DataTableEager.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,14 @@ export const TableProviderEager = <D extends object>(props: TableProviderEagerPr
9292
...plugins,
9393
);
9494

95-
const context = React.useMemo<TableContextState<D>>(() => ({
95+
// Note: the `table` reference is mutated, so cannot use it as dependency for `useMemo` directly
96+
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
97+
const context = React.useMemo<TableContextState<D>>(() => ({
9698
status: { ready: isReady, loading: false, error: null },
9799
setStatus() {},
98100
reload() {},
99101
table,
100102
}), [table.state, ...Object.values(tableOptions)]);
101-
// Note: the `table` reference is mutated, so cannot use it as dependency for `useMemo` directly
102103

103104
const TableContext = React.useMemo(() => createTableContext<D>(), []);
104105

@@ -151,7 +152,7 @@ export const DataTableEager = ({ children, className, footer, ...propsRest }: Da
151152
// Edge case: no items and yet we are not on the first page. Navigate back to the previous page.
152153
table.previousPage();
153154
}
154-
}, [table.page.length, table.state.pageIndex, table.canPreviousPage]);
155+
}, [table.page.length, table.state.pageIndex, table.canPreviousPage, table.previousPage]);
155156

156157
// Use `<Pagination/>` by default, unless the table is empty (in which case there are "zero" pages)
157158
const footerDefault = status.ready && table.rows.length > 0 ? <Pagination/> : null;

src/components/tables/DataTable/DataTableStream.stories.tsx

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,19 @@ const DataTableStreamTemplate = (props : dataTeableLazyTemplateProps) => {
4848

4949
const [itemsProcessed, setItemsProcessed] = useState<Array<User>>([]);
5050

51-
const query: DataTableStream.DataTableQuery<User, UserPageState> = useCallback(
51+
const query: DataTableStream.DataTableQuery<User, UserPageState | null> = useCallback(
5252
async ({ previousItem, previousPageState, limit, orderings, globalFilter }) => {
5353
if (delayQuery === Number.POSITIVE_INFINITY) return new Promise(() => {}); // Infinite delay
5454
if (delayQuery === -1) throw new Error('Failed'); // Simulate failure
5555

5656
if (delayQuery) await delay(delayQuery);
57+
58+
let offset = 0;
5759

58-
const previousItemIndex = items.indexOf(previousItem);
59-
const offset = previousItemIndex === -1 ? 0 : previousItemIndex + 1;
60+
if (previousItem) {
61+
const previousItemIndex = items.indexOf(previousItem);
62+
offset = previousItemIndex === -1 ? 0 : previousItemIndex + 1;
63+
}
6064

6165
const filteredItems = items
6266
.filter((row) => {
@@ -66,15 +70,24 @@ const DataTableStreamTemplate = (props : dataTeableLazyTemplateProps) => {
6670
if (!columnsFilterable.length) return false;
6771

6872
return columnsFilterable.some((column) => {
69-
const cell = typeof column.accessor === 'function' ? column.accessor(row) : undefined;
73+
const cell = typeof column.accessor === 'function'
74+
? column.accessor(row, 0, { subRows: [], depth: 0, data: [row] })
75+
: undefined;
7076
return typeof cell === 'string' && cell.toLowerCase().includes(globalFilter.trim().toLowerCase());
7177
});
7278
})
7379
.sort((a, b) => {
74-
if (!orderings.length) return 0;
80+
if (!orderings[0]) return 0;
7581
const { column, direction } = orderings[0];
7682
const factor = direction === 'DESC' ? -1 : 1;
77-
return a[column]?.localeCompare(b[column]) * factor || 0;
83+
84+
const aValue = a[column as keyof User];
85+
const bValue = b[column as keyof User];
86+
87+
const aNormalized = aValue instanceof Date ? aValue.toISOString() : aValue?.toString();
88+
const bNormalized = bValue instanceof Date ? bValue.toISOString() : bValue?.toString();
89+
90+
return (aNormalized?.localeCompare(bNormalized) || 0) * factor;
7891
})
7992
.slice(offset, offset + limit);
8093

src/components/tables/DataTable/DataTableStream.tsx

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ const usePageHistory = <D extends object, PageHistoryItem extends object>() => {
7171
},
7272
push: (pageIndex: PageIndex, pageHistoryItem: PageHistoryItem) => {
7373
const indices = [...pageHistory.keys()];
74-
const lastIndex: undefined | PageIndex = indices[indices.length - 1];
74+
// biome-ignore lint/style/noNonNullAssertion: <explanation>
75+
const lastIndex: PageIndex = indices[indices.length - 1]!;
7576
// Make sure the page indices are contiguous
7677
if (pageIndex > lastIndex + 1) {
7778
throw new Error('Non-contiguous page indices'); // Should never happen
@@ -355,13 +356,17 @@ export const TableProviderStream = <D extends object, P = undefined>(
355356
// to ensure the latest partial page state is stored.
356357
// 2. If end of stream hasn't been reached, then add the current page state to the
357358
// page history
358-
const itemLast = items.slice(-1)[0];
359+
const itemLast = items.slice(-1)[0] || null;
359360

360361
if (partialPageHistoryItem) {
361362
updatedPageHistory = updatedPageHistory.pop(state.pageIndex);
362363
}
363364

364-
updatedPageHistory = updatedPageHistory.push(state.pageIndex, { itemLast, pageState });
365+
const pageHistoryItem = pageState !== undefined
366+
? { itemLast, pageState }
367+
: { itemLast };
368+
369+
updatedPageHistory = updatedPageHistory.push(state.pageIndex, pageHistoryItem);
365370
}
366371

367372
// Update page history state
@@ -377,16 +382,13 @@ export const TableProviderStream = <D extends object, P = undefined>(
377382
return state;
378383
},
379384
useControlledState: state => {
380-
return React.useMemo(
381-
() => ({
382-
...state,
383-
pageSize,
384-
pageCount,
385-
endOfStream,
386-
partialStream,
387-
}),
388-
[state, pageSize, pageCount, endOfStream, partialStream],
389-
);
385+
return ({
386+
...state,
387+
pageSize,
388+
pageCount,
389+
endOfStream,
390+
partialStream,
391+
})
390392
},
391393

392394
// https://react-table.tanstack.com/docs/faq
@@ -424,6 +426,7 @@ export const TableProviderStream = <D extends object, P = undefined>(
424426
...plugins,
425427
);
426428

429+
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
427430
React.useEffect(() => {
428431
table.dispatch({ type: 'tableLoad' });
429432
}, []);
@@ -432,22 +435,24 @@ export const TableProviderStream = <D extends object, P = undefined>(
432435
table.dispatch({ type: 'reload' });
433436
};
434437

435-
const context = React.useMemo<TableContextState<D>>(() => ({
438+
// Note: the `table` reference is mutated, so cannot use it as dependency for `useMemo` directly
439+
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
440+
const context = React.useMemo<TableContextState<D>>(() => ({
436441
status,
437442
setStatus,
438443
reload,
439444
table,
440445
}), [
441446
JSON.stringify(status),
442-
// Note: the `table` reference is mutated, so cannot use it as dependency for `useMemo` directly
443447
table.state,
444448
...Object.values(tableOptions),
445449
]);
446450

447451
const TableContext = React.useMemo(() => createTableContext<D>(), []);
448452

449453
// If `pageSize` changes, we need to reset to the first page. Otherwise, our `previousItems` cache is no longer valid.
450-
React.useEffect(() => {
454+
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
455+
React.useEffect(() => {
451456
if (table.state.pageIndex !== 0) {
452457
table.gotoPage(0);
453458
}

0 commit comments

Comments
 (0)