@axinom/mosaic-ui 0.51.0-rc.9 → 0.52.0-rc.0
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/Explorer/ConditionalSplit/ConditionalSplit.d.ts +8 -0
- package/dist/components/Explorer/ConditionalSplit/ConditionalSplit.d.ts.map +1 -0
- package/dist/components/Explorer/Explorer.d.ts +3 -1
- package/dist/components/Explorer/Explorer.d.ts.map +1 -1
- package/dist/components/Explorer/Explorer.model.d.ts +18 -1
- package/dist/components/Explorer/Explorer.model.d.ts.map +1 -1
- package/dist/components/Explorer/QuickEdit/QuickEditContext.d.ts +11 -0
- package/dist/components/Explorer/QuickEdit/QuickEditContext.d.ts.map +1 -0
- package/dist/components/Explorer/QuickEdit/useQuickEdit.d.ts +22 -0
- package/dist/components/Explorer/QuickEdit/useQuickEdit.d.ts.map +1 -0
- package/dist/components/Explorer/{InMemoryDataProvider.d.ts → helpers/InMemoryDataProvider.d.ts} +3 -3
- package/dist/components/Explorer/helpers/InMemoryDataProvider.d.ts.map +1 -0
- package/dist/components/Explorer/helpers/useActions.d.ts +31 -0
- package/dist/components/Explorer/helpers/useActions.d.ts.map +1 -0
- package/dist/components/Explorer/{useDataProvider.d.ts → helpers/useDataProvider.d.ts} +6 -6
- package/dist/components/Explorer/helpers/useDataProvider.d.ts.map +1 -0
- package/dist/components/Explorer/helpers/useFilters.d.ts +21 -0
- package/dist/components/Explorer/helpers/useFilters.d.ts.map +1 -0
- package/dist/components/Explorer/helpers/useStationMessage.d.ts +17 -0
- package/dist/components/Explorer/helpers/useStationMessage.d.ts.map +1 -0
- package/dist/components/Explorer/index.d.ts +2 -1
- package/dist/components/Explorer/index.d.ts.map +1 -1
- package/dist/components/FormStation/Create/Create.d.ts.map +1 -1
- package/dist/components/FormStation/FormStation.d.ts +4 -1
- package/dist/components/FormStation/FormStation.d.ts.map +1 -1
- package/dist/components/FormStation/FormStationHeader/FormStationHeader.d.ts +1 -0
- package/dist/components/FormStation/FormStationHeader/FormStationHeader.d.ts.map +1 -1
- package/dist/components/FormStation/SaveOnDemand/SaveOnDemand.d.ts +11 -0
- package/dist/components/FormStation/SaveOnDemand/SaveOnDemand.d.ts.map +1 -0
- package/dist/components/FormStation/helpers/useDataProvider.d.ts.map +1 -1
- package/dist/components/Icons/Icons.d.ts.map +1 -1
- package/dist/components/Icons/Icons.models.d.ts +28 -24
- package/dist/components/Icons/Icons.models.d.ts.map +1 -1
- package/dist/components/List/List.d.ts +1 -1
- package/dist/components/List/List.d.ts.map +1 -1
- package/dist/components/List/List.model.d.ts +4 -0
- package/dist/components/List/List.model.d.ts.map +1 -1
- package/dist/components/PageHeader/PageHeader.d.ts.map +1 -1
- package/dist/components/PageHeader/PageHeaderAction/PageHeaderAction.d.ts.map +1 -1
- package/dist/components/PageHeader/PageHeaderAction/PageHeaderAction.model.d.ts +2 -1
- package/dist/components/PageHeader/PageHeaderAction/PageHeaderAction.model.d.ts.map +1 -1
- package/dist/components/PageHeader/PageHeaderActionsGroup/PageHeaderActionsGroup.d.ts +1 -1
- package/dist/components/PageHeader/PageHeaderActionsGroup/PageHeaderActionsGroup.d.ts.map +1 -1
- package/dist/components/PageHeader/helpers/useElementWidthObserver.d.ts +6 -0
- package/dist/components/PageHeader/helpers/useElementWidthObserver.d.ts.map +1 -0
- package/dist/index.es.js +4 -4
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/initialize.d.ts +1 -1
- package/dist/initialize.d.ts.map +1 -1
- package/package.json +4 -3
- package/src/components/EmptyStation/EmptyStation.spec.tsx +24 -0
- package/src/components/Explorer/ConditionalSplit/ConditionalSplit.tsx +23 -0
- package/src/components/Explorer/Explorer.model.ts +19 -1
- package/src/components/Explorer/Explorer.scss +4 -0
- package/src/components/Explorer/Explorer.spec.tsx +28 -3
- package/src/components/Explorer/Explorer.stories.tsx +90 -5
- package/src/components/Explorer/Explorer.tsx +149 -185
- package/src/components/Explorer/NavigationExplorer/NavigationExplorer.spec.tsx +26 -0
- package/src/components/Explorer/NavigationExplorer/NavigationExplorer.stories.tsx +2 -2
- package/src/components/Explorer/QuickEdit/QuickEditContext.tsx +16 -0
- package/src/components/Explorer/QuickEdit/useQuickEdit.spec.tsx +461 -0
- package/src/components/Explorer/QuickEdit/useQuickEdit.tsx +169 -0
- package/src/components/Explorer/SelectionExplorer/SelectionExplorer.spec.tsx +6 -0
- package/src/components/Explorer/SelectionExplorer/SelectionExplorer.stories.tsx +2 -2
- package/src/components/Explorer/{InMemoryDataProvider.ts → helpers/InMemoryDataProvider.ts} +4 -4
- package/src/components/Explorer/helpers/useActions.ts +203 -0
- package/src/components/Explorer/{useDataProvider.tsx → helpers/useDataProvider.tsx} +11 -11
- package/src/components/Explorer/helpers/useFilters.tsx +77 -0
- package/src/components/Explorer/{useStationMessage.tsx → helpers/useStationMessage.tsx} +8 -6
- package/src/components/Explorer/index.ts +10 -6
- package/src/components/FormStation/Create/Create.tsx +1 -0
- package/src/components/FormStation/FormStation.spec.tsx +62 -73
- package/src/components/FormStation/FormStation.tsx +31 -15
- package/src/components/FormStation/FormStationHeader/FormStationHeader.tsx +38 -18
- package/src/components/FormStation/SaveOnDemand/SaveOnDemand.tsx +55 -0
- package/src/components/FormStation/helpers/useDataProvider.ts +1 -8
- package/src/components/Icons/Icons.models.ts +4 -0
- package/src/components/Icons/Icons.tsx +78 -0
- package/src/components/InlineMenu/InlineMenu.spec.tsx +18 -0
- package/src/components/List/List.model.ts +5 -0
- package/src/components/List/List.tsx +29 -5
- package/src/components/List/ListRow/ListRow.spec.tsx +0 -10
- package/src/components/List/ListRow/ListRow.tsx +1 -1
- package/src/components/PageHeader/PageHeader.scss +1 -2
- package/src/components/PageHeader/PageHeader.stories.tsx +6 -2
- package/src/components/PageHeader/PageHeader.tsx +10 -16
- package/src/components/PageHeader/PageHeaderAction/PageHeaderAction.model.ts +1 -0
- package/src/components/PageHeader/PageHeaderAction/PageHeaderAction.scss +7 -0
- package/src/components/PageHeader/PageHeaderAction/PageHeaderAction.tsx +1 -0
- package/src/components/PageHeader/PageHeaderActionsGroup/PageHeaderActionsGroup.spec.tsx +19 -7
- package/src/components/PageHeader/PageHeaderActionsGroup/PageHeaderActionsGroup.tsx +19 -12
- package/src/components/PageHeader/helpers/useElementWidthObserver.tsx +30 -0
- package/src/initialize.ts +2 -2
- package/dist/components/Explorer/InMemoryDataProvider.d.ts.map +0 -1
- package/dist/components/Explorer/useDataProvider.d.ts.map +0 -1
- package/dist/components/Explorer/useStationMessage.d.ts +0 -15
- package/dist/components/Explorer/useStationMessage.d.ts.map +0 -1
- /package/src/components/Explorer/{InMemoryDataProvider.spec.ts → helpers/InMemoryDataProvider.spec.ts} +0 -0
|
@@ -8,14 +8,11 @@ import {
|
|
|
8
8
|
useState,
|
|
9
9
|
} from 'react';
|
|
10
10
|
import { noop } from '../../helpers/utils';
|
|
11
|
-
import { showNotification } from '../../initialize';
|
|
12
11
|
import { Data } from '../../types/data';
|
|
13
12
|
import { ErrorTypeToStationError } from '../../utils/ErrorTypeToStationError';
|
|
14
13
|
import { isContextAction } from '../Actions/Action/Action';
|
|
15
14
|
import { ActionData } from '../Actions/Actions.models';
|
|
16
|
-
import { Filters } from '../Filters/Filters';
|
|
17
15
|
import { FilterType, FilterValues } from '../Filters/Filters.model';
|
|
18
|
-
import { IconName } from '../Icons/Icons.models';
|
|
19
16
|
import {
|
|
20
17
|
Column,
|
|
21
18
|
ItemSelectEventArgs,
|
|
@@ -24,25 +21,24 @@ import {
|
|
|
24
21
|
ListSelectMode,
|
|
25
22
|
SortData,
|
|
26
23
|
} from '../List';
|
|
27
|
-
import {
|
|
28
|
-
PageHeader,
|
|
29
|
-
PageHeaderActionItemProps,
|
|
30
|
-
PageHeaderActionProps,
|
|
31
|
-
} from '../PageHeader';
|
|
32
|
-
import { isPageHeaderNavigationAction } from '../PageHeader/PageHeaderAction/PageHeaderAction';
|
|
33
|
-
import { PageHeaderJsActionProps } from '../PageHeader/PageHeaderAction/PageHeaderAction.model';
|
|
24
|
+
import { PageHeader, PageHeaderActionProps } from '../PageHeader';
|
|
34
25
|
import { getState, storeState } from '../Utils/State/GlobalState';
|
|
35
26
|
import { ErrorType } from '../models';
|
|
27
|
+
import { ConditionalSplit } from './ConditionalSplit/ConditionalSplit';
|
|
36
28
|
import {
|
|
37
29
|
ExplorerBulkAction,
|
|
38
30
|
ExplorerDataProvider,
|
|
39
31
|
ExplorerDataProviderConnection,
|
|
40
32
|
ExplorerStateOptions,
|
|
41
33
|
ItemSelection,
|
|
34
|
+
QuickEditRegistration,
|
|
42
35
|
} from './Explorer.model';
|
|
43
36
|
import classes from './Explorer.scss';
|
|
44
|
-
import {
|
|
45
|
-
import {
|
|
37
|
+
import { useQuickEdit } from './QuickEdit/useQuickEdit';
|
|
38
|
+
import { useActions } from './helpers/useActions';
|
|
39
|
+
import { ResultCounts, useDataProvider } from './helpers/useDataProvider';
|
|
40
|
+
import { useFilters } from './helpers/useFilters';
|
|
41
|
+
import { StationMessage, useStationMessage } from './helpers/useStationMessage';
|
|
46
42
|
|
|
47
43
|
export interface ExplorerProps<T extends Data> {
|
|
48
44
|
/** Title shown in page header */
|
|
@@ -136,6 +132,9 @@ export interface ExplorerProps<T extends Data> {
|
|
|
136
132
|
/** Update the tab title using the 'title' field. (default: true) */
|
|
137
133
|
setTabTitle?: boolean;
|
|
138
134
|
|
|
135
|
+
/** Quick Edit Registrations */
|
|
136
|
+
quickEditRegistrations?: QuickEditRegistration<T>[];
|
|
137
|
+
|
|
139
138
|
/**
|
|
140
139
|
* When set, this function is used to generate the link that the user should be navigated to for each item.
|
|
141
140
|
*
|
|
@@ -211,6 +210,8 @@ export const Explorer = React.forwardRef(function Explorer<T extends Data>(
|
|
|
211
210
|
defaultSortOrder,
|
|
212
211
|
setTabTitle = true,
|
|
213
212
|
|
|
213
|
+
quickEditRegistrations,
|
|
214
|
+
|
|
214
215
|
onItemClicked,
|
|
215
216
|
onBulkActionsToggled = noop,
|
|
216
217
|
generateItemLink,
|
|
@@ -227,30 +228,12 @@ export const Explorer = React.forwardRef(function Explorer<T extends Data>(
|
|
|
227
228
|
...persistExplorerStates,
|
|
228
229
|
};
|
|
229
230
|
|
|
230
|
-
const [activeFilters, setActiveFilters] = useState<FilterValues<T>>(
|
|
231
|
-
getState<FilterValues<T>>(stationKey, 'filters') ??
|
|
232
|
-
defaultFilterValues ??
|
|
233
|
-
{},
|
|
234
|
-
);
|
|
235
|
-
|
|
236
231
|
const [sortOrder, setSortOrder] = useState<SortData<T>>(
|
|
237
232
|
getState<SortData<T>>(stationKey, 'sort') ?? defaultSortOrder,
|
|
238
233
|
);
|
|
239
234
|
|
|
240
235
|
const listRef = React.useRef<ListElement>(null);
|
|
241
236
|
|
|
242
|
-
useEffect(() => {
|
|
243
|
-
if (
|
|
244
|
-
globalStateOptions.filters &&
|
|
245
|
-
activeFilters !== defaultFilterValues &&
|
|
246
|
-
Object.keys(activeFilters).length > 0
|
|
247
|
-
) {
|
|
248
|
-
storeState(stationKey, 'filters', activeFilters);
|
|
249
|
-
} else {
|
|
250
|
-
storeState(stationKey, 'filters', undefined);
|
|
251
|
-
}
|
|
252
|
-
}, [activeFilters, defaultFilterValues, globalStateOptions.filters, stationKey]);
|
|
253
|
-
|
|
254
237
|
useEffect(() => {
|
|
255
238
|
if (globalStateOptions.sort && sortOrder !== defaultSortOrder) {
|
|
256
239
|
storeState(stationKey, 'sort', sortOrder);
|
|
@@ -259,6 +242,25 @@ export const Explorer = React.forwardRef(function Explorer<T extends Data>(
|
|
|
259
242
|
}
|
|
260
243
|
}, [defaultSortOrder, globalStateOptions.sort, sortOrder, stationKey]);
|
|
261
244
|
|
|
245
|
+
const onFilterChangedHandler = (filters: FilterValues<T>): void => {
|
|
246
|
+
onFiltersChange(filters);
|
|
247
|
+
listRef.current?.resetSelection();
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const {
|
|
251
|
+
activeFilters,
|
|
252
|
+
Filters,
|
|
253
|
+
filtersVisible,
|
|
254
|
+
toggleFiltersVisible,
|
|
255
|
+
collapseFilters,
|
|
256
|
+
} = useFilters<T>({
|
|
257
|
+
stationKey,
|
|
258
|
+
globalStateOptions,
|
|
259
|
+
filterOptions,
|
|
260
|
+
defaultFilterValues,
|
|
261
|
+
onFiltersChange: onFilterChangedHandler,
|
|
262
|
+
});
|
|
263
|
+
|
|
262
264
|
const {
|
|
263
265
|
data,
|
|
264
266
|
isLoading,
|
|
@@ -277,9 +279,24 @@ export const Explorer = React.forwardRef(function Explorer<T extends Data>(
|
|
|
277
279
|
keyProperty,
|
|
278
280
|
});
|
|
279
281
|
|
|
282
|
+
const {
|
|
283
|
+
isQuickEditMode,
|
|
284
|
+
quickEditAction,
|
|
285
|
+
QuickEditContextProvider,
|
|
286
|
+
quickEditStation,
|
|
287
|
+
changeSelectedItem,
|
|
288
|
+
} = useQuickEdit({
|
|
289
|
+
listRef,
|
|
290
|
+
registrations: quickEditRegistrations,
|
|
291
|
+
hasData: data.length > 0,
|
|
292
|
+
collapseFilters,
|
|
293
|
+
generateItemLink,
|
|
294
|
+
});
|
|
295
|
+
|
|
280
296
|
const { mode, setIsBulkOpen } = useListSelectionMode(
|
|
281
297
|
selectionMode,
|
|
282
298
|
openBulkActionsOnStart,
|
|
299
|
+
isQuickEditMode,
|
|
283
300
|
);
|
|
284
301
|
|
|
285
302
|
// TODO: Put into hook?------------------
|
|
@@ -323,23 +340,23 @@ export const Explorer = React.forwardRef(function Explorer<T extends Data>(
|
|
|
323
340
|
|
|
324
341
|
// Emits selected row data and current ListSelectMode state
|
|
325
342
|
const onItemClickedHandler = useCallback(
|
|
326
|
-
(item: T)
|
|
327
|
-
if (
|
|
343
|
+
async (item: T) => {
|
|
344
|
+
if (isQuickEditMode) {
|
|
345
|
+
await changeSelectedItem(item);
|
|
346
|
+
} else if (onItemClicked !== undefined) {
|
|
328
347
|
onItemClicked(item, mode);
|
|
329
348
|
}
|
|
330
349
|
},
|
|
331
|
-
[
|
|
350
|
+
[isQuickEditMode, onItemClicked, changeSelectedItem, mode],
|
|
332
351
|
);
|
|
333
352
|
|
|
334
353
|
const { resultsTitle } = useSubtitle<T>(mode, itemSelection, resultCount);
|
|
335
354
|
|
|
336
355
|
const errAction = 'An error occurred when trying to execute the operation.';
|
|
337
|
-
const errBulk =
|
|
338
|
-
'An error occurred when trying to execute the bulk operation.';
|
|
339
356
|
|
|
340
|
-
const inlineMenuActionsHandler = (data: T): ActionData[] =>
|
|
341
|
-
|
|
342
|
-
|
|
357
|
+
const inlineMenuActionsHandler = (data: T): ActionData[] =>
|
|
358
|
+
(inlineMenuActions?.(data) ?? []).map((action) =>
|
|
359
|
+
isContextAction(action)
|
|
343
360
|
? {
|
|
344
361
|
...action,
|
|
345
362
|
onActionSelected: async () => {
|
|
@@ -353,157 +370,95 @@ export const Explorer = React.forwardRef(function Explorer<T extends Data>(
|
|
|
353
370
|
}
|
|
354
371
|
},
|
|
355
372
|
}
|
|
356
|
-
: action
|
|
357
|
-
|
|
358
|
-
};
|
|
373
|
+
: action,
|
|
374
|
+
);
|
|
359
375
|
|
|
360
|
-
const
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
headerActions.push({ kind: 'spacer' });
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
actions?.forEach((action) => {
|
|
381
|
-
headerActions.push({
|
|
382
|
-
...(isPageHeaderNavigationAction(action)
|
|
383
|
-
? action
|
|
384
|
-
: {
|
|
385
|
-
...action,
|
|
386
|
-
onClick: async () => {
|
|
387
|
-
try {
|
|
388
|
-
const result = await action.onClick();
|
|
389
|
-
if (result) {
|
|
390
|
-
setStationMessage(errMsg(result));
|
|
391
|
-
}
|
|
392
|
-
} catch (error) {
|
|
393
|
-
setStationMessage(errMsg(error, errAction));
|
|
394
|
-
}
|
|
395
|
-
},
|
|
396
|
-
}),
|
|
397
|
-
kind: 'action',
|
|
398
|
-
});
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
return headerActions;
|
|
402
|
-
};
|
|
403
|
-
|
|
404
|
-
const bulkActionsHandler = (): PageHeaderJsActionProps[] => {
|
|
405
|
-
return (bulkActions ?? []).map((action) => {
|
|
406
|
-
return {
|
|
407
|
-
...action,
|
|
408
|
-
onClick: async () => {
|
|
409
|
-
if (action.showStartedNotification !== false) {
|
|
410
|
-
showNotification({
|
|
411
|
-
title: `Bulk Action '${action.label}' Started`,
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
try {
|
|
416
|
-
const result = await action.onClick(getBulkActionSelection());
|
|
417
|
-
if (result) {
|
|
418
|
-
const message = errMsg(result);
|
|
419
|
-
showNotification({
|
|
420
|
-
title:
|
|
421
|
-
typeof message.title === 'string'
|
|
422
|
-
? message.title
|
|
423
|
-
: 'An error occurred',
|
|
424
|
-
body: message.body,
|
|
425
|
-
options: {
|
|
426
|
-
type: 'error',
|
|
427
|
-
},
|
|
428
|
-
});
|
|
429
|
-
} else {
|
|
430
|
-
if (action.reloadData) {
|
|
431
|
-
onReloadData();
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
} catch (error) {
|
|
435
|
-
setStationMessage(errMsg(error, errBulk));
|
|
436
|
-
}
|
|
437
|
-
},
|
|
438
|
-
};
|
|
439
|
-
});
|
|
440
|
-
};
|
|
376
|
+
const { actions: pageHeaderActions } = useActions<T>({
|
|
377
|
+
actions,
|
|
378
|
+
bulkActions,
|
|
379
|
+
quickEditAction,
|
|
380
|
+
openBulkActionsOnStart,
|
|
381
|
+
filtersVisible,
|
|
382
|
+
hasFilters: filterOptions !== undefined,
|
|
383
|
+
resultCount,
|
|
384
|
+
activeFilterCount: Object.keys(activeFilters).length,
|
|
385
|
+
itemSelection,
|
|
386
|
+
getBulkActionSelection,
|
|
387
|
+
onReloadData,
|
|
388
|
+
setStationMessage,
|
|
389
|
+
onBulkActionsToggled,
|
|
390
|
+
setIsBulkOpen,
|
|
391
|
+
toggleFiltersVisible,
|
|
392
|
+
});
|
|
441
393
|
|
|
442
394
|
return (
|
|
443
|
-
<
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
{StationMessage}
|
|
461
|
-
<Filters<T>
|
|
462
|
-
options={filterOptions}
|
|
463
|
-
defaultValues={activeFilters}
|
|
464
|
-
onFiltersChange={(args) => {
|
|
465
|
-
onFiltersChange(args);
|
|
466
|
-
setActiveFilters(args);
|
|
467
|
-
listRef.current?.resetSelection();
|
|
468
|
-
}}
|
|
469
|
-
/>
|
|
470
|
-
<div>
|
|
471
|
-
<List<T>
|
|
472
|
-
ref={listRef}
|
|
473
|
-
columns={columns}
|
|
474
|
-
data={data}
|
|
475
|
-
isLoading={isLoading}
|
|
476
|
-
isError={Boolean(stationMessage?.type === 'error')}
|
|
477
|
-
handleRetry={false}
|
|
478
|
-
minimumWidth={minimumWidth}
|
|
479
|
-
columnGap={columnGap}
|
|
480
|
-
rowGap={rowGap}
|
|
481
|
-
headerRowHeight={headerRowHeight}
|
|
482
|
-
listRowHeight={listRowHeight}
|
|
483
|
-
listRowActionSize={listRowActionSize}
|
|
484
|
-
headerRowActionSize={headerRowActionSize}
|
|
485
|
-
horizontalTextAlign={horizontalTextAlign}
|
|
486
|
-
verticalTextAlign={verticalTextAlign}
|
|
487
|
-
textWrap={textWrap}
|
|
488
|
-
keyProperty={keyProperty}
|
|
489
|
-
showActionButton={Boolean(generateItemLink) || Boolean(onItemClicked)} // or hard code to `true`?
|
|
490
|
-
selectionMode={mode}
|
|
491
|
-
enableSelectAll={enableSelectAll}
|
|
492
|
-
enableSelectAllDeselect={enableSelectAll && !hasMoreData}
|
|
493
|
-
loadingTriggerOffset={loadingTriggerOffset}
|
|
494
|
-
defaultSortOrder={sortOrder}
|
|
495
|
-
generateItemLink={generateItemLink}
|
|
496
|
-
onItemClicked={onItemClickedHandler}
|
|
497
|
-
onItemSelected={itemSelectedHandler}
|
|
498
|
-
onRequestMoreData={onRequestMoreData}
|
|
499
|
-
onSortChanged={(sortData: SortData<T>) => {
|
|
500
|
-
onSortChanged(sortData);
|
|
501
|
-
setSortOrder(sortData);
|
|
502
|
-
}}
|
|
503
|
-
inlineMenuActions={inlineMenuActions && inlineMenuActionsHandler}
|
|
395
|
+
<ConditionalSplit shouldSplit={isQuickEditMode} minSecondarySize="500px">
|
|
396
|
+
<div
|
|
397
|
+
className={clsx(
|
|
398
|
+
classes.container,
|
|
399
|
+
{
|
|
400
|
+
[classes.hasStationError]: stationMessage,
|
|
401
|
+
[classes.modalMode]: modalMode,
|
|
402
|
+
},
|
|
403
|
+
'explorer-container',
|
|
404
|
+
className,
|
|
405
|
+
)}
|
|
406
|
+
>
|
|
407
|
+
<PageHeader
|
|
408
|
+
title={title}
|
|
409
|
+
subtitle={resultsTitle}
|
|
410
|
+
actions={pageHeaderActions}
|
|
411
|
+
setTabTitle={setTabTitle}
|
|
504
412
|
/>
|
|
413
|
+
{StationMessage}
|
|
414
|
+
{Filters}
|
|
415
|
+
<div
|
|
416
|
+
className={clsx({
|
|
417
|
+
[classes.filtersHidden]: !filtersVisible,
|
|
418
|
+
})}
|
|
419
|
+
>
|
|
420
|
+
<List<T>
|
|
421
|
+
ref={listRef}
|
|
422
|
+
columns={columns}
|
|
423
|
+
data={data}
|
|
424
|
+
isLoading={isLoading}
|
|
425
|
+
isError={Boolean(stationMessage?.type === 'error')}
|
|
426
|
+
handleRetry={false}
|
|
427
|
+
minimumWidth={minimumWidth}
|
|
428
|
+
columnGap={columnGap}
|
|
429
|
+
rowGap={rowGap}
|
|
430
|
+
headerRowHeight={headerRowHeight}
|
|
431
|
+
listRowHeight={listRowHeight}
|
|
432
|
+
listRowActionSize={listRowActionSize}
|
|
433
|
+
headerRowActionSize={headerRowActionSize}
|
|
434
|
+
horizontalTextAlign={horizontalTextAlign}
|
|
435
|
+
verticalTextAlign={verticalTextAlign}
|
|
436
|
+
textWrap={textWrap}
|
|
437
|
+
keyProperty={keyProperty}
|
|
438
|
+
showActionButton={
|
|
439
|
+
Boolean(generateItemLink) || Boolean(onItemClicked)
|
|
440
|
+
} // or hard code to `true`?
|
|
441
|
+
selectionMode={mode}
|
|
442
|
+
enableSelectAll={enableSelectAll}
|
|
443
|
+
enableSelectAllDeselect={enableSelectAll && !hasMoreData}
|
|
444
|
+
loadingTriggerOffset={loadingTriggerOffset}
|
|
445
|
+
defaultSortOrder={sortOrder}
|
|
446
|
+
generateItemLink={!isQuickEditMode ? generateItemLink : undefined}
|
|
447
|
+
onItemClicked={onItemClickedHandler}
|
|
448
|
+
onItemSelected={itemSelectedHandler}
|
|
449
|
+
onRequestMoreData={onRequestMoreData}
|
|
450
|
+
onSortChanged={(sortData: SortData<T>) => {
|
|
451
|
+
onSortChanged(sortData);
|
|
452
|
+
setSortOrder(sortData);
|
|
453
|
+
}}
|
|
454
|
+
inlineMenuActions={inlineMenuActions && inlineMenuActionsHandler}
|
|
455
|
+
/>
|
|
456
|
+
</div>
|
|
505
457
|
</div>
|
|
506
|
-
|
|
458
|
+
{isQuickEditMode && (
|
|
459
|
+
<QuickEditContextProvider>{quickEditStation}</QuickEditContextProvider>
|
|
460
|
+
)}
|
|
461
|
+
</ConditionalSplit>
|
|
507
462
|
);
|
|
508
463
|
});
|
|
509
464
|
|
|
@@ -515,6 +470,7 @@ export const Explorer = React.forwardRef(function Explorer<T extends Data>(
|
|
|
515
470
|
const useListSelectionMode = (
|
|
516
471
|
selectionMode: ListSelectMode,
|
|
517
472
|
openBulkActionsOnStart?: boolean,
|
|
473
|
+
isQuickEditMode?: boolean,
|
|
518
474
|
): {
|
|
519
475
|
readonly mode: ListSelectMode;
|
|
520
476
|
readonly setIsBulkOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
|
@@ -523,8 +479,16 @@ const useListSelectionMode = (
|
|
|
523
479
|
openBulkActionsOnStart ?? false,
|
|
524
480
|
);
|
|
525
481
|
|
|
482
|
+
let mode = selectionMode;
|
|
483
|
+
|
|
484
|
+
if (isQuickEditMode) {
|
|
485
|
+
mode = ListSelectMode.Single;
|
|
486
|
+
} else if (isBulkOpen) {
|
|
487
|
+
mode = ListSelectMode.Multi;
|
|
488
|
+
}
|
|
489
|
+
|
|
526
490
|
// If bulk actions is open, set ListSelectMode to Multi
|
|
527
|
-
const mode = isBulkOpen ? ListSelectMode.Multi : selectionMode;
|
|
491
|
+
// const mode = isBulkOpen ? ListSelectMode.Multi : selectionMode;
|
|
528
492
|
|
|
529
493
|
return { mode, setIsBulkOpen } as const;
|
|
530
494
|
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { mount, shallow } from 'enzyme';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { actWithReturn } from '../../../helpers/testing';
|
|
4
|
+
import { noop } from '../../../helpers/utils';
|
|
5
|
+
import { initializeUi } from '../../../initialize';
|
|
4
6
|
import { IconName } from '../../Icons';
|
|
5
7
|
import { Column, ListSelectMode } from '../../List';
|
|
6
8
|
import {
|
|
@@ -50,6 +52,28 @@ const getDataProvider = (): readonly [
|
|
|
50
52
|
};
|
|
51
53
|
|
|
52
54
|
describe('NavigationExplorer', () => {
|
|
55
|
+
global.ResizeObserver = jest.fn().mockImplementation(() => ({
|
|
56
|
+
observe: jest.fn(),
|
|
57
|
+
unobserve: jest.fn(),
|
|
58
|
+
disconnect: jest.fn(),
|
|
59
|
+
}));
|
|
60
|
+
|
|
61
|
+
beforeEach(() => {
|
|
62
|
+
initializeUi({
|
|
63
|
+
showNotification: () => {
|
|
64
|
+
// not implemented
|
|
65
|
+
return -1;
|
|
66
|
+
},
|
|
67
|
+
addIndicator: () => {
|
|
68
|
+
return -1;
|
|
69
|
+
},
|
|
70
|
+
removeIndicator: noop,
|
|
71
|
+
on: noop,
|
|
72
|
+
setTitle: noop,
|
|
73
|
+
setSaveIndicator: noop,
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
53
77
|
it('renders the component without crashing', () => {
|
|
54
78
|
const [provider] = getDataProvider();
|
|
55
79
|
const wrapper = shallow(
|
|
@@ -161,6 +185,7 @@ describe('NavigationExplorer', () => {
|
|
|
161
185
|
const pageHeader = wrapper.find(PageHeader);
|
|
162
186
|
|
|
163
187
|
expect(pageHeader.prop('actions')).toMatchObject([
|
|
188
|
+
{ kind: 'spacer' },
|
|
164
189
|
{
|
|
165
190
|
label: 'New',
|
|
166
191
|
icon: IconName.Plus,
|
|
@@ -193,6 +218,7 @@ describe('NavigationExplorer', () => {
|
|
|
193
218
|
const pageHeader = wrapper.find(PageHeader);
|
|
194
219
|
|
|
195
220
|
expect(pageHeader.prop('actions')).toMatchObject([
|
|
221
|
+
{ kind: 'spacer' },
|
|
196
222
|
{ label: 'test' },
|
|
197
223
|
{
|
|
198
224
|
label: 'New',
|
|
@@ -12,11 +12,11 @@ import { Data } from '../../../types/data';
|
|
|
12
12
|
import { FilterType, FilterTypes } from '../../Filters/Filters.model';
|
|
13
13
|
import { IconName } from '../../Icons';
|
|
14
14
|
import { ExplorerBulkAction, ExplorerDataProvider } from '../Explorer.model';
|
|
15
|
+
import { NavigationExplorer } from '../NavigationExplorer/NavigationExplorer';
|
|
15
16
|
import {
|
|
16
17
|
createInMemoryDataProvider,
|
|
17
18
|
findAnywhereInStringCaseInsensitive,
|
|
18
|
-
} from '../InMemoryDataProvider';
|
|
19
|
-
import { NavigationExplorer } from '../NavigationExplorer/NavigationExplorer';
|
|
19
|
+
} from '../helpers/InMemoryDataProvider';
|
|
20
20
|
|
|
21
21
|
interface NavExplorerStoryData {
|
|
22
22
|
id: number;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { LocationDescriptor } from 'history';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
export interface QuickEditContextType<T> {
|
|
6
|
+
selectedItem?: T;
|
|
7
|
+
detailsLink?: LocationDescriptor<unknown>;
|
|
8
|
+
isQuickEditMode?: boolean;
|
|
9
|
+
registerSaveCallback?: (callback: () => Promise<void>) => void;
|
|
10
|
+
refresh: () => Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// TODO: Find an elegant way to type this context
|
|
14
|
+
export const QuickEditContext = React.createContext<QuickEditContextType<any>>(
|
|
15
|
+
undefined as any,
|
|
16
|
+
);
|