@addev-be/ui 0.14.1 → 0.14.2
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/floppy-disk.svg +1 -0
- package/package.json +2 -1
- package/src/Icons.tsx +2 -0
- package/src/components/data/DataGrid/DataGridCell.tsx +3 -3
- package/src/components/data/DataGrid/DataGridColumnsModal/helpers.ts +7 -12
- package/src/components/data/DataGrid/DataGridColumnsModal/hooks.tsx +2 -2
- package/src/components/data/DataGrid/DataGridColumnsModal/index.tsx +31 -30
- package/src/components/data/DataGrid/DataGridEditableCell/CheckboxEditableCell.tsx +38 -0
- package/src/components/data/DataGrid/DataGridEditableCell/DateEditableCell.tsx +39 -0
- package/src/components/data/DataGrid/DataGridEditableCell/NumberEditableCell.tsx +68 -0
- package/src/components/data/DataGrid/DataGridEditableCell/TextEditableCell.tsx +38 -0
- package/src/components/data/DataGrid/DataGridEditableCell/index.tsx +60 -0
- package/src/components/data/DataGrid/DataGridEditableCell/types.ts +14 -0
- package/src/components/data/DataGrid/DataGridFilterMenu/hooks.tsx +13 -10
- package/src/components/data/DataGrid/DataGridFilterMenu/index.tsx +27 -29
- package/src/components/data/DataGrid/DataGridFooter.tsx +3 -3
- package/src/components/data/DataGrid/DataGridHeader.tsx +52 -7
- package/src/components/data/DataGrid/DataGridHeaderCell.tsx +16 -2
- package/src/components/data/DataGrid/DataGridRowTemplate.tsx +23 -16
- package/src/components/data/DataGrid/helpers/columns.tsx +238 -236
- package/src/components/data/DataGrid/hooks/index.ts +6 -7
- package/src/components/data/DataGrid/hooks/useDataGrid.tsx +89 -16
- package/src/components/data/DataGrid/hooks/useDataGridChangedRows.ts +56 -0
- package/src/components/data/DataGrid/hooks/useDataGridCopy.ts +18 -19
- package/src/components/data/DataGrid/styles.ts +56 -1
- package/src/components/data/DataGrid/types.ts +69 -17
- package/src/components/data/SqlRequestDataGrid/helpers/columns.tsx +240 -216
- package/src/components/data/SqlRequestDataGrid/index.tsx +58 -43
- package/src/components/data/SqlRequestDataGrid/types.ts +21 -6
- package/src/components/data/SqlRequestForeignList/index.tsx +157 -0
- package/src/components/data/SqlRequestForeignList/styles.ts +38 -0
- package/src/components/data/SqlRequestGrid/filters/FiltersSidebar.tsx +8 -4
- package/src/components/data/SqlRequestGrid/index.tsx +24 -18
- package/src/components/data/SqlRequestGrid/types.ts +25 -3
- package/src/components/data/index.ts +2 -0
- package/src/helpers/numbers.ts +37 -0
- package/src/services/index.ts +1 -0
- package/src/services/updateSqlRequests.ts +34 -0
- package/src/components/data/DataGrid/DataGridEditableCell.tsx +0 -43
- package/src/components/data/SqlRequestDataGrid/index.ts +0 -1
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
XBarIcon,
|
|
24
24
|
} from '../../../../Icons';
|
|
25
25
|
import {
|
|
26
|
+
DataGridColumnWithFilter,
|
|
26
27
|
DataGridContext,
|
|
27
28
|
DataGridFilterType,
|
|
28
29
|
DataGridFilterValue,
|
|
@@ -50,8 +51,7 @@ import { MenuContainer } from '../../../ui/ContextMenu/styles';
|
|
|
50
51
|
import { useFilterModal } from './hooks';
|
|
51
52
|
|
|
52
53
|
type FilterValuesProps<R> = {
|
|
53
|
-
|
|
54
|
-
columnIndex: number;
|
|
54
|
+
column: DataGridColumnWithFilter<R>;
|
|
55
55
|
context: DataGridContext<R>;
|
|
56
56
|
onClose?: () => void;
|
|
57
57
|
contextMenu?: boolean;
|
|
@@ -87,24 +87,22 @@ const footerFunctionsIcons: Record<DataGridFooterPredefinedFunction, IconFC> = {
|
|
|
87
87
|
};
|
|
88
88
|
|
|
89
89
|
export const DataGridFilterMenu = <R,>({
|
|
90
|
-
|
|
90
|
+
column,
|
|
91
91
|
context,
|
|
92
92
|
onClose,
|
|
93
93
|
contextMenu = true,
|
|
94
94
|
showTotalButton = true,
|
|
95
95
|
}: FilterValuesProps<R>) => {
|
|
96
|
-
const { openModal, modal } = useFilterModal({
|
|
96
|
+
const { openModal, modal } = useFilterModal({ column, context, onClose });
|
|
97
97
|
const {
|
|
98
98
|
filters = {},
|
|
99
99
|
footers = {},
|
|
100
100
|
rows,
|
|
101
|
-
columns,
|
|
102
101
|
setFilters,
|
|
103
102
|
filterValuesLoader,
|
|
104
103
|
setSorts,
|
|
105
104
|
setFooters,
|
|
106
105
|
} = useContext(context);
|
|
107
|
-
const column = columns[columnKey] ?? {};
|
|
108
106
|
const textFilterInputRef = useRef<HTMLInputElement>(null);
|
|
109
107
|
const [textFilter, setTextFilter] = useState('');
|
|
110
108
|
|
|
@@ -114,12 +112,12 @@ export const DataGridFilterMenu = <R,>({
|
|
|
114
112
|
|
|
115
113
|
useEffect(() => {
|
|
116
114
|
if (filterValuesLoader) {
|
|
117
|
-
filterValuesLoader(
|
|
115
|
+
filterValuesLoader(column.key).then((values) => {
|
|
118
116
|
setAvailableValues(() => values);
|
|
119
117
|
});
|
|
120
118
|
} else {
|
|
121
119
|
const otherFilters = Object.entries(filters)
|
|
122
|
-
.filter(([key]) => key !==
|
|
120
|
+
.filter(([key]) => key !== column.key)
|
|
123
121
|
.map(([, filter]) => filter);
|
|
124
122
|
const availableRows = applyFilters(rows, otherFilters);
|
|
125
123
|
const values = availableRows.map((row) => column.filter!.getter(row));
|
|
@@ -131,34 +129,34 @@ export const DataGridFilterMenu = <R,>({
|
|
|
131
129
|
)
|
|
132
130
|
);
|
|
133
131
|
}
|
|
134
|
-
}, [column.filter,
|
|
132
|
+
}, [column.filter, column.key, filterValuesLoader, filters, rows]);
|
|
135
133
|
|
|
136
134
|
const selectedValues = useMemo(
|
|
137
|
-
() => filters?.[
|
|
138
|
-
[
|
|
135
|
+
() => filters?.[column.key]?.values ?? [],
|
|
136
|
+
[column.key, filters]
|
|
139
137
|
);
|
|
140
138
|
|
|
141
139
|
const clearFilter = useCallback(() => {
|
|
142
140
|
const newFilters = { ...filters };
|
|
143
|
-
delete newFilters[
|
|
141
|
+
delete newFilters[column.key];
|
|
144
142
|
setFilters(newFilters);
|
|
145
143
|
onClose?.();
|
|
146
|
-
}, [filters,
|
|
144
|
+
}, [filters, column.key, setFilters, onClose]);
|
|
147
145
|
|
|
148
146
|
const setValuesChecked = useCallback(
|
|
149
147
|
(values: any[], checked?: boolean) => {
|
|
150
148
|
setFilters((prevFilters) => {
|
|
151
149
|
const newValues = checked
|
|
152
|
-
? [...(prevFilters[
|
|
153
|
-
: without(prevFilters[
|
|
150
|
+
? [...(prevFilters[column.key]?.values ?? []), ...values]
|
|
151
|
+
: without(prevFilters[column.key]?.values ?? [], ...values);
|
|
154
152
|
const newFilters = {
|
|
155
153
|
...prevFilters,
|
|
156
154
|
};
|
|
157
155
|
if (newValues.length === 0) {
|
|
158
|
-
delete newFilters[
|
|
156
|
+
delete newFilters[column.key];
|
|
159
157
|
} else {
|
|
160
|
-
newFilters[
|
|
161
|
-
...(prevFilters[
|
|
158
|
+
newFilters[column.key] = {
|
|
159
|
+
...(prevFilters[column.key] ?? column.filter),
|
|
162
160
|
operator: 'inArray',
|
|
163
161
|
values: newValues,
|
|
164
162
|
};
|
|
@@ -166,7 +164,7 @@ export const DataGridFilterMenu = <R,>({
|
|
|
166
164
|
return newFilters;
|
|
167
165
|
});
|
|
168
166
|
},
|
|
169
|
-
[setFilters,
|
|
167
|
+
[setFilters, column.key, column.filter]
|
|
170
168
|
);
|
|
171
169
|
|
|
172
170
|
const toggleValues = useCallback(
|
|
@@ -228,40 +226,40 @@ export const DataGridFilterMenu = <R,>({
|
|
|
228
226
|
]);
|
|
229
227
|
|
|
230
228
|
const onSortAscClicked = useCallback(() => {
|
|
231
|
-
setSorts({ [
|
|
229
|
+
setSorts({ [column.key]: 'asc' });
|
|
232
230
|
onClose?.();
|
|
233
|
-
}, [
|
|
231
|
+
}, [column.key, onClose, setSorts]);
|
|
234
232
|
const onSortDescClicked = useCallback(() => {
|
|
235
|
-
setSorts({ [
|
|
233
|
+
setSorts({ [column.key]: 'desc' });
|
|
236
234
|
onClose?.();
|
|
237
|
-
}, [
|
|
235
|
+
}, [column.key, onClose, setSorts]);
|
|
238
236
|
|
|
239
|
-
const hasFilters = filters[
|
|
237
|
+
const hasFilters = filters[column.key]?.values.length > 0;
|
|
240
238
|
const [[sortAscText, SortAscIcon], [sortDescText, SortDescIcon]] = [
|
|
241
239
|
sortAsc[column.filter?.type ?? 'text'],
|
|
242
240
|
sortDesc[column.filter?.type ?? 'text'],
|
|
243
241
|
];
|
|
244
242
|
|
|
245
243
|
const isFooterVisible =
|
|
246
|
-
|
|
244
|
+
column.key in footers && footers[column.key] !== undefined;
|
|
247
245
|
const showFooter = useCallback(
|
|
248
246
|
(key: string) => {
|
|
249
247
|
setFooters((prevFooters) => ({
|
|
250
248
|
...prevFooters,
|
|
251
|
-
[
|
|
249
|
+
[column.key]: key,
|
|
252
250
|
}));
|
|
253
251
|
onClose?.();
|
|
254
252
|
},
|
|
255
|
-
[
|
|
253
|
+
[column.key, onClose, setFooters]
|
|
256
254
|
);
|
|
257
255
|
const hideFooter = useCallback(() => {
|
|
258
256
|
setFooters((prevFooters) => {
|
|
259
257
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
260
|
-
const { [
|
|
258
|
+
const { [column.key]: _, ...newFooters } = prevFooters;
|
|
261
259
|
return newFooters;
|
|
262
260
|
});
|
|
263
261
|
onClose?.();
|
|
264
|
-
}, [
|
|
262
|
+
}, [column.key, onClose, setFooters]);
|
|
265
263
|
|
|
266
264
|
const content = (
|
|
267
265
|
<>
|
|
@@ -31,13 +31,13 @@ export const DataGridFooter = <R,>({
|
|
|
31
31
|
return (
|
|
32
32
|
<styles.DataGridFooterRow $gridTemplateColumns={gridTemplateColumns}>
|
|
33
33
|
{!!selectable && <styles.HeaderSelectionCell />}
|
|
34
|
-
{visibleColumns.map((
|
|
34
|
+
{visibleColumns.map((col) => (
|
|
35
35
|
<styles.DataGridHeaderCellContainer
|
|
36
|
-
key={key}
|
|
36
|
+
key={col.key}
|
|
37
37
|
style={{ width: (col.width ?? DEFAULT_COLUMN_WIDTH) + 'px' }}
|
|
38
38
|
$headerColor={col.color ?? headerColor}
|
|
39
39
|
>
|
|
40
|
-
{footerFunctions?.[key]?.(rows, sortedRows, selectedRows)}
|
|
40
|
+
{footerFunctions?.[col.key]?.(rows, sortedRows, selectedRows)}
|
|
41
41
|
</styles.DataGridHeaderCellContainer>
|
|
42
42
|
))}
|
|
43
43
|
</styles.DataGridFooterRow>
|
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
ArrowsRotateIcon,
|
|
8
8
|
CopyIcon,
|
|
9
9
|
FilterSlashIcon,
|
|
10
|
+
FloppyDiskIcon,
|
|
11
|
+
PlusIcon,
|
|
10
12
|
TableColumnsIcon,
|
|
11
13
|
} from '../../../Icons';
|
|
12
14
|
import { useCallback, useState } from 'react';
|
|
@@ -38,6 +40,13 @@ export const DataGridHeader = <R,>({
|
|
|
38
40
|
rowKeyGetter,
|
|
39
41
|
gridTemplateColumns,
|
|
40
42
|
getAllIds,
|
|
43
|
+
editable,
|
|
44
|
+
onSaveClicked,
|
|
45
|
+
onAddClicked,
|
|
46
|
+
addedRows,
|
|
47
|
+
updatedRows,
|
|
48
|
+
addRow,
|
|
49
|
+
clearChangedRows,
|
|
41
50
|
} = useDataGridContext(context);
|
|
42
51
|
const [visibleFilter, setVisibleFilter] = useState<string | undefined>();
|
|
43
52
|
|
|
@@ -67,16 +76,52 @@ export const DataGridHeader = <R,>({
|
|
|
67
76
|
copyTable().then(() => setIsLoadingVisible(false));
|
|
68
77
|
}, [copyTable]);
|
|
69
78
|
|
|
79
|
+
const save = useCallback(async () => {
|
|
80
|
+
if (
|
|
81
|
+
Object.keys(addedRows).length + Object.keys(updatedRows).length > 0 &&
|
|
82
|
+
onSaveClicked
|
|
83
|
+
) {
|
|
84
|
+
const savedIds = await onSaveClicked(addedRows, updatedRows);
|
|
85
|
+
clearChangedRows(savedIds);
|
|
86
|
+
}
|
|
87
|
+
}, [addedRows, clearChangedRows, onSaveClicked, updatedRows]);
|
|
88
|
+
|
|
89
|
+
const add = useCallback(async () => {
|
|
90
|
+
if (onAddClicked) {
|
|
91
|
+
const row = await onAddClicked();
|
|
92
|
+
const key = rowKeyGetter(row);
|
|
93
|
+
addRow(key, row);
|
|
94
|
+
}
|
|
95
|
+
}, [addRow, onAddClicked, rowKeyGetter]);
|
|
96
|
+
|
|
97
|
+
const onRefreshClicked = useCallback(() => {
|
|
98
|
+
refresh?.();
|
|
99
|
+
clearChangedRows();
|
|
100
|
+
setSelectedKeys([]);
|
|
101
|
+
}, [clearChangedRows, refresh, setSelectedKeys]);
|
|
102
|
+
|
|
70
103
|
const toolsRow = (
|
|
71
104
|
<styles.DataGridToolsRow>
|
|
72
105
|
<styles.DataGridToolsRowButtonsContainer>
|
|
73
106
|
<Loading visible={isLoadingVisible} />
|
|
74
|
-
{
|
|
75
|
-
<Button size="small" onClick={
|
|
107
|
+
{editable && onSaveClicked && (
|
|
108
|
+
<Button size="small" $color="primary" onClick={save}>
|
|
109
|
+
<FloppyDiskIcon />
|
|
110
|
+
Enregistrer
|
|
111
|
+
</Button>
|
|
112
|
+
)}
|
|
113
|
+
{editable && onAddClicked && (
|
|
114
|
+
<Button size="small" $color="success" onClick={add}>
|
|
115
|
+
<PlusIcon />
|
|
116
|
+
Ajouter
|
|
117
|
+
</Button>
|
|
118
|
+
)}
|
|
119
|
+
{
|
|
120
|
+
<Button size="small" onClick={onRefreshClicked}>
|
|
76
121
|
<ArrowsRotateIcon />
|
|
77
122
|
Rafraîchir
|
|
78
123
|
</Button>
|
|
79
|
-
|
|
124
|
+
}
|
|
80
125
|
<Button $color="emerald" size="small" onClick={runCopyTable}>
|
|
81
126
|
<CopyIcon />
|
|
82
127
|
Copier la table
|
|
@@ -111,14 +156,14 @@ export const DataGridHeader = <R,>({
|
|
|
111
156
|
<IndeterminateCheckbox checked={checkboxStatus} readOnly />
|
|
112
157
|
</styles.HeaderSelectionCell>
|
|
113
158
|
)}
|
|
114
|
-
{visibleColumns.map((
|
|
159
|
+
{visibleColumns.map((col, index) => (
|
|
115
160
|
<DataGridHeaderCell
|
|
116
|
-
key={key}
|
|
117
|
-
columnKey={key}
|
|
161
|
+
key={col.key}
|
|
162
|
+
columnKey={col.key}
|
|
118
163
|
column={col}
|
|
119
164
|
context={context}
|
|
120
165
|
columnIndex={index}
|
|
121
|
-
isFilterOpen={visibleFilter === key}
|
|
166
|
+
isFilterOpen={visibleFilter === col.key}
|
|
122
167
|
onFilterButtonClicked={onFilterButtonClicked}
|
|
123
168
|
/>
|
|
124
169
|
))}
|
|
@@ -33,7 +33,12 @@ export const DataGridHeaderCell = <R,>({
|
|
|
33
33
|
|
|
34
34
|
const [isFilterDropdownVisible, setIsFilterDropdownVisible] = useState(false);
|
|
35
35
|
const filterDropdown = useMemo(() => {
|
|
36
|
-
if (
|
|
36
|
+
if (
|
|
37
|
+
!isFilterDropdownVisible ||
|
|
38
|
+
!filterButtonRef.current ||
|
|
39
|
+
!columnKey ||
|
|
40
|
+
!column.filter
|
|
41
|
+
) {
|
|
37
42
|
return null;
|
|
38
43
|
}
|
|
39
44
|
const filterButtonRect = getElementScreenRect(filterButtonRef.current);
|
|
@@ -48,6 +53,7 @@ export const DataGridHeaderCell = <R,>({
|
|
|
48
53
|
$autoPositionX
|
|
49
54
|
>
|
|
50
55
|
<DataGridFilterMenu
|
|
56
|
+
column={column}
|
|
51
57
|
columnKey={columnKey}
|
|
52
58
|
columnIndex={columnIndex}
|
|
53
59
|
context={context}
|
|
@@ -56,6 +62,7 @@ export const DataGridHeaderCell = <R,>({
|
|
|
56
62
|
</Dropdown>
|
|
57
63
|
);
|
|
58
64
|
}, [
|
|
65
|
+
column,
|
|
59
66
|
columnIndex,
|
|
60
67
|
columnKey,
|
|
61
68
|
context,
|
|
@@ -76,7 +83,14 @@ export const DataGridHeaderCell = <R,>({
|
|
|
76
83
|
$isResizing={isResizing}
|
|
77
84
|
>
|
|
78
85
|
{filterDropdown}
|
|
79
|
-
|
|
86
|
+
|
|
87
|
+
{typeof column.name === 'string' ? (
|
|
88
|
+
<span>{column.name}</span>
|
|
89
|
+
) : (
|
|
90
|
+
<styles.DataGridHeaderTextContainer>
|
|
91
|
+
{column.name}
|
|
92
|
+
</styles.DataGridHeaderTextContainer>
|
|
93
|
+
)}
|
|
80
94
|
{!!column.filter && (
|
|
81
95
|
<IconButton
|
|
82
96
|
size="small"
|
|
@@ -7,15 +7,20 @@ import { useContext } from 'react';
|
|
|
7
7
|
|
|
8
8
|
export const DataGridRowTemplate = <R,>({
|
|
9
9
|
item,
|
|
10
|
-
index,
|
|
10
|
+
index: rowIndex,
|
|
11
11
|
context,
|
|
12
12
|
}: VirtualScrollerTemplateProps<R, DataGridRowTemplateProps<R>>) => {
|
|
13
|
-
const {
|
|
14
|
-
|
|
13
|
+
const {
|
|
14
|
+
visibleColumns,
|
|
15
|
+
rowKeyGetter,
|
|
16
|
+
toggleSelection,
|
|
17
|
+
addedRows: editedRows,
|
|
18
|
+
...props
|
|
19
|
+
} = useContext(context);
|
|
15
20
|
|
|
16
21
|
if (!item) {
|
|
17
22
|
return (
|
|
18
|
-
<styles.DataGridRow key={`loading-row-${
|
|
23
|
+
<styles.DataGridRow key={`loading-row-${rowIndex}`}>
|
|
19
24
|
{!!props.selectable && (
|
|
20
25
|
<styles.LoadingCell className="animate-pulse">
|
|
21
26
|
<div />
|
|
@@ -24,7 +29,7 @@ export const DataGridRowTemplate = <R,>({
|
|
|
24
29
|
{visibleColumns.map((_, colIndex) => (
|
|
25
30
|
<styles.LoadingCell
|
|
26
31
|
className="animate-pulse"
|
|
27
|
-
key={`loading-${
|
|
32
|
+
key={`loading-${rowIndex}-${colIndex}`}
|
|
28
33
|
>
|
|
29
34
|
<div />
|
|
30
35
|
</styles.LoadingCell>
|
|
@@ -32,37 +37,39 @@ export const DataGridRowTemplate = <R,>({
|
|
|
32
37
|
</styles.DataGridRow>
|
|
33
38
|
);
|
|
34
39
|
}
|
|
35
|
-
const
|
|
36
|
-
const selected = props.selectedKeys.includes(
|
|
40
|
+
const rowKey = rowKeyGetter(item);
|
|
41
|
+
const selected = props.selectedKeys.includes(rowKey);
|
|
37
42
|
const { className, style } = props.rowClassNameGetter?.(item) ?? {
|
|
38
43
|
className: '',
|
|
39
44
|
style: undefined,
|
|
40
45
|
};
|
|
46
|
+
const isEdited = rowKey in editedRows;
|
|
47
|
+
|
|
41
48
|
return (
|
|
42
|
-
<styles.DataGridRow key={
|
|
49
|
+
<styles.DataGridRow key={rowKey} $edited={isEdited}>
|
|
43
50
|
{!!props.selectable && (
|
|
44
51
|
<styles.SelectionCell
|
|
45
52
|
key="__select_checkbox__"
|
|
46
|
-
onClick={() => toggleSelection(
|
|
53
|
+
onClick={() => toggleSelection(rowKey)}
|
|
47
54
|
>
|
|
48
55
|
<input
|
|
49
56
|
type="checkbox"
|
|
50
|
-
value={
|
|
57
|
+
value={rowKey as string}
|
|
51
58
|
checked={selected}
|
|
52
59
|
readOnly
|
|
53
60
|
/>
|
|
54
61
|
</styles.SelectionCell>
|
|
55
62
|
)}
|
|
56
|
-
{visibleColumns.map((
|
|
63
|
+
{visibleColumns.map((col, colIndex) => (
|
|
57
64
|
<DataGridCell
|
|
58
|
-
key={`loading-${
|
|
59
|
-
{...(
|
|
65
|
+
key={`loading-${colIndex}-${colIndex}`}
|
|
66
|
+
{...(colIndex === 0 ? { className, style } : {})}
|
|
60
67
|
row={item}
|
|
61
|
-
rowIndex={
|
|
68
|
+
rowIndex={rowIndex}
|
|
62
69
|
column={col}
|
|
63
|
-
columnIndex={
|
|
70
|
+
columnIndex={colIndex}
|
|
64
71
|
context={context}
|
|
65
|
-
columnKey={key}
|
|
72
|
+
columnKey={col.key}
|
|
66
73
|
color={col.color}
|
|
67
74
|
/>
|
|
68
75
|
))}
|