Skip to content

Commit 90621db

Browse files
committed
update
1 parent 50ecbb1 commit 90621db

17 files changed

Lines changed: 564 additions & 350 deletions

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"tsc": "tsc"
4646
},
4747
"dependencies": {
48-
"@neolution-ch/react-pattern-ui": "2.9.0",
48+
"@neolution-ch/react-pattern-ui": "^3.1.0",
4949
"@tanstack/react-table": "^8.10.7",
5050
"react-loading-skeleton": "^3.3.1"
5151
},

src/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
export * from "./lib/translations/translations";
2+
export * from "./lib/useReactDataTableState.ts/useReactDataTableState";
3+
export * from "./lib/useReactDataTable/useReactDataTable";
14
export * from "./lib/ReactDataTable/ReactDataTable";
2-
export * from "./lib/ReactDataTable/ReactDataTableProps";
3-
export * from "./lib/ReactDataTable/translations";
4-
export * from "./lib/ReactDataTable/useReactDataTableState";
5+
export * from "./lib/utils/getStronglyTypedColumnFilter";
6+
export * from "./lib/useFullyControlledReactDataTable/useFullyControlledReactDataTable";
7+
export * from "./lib/utils/createReactDataTableColumnHelper";
Lines changed: 163 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,134 +1,179 @@
1-
/* eslint-disable complexity */
2-
import { getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table";
3-
import Skeleton from "react-loading-skeleton";
1+
import { faSortDown, faSortUp, faSearch, faTimes } from "@fortawesome/free-solid-svg-icons";
2+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
3+
import { Paging } from "@neolution-ch/react-pattern-ui";
4+
import { flexRender } from "@tanstack/react-table";
5+
import { Spinner, Table as ReactStrapTable, Input } from "reactstrap";
6+
import { reactDataTableTranslations } from "../translations/translations";
47
import { ReactDataTableProps } from "./ReactDataTableProps";
5-
import { useReactTableState } from "./useReactDataTableState";
6-
import { ReactDataTableRenderer } from "./ReactDataTableRenderer";
78

9+
/**
10+
* The table renderer for the react data table
11+
* @param props according to {@link ReactDataTableProps}
12+
*/
813
const ReactDataTable = <TData,>(props: ReactDataTableProps<TData>) => {
914
const {
10-
data = [],
11-
columns,
12-
onFilterChange,
13-
onSortingChange,
14-
onPaginationChange,
15-
reactTableOptions,
16-
state,
1715
isLoading,
18-
rowStyle,
1916
isFetching,
17+
table,
2018
tableClassName,
2119
tableStyle,
22-
showPaging = true,
23-
pageSizes = [5, 10, 25, 50, 100],
24-
totalRecords = data.length,
20+
rowStyle,
21+
pageSizes,
22+
showPaging,
23+
totalRecords = table.getCoreRowModel().rows.length,
2524
} = props;
2625

27-
const { columnFilters: columnFiltersProps, sorting: sortingProps, pagination: paginationProps } = state ?? {};
28-
29-
const {
30-
columnFilters: initialColumnFilters,
31-
sorting: initialSorting,
32-
pagination: initialPagination,
33-
} = reactTableOptions?.initialState ?? {};
34-
35-
const {
36-
sorting: internalSorting,
37-
columnFilters: internalColumnFilters,
38-
pagination: internalPagination,
39-
setColumnFilters: setInternalColumnFilters,
40-
setPagination: setInternalPagination,
41-
setSorting: setInternalSorting,
42-
} = useReactTableState({
43-
initialColumnFilters,
44-
initialSorting,
45-
initialPagination,
46-
});
47-
48-
const effectiveColumnFilters = columnFiltersProps ?? internalColumnFilters;
49-
const effectiveSorting = sortingProps ?? internalSorting;
50-
const effectivePagination = paginationProps ?? internalPagination;
51-
52-
if (!pageSizes.includes(effectivePagination.pageSize)) {
53-
throw new Error(`The page size ${effectivePagination.pageSize} is not in the list of possible page sizes ${pageSizes.join(", ")}`);
54-
}
55-
56-
if (onFilterChange && columnFiltersProps === undefined) {
57-
throw new Error("When using onFilterChange, the columnFilters state must be supplied");
58-
}
59-
60-
if (onSortingChange && sortingProps === undefined) {
61-
throw new Error("When using onSortingChange, the sorting state must be supplied");
62-
}
63-
64-
if (onPaginationChange && paginationProps === undefined) {
65-
throw new Error("When using onPaginationChange, the pagination state must be supplied");
66-
}
67-
68-
if (sortingProps !== undefined && onSortingChange === undefined) {
69-
throw new Error("When using sorting state, the onSortingChange callback must be supplied");
70-
}
71-
72-
if (columnFiltersProps !== undefined && onFilterChange === undefined) {
73-
throw new Error("When using columnFilters state, the onFilterChange callback must be supplied");
74-
}
75-
76-
if (paginationProps !== undefined && onPaginationChange === undefined) {
77-
throw new Error("When using pagination state, the onPaginationChange callback must be supplied");
78-
}
79-
80-
const skeletonColumns = columns.map((column) => ({
81-
...column,
82-
cell: () => <Skeleton />,
83-
}));
84-
const skeletonData = Array.from({ length: effectivePagination.pageSize }, () => ({} as TData));
85-
86-
const table = useReactTable<TData>({
87-
data: isLoading ? skeletonData : data,
88-
columns: isLoading ? skeletonColumns : columns,
89-
90-
manualFiltering: !!onFilterChange,
91-
manualSorting: !!onSortingChange,
92-
manualPagination: !!onPaginationChange,
93-
94-
enableColumnFilters: true,
95-
enableSorting: true,
96-
enableMultiSort: false,
97-
98-
getCoreRowModel: getCoreRowModel(),
99-
getFilteredRowModel: onFilterChange ? undefined : getFilteredRowModel(),
100-
getSortedRowModel: onSortingChange ? undefined : getSortedRowModel(),
101-
getPaginationRowModel: onPaginationChange ? undefined : getPaginationRowModel(),
102-
103-
onColumnFiltersChange: onFilterChange ? onFilterChange : setInternalColumnFilters,
104-
onSortingChange: onSortingChange ? onSortingChange : setInternalSorting,
105-
onPaginationChange: onPaginationChange ? onPaginationChange : setInternalPagination,
106-
107-
state: {
108-
columnFilters: effectiveColumnFilters,
109-
sorting: effectiveSorting,
110-
pagination: effectivePagination,
111-
},
112-
113-
...reactTableOptions,
114-
});
26+
const { pagination } = table.getState();
11527

116-
const effectiveTotalRecords = onFilterChange ? totalRecords : table.getFilteredRowModel().rows.length;
28+
console.log(table.getFooterGroups());
11729

11830
return (
119-
<ReactDataTableRenderer
120-
table={table}
121-
pageSizes={pageSizes}
122-
pagination={effectivePagination}
123-
totalRecords={effectiveTotalRecords}
124-
isFetching={isFetching}
125-
isLoading={isLoading}
126-
rowStyle={rowStyle}
127-
showPaging={showPaging}
128-
tableClassName={tableClassName}
129-
tableStyle={tableStyle}
130-
/>
31+
<>
32+
{!isLoading && isFetching && (
33+
<Spinner color="primary" type="grow">
34+
Loading...
35+
</Spinner>
36+
)}
37+
<ReactStrapTable striped hover size="sm" className={tableClassName} style={tableStyle}>
38+
<thead>
39+
{table.getHeaderGroups().map((headerGroup) => (
40+
<>
41+
<tr key={headerGroup.id}>
42+
{headerGroup.headers.map((header) => (
43+
<th
44+
key={header.id}
45+
onClick={header.column.getToggleSortingHandler()}
46+
style={header.column.getCanSort() ? { cursor: "pointer" } : {}}
47+
>
48+
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
49+
50+
{header.column.getIsSorted() === "desc" ? (
51+
<FontAwesomeIcon icon={faSortDown} />
52+
) : header.column.getIsSorted() === "asc" ? (
53+
<FontAwesomeIcon icon={faSortUp} />
54+
) : (
55+
""
56+
)}
57+
</th>
58+
))}
59+
</tr>
60+
<tr key={`${headerGroup.id}-col-filters`}>
61+
{headerGroup.headers.map((header) => {
62+
const {
63+
column: {
64+
columnDef: { meta },
65+
},
66+
} = header;
67+
68+
return (
69+
<>
70+
<th>
71+
{header.index === 0 && (
72+
<>
73+
<FontAwesomeIcon
74+
style={{ cursor: "pointer", marginBottom: "4px", marginRight: "5px" }}
75+
icon={faSearch}
76+
onClick={() => {
77+
// onSearch();
78+
}}
79+
/>
80+
81+
<FontAwesomeIcon
82+
style={{ cursor: "pointer", marginBottom: "4px", marginRight: "5px" }}
83+
icon={faTimes}
84+
onClick={() => {
85+
table.resetColumnFilters();
86+
}}
87+
/>
88+
</>
89+
)}
90+
91+
{header.column.getCanFilter() && (
92+
<>
93+
{meta?.dropdownFilter ? (
94+
<Input
95+
type="select"
96+
onChange={(e) => {
97+
header.column.setFilterValue(e.target.value);
98+
}}
99+
bsSize="sm"
100+
>
101+
{meta.dropdownFilter.options.map(({ label, value }, i) => (
102+
<option key={i} value={value}>
103+
{label}
104+
</option>
105+
))}
106+
</Input>
107+
) : (
108+
<Input
109+
type="text"
110+
value={(header.column.getFilterValue() as string) ?? ""}
111+
onChange={(e) => {
112+
header.column.setFilterValue(e.target.value);
113+
}}
114+
bsSize="sm"
115+
></Input>
116+
)}
117+
</>
118+
)}
119+
</th>
120+
</>
121+
);
122+
})}
123+
</tr>
124+
</>
125+
))}
126+
</thead>
127+
<tbody>
128+
{table.getRowModel().rows.length === 0 && (
129+
<tr>
130+
<td colSpan={table.getVisibleFlatColumns().length}>{reactDataTableTranslations.noEntries}</td>
131+
</tr>
132+
)}
133+
{table.getRowModel().rows.map((row) => (
134+
<tr key={row.id} style={rowStyle && rowStyle(row.original)}>
135+
{row.getVisibleCells().map((cell) => (
136+
<td key={cell.id} style={cell.column.columnDef.meta?.cellStyle}>
137+
{flexRender(cell.column.columnDef.cell, cell.getContext())}
138+
</td>
139+
))}
140+
</tr>
141+
))}
142+
</tbody>
143+
{table.getFooterGroups().length > 0 &&
144+
table.getFooterGroups().some((x) => x.headers.some((y) => !y.isPlaceholder && y.column.columnDef.footer)) && (
145+
<tfoot>
146+
{table.getFooterGroups().map((footerGroup) => (
147+
<tr key={footerGroup.id}>
148+
{footerGroup.headers.map((header) => (
149+
<th key={header.id}>{header.isPlaceholder ? null : flexRender(header.column.columnDef.footer, header.getContext())}</th>
150+
))}
151+
</tr>
152+
))}
153+
</tfoot>
154+
)}
155+
</ReactStrapTable>
156+
157+
{showPaging && (
158+
<Paging
159+
currentItemsPerPage={pagination.pageSize}
160+
currentPage={pagination.pageIndex + 1}
161+
totalRecords={totalRecords}
162+
currentRecordCount={table.getRowModel().rows.length}
163+
setItemsPerPage={(x) => {
164+
table.setPageSize(x);
165+
}}
166+
setCurrentPage={(x) => table.setPageIndex(x - 1)}
167+
possiblePageItemCounts={pageSizes}
168+
translations={{
169+
itemsPerPageDropdown: reactDataTableTranslations.itemsPerPageDropdown,
170+
showedItemsText: reactDataTableTranslations.showedItemsText,
171+
}}
172+
pagingPossible={true}
173+
/>
174+
)}
175+
</>
131176
);
132177
};
133178

134-
export { ReactDataTable };
179+
export { ReactDataTable, ReactDataTableProps };

0 commit comments

Comments
 (0)