@dashadmin/dash-components 1.3.24 → 1.3.26
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/dist/components/AuditLog/AuditLog.js +345 -1
- package/dist/components/AuditLog/index.js +4 -1
- package/dist/components/AutoCompleteArrayInput/AutoCompleteCheckBoxInput.js +630 -3
- package/dist/components/AutoCompleteArrayInput/AutocompleteCheckBoxArrayInput.js +53 -1
- package/dist/components/AutoCompleteArrayInputAutoSearch/AutoCompleteCheckBoxInput.js +647 -3
- package/dist/components/AutoCompleteArrayInputAutoSearch/AutocompleteCheckBoxArrayInput.js +53 -1
- package/dist/components/Json/Json.js +235 -1
- package/dist/components/JsonColorSelector/JsonColorSelector.js +1172 -1
- package/dist/components/JsonColorSelector/JsonColorSelectorEnhanced.js +863 -2
- package/dist/components/JsonColorSelector/JsonCssVarValues.js +738 -1
- package/dist/components/JsonColorSelector/components/ColorEditDialog.js +426 -1
- package/dist/components/JsonColorSelector/components/ColorPaletteItem.js +75 -1
- package/dist/components/JsonColorSelector/components/ImageColorExtractor.js +283 -1
- package/dist/components/JsonColorSelector/helpers/functions.js +101 -1
- package/dist/components/JsonColorSelector/useAsyncColorThief.js +105 -1
- package/dist/components/ListActive/ListActive.js +126 -1
- package/dist/components/ListActive/ListBoolean.js +124 -1
- package/dist/components/NotificationPreferences/NotificationPreferences.js +317 -1
- package/dist/components/NotificationPreferences/index.js +7 -1
- package/dist/components/SearchableSelects/RASearchableSelect.js +236 -1
- package/dist/components/SearchableSelects/RASearchableSelectCheckboxes.js +479 -1
- package/dist/components/SearchableSelects/RASearchableSelectChips.js +465 -1
- package/dist/components/SearchableSelects/RASearchableSelectChipsRecordContext.js +295 -1
- package/dist/components/SearchableSelects/SearchableSelect.js +202 -1
- package/dist/components/SearchableSelects/SearchableSelectCheckboxes.js +290 -1
- package/dist/components/SortableDataGrid/SortableDataGrid.js +72 -1
- package/dist/components/SortableDataGrid/SortableDataGridBody.js +167 -1
- package/dist/components/SortableDataGrid/SortableDataGridHeader.js +109 -1
- package/dist/components/SortableDataGrid/SortableDataGridRow.js +283 -1
- package/dist/components/Upload/SingleImageUploader.js +40 -1
- package/dist/components/custom/PackageCopyMethod.js +78 -1
- package/dist/components/custom/PackageRadioButtonGroup.js +45 -1
- package/dist/components/dialog/Basic.js +8 -1
- package/dist/components/dialog/Correct.js +14 -1
- package/dist/components/dialog/Error.js +14 -1
- package/dist/components/dialog/Info.js +14 -1
- package/dist/components/dialog/InfoV2.js +21 -1
- package/dist/components/dialog/NotFound.js +14 -1
- package/dist/components/dialog/QuickSearch.js +117 -1
- package/dist/components/notifications/NotificationsCenter.js +597 -1
- package/dist/components/notifications/index.js +24 -1
- package/dist/components/tables/PaginationComponent.js +36 -1
- package/dist/components/theme/AppLoadingFallback.js +38 -2
- package/dist/components/theme/ErrorBoundary.js +52 -1
- package/dist/components/theme/InitialLoader.js +13 -1
- package/dist/components/theme/NotFound.js +136 -1
- package/dist/components/theme/NotResults.js +38 -1
- package/dist/hooks/useDraggable.js +6 -1
- package/dist/hooks/useNotifications.js +8 -1
- package/dist/hooks/useQuickSearch.js +26 -1
- package/dist/index.js +66 -5567
- package/dist/utils/setNativeValue.js +17 -1
- package/package.json +149 -132
- package/src/components/AuditLog/AuditLog.tsx +476 -0
- package/src/components/AuditLog/index.ts +2 -0
- package/src/components/AutoCompleteArrayInput/AutoCompleteCheckBoxInput.tsx +917 -0
- package/src/components/AutoCompleteArrayInput/AutocompleteCheckBoxArrayInput.tsx +39 -0
- package/src/components/AutoCompleteArrayInputAutoSearch/AutoCompleteCheckBoxInput.tsx +916 -0
- package/src/components/AutoCompleteArrayInputAutoSearch/AutocompleteCheckBoxArrayInput.tsx +44 -0
- package/src/components/Json/Json.tsx +312 -0
- package/src/components/JsonColorSelector/JsonColorSelector.tsx +1435 -0
- package/src/components/JsonColorSelector/JsonColorSelectorEnhanced.tsx +1029 -0
- package/src/components/JsonColorSelector/JsonCssVarValues.tsx +863 -0
- package/src/components/JsonColorSelector/components/ColorEditDialog.tsx +491 -0
- package/src/components/JsonColorSelector/components/ColorPaletteItem.tsx +80 -0
- package/src/components/JsonColorSelector/components/ImageColorExtractor.tsx +328 -0
- package/src/components/JsonColorSelector/helpers/functions.tsx +123 -0
- package/src/components/JsonColorSelector/interfaces/interfaces.tsx +22 -0
- package/src/components/JsonColorSelector/useAsyncColorThief.tsx +97 -0
- package/src/components/ListActive/ListActive.tsx +106 -0
- package/src/components/ListActive/ListBoolean.tsx +96 -0
- package/src/components/NotificationPreferences/NotificationPreferences.tsx +463 -0
- package/src/components/NotificationPreferences/index.tsx +2 -0
- package/src/components/SearchableSelects/RASearchableSelect.tsx +300 -0
- package/src/components/SearchableSelects/RASearchableSelectCheckboxes.tsx +604 -0
- package/src/components/SearchableSelects/RASearchableSelectChips.tsx +558 -0
- package/src/components/SearchableSelects/RASearchableSelectChipsRecordContext.tsx +362 -0
- package/src/components/SearchableSelects/SearchableSelect.tsx +321 -0
- package/src/components/SearchableSelects/SearchableSelectCheckboxes.tsx +355 -0
- package/src/components/SortableDataGrid/SortableDataGrid.tsx +56 -0
- package/src/components/SortableDataGrid/SortableDataGridBody.tsx +175 -0
- package/src/components/SortableDataGrid/SortableDataGridHeader.tsx +171 -0
- package/src/components/SortableDataGrid/SortableDataGridRow.tsx +247 -0
- package/src/components/Upload/SingleImageUploader.tsx +55 -0
- package/src/components/custom/PackageCopyMethod.tsx +109 -0
- package/src/components/custom/PackageRadioButtonGroup.tsx +47 -0
- package/src/components/dialog/Basic.tsx +11 -0
- package/src/components/dialog/Correct.tsx +16 -0
- package/src/components/dialog/Error.tsx +15 -0
- package/src/components/dialog/Info.tsx +15 -0
- package/src/components/dialog/InfoV2.tsx +35 -0
- package/src/components/dialog/NotFound.tsx +18 -0
- package/src/components/dialog/QuickSearch.tsx +115 -0
- package/src/components/notifications/NotificationsCenter.tsx +792 -0
- package/src/components/notifications/index.ts +42 -0
- package/src/components/tables/PaginationComponent.tsx +17 -0
- package/src/components/theme/AppLoadingFallback.tsx +42 -0
- package/src/components/theme/ErrorBoundary.tsx +57 -0
- package/src/components/theme/InitialLoader.tsx +16 -0
- package/src/components/theme/NotFound.tsx +124 -0
- package/src/components/theme/NotResults.tsx +54 -0
- package/src/hooks/useDraggable.ts +11 -0
- package/src/hooks/useNotifications.ts +14 -0
- package/src/hooks/useQuickSearch.tsx +29 -0
- package/src/index.tsx +77 -0
- package/src/utils/setNativeValue.tsx +23 -0
- package/dist/color-thief-CTwGFhOB.js +0 -272
- /package/{dist → src}/components/AutoCompleteArrayInputAutoSearch/AutocompleteCheckBoxArrayAutoSearch.tsx.wip +0 -0
- /package/{dist → src}/components/JsonColorSelector/JsonColorSelector.tsx.bkup +0 -0
- /package/{dist → src}/components/SortableDataGrid/README.md +0 -0
- /package/{dist → src}/styles/index.less +0 -0
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Auto Admin - SearchableSelect
|
|
3
|
+
*
|
|
4
|
+
* @author Franisco Aranda <francisco.aranda@dash.cl> <faranda@gmail.com>
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
Autocomplete,
|
|
9
|
+
AutocompleteProps,
|
|
10
|
+
Box,
|
|
11
|
+
Checkbox,
|
|
12
|
+
CircularProgress,
|
|
13
|
+
TextField,
|
|
14
|
+
} from '@mui/material';
|
|
15
|
+
import React, { JSX, useEffect, useState } from 'react';
|
|
16
|
+
import { isArray } from 'lodash';
|
|
17
|
+
import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';
|
|
18
|
+
import CheckBoxIcon from '@mui/icons-material/CheckBox';
|
|
19
|
+
import { useAxios } from 'dash-axios-hook';
|
|
20
|
+
|
|
21
|
+
export interface ISearchableSelect<
|
|
22
|
+
T,
|
|
23
|
+
//Multiple extends boolean | undefined = false,
|
|
24
|
+
//DisableClearable extends boolean | undefined = false,
|
|
25
|
+
//FreeSolo extends boolean | undefined = false,
|
|
26
|
+
> extends Omit<
|
|
27
|
+
AutocompleteProps<T | string, boolean, boolean, boolean>,
|
|
28
|
+
| 'renderInput'
|
|
29
|
+
| 'options'
|
|
30
|
+
| 'isOptionEqualToValue'
|
|
31
|
+
| 'getOptionLabel'
|
|
32
|
+
| 'renderOption'
|
|
33
|
+
> {
|
|
34
|
+
/** Options are ingored because they are calculated within this component */
|
|
35
|
+
/** renderInput is ignored because is implemented privately within this component */
|
|
36
|
+
|
|
37
|
+
name: string;
|
|
38
|
+
/** url path to the resource, a getList or getForSelect e.g: 'system/user' */
|
|
39
|
+
resource: string;
|
|
40
|
+
/** label for the select */
|
|
41
|
+
selectLabel: string;
|
|
42
|
+
/** Optional function to parse the item and return a string or JSX.Element to show in the selector list*/
|
|
43
|
+
renderText?: (object: any) => string | JSX.Element;
|
|
44
|
+
/** @deprecated Optional function will transform the item at the moment of field.onChange */
|
|
45
|
+
transformData?: (val: any) => any;
|
|
46
|
+
/** Optional defaultValue, or defaultValues array */
|
|
47
|
+
defaultValues?: T | T[];
|
|
48
|
+
|
|
49
|
+
/** @deprecated pagination, must be sent on filters */
|
|
50
|
+
pagination?: boolean,
|
|
51
|
+
/** Min character input to perform search */
|
|
52
|
+
minSearch?: number;
|
|
53
|
+
/** @deprecated searchResults, must be sent on filters as perPage */
|
|
54
|
+
searchResults?: number;
|
|
55
|
+
/** Search after x ms */
|
|
56
|
+
timerSearch?: number;
|
|
57
|
+
/** isEmpty - TODO: this flow is not tested. */
|
|
58
|
+
isEmpty?: boolean;
|
|
59
|
+
/** filter - optional parameters for the axios query */
|
|
60
|
+
filter?: { [x: string]: any };
|
|
61
|
+
/** name of the query parameter, usually just 'q' or 'search' */
|
|
62
|
+
queryFilter?: string;
|
|
63
|
+
/**
|
|
64
|
+
* The default function will compare the raw values equality
|
|
65
|
+
* the edge case is when a transformData is implemented, then the isOptionEqualToValue will have to compare to the transformation output.
|
|
66
|
+
* e.g: isOptionEqualToValue={(option, value) => value === option.id }
|
|
67
|
+
transformData={(data) => data?.id || null}
|
|
68
|
+
*/
|
|
69
|
+
isOptionEqualToValue?: (option: T, value: T) => boolean;
|
|
70
|
+
/**
|
|
71
|
+
* if not specified it will render the raw value for options
|
|
72
|
+
* if the response is not just a string or number array, you will have to specify which attribute from the option object you want to render
|
|
73
|
+
*/
|
|
74
|
+
renderAttribute?: string;
|
|
75
|
+
/** elementKeyID, Advanced usage, by default id, specify the attribute from the option object representing the key or id */
|
|
76
|
+
elementKeyId?: string;
|
|
77
|
+
/** onChange */
|
|
78
|
+
//onChange?: (value: T | T[]) => void;
|
|
79
|
+
/* renderInputTextFieldProps - Partial<TextFieldProps> */
|
|
80
|
+
renderInputTextFieldProps?: any; // It should be: Partial<TextFieldProps>
|
|
81
|
+
checkboxes?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* if its not possible to pass the default values according to the option interface, then set selectedIds, only works when multiple.
|
|
84
|
+
* once fetched the options and parsedOptions are available.
|
|
85
|
+
*/
|
|
86
|
+
selectedIds?: number[];
|
|
87
|
+
useDefaultSearch?: boolean;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const icon = <CheckBoxOutlineBlankIcon fontSize='small' />;
|
|
91
|
+
const checkedIcon = <CheckBoxIcon fontSize='small' />;
|
|
92
|
+
|
|
93
|
+
const SearchableSelectCheckboxes = function WrappedAutoComplete<
|
|
94
|
+
T,
|
|
95
|
+
>({ ...props }: ISearchableSelect<T>) {
|
|
96
|
+
const {
|
|
97
|
+
multiple,
|
|
98
|
+
freeSolo,
|
|
99
|
+
minSearch = 3,
|
|
100
|
+
timerSearch = 500,
|
|
101
|
+
checkboxes = false,
|
|
102
|
+
resource,
|
|
103
|
+
selectLabel,
|
|
104
|
+
renderText,
|
|
105
|
+
queryFilter = 'q',
|
|
106
|
+
defaultValues = null,
|
|
107
|
+
elementKeyId = 'id',
|
|
108
|
+
isEmpty = false,
|
|
109
|
+
filter,
|
|
110
|
+
isOptionEqualToValue = (option, value) => value === option,
|
|
111
|
+
renderAttribute = null,
|
|
112
|
+
name,
|
|
113
|
+
onChange,
|
|
114
|
+
renderInputTextFieldProps,
|
|
115
|
+
selectedIds,
|
|
116
|
+
useDefaultSearch = false,
|
|
117
|
+
...rest
|
|
118
|
+
} = props;
|
|
119
|
+
|
|
120
|
+
const [open, setOpen] = useState(false);
|
|
121
|
+
const [parsedOptions, setParsedOptions] = useState<T[]>(null);
|
|
122
|
+
const [q, setQ] = useState(null);
|
|
123
|
+
|
|
124
|
+
const [resourceData, setResourceData] = useState(null);
|
|
125
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
126
|
+
|
|
127
|
+
const [initialSelectedIds, setInitalSelectedIds] = useState(null);
|
|
128
|
+
|
|
129
|
+
const initialIncludes =
|
|
130
|
+
defaultValues && Array.isArray(defaultValues)
|
|
131
|
+
? defaultValues.map((element: any) =>
|
|
132
|
+
element[elementKeyId]
|
|
133
|
+
? element[elementKeyId]
|
|
134
|
+
: element)
|
|
135
|
+
: multiple && initialSelectedIds
|
|
136
|
+
? initialSelectedIds
|
|
137
|
+
: defaultValues;
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
const [includes, setIncludes] = useState(initialIncludes);
|
|
141
|
+
|
|
142
|
+
const [controlledValue, setControlledValue] = useState<T | T[]>(null);
|
|
143
|
+
const axios = useAxios();
|
|
144
|
+
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
setInitalSelectedIds(selectedIds);
|
|
147
|
+
}, []);
|
|
148
|
+
|
|
149
|
+
const updateControlledValue = (val: T | T[], origin?: string) => {
|
|
150
|
+
if (Array.isArray(val)) {
|
|
151
|
+
setControlledValue(val as T[]);
|
|
152
|
+
if ( origin === 'onChange') { setIncludes(val.map((v: any) => v[elementKeyId])); }
|
|
153
|
+
} else {
|
|
154
|
+
setControlledValue(val as T);
|
|
155
|
+
if ( origin === 'onChange') { setIncludes((val as any)[elementKeyId]); }
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const search = async () => {
|
|
160
|
+
setIsLoading(true);
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
const params = { [queryFilter]: q, ...filter, includes: includes };
|
|
164
|
+
|
|
165
|
+
const { data } = await axios.get(resource, {
|
|
166
|
+
params,
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
setResourceData(data.data);
|
|
170
|
+
} catch (e: any) {
|
|
171
|
+
console.error(e);
|
|
172
|
+
} finally {
|
|
173
|
+
setIsLoading(false);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
useEffect(() => {
|
|
178
|
+
search();
|
|
179
|
+
}, []);
|
|
180
|
+
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
if (q && q !== '' && !useDefaultSearch) {
|
|
183
|
+
search();
|
|
184
|
+
}
|
|
185
|
+
}, [q]);
|
|
186
|
+
|
|
187
|
+
useEffect(() => {
|
|
188
|
+
if (resourceData && !isLoading) {
|
|
189
|
+
if (parsedOptions)
|
|
190
|
+
setParsedOptions([
|
|
191
|
+
...parsedOptions,
|
|
192
|
+
...resourceData.map((ele: any) => {
|
|
193
|
+
return { ...ele, key: 'option' + ele.id };
|
|
194
|
+
}),
|
|
195
|
+
]);
|
|
196
|
+
setParsedOptions(
|
|
197
|
+
resourceData.map((ele: any) => {
|
|
198
|
+
return { ...ele, key: 'option' + ele.id };
|
|
199
|
+
}),
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
return () => setParsedOptions([]);
|
|
203
|
+
}, [resourceData, isLoading]);
|
|
204
|
+
|
|
205
|
+
const [timeOutSearch, setTimeOutSearch] = useState(undefined);
|
|
206
|
+
|
|
207
|
+
const debounce = (fn: Function, delay = 500) => {
|
|
208
|
+
clearTimeout(timeOutSearch);
|
|
209
|
+
setTimeOutSearch(
|
|
210
|
+
setTimeout(() => {
|
|
211
|
+
fn();
|
|
212
|
+
}, delay),
|
|
213
|
+
);
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const checkboxRenderOptions = (p, option, { selected }) => {
|
|
217
|
+
const { key, ...r } = p as any;
|
|
218
|
+
return (
|
|
219
|
+
<li key={option.key} {...r}>
|
|
220
|
+
<Checkbox
|
|
221
|
+
icon={icon}
|
|
222
|
+
checkedIcon={checkedIcon}
|
|
223
|
+
style={{ marginRight: 8 }}
|
|
224
|
+
checked={selected}
|
|
225
|
+
/>
|
|
226
|
+
|
|
227
|
+
{renderAttribute && !renderText
|
|
228
|
+
? option[renderAttribute]
|
|
229
|
+
: renderText(option)}
|
|
230
|
+
</li>
|
|
231
|
+
);
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const boxRenderOptions = (p, option: any) => {
|
|
235
|
+
const { key, ...newProps } = p as any;
|
|
236
|
+
return (
|
|
237
|
+
<Box
|
|
238
|
+
key={option.key}
|
|
239
|
+
component='li'
|
|
240
|
+
sx={{ '& > img': { mr: 2, flexShrink: 0 } }}
|
|
241
|
+
{...newProps}
|
|
242
|
+
>
|
|
243
|
+
{renderAttribute && !renderText
|
|
244
|
+
? option[renderAttribute]
|
|
245
|
+
: renderText(option)}
|
|
246
|
+
</Box>
|
|
247
|
+
);
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const _renderOption = checkboxes ? checkboxRenderOptions : boxRenderOptions;
|
|
251
|
+
|
|
252
|
+
useEffect(() => {
|
|
253
|
+
if (multiple && parsedOptions && initialSelectedIds) {
|
|
254
|
+
const values = parsedOptions.filter((option: any) =>
|
|
255
|
+
initialSelectedIds.includes(option[elementKeyId]),
|
|
256
|
+
);
|
|
257
|
+
updateControlledValue(values, 'selectedIds');
|
|
258
|
+
}
|
|
259
|
+
}, [parsedOptions, initialSelectedIds, multiple]);
|
|
260
|
+
|
|
261
|
+
useEffect(() => {
|
|
262
|
+
if (onChange &&
|
|
263
|
+
controlledValue) {
|
|
264
|
+
onChange(null, controlledValue as T | T[], null);
|
|
265
|
+
}
|
|
266
|
+
}, [controlledValue]);
|
|
267
|
+
return (
|
|
268
|
+
<>
|
|
269
|
+
{isLoading && !parsedOptions ? (
|
|
270
|
+
<CircularProgress color='inherit' size={20} />
|
|
271
|
+
) : (
|
|
272
|
+
<></>
|
|
273
|
+
)}
|
|
274
|
+
{parsedOptions && (
|
|
275
|
+
<Autocomplete
|
|
276
|
+
key={'autocomplete-' + name}
|
|
277
|
+
multiple={multiple}
|
|
278
|
+
freeSolo={freeSolo}
|
|
279
|
+
loading={isLoading && open}
|
|
280
|
+
{...(checkboxes && { disableCloseOnSelect: true })}
|
|
281
|
+
options={parsedOptions}
|
|
282
|
+
open={open}
|
|
283
|
+
onOpen={() => setOpen(true)}
|
|
284
|
+
onClose={() => setOpen(false)}
|
|
285
|
+
value={controlledValue ? controlledValue : multiple ? [] : null}
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
/* @ts-ignore */
|
|
289
|
+
isOptionEqualToValue={isOptionEqualToValue}
|
|
290
|
+
|
|
291
|
+
autoHighlight
|
|
292
|
+
getOptionLabel={(option: any) => {
|
|
293
|
+
return renderAttribute && !renderText
|
|
294
|
+
? option[renderAttribute]
|
|
295
|
+
: (renderText ? renderText(option) : option)
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
renderOption={_renderOption}
|
|
299
|
+
onChange={(event: any, rawValue, _reason) => {
|
|
300
|
+
updateControlledValue(rawValue as T | T[], 'onChange');
|
|
301
|
+
}}
|
|
302
|
+
renderInput={(params) => {
|
|
303
|
+
return (
|
|
304
|
+
<TextField
|
|
305
|
+
key={params.id}
|
|
306
|
+
{...params}
|
|
307
|
+
label={selectLabel}
|
|
308
|
+
variant='outlined'
|
|
309
|
+
onChange={(ev) => {
|
|
310
|
+
|
|
311
|
+
if(useDefaultSearch !== true) {
|
|
312
|
+
const searchValue = ev.target.value;
|
|
313
|
+
|
|
314
|
+
if (
|
|
315
|
+
searchValue &&
|
|
316
|
+
searchValue !== '' &&
|
|
317
|
+
searchValue.length >= minSearch
|
|
318
|
+
) {
|
|
319
|
+
|
|
320
|
+
debounce(() => setQ(searchValue), timerSearch);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
}
|
|
324
|
+
}}
|
|
325
|
+
InputProps={{
|
|
326
|
+
...params.InputProps,
|
|
327
|
+
autoComplete: 'new-password',
|
|
328
|
+
endAdornment: (
|
|
329
|
+
<>
|
|
330
|
+
{isLoading ? (
|
|
331
|
+
<CircularProgress color='inherit' size={20} />
|
|
332
|
+
) : null}
|
|
333
|
+
{params.InputProps.endAdornment}
|
|
334
|
+
</>
|
|
335
|
+
),
|
|
336
|
+
}}
|
|
337
|
+
{...renderInputTextFieldProps}
|
|
338
|
+
/>
|
|
339
|
+
);
|
|
340
|
+
}}
|
|
341
|
+
{...rest}
|
|
342
|
+
/>
|
|
343
|
+
)}
|
|
344
|
+
</>
|
|
345
|
+
);
|
|
346
|
+
};
|
|
347
|
+
export const MemoizedSearchableSelectCheckboxes = React.memo(
|
|
348
|
+
SearchableSelectCheckboxes,
|
|
349
|
+
() => {
|
|
350
|
+
// never refresh
|
|
351
|
+
return true;
|
|
352
|
+
},
|
|
353
|
+
) as typeof SearchableSelectCheckboxes;
|
|
354
|
+
|
|
355
|
+
export default SearchableSelectCheckboxes;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FC,
|
|
3
|
+
PropsWithChildren,
|
|
4
|
+
memo,
|
|
5
|
+
useRef,
|
|
6
|
+
} from 'react';
|
|
7
|
+
|
|
8
|
+
import { Datagrid } from 'react-admin';
|
|
9
|
+
import { DatagridProps } from 'react-admin';
|
|
10
|
+
import SortableDatagridBody from './SortableDataGridBody';
|
|
11
|
+
import { SortableDatagridHeader } from './SortableDataGridHeader';
|
|
12
|
+
import SortableDatagridRow from './SortableDataGridRow';
|
|
13
|
+
import React from 'react';
|
|
14
|
+
|
|
15
|
+
interface ISortableDatagrid extends DatagridProps, PropsWithChildren {
|
|
16
|
+
onOrderUpdate?: (data: any) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const SortableDatagrid: FC<ISortableDatagrid> = (props) => {
|
|
20
|
+
const { children, onOrderUpdate, ...rest } = props;
|
|
21
|
+
const bodyRef = React.useRef(null);
|
|
22
|
+
//const [tableEl, setTableEl] = useState(null);
|
|
23
|
+
|
|
24
|
+
const _onOrderUpdate = (d: any[]) => {
|
|
25
|
+
if (onOrderUpdate) { onOrderUpdate(d); }
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const SortableRootDatagrid = (p) => (
|
|
29
|
+
<Datagrid
|
|
30
|
+
{...p}
|
|
31
|
+
header={<SortableDatagridHeader />}
|
|
32
|
+
body={
|
|
33
|
+
<SortableDatagridBody
|
|
34
|
+
/* @ts-ignore : Expected */
|
|
35
|
+
onOrderUpdate={_onOrderUpdate}
|
|
36
|
+
ref={bodyRef}
|
|
37
|
+
//{...props}
|
|
38
|
+
row={<SortableDatagridRow />}
|
|
39
|
+
/>
|
|
40
|
+
}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const SortableRootDatagridPure = memo(
|
|
45
|
+
SortableRootDatagrid,
|
|
46
|
+
() => true,
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div id='sortable-list'>
|
|
51
|
+
<SortableRootDatagridPure {...rest}>{children}</SortableRootDatagridPure>
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export default SortableDatagrid;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { cloneElement, memo, FC, forwardRef } from 'react';
|
|
3
|
+
import { TableBody } from '@mui/material';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
DatagridBody,
|
|
7
|
+
DatagridBodyProps,
|
|
8
|
+
DatagridRow,
|
|
9
|
+
PureDatagridRow,
|
|
10
|
+
} from 'react-admin';
|
|
11
|
+
|
|
12
|
+
import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd';
|
|
13
|
+
|
|
14
|
+
export interface ISortableDatagridBodyProps extends DatagridBodyProps {
|
|
15
|
+
onOrderUpdate?: (data: any[]) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const defaultChildren = <DatagridRow />;
|
|
19
|
+
const defaultData = [];
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
const SortableDatagridBody: FC<ISortableDatagridBodyProps> = forwardRef(
|
|
23
|
+
(
|
|
24
|
+
{
|
|
25
|
+
children,
|
|
26
|
+
className,
|
|
27
|
+
data = defaultData,
|
|
28
|
+
expand,
|
|
29
|
+
hasBulkActions = false,
|
|
30
|
+
hover,
|
|
31
|
+
onToggleItem,
|
|
32
|
+
resource,
|
|
33
|
+
row = defaultChildren,
|
|
34
|
+
rowClick,
|
|
35
|
+
rowStyle,
|
|
36
|
+
selectedIds,
|
|
37
|
+
isRowSelectable,
|
|
38
|
+
onOrderUpdate,
|
|
39
|
+
...rest
|
|
40
|
+
},
|
|
41
|
+
_ref,
|
|
42
|
+
) => {
|
|
43
|
+
React.useEffect(() => {
|
|
44
|
+
console.log('data has been updated');
|
|
45
|
+
}, [data]);
|
|
46
|
+
|
|
47
|
+
const [orderedData, setOrderedData] = React.useState(data);
|
|
48
|
+
|
|
49
|
+
/*const updateOrderedData = (data) => {
|
|
50
|
+
onOrderUpdate && onOrderUpdate(orderedData);
|
|
51
|
+
setOrderedData(data);
|
|
52
|
+
};*/
|
|
53
|
+
|
|
54
|
+
const reorder = (list, startIndex, endIndex) => {
|
|
55
|
+
const result = Array.from(list);
|
|
56
|
+
const [removed] = result.splice(startIndex, 1);
|
|
57
|
+
result.splice(endIndex, 0, removed);
|
|
58
|
+
|
|
59
|
+
return result;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const getItemStyle = (isDragging, draggableStyle) => ({
|
|
63
|
+
border: isDragging ? '1px dashed #ccc' : 'none',
|
|
64
|
+
...draggableStyle,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const onDragEnd = (result) => {
|
|
68
|
+
if (!result.destination) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const movedItems = reorder(
|
|
73
|
+
orderedData,
|
|
74
|
+
result.source.index,
|
|
75
|
+
result.destination.index,
|
|
76
|
+
);
|
|
77
|
+
setOrderedData(movedItems);
|
|
78
|
+
if (onOrderUpdate) { onOrderUpdate(movedItems); }
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
(<DragDropContext onDragEnd={onDragEnd}>
|
|
83
|
+
<Droppable droppableId='droppable'>
|
|
84
|
+
{(provided) => (
|
|
85
|
+
/* @ts-ignore Expected KnownIssue1 */
|
|
86
|
+
(<TableBody
|
|
87
|
+
ref={provided.innerRef}
|
|
88
|
+
className={'datagrid-body'}
|
|
89
|
+
{...rest}
|
|
90
|
+
>
|
|
91
|
+
{orderedData.map((record, rowIndex) => {
|
|
92
|
+
return (
|
|
93
|
+
<Draggable
|
|
94
|
+
key={record.id}
|
|
95
|
+
draggableId={'q-' + record.id}
|
|
96
|
+
index={rowIndex}
|
|
97
|
+
>
|
|
98
|
+
{(p, snapshot) => {
|
|
99
|
+
const defaultStyles = rowStyle
|
|
100
|
+
? rowStyle(record, rowIndex)
|
|
101
|
+
: {};
|
|
102
|
+
return cloneElement(
|
|
103
|
+
row,
|
|
104
|
+
{
|
|
105
|
+
ref: p.innerRef,
|
|
106
|
+
...p.draggableProps,
|
|
107
|
+
...p.dragHandleProps,
|
|
108
|
+
|
|
109
|
+
/*className: clsx(DatagridClasses.row, {
|
|
110
|
+
[DatagridClasses.rowEven]: rowIndex % 2 === 0,
|
|
111
|
+
[DatagridClasses.rowOdd]: rowIndex % 2 !== 0,
|
|
112
|
+
}),*/
|
|
113
|
+
expand,
|
|
114
|
+
hasBulkActions: hasBulkActions && !!selectedIds,
|
|
115
|
+
hover,
|
|
116
|
+
id: record.id ?? `row${rowIndex}`,
|
|
117
|
+
key: record.id ?? `row${rowIndex}`,
|
|
118
|
+
onToggleItem,
|
|
119
|
+
record,
|
|
120
|
+
resource,
|
|
121
|
+
rowClick,
|
|
122
|
+
selectable:
|
|
123
|
+
!isRowSelectable || isRowSelectable(record),
|
|
124
|
+
selected: selectedIds?.includes(record.id),
|
|
125
|
+
style: {
|
|
126
|
+
...defaultStyles,
|
|
127
|
+
...getItemStyle(
|
|
128
|
+
snapshot.isDragging,
|
|
129
|
+
p.draggableProps.style,
|
|
130
|
+
),
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
children,
|
|
134
|
+
);
|
|
135
|
+
}}
|
|
136
|
+
</Draggable>
|
|
137
|
+
);
|
|
138
|
+
})}
|
|
139
|
+
</TableBody>)
|
|
140
|
+
)}
|
|
141
|
+
</Droppable>
|
|
142
|
+
</DragDropContext>)
|
|
143
|
+
);
|
|
144
|
+
},
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
// @ts-ignore Trick Material UI Table into thinking this is one of the child type it supports.
|
|
150
|
+
SortableDatagridBody.muiName = 'TableBody';
|
|
151
|
+
|
|
152
|
+
export const PureSortableDatagridBody = memo(
|
|
153
|
+
(props) => <SortableDatagridBody row={<PureDatagridRow />} {...props} />,
|
|
154
|
+
() => true,
|
|
155
|
+
); // Memo the sortable table, to avoid data updates.
|
|
156
|
+
|
|
157
|
+
// @ts-ignore Trick Material UI Table into thinking this is one of the child type it supports
|
|
158
|
+
PureSortableDatagridBody.muiName = 'TableBody';
|
|
159
|
+
|
|
160
|
+
export default PureSortableDatagridBody;
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
/* KnownIssue1 = No overload matches this call.
|
|
164
|
+
Overload 1 of 2, '(props: { component: ElementType<any>; } & TableBodyOwnProps & CommonProps & Omit<any, "className" | "style" | "classes" | "children" | "sx">): Element', gave the following error.
|
|
165
|
+
Type '{ children: Element[]; record?: RaRecord<Identifier>; rowSx?: (record: RaRecord<Identifier>, index: number) => SxProps; ... 262 more ...; className: string; }' is not assignable to type '{ component: ElementType<any>; }'.
|
|
166
|
+
Property 'component' is optional in type '{ children: Element[]; record?: RaRecord<Identifier>; rowSx?: (record: RaRecord<Identifier>, index: number) => SxProps; ... 262 more ...; className: string; }' but required in type '{ component: ElementType<any>; }'.
|
|
167
|
+
Overload 2 of 2, '(props: DefaultComponentProps<TableBodyTypeMap<{}, "tbody">>): Element', gave the following error.
|
|
168
|
+
Types of property 'sx' are incompatible.
|
|
169
|
+
Type 'import("/node_modules/@mui/system/styleFunctionSx/styleFunctionSx").SxProps<import("/node_modules/react-admin/node_modules/@mui/material/styles/createTheme").Theme>' is not assignable to type 'import("/node_modules/@mui/system/styleFunctionSx/styleFunctionSx").SxProps<import("/node_modules/@mui/material/styles/createTheme").Theme>'.
|
|
170
|
+
Type 'SystemCssProperties<Theme>' is not assignable to type 'SxProps<Theme>'.
|
|
171
|
+
Type 'SystemCssProperties<Theme>' is not assignable to type 'CSSSelectorObjectOrCssVariables<Theme>'.
|
|
172
|
+
Property 'clipPath' is incompatible with index signature.
|
|
173
|
+
Type 'SystemStyleObject<Theme> | ResponsiveStyleValue<ClipPath | string[]> | ((theme: Theme) => ResponsiveStyleValue<ClipPath | string[]>)' is not assignable to type 'CssVariableType | SystemStyleObject<Theme> | ((theme: Theme) => string | number | SystemStyleObject<Theme>)'.
|
|
174
|
+
Type 'SystemCssProperties<Theme>' is not assignable to type 'CssVariableType | SystemStyleObject<Theme> | ((theme: Theme) => string | number | SystemStyleObject<Theme>)'.ts(2769)
|
|
175
|
+
*/
|