@addev-be/ui 0.2.6 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/icons/arrow-down-1-9.svg +1 -0
- package/assets/icons/arrow-down-big-small.svg +1 -0
- package/assets/icons/arrow-up-9-1.svg +1 -0
- package/assets/icons/arrow-up-big-small.svg +1 -0
- package/assets/icons/chevron-down.svg +1 -0
- package/assets/icons/ellipsis.svg +1 -0
- package/assets/icons/sigma.svg +1 -0
- package/assets/icons/table-footer-slash.svg +5 -0
- package/assets/icons/table-footer.svg +4 -0
- package/assets/icons/table.svg +1 -0
- package/assets/icons/tally.svg +1 -0
- package/assets/icons/x-bar.svg +4 -0
- package/dist/Icons.d.ts +13 -1
- package/dist/Icons.js +25 -1
- package/dist/components/data/AdvancedRequestDataGrid/index.js +3 -3
- package/dist/components/data/DataGrid/DataGridColumnsModal/hooks.js +2 -1
- package/dist/components/data/DataGrid/DataGridFilterMenu/index.js +85 -7
- package/dist/components/data/DataGrid/DataGridFilterMenu/styles.d.ts +3 -9
- package/dist/components/data/DataGrid/DataGridFilterMenu/styles.js +10 -37
- package/dist/components/data/DataGrid/DataGridFooter.d.ts +1 -1
- package/dist/components/data/DataGrid/DataGridFooter.js +35 -12
- package/dist/components/data/DataGrid/DataGridHeader.js +1 -1
- package/dist/components/data/DataGrid/DataGridHeaderCell.js +6 -22
- package/dist/components/data/DataGrid/helpers/columns.d.ts +1 -1
- package/dist/components/data/DataGrid/helpers/columns.js +71 -16
- package/dist/components/data/DataGrid/hooks/useDataGrid.d.ts +1 -1
- package/dist/components/data/DataGrid/hooks/useDataGrid.js +60 -30
- package/dist/components/data/DataGrid/hooks/useDataGridCopy.d.ts +2 -2
- package/dist/components/data/DataGrid/hooks/useDataGridCopy.js +41 -39
- package/dist/components/data/DataGrid/index.d.ts +4 -2
- package/dist/components/data/DataGrid/index.js +22 -12
- package/dist/components/data/DataGrid/styles.d.ts +8 -4
- package/dist/components/data/DataGrid/styles.js +27 -17
- package/dist/components/data/DataGrid/types.d.ts +8 -1
- package/dist/components/data/SqlRequestDataGrid/helpers/columns.d.ts +1 -1
- package/dist/components/data/SqlRequestDataGrid/helpers/columns.js +24 -11
- package/dist/components/data/SqlRequestDataGrid/index.js +105 -33
- package/dist/components/ui/ContextMenu/index.d.ts +11 -0
- package/dist/components/ui/ContextMenu/index.js +58 -0
- package/dist/components/ui/ContextMenu/styles.d.ts +18 -0
- package/dist/components/ui/ContextMenu/styles.js +56 -0
- package/dist/services/advancedRequests.d.ts +1 -1
- package/dist/services/sqlRequests.d.ts +9 -4
- package/dist/services/sqlRequests.js +1 -0
- package/package.json +1 -1
- package/src/Icons.tsx +24 -0
- package/src/components/data/AdvancedRequestDataGrid/index.tsx +3 -5
- package/src/components/data/DataGrid/DataGridColumnsModal/hooks.tsx +2 -1
- package/src/components/data/DataGrid/DataGridFilterMenu/index.tsx +180 -22
- package/src/components/data/DataGrid/DataGridFilterMenu/styles.ts +13 -64
- package/src/components/data/DataGrid/DataGridFooter.tsx +20 -22
- package/src/components/data/DataGrid/DataGridHeader.tsx +5 -5
- package/src/components/data/DataGrid/DataGridHeaderCell.tsx +3 -38
- package/src/components/data/DataGrid/FilterValuesScroller.tsx +33 -27
- package/src/components/data/DataGrid/helpers/columns.tsx +103 -8
- package/src/components/data/DataGrid/helpers/filters.ts +29 -19
- package/src/components/data/DataGrid/hooks/useDataGrid.tsx +58 -17
- package/src/components/data/DataGrid/hooks/useDataGridCopy.ts +35 -30
- package/src/components/data/DataGrid/index.tsx +22 -14
- package/src/components/data/DataGrid/styles.ts +50 -9
- package/src/components/data/DataGrid/types.ts +24 -3
- package/src/components/data/SqlRequestDataGrid/helpers/columns.tsx +39 -3
- package/src/components/data/SqlRequestDataGrid/index.tsx +116 -21
- package/src/components/ui/ContextMenu/index.tsx +79 -0
- package/src/components/ui/ContextMenu/styles.ts +119 -0
- package/src/services/advancedRequests.ts +1 -1
- package/src/services/sqlRequests.ts +16 -5
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as styles from './styles';
|
|
2
2
|
|
|
3
|
+
import { DataGridContextProps, DataGridProps } from './types';
|
|
4
|
+
|
|
3
5
|
import { DataGridCell } from './DataGridCell';
|
|
4
6
|
import { DataGridFooter } from './DataGridFooter';
|
|
5
7
|
import { DataGridHeader } from './DataGridHeader';
|
|
6
|
-
import { DataGridProps } from './types';
|
|
7
8
|
import { VirtualScroller } from './VirtualScroller';
|
|
8
9
|
import { useCallback } from 'react';
|
|
9
10
|
import { useDataGrid } from './hooks';
|
|
@@ -11,13 +12,18 @@ import { useDataGrid } from './hooks';
|
|
|
11
12
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
12
13
|
/* eslint-disable @typescript-eslint/no-unnecessary-type-constraint */
|
|
13
14
|
|
|
14
|
-
export const DataGrid = <R,>(
|
|
15
|
+
export const DataGrid = <R,>({
|
|
16
|
+
contextOverride,
|
|
17
|
+
...props
|
|
18
|
+
}: DataGridProps<R> & {
|
|
19
|
+
contextOverride?: Partial<DataGridContextProps<R>>;
|
|
20
|
+
}) => {
|
|
15
21
|
const {
|
|
16
22
|
className,
|
|
17
23
|
// onRowDoubleClick,
|
|
18
24
|
onVisibleRowsChange,
|
|
19
25
|
} = props;
|
|
20
|
-
const [contextProps, DataGridContext] = useDataGrid(props);
|
|
26
|
+
const [contextProps, DataGridContext] = useDataGrid(props, contextOverride);
|
|
21
27
|
const {
|
|
22
28
|
selectedKeys,
|
|
23
29
|
setSelectedKeys,
|
|
@@ -32,17 +38,15 @@ export const DataGrid = <R,>(props: DataGridProps<R>) => {
|
|
|
32
38
|
|
|
33
39
|
const hasFooter = Object.values(columns).some((col) => col.footer);
|
|
34
40
|
|
|
35
|
-
const
|
|
36
|
-
(
|
|
37
|
-
|
|
38
|
-
if (selected) {
|
|
39
|
-
if (!selectedKeys.includes(key))
|
|
40
|
-
setSelectedKeys([...selectedKeys, key]);
|
|
41
|
-
} else {
|
|
41
|
+
const toggleSelection = useCallback(
|
|
42
|
+
(key: string) => {
|
|
43
|
+
if (selectedKeys.includes(key)) {
|
|
42
44
|
setSelectedKeys(selectedKeys.filter((p) => p !== key));
|
|
45
|
+
} else {
|
|
46
|
+
setSelectedKeys([...selectedKeys, key]);
|
|
43
47
|
}
|
|
44
48
|
},
|
|
45
|
-
[
|
|
49
|
+
[selectedKeys, setSelectedKeys]
|
|
46
50
|
);
|
|
47
51
|
|
|
48
52
|
const rowTemplate = useCallback(
|
|
@@ -74,12 +78,15 @@ export const DataGrid = <R,>(props: DataGridProps<R>) => {
|
|
|
74
78
|
return (
|
|
75
79
|
<styles.DataGridRow key={key}>
|
|
76
80
|
{!!props.selectable && (
|
|
77
|
-
<styles.SelectionCell
|
|
81
|
+
<styles.SelectionCell
|
|
82
|
+
key="__select_checkbox__"
|
|
83
|
+
onClick={() => toggleSelection(key)}
|
|
84
|
+
>
|
|
78
85
|
<input
|
|
79
86
|
type="checkbox"
|
|
80
87
|
value={key as string}
|
|
81
88
|
checked={selectedKeys.includes(key)}
|
|
82
|
-
|
|
89
|
+
readOnly
|
|
83
90
|
/>
|
|
84
91
|
</styles.SelectionCell>
|
|
85
92
|
)}
|
|
@@ -103,7 +110,7 @@ export const DataGrid = <R,>(props: DataGridProps<R>) => {
|
|
|
103
110
|
props,
|
|
104
111
|
rowKeyGetter,
|
|
105
112
|
selectedKeys,
|
|
106
|
-
|
|
113
|
+
toggleSelection,
|
|
107
114
|
visibleColumns,
|
|
108
115
|
]
|
|
109
116
|
);
|
|
@@ -116,6 +123,7 @@ export const DataGrid = <R,>(props: DataGridProps<R>) => {
|
|
|
116
123
|
$headerRowHeight={headerRowHeight}
|
|
117
124
|
$rowHeight={rowHeight}
|
|
118
125
|
$rowsCount={contextProps.sortedRows.length}
|
|
126
|
+
$withFooter={hasFooter}
|
|
119
127
|
className={className}
|
|
120
128
|
>
|
|
121
129
|
<DataGridHeader context={DataGridContext} />
|
|
@@ -5,6 +5,7 @@ import { ThemeColor } from '../../../providers/ThemeProvider/types';
|
|
|
5
5
|
export const VIRTUAL_SCROLL_TOLERANCE = 20;
|
|
6
6
|
export const TOOLBAR_HEIGHT = 40;
|
|
7
7
|
export const DEFAULT_HEADER_ROW_HEIGHT = 40;
|
|
8
|
+
export const DEFAULT_FOOTER_ROW_HEIGHT = 40;
|
|
8
9
|
export const DEFAULT_ROW_HEIGHT = 32;
|
|
9
10
|
export const DEFAULT_FILTER_ROW_HEIGHT = 24;
|
|
10
11
|
|
|
@@ -175,6 +176,7 @@ export const DataGridContainer = styled.div<{
|
|
|
175
176
|
$rowHeight?: number;
|
|
176
177
|
$rowsCount: number;
|
|
177
178
|
$showToolsHeader?: boolean;
|
|
179
|
+
$withFooter?: boolean;
|
|
178
180
|
}>`
|
|
179
181
|
display: grid;
|
|
180
182
|
width: 100%;
|
|
@@ -182,8 +184,13 @@ export const DataGridContainer = styled.div<{
|
|
|
182
184
|
background-color: var(--color-neutral-50);
|
|
183
185
|
font-size: var(--text-base);
|
|
184
186
|
overflow: scroll;
|
|
185
|
-
grid-template-rows: ${({
|
|
186
|
-
|
|
187
|
+
grid-template-rows: ${({
|
|
188
|
+
$headerRowHeight = DEFAULT_HEADER_ROW_HEIGHT,
|
|
189
|
+
$withFooter = false,
|
|
190
|
+
}) =>
|
|
191
|
+
`${TOOLBAR_HEIGHT}px ${$headerRowHeight}px auto ${
|
|
192
|
+
$withFooter ? DEFAULT_FOOTER_ROW_HEIGHT + 'px' : ''
|
|
193
|
+
}`};
|
|
187
194
|
|
|
188
195
|
${DataGridToolsRow} {
|
|
189
196
|
height: ${TOOLBAR_HEIGHT}px;
|
|
@@ -208,21 +215,18 @@ export const DataGridContainer = styled.div<{
|
|
|
208
215
|
`;
|
|
209
216
|
DataGridContainer.displayName = 'DataGridContainer';
|
|
210
217
|
|
|
211
|
-
|
|
218
|
+
type DataGridHeaderOrFooterRowProps = {
|
|
212
219
|
$headerRowHeight?: number;
|
|
213
220
|
$headerColor?: ThemeColor;
|
|
214
221
|
$gridTemplateColumns: string;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
},
|
|
219
|
-
}))`
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
const dataGridHeaderOrFooterRowCss = css<DataGridHeaderOrFooterRowProps>`
|
|
220
225
|
display: grid;
|
|
221
226
|
grid-template-rows: ${({ $headerRowHeight = DEFAULT_HEADER_ROW_HEIGHT }) =>
|
|
222
227
|
`${$headerRowHeight}px`};
|
|
223
228
|
z-index: 10;
|
|
224
229
|
position: sticky;
|
|
225
|
-
top: ${TOOLBAR_HEIGHT}px;
|
|
226
230
|
align-items: center;
|
|
227
231
|
|
|
228
232
|
${({ $headerColor }) =>
|
|
@@ -236,8 +240,31 @@ export const DataGridHeaderRow = styled.div.attrs<{
|
|
|
236
240
|
color: var(--color-neutral-900);
|
|
237
241
|
`}
|
|
238
242
|
`;
|
|
243
|
+
|
|
244
|
+
export const DataGridHeaderRow = styled.div.attrs<DataGridHeaderOrFooterRowProps>(
|
|
245
|
+
({ $gridTemplateColumns }) => ({
|
|
246
|
+
style: {
|
|
247
|
+
gridTemplateColumns: $gridTemplateColumns,
|
|
248
|
+
},
|
|
249
|
+
})
|
|
250
|
+
)`
|
|
251
|
+
${dataGridHeaderOrFooterRowCss}
|
|
252
|
+
top: ${TOOLBAR_HEIGHT}px;
|
|
253
|
+
`;
|
|
239
254
|
DataGridHeaderRow.displayName = 'DataGridHeaderRow';
|
|
240
255
|
|
|
256
|
+
export const DataGridFooterRow = styled.div.attrs<DataGridHeaderOrFooterRowProps>(
|
|
257
|
+
({ $gridTemplateColumns }) => ({
|
|
258
|
+
style: {
|
|
259
|
+
gridTemplateColumns: $gridTemplateColumns,
|
|
260
|
+
},
|
|
261
|
+
})
|
|
262
|
+
)`
|
|
263
|
+
${dataGridHeaderOrFooterRowCss}
|
|
264
|
+
bottom: 0;
|
|
265
|
+
`;
|
|
266
|
+
DataGridFooterRow.displayName = 'DataGridFooterRow';
|
|
267
|
+
|
|
241
268
|
export const DataGridRow = styled.div`
|
|
242
269
|
display: contents;
|
|
243
270
|
`;
|
|
@@ -262,6 +289,7 @@ const selectionCellStyle = css`
|
|
|
262
289
|
justify-content: center;
|
|
263
290
|
width: var(--space-8);
|
|
264
291
|
padding: 0 var(--space-1);
|
|
292
|
+
cursor: pointer;
|
|
265
293
|
|
|
266
294
|
& > input[type='checkbox'] {
|
|
267
295
|
height: var(--space-4);
|
|
@@ -324,3 +352,16 @@ export const FilterValuesScrollerContainer = styled.div.attrs({
|
|
|
324
352
|
}
|
|
325
353
|
}
|
|
326
354
|
`;
|
|
355
|
+
|
|
356
|
+
export const FilterValueContainer = styled.div.attrs({
|
|
357
|
+
className: 'FilterValueContainer',
|
|
358
|
+
})`
|
|
359
|
+
position: absolute;
|
|
360
|
+
display: flex;
|
|
361
|
+
flex-direction: row;
|
|
362
|
+
align-items: center;
|
|
363
|
+
cursor: pointer;
|
|
364
|
+
&:hover {
|
|
365
|
+
background-color: var(--color-neutral-50);
|
|
366
|
+
}
|
|
367
|
+
`;
|
|
@@ -21,13 +21,28 @@ export type DataGridCellFC = FC<{
|
|
|
21
21
|
style?: CSSProperties;
|
|
22
22
|
}>;
|
|
23
23
|
|
|
24
|
+
export type DataGridFooterPredefinedFunction =
|
|
25
|
+
| 'average'
|
|
26
|
+
| 'avg'
|
|
27
|
+
| 'count'
|
|
28
|
+
| 'max'
|
|
29
|
+
| 'min'
|
|
30
|
+
| 'sum';
|
|
31
|
+
export type DataGridFooterFunction<R> = (
|
|
32
|
+
allRows: R[],
|
|
33
|
+
filteredRows: R[],
|
|
34
|
+
selectedRows: R[]
|
|
35
|
+
) => ReactNode;
|
|
36
|
+
|
|
24
37
|
export type DataGridColumn<R> = {
|
|
25
38
|
component?: DataGridCellFC;
|
|
26
39
|
editable?: boolean;
|
|
27
40
|
excelFormatter?: (value: any) => string;
|
|
28
41
|
excelValue?: (value: any) => string;
|
|
29
42
|
filter?: DataGridFilter;
|
|
30
|
-
footer?:
|
|
43
|
+
footer?:
|
|
44
|
+
| DataGridFooterFunction<R>
|
|
45
|
+
| Record<string, DataGridFooterFunction<R> | null>;
|
|
31
46
|
getter?: (row: R) => string | number;
|
|
32
47
|
name: string;
|
|
33
48
|
order?: number;
|
|
@@ -71,6 +86,8 @@ export type DataGridProps<R> = {
|
|
|
71
86
|
filter?: boolean;
|
|
72
87
|
sort?: boolean;
|
|
73
88
|
initialSorts?: Record<string, DataGridSort>;
|
|
89
|
+
initialFooters?: Record<string, string>;
|
|
90
|
+
onFootersChanged?: (footers: Record<string, string>) => void;
|
|
74
91
|
filterValuesLoader?: (
|
|
75
92
|
columnKey: string
|
|
76
93
|
) => Promise<(string | number | null)[]>;
|
|
@@ -94,6 +111,9 @@ export type DataGridContextProps<R> = DataGridProps<R> & {
|
|
|
94
111
|
setSorts: (sorts: Record<string, DataGridSort>) => void;
|
|
95
112
|
filters?: DataGridFilters;
|
|
96
113
|
setFilters: Dispatch<SetStateAction<DataGridFilters>>;
|
|
114
|
+
footers?: Record<string, string>;
|
|
115
|
+
setFooters: Dispatch<SetStateAction<Record<string, string>>>;
|
|
116
|
+
footerFunctions?: Record<string, DataGridFooterFunction<R>>;
|
|
97
117
|
visibleColumns: DataGridColumnKeyValuePair<R>[];
|
|
98
118
|
copyTable: (
|
|
99
119
|
includeHeaders?: boolean,
|
|
@@ -227,7 +247,8 @@ export type DataGridFilter<T extends string = DataGridFilterType> =
|
|
|
227
247
|
|
|
228
248
|
export type DataGridFilterGroup = {
|
|
229
249
|
name: string;
|
|
230
|
-
|
|
250
|
+
displayValue: DataGridFilterValue;
|
|
251
|
+
values?: DataGridFilterValue[];
|
|
231
252
|
groups?: DataGridFilterGroup[];
|
|
232
253
|
};
|
|
233
254
|
|
|
@@ -236,6 +257,6 @@ export type DataGridFilterValue = string | number | null;
|
|
|
236
257
|
export type DataGridFilterCheckbox = {
|
|
237
258
|
displayValue: ReactNode;
|
|
238
259
|
title: string;
|
|
239
|
-
|
|
260
|
+
values: DataGridFilterValue[];
|
|
240
261
|
level: number;
|
|
241
262
|
};
|
|
@@ -22,6 +22,7 @@ export const sqlTextColumn = <R extends Record<string, any>>(
|
|
|
22
22
|
sortGetter: (row) => row[key] ?? '',
|
|
23
23
|
filter: { ...textFilter(key), getter: (value) => value[key] ?? '' },
|
|
24
24
|
...options,
|
|
25
|
+
footer: (rows) => `${rows[0][key]} éléments`,
|
|
25
26
|
},
|
|
26
27
|
});
|
|
27
28
|
|
|
@@ -54,6 +55,7 @@ export const sqlComposedColumn = <R extends Record<string, any>>(
|
|
|
54
55
|
},
|
|
55
56
|
filterField: fields[0],
|
|
56
57
|
sortField: fields[0],
|
|
58
|
+
footer: (rows) => `${rows[0][key]} éléments`,
|
|
57
59
|
...options,
|
|
58
60
|
},
|
|
59
61
|
});
|
|
@@ -69,6 +71,7 @@ export const sqlMailColumn = <R extends Record<string, any>>(
|
|
|
69
71
|
getter: (row) => row[key] ?? '',
|
|
70
72
|
sortGetter: (row) => row[key] ?? '',
|
|
71
73
|
filter: { ...textFilter(key), getter: (value) => value[key] ?? '' },
|
|
74
|
+
footer: (rows) => `${rows[0][key]} éléments`,
|
|
72
75
|
...options,
|
|
73
76
|
},
|
|
74
77
|
});
|
|
@@ -84,6 +87,7 @@ export const sqlPhoneColumn = <R extends Record<string, any>>(
|
|
|
84
87
|
getter: (row) => row[key] ?? '',
|
|
85
88
|
sortGetter: (row) => row[key] ?? '',
|
|
86
89
|
filter: { ...textFilter(key), getter: (value) => value[key] ?? '' },
|
|
90
|
+
footer: (rows) => `${rows[0][key]} éléments`,
|
|
87
91
|
...options,
|
|
88
92
|
},
|
|
89
93
|
});
|
|
@@ -95,10 +99,12 @@ export const sqlDateColumn = <R extends Record<string, any>>(
|
|
|
95
99
|
): SqlRequestDataGridColumns<R> => ({
|
|
96
100
|
[key]: {
|
|
97
101
|
name: title,
|
|
102
|
+
type: 'date',
|
|
98
103
|
render: (row) => formatDate(row[key]),
|
|
99
104
|
getter: (row) => row[key] ?? '',
|
|
100
105
|
sortGetter: (row) => row[key] ?? '',
|
|
101
106
|
filter: { ...textFilter(key), getter: (value) => value[key] ?? '' },
|
|
107
|
+
footer: (rows) => `${rows[0][key]} éléments`,
|
|
102
108
|
...options,
|
|
103
109
|
},
|
|
104
110
|
});
|
|
@@ -114,6 +120,7 @@ export const sqlMonthColumn = <R extends Record<string, any>>(
|
|
|
114
120
|
getter: (row) => row[key] ?? '',
|
|
115
121
|
sortGetter: (row) => row[key] ?? '',
|
|
116
122
|
filter: { ...textFilter(key), getter: (value) => value[key] ?? '' },
|
|
123
|
+
footer: (rows) => `${rows[0][key]} éléments`,
|
|
117
124
|
...options,
|
|
118
125
|
},
|
|
119
126
|
});
|
|
@@ -130,7 +137,18 @@ export const sqlNumberColumn = <R extends Record<string, any>>(
|
|
|
130
137
|
excelFormatter: () => '#',
|
|
131
138
|
getter: (row) => row[key] ?? '',
|
|
132
139
|
sortGetter: (row) => row[key] ?? '',
|
|
133
|
-
filter: {
|
|
140
|
+
filter: {
|
|
141
|
+
...numberFilter(key),
|
|
142
|
+
getter: (value) => value[key] ?? 0,
|
|
143
|
+
renderer: (value) => formatNumber(value, decimals) ?? '',
|
|
144
|
+
},
|
|
145
|
+
footer: {
|
|
146
|
+
sum: null,
|
|
147
|
+
avg: null,
|
|
148
|
+
count: null,
|
|
149
|
+
max: null,
|
|
150
|
+
min: null,
|
|
151
|
+
},
|
|
134
152
|
...options,
|
|
135
153
|
},
|
|
136
154
|
});
|
|
@@ -143,11 +161,23 @@ export const sqlMoneyColumn = <R extends Record<string, any>>(
|
|
|
143
161
|
): SqlRequestDataGridColumns<R> => ({
|
|
144
162
|
[key]: {
|
|
145
163
|
name: title,
|
|
164
|
+
type: 'number',
|
|
146
165
|
render: (row) => formatMoney(row[key], decimals) ?? '',
|
|
147
166
|
excelFormatter: () => '#0.00',
|
|
148
167
|
getter: (row) => row[key] ?? '',
|
|
149
168
|
sortGetter: (row) => row[key] ?? '',
|
|
150
|
-
filter: {
|
|
169
|
+
filter: {
|
|
170
|
+
...numberFilter(key),
|
|
171
|
+
getter: (value) => value[key] ?? 0,
|
|
172
|
+
renderer: (value) => formatMoney(value, decimals) ?? '',
|
|
173
|
+
},
|
|
174
|
+
footer: {
|
|
175
|
+
sum: null,
|
|
176
|
+
avg: null,
|
|
177
|
+
count: null,
|
|
178
|
+
max: null,
|
|
179
|
+
min: null,
|
|
180
|
+
},
|
|
151
181
|
...options,
|
|
152
182
|
},
|
|
153
183
|
});
|
|
@@ -155,6 +185,7 @@ export const sqlMoneyColumn = <R extends Record<string, any>>(
|
|
|
155
185
|
export const sqlPercentageColumn = <R extends Record<string, any>>(
|
|
156
186
|
key: string,
|
|
157
187
|
title: string,
|
|
188
|
+
decimals = 2,
|
|
158
189
|
options?: Partial<SqlRequestDataGridColumn<R>>
|
|
159
190
|
): SqlRequestDataGridColumns<R> => ({
|
|
160
191
|
[key]: {
|
|
@@ -163,7 +194,11 @@ export const sqlPercentageColumn = <R extends Record<string, any>>(
|
|
|
163
194
|
excelFormatter: () => '#0.00',
|
|
164
195
|
getter: (row) => row[key] ?? '',
|
|
165
196
|
sortGetter: (row) => row[key] ?? '',
|
|
166
|
-
filter: {
|
|
197
|
+
filter: {
|
|
198
|
+
...numberFilter(key),
|
|
199
|
+
getter: (value) => value[key] ?? 0,
|
|
200
|
+
renderer: (value) => formatPercentage(value, decimals) ?? '',
|
|
201
|
+
},
|
|
167
202
|
...options,
|
|
168
203
|
},
|
|
169
204
|
});
|
|
@@ -184,6 +219,7 @@ export const sqlCheckboxColumn = <R extends Record<string, any>>(
|
|
|
184
219
|
getter: (row) => row[key] ?? '',
|
|
185
220
|
sortGetter: (row) => row[key] ?? '',
|
|
186
221
|
filter: { ...numberFilter(key), getter: (value) => value[key] ?? 0 },
|
|
222
|
+
footer: (rows) => `${rows[0][key]} éléments`,
|
|
187
223
|
...options,
|
|
188
224
|
},
|
|
189
225
|
});
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ConditionDTO,
|
|
3
3
|
OrderByDTO,
|
|
4
|
+
SqlRequestFooterFunction,
|
|
5
|
+
SqlRequestRow,
|
|
4
6
|
useSqlRequestHandler,
|
|
5
7
|
} from '../../../services/sqlRequests';
|
|
6
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
DataGridFilters,
|
|
10
|
+
DataGridFooterFunction,
|
|
11
|
+
DataGridSort,
|
|
12
|
+
} from '../DataGrid/types';
|
|
7
13
|
import _, { debounce } from 'lodash';
|
|
8
14
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
9
15
|
|
|
@@ -20,8 +26,10 @@ export const SqlRequestDataGrid = <R,>({
|
|
|
20
26
|
const [rows, setRows] = useState<R[]>([]);
|
|
21
27
|
const [start, setStart] = useState(0);
|
|
22
28
|
const [length, setLength] = useState(50);
|
|
23
|
-
const [
|
|
24
|
-
const [sqlRequest, sqlIdRequest] = useSqlRequestHandler<R>(
|
|
29
|
+
const [count, setCount] = useState(-1);
|
|
30
|
+
const [sqlRequest, sqlIdRequest, sqlPartialRequest] = useSqlRequestHandler<R>(
|
|
31
|
+
props.type
|
|
32
|
+
);
|
|
25
33
|
|
|
26
34
|
const [conditions, setConditions] = useState<Record<string, ConditionDTO>>(
|
|
27
35
|
{}
|
|
@@ -30,6 +38,7 @@ export const SqlRequestDataGrid = <R,>({
|
|
|
30
38
|
Object.entries(props.initialSorts ?? {}).map(
|
|
31
39
|
([columnKey, direction]): OrderByDTO => ({
|
|
32
40
|
field: props.columns[columnKey].field?.fieldAlias ?? columnKey,
|
|
41
|
+
type: props.columns[columnKey].type ?? 'text',
|
|
33
42
|
direction: direction.toUpperCase() as 'ASC' | 'DESC',
|
|
34
43
|
})
|
|
35
44
|
)
|
|
@@ -47,17 +56,24 @@ export const SqlRequestDataGrid = <R,>({
|
|
|
47
56
|
],
|
|
48
57
|
[props.columns, props.hiddenColumns]
|
|
49
58
|
);
|
|
59
|
+
const columnTypes = useMemo(
|
|
60
|
+
() =>
|
|
61
|
+
visibleColumnsKeys.map((key) =>
|
|
62
|
+
String(props.columns[key]?.type ?? 'text')
|
|
63
|
+
),
|
|
64
|
+
[visibleColumnsKeys, props.columns]
|
|
65
|
+
);
|
|
50
66
|
|
|
51
67
|
const refresh = useCallback(() => {
|
|
52
68
|
setRows([]);
|
|
53
69
|
setStart(0);
|
|
54
70
|
setLength(50);
|
|
55
|
-
|
|
71
|
+
setCount(-1);
|
|
56
72
|
}, []);
|
|
57
73
|
|
|
58
74
|
const onFiltersChanged = useCallback((filters: DataGridFilters) => {
|
|
59
75
|
const newConditions = convertSqlFiltersToConditions(filters);
|
|
60
|
-
|
|
76
|
+
setCount(-1);
|
|
61
77
|
setConditions(newConditions);
|
|
62
78
|
}, []);
|
|
63
79
|
|
|
@@ -85,22 +101,25 @@ export const SqlRequestDataGrid = <R,>({
|
|
|
85
101
|
orderBy: OrderByDTO[] = [],
|
|
86
102
|
start = 0,
|
|
87
103
|
length = 100,
|
|
88
|
-
|
|
104
|
+
getCount = false
|
|
89
105
|
) => {
|
|
90
106
|
sqlRequest({
|
|
91
107
|
columns: columns.includes('Id') ? columns : [...columns, 'Id'],
|
|
92
108
|
returnColumns: returnColumns.includes('Id')
|
|
93
109
|
? returnColumns
|
|
94
110
|
: [...returnColumns, 'Id'],
|
|
111
|
+
columnTypes: columnTypes.includes('Id')
|
|
112
|
+
? columnTypes
|
|
113
|
+
: [...columnTypes, 'Id'],
|
|
95
114
|
conditions,
|
|
96
115
|
orderBy,
|
|
97
116
|
start,
|
|
98
117
|
length,
|
|
99
|
-
|
|
118
|
+
getCount,
|
|
100
119
|
}).then((response) => {
|
|
101
|
-
if (
|
|
102
|
-
currentRows.current = Array(response.
|
|
103
|
-
if (
|
|
120
|
+
if (getCount) {
|
|
121
|
+
currentRows.current = Array(response.count).fill(null);
|
|
122
|
+
if (getCount) setCount(response.count ?? 0);
|
|
104
123
|
}
|
|
105
124
|
const parsedRows = props.parser
|
|
106
125
|
? response.data.map(props.parser)
|
|
@@ -122,11 +141,10 @@ export const SqlRequestDataGrid = <R,>({
|
|
|
122
141
|
return sqlRequest({
|
|
123
142
|
columns: columnsKeys,
|
|
124
143
|
returnColumns: [columnKey],
|
|
144
|
+
columnTypes: [props.columns[columnKey].type ?? 'text'],
|
|
125
145
|
conditions: [
|
|
126
146
|
...(props.conditions ?? []),
|
|
127
|
-
...Object.values(
|
|
128
|
-
_.pickBy(conditions, (condition, key) => key !== columnKey)
|
|
129
|
-
),
|
|
147
|
+
...Object.values(_.pickBy(conditions, (_, key) => key !== columnKey)),
|
|
130
148
|
].filter((condition) => condition.field !== columnKey),
|
|
131
149
|
orderBy: [
|
|
132
150
|
{
|
|
@@ -135,10 +153,11 @@ export const SqlRequestDataGrid = <R,>({
|
|
|
135
153
|
props.columns[columnKey].field?.fieldAlias ??
|
|
136
154
|
props.columns[columnKey].field?.fieldName ??
|
|
137
155
|
columnKey,
|
|
156
|
+
type: props.columns[columnKey].type ?? 'text',
|
|
138
157
|
direction: 'ASC',
|
|
139
158
|
},
|
|
140
159
|
],
|
|
141
|
-
|
|
160
|
+
getCount: false,
|
|
142
161
|
unique: true,
|
|
143
162
|
}).then((response) =>
|
|
144
163
|
response.data.map(
|
|
@@ -158,7 +177,7 @@ export const SqlRequestDataGrid = <R,>({
|
|
|
158
177
|
orderBy,
|
|
159
178
|
start,
|
|
160
179
|
length,
|
|
161
|
-
|
|
180
|
+
count < 0
|
|
162
181
|
),
|
|
163
182
|
[
|
|
164
183
|
props.columns,
|
|
@@ -166,7 +185,7 @@ export const SqlRequestDataGrid = <R,>({
|
|
|
166
185
|
orderBy,
|
|
167
186
|
start,
|
|
168
187
|
length,
|
|
169
|
-
|
|
188
|
+
count,
|
|
170
189
|
props.conditions,
|
|
171
190
|
columnsKeys,
|
|
172
191
|
visibleColumnsKeys,
|
|
@@ -178,13 +197,14 @@ export const SqlRequestDataGrid = <R,>({
|
|
|
178
197
|
sqlRequest({
|
|
179
198
|
columns: columnsKeys,
|
|
180
199
|
returnColumns: visibleColumnsKeys,
|
|
200
|
+
columnTypes,
|
|
181
201
|
conditions: [
|
|
182
202
|
...(props.conditions ?? []),
|
|
183
203
|
...(Object.values(conditions) ?? []),
|
|
184
204
|
],
|
|
185
205
|
orderBy,
|
|
186
206
|
start: 0,
|
|
187
|
-
length:
|
|
207
|
+
length: count,
|
|
188
208
|
}).then((response) =>
|
|
189
209
|
props.parser ? response.data.map(props.parser) : (response.data as R[])
|
|
190
210
|
),
|
|
@@ -192,28 +212,32 @@ export const SqlRequestDataGrid = <R,>({
|
|
|
192
212
|
sqlRequest,
|
|
193
213
|
columnsKeys,
|
|
194
214
|
visibleColumnsKeys,
|
|
215
|
+
columnTypes,
|
|
195
216
|
props.conditions,
|
|
196
217
|
props.parser,
|
|
197
218
|
conditions,
|
|
198
219
|
orderBy,
|
|
199
|
-
|
|
220
|
+
count,
|
|
200
221
|
]
|
|
201
222
|
);
|
|
202
223
|
|
|
203
224
|
const loadAllIds = useCallback(
|
|
204
225
|
() =>
|
|
205
226
|
sqlIdRequest({
|
|
206
|
-
columns: columnsKeys
|
|
227
|
+
columns: columnsKeys.includes('Id')
|
|
228
|
+
? columnsKeys
|
|
229
|
+
: [...columnsKeys, 'Id'],
|
|
207
230
|
returnColumns: ['Id'],
|
|
231
|
+
columnTypes: ['text'],
|
|
208
232
|
conditions: [
|
|
209
233
|
...(props.conditions ?? []),
|
|
210
234
|
...(Object.values(conditions) ?? []),
|
|
211
235
|
],
|
|
212
236
|
orderBy,
|
|
213
237
|
start: 0,
|
|
214
|
-
length:
|
|
238
|
+
length: count,
|
|
215
239
|
}).then((response) => response.data.map((row) => row['Id'])),
|
|
216
|
-
[columnsKeys, conditions, orderBy, props.conditions, sqlIdRequest,
|
|
240
|
+
[columnsKeys, conditions, orderBy, props.conditions, sqlIdRequest, count]
|
|
217
241
|
);
|
|
218
242
|
|
|
219
243
|
const onVisibleRowsChanged = useCallback(
|
|
@@ -233,6 +257,76 @@ export const SqlRequestDataGrid = <R,>({
|
|
|
233
257
|
[onSelectionChangeFromProps]
|
|
234
258
|
);
|
|
235
259
|
|
|
260
|
+
/** FOOTERS */
|
|
261
|
+
const [footers, setFooters] = useState<Record<string, string>>(
|
|
262
|
+
props.initialFooters ?? {}
|
|
263
|
+
);
|
|
264
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
265
|
+
const [footerData, setFooterData] = useState<SqlRequestRow<any>>({});
|
|
266
|
+
|
|
267
|
+
const loadFooters = useCallback(() => {
|
|
268
|
+
if (Object.keys(footers).length === 0) {
|
|
269
|
+
setFooterData({});
|
|
270
|
+
} else {
|
|
271
|
+
sqlPartialRequest({
|
|
272
|
+
columns: columnsKeys.includes('Id')
|
|
273
|
+
? columnsKeys
|
|
274
|
+
: [...columnsKeys, 'Id'],
|
|
275
|
+
returnColumns: [],
|
|
276
|
+
columnTypes: [],
|
|
277
|
+
totalColumns: footers as Record<string, SqlRequestFooterFunction>,
|
|
278
|
+
conditions: [
|
|
279
|
+
...(props.conditions ?? []),
|
|
280
|
+
...(Object.values(conditions) ?? []),
|
|
281
|
+
],
|
|
282
|
+
orderBy,
|
|
283
|
+
}).then((response) => setFooterData(response.totals ?? {}));
|
|
284
|
+
}
|
|
285
|
+
}, [
|
|
286
|
+
columnsKeys,
|
|
287
|
+
conditions,
|
|
288
|
+
footers,
|
|
289
|
+
orderBy,
|
|
290
|
+
props.conditions,
|
|
291
|
+
sqlPartialRequest,
|
|
292
|
+
]);
|
|
293
|
+
|
|
294
|
+
useEffect(() => {
|
|
295
|
+
loadFooters();
|
|
296
|
+
}, [loadFooters]);
|
|
297
|
+
|
|
298
|
+
const footerFunctions = useMemo(
|
|
299
|
+
() =>
|
|
300
|
+
!footerData
|
|
301
|
+
? {}
|
|
302
|
+
: Object.entries(footers).reduce((acc, [columnKey, footerKey]) => {
|
|
303
|
+
const column = props.columns[columnKey];
|
|
304
|
+
const footerFunc =
|
|
305
|
+
typeof column?.footer === 'function'
|
|
306
|
+
? column.footer
|
|
307
|
+
: column?.footer?.[footerKey];
|
|
308
|
+
const render = footerFunc
|
|
309
|
+
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
310
|
+
(data: any) => footerFunc([data], [], [])
|
|
311
|
+
: column?.render ?? _.identity;
|
|
312
|
+
if (!column) {
|
|
313
|
+
return acc;
|
|
314
|
+
}
|
|
315
|
+
acc[columnKey] = () => render(footerData, column);
|
|
316
|
+
return acc;
|
|
317
|
+
}, {} as Record<string, DataGridFooterFunction<R>>),
|
|
318
|
+
[footerData, footers, props.columns]
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
const contextOverride = useMemo(
|
|
322
|
+
() => ({
|
|
323
|
+
footers,
|
|
324
|
+
setFooters,
|
|
325
|
+
footerFunctions,
|
|
326
|
+
}),
|
|
327
|
+
[footers, setFooters, footerFunctions]
|
|
328
|
+
);
|
|
329
|
+
|
|
236
330
|
return (
|
|
237
331
|
<DataGrid
|
|
238
332
|
onVisibleRowsChange={onVisibleRowsChanged}
|
|
@@ -246,6 +340,7 @@ export const SqlRequestDataGrid = <R,>({
|
|
|
246
340
|
refresh={refresh}
|
|
247
341
|
onSelectionChange={onSelectionChange}
|
|
248
342
|
getAllIds={loadAllIds}
|
|
343
|
+
contextOverride={contextOverride}
|
|
249
344
|
{...props}
|
|
250
345
|
/>
|
|
251
346
|
);
|