@onehat/ui 0.4.102 → 0.4.103

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.
Files changed (46) hide show
  1. package/package.json +1 -1
  2. package/src/Components/Accordion/Accordion.js +65 -6
  3. package/src/Components/Container/Container.js +10 -4
  4. package/src/Components/Form/Form.js +8 -3
  5. package/src/Components/Grid/Grid.js +230 -154
  6. package/src/Components/Hoc/withPresetButtons.js +18 -6
  7. package/src/Components/Icons/ArrowsLeftRight.js +10 -0
  8. package/src/Components/Icons/Bar.js +10 -0
  9. package/src/Components/Icons/Box.js +11 -0
  10. package/src/Components/Icons/BoxOpen.js +11 -0
  11. package/src/Components/Icons/Bucket.js +10 -0
  12. package/src/Components/Icons/Bump.js +21 -0
  13. package/src/Components/Icons/Calculator.js +12 -0
  14. package/src/Components/Icons/Dots.js +20 -0
  15. package/src/Components/Icons/Fleets.js +26 -0
  16. package/src/Components/Icons/Microchip.js +12 -0
  17. package/src/Components/Icons/Num1.js +10 -0
  18. package/src/Components/Icons/Num2.js +10 -0
  19. package/src/Components/Icons/Num3.js +10 -0
  20. package/src/Components/Icons/Num4.js +10 -0
  21. package/src/Components/Icons/OilCan.js +11 -0
  22. package/src/Components/Icons/Operations.js +10 -0
  23. package/src/Components/Icons/OverduePms.js +10 -0
  24. package/src/Components/Icons/SackDollar.js +11 -0
  25. package/src/Components/Icons/ShortBar.js +15 -0
  26. package/src/Components/Icons/Tower.js +10 -0
  27. package/src/Components/Icons/UpcomingPms.js +10 -0
  28. package/src/Components/Layout/ScreenHeader.js +35 -3
  29. package/src/Components/Layout/SetupButton.js +31 -0
  30. package/src/Components/Layout/UserIndicator.js +35 -0
  31. package/src/Components/Pms/Editor/BumpPmsEditor.js +9 -0
  32. package/src/Components/Pms/Editor/MetersEditor.js +173 -0
  33. package/src/Components/Pms/Editor/PmEventsEditor.js +291 -0
  34. package/src/Components/Pms/Grid/UpcomingPmsGrid.js +569 -0
  35. package/src/Components/Pms/Layout/TreeSpecific/MakeTreeSelection.js +11 -0
  36. package/src/Components/Pms/Layout/TreeSpecific/TreeSpecific.js +30 -0
  37. package/src/Components/Pms/Modals/BulkAssignTechnician.js +104 -0
  38. package/src/Components/Pms/Screens/PmsManager.js +136 -0
  39. package/src/Components/Pms/Window/BumpPmsEditorWindow.js +25 -0
  40. package/src/Components/Screens/Manager.js +3 -0
  41. package/src/Components/Tree/Tree.js +15 -6
  42. package/src/Components/Viewer/PmCalcDebugViewer.js +164 -146
  43. package/src/Components/Viewer/TextWithLinks.js +9 -1
  44. package/src/Components/Viewer/Viewer.js +38 -30
  45. package/src/Functions/flatten.js +39 -0
  46. package/src/Functions/verifyCanCrudPmEvents.js +33 -0
@@ -296,6 +296,11 @@ function GridComponent(props) {
296
296
  footerToolbarRef = useRef(null),
297
297
  rowRefs = useRef([]),
298
298
  previousEntitiesLength = useRef(0),
299
+ paginationSelectionGuardRef = useRef({
300
+ source: null,
301
+ pending: new Set(),
302
+ expiresAt: 0,
303
+ }),
299
304
  hasRemeasuredAfterRowsAppeared = useRef(false),
300
305
  [isInited, setIsInited] = useState(false),
301
306
  [isReady, setIsReady] = useState(false),
@@ -305,20 +310,6 @@ function GridComponent(props) {
305
310
  showRowHandle = showSelectHandle || areRowsDragSource || (canRowsReorder && isReorderMode),
306
311
  rowLongPressDelay = rowLongPressDelayMs ?? ((areRowsDragSource || canRowsReorder) ? 800 : undefined),
307
312
  [lastMeasuredContainerHeight, setLastMeasuredContainerHeight] = useState(0),
308
- getMeasurementPhase = () => {
309
- return measurementPhaseRaw.current;
310
- },
311
- setMeasurementPhase = (phase) => {
312
- measurementPhaseRaw.current = phase;
313
- forceUpdate();
314
- },
315
- getMeasuredRowHeight = () => {
316
- return measuredRowHeightRaw.current;
317
- },
318
- setMeasuredRowHeight = (height) => {
319
- measuredRowHeightRaw.current = height;
320
- forceUpdate();
321
- },
322
313
  getIsExpanded = (index) => {
323
314
  return !!expandedRowsRef.current[index];
324
315
  },
@@ -427,13 +418,15 @@ function GridComponent(props) {
427
418
  }
428
419
  },
429
420
  getFooterToolbarItems = () => {
430
- // Process additionalToolbarButtons to evaluate getIsButtonDisabled functions
421
+ // Process additionalToolbarButtons to evaluate functions
431
422
  const processedButtons = _.map(additionalToolbarButtons, (config) => {
432
423
  const processedConfig = { ...config };
433
- // If the button has an getIsButtonDisabled function, evaluate it with current selection
434
424
  if (_.isFunction(config.getIsButtonDisabled)) {
435
425
  processedConfig.isDisabled = config.getIsButtonDisabled(selection);
436
426
  }
427
+ if (_.isFunction(config.getText)) {
428
+ processedConfig.text = config.getText(selection);
429
+ }
437
430
  return processedConfig;
438
431
  });
439
432
  const items = _.map(processedButtons, (config, ix) => getIconButtonFromConfig(config, ix, self));
@@ -1018,6 +1011,151 @@ function GridComponent(props) {
1018
1011
  marker.remove();
1019
1012
  cachedDragElements.current = null;
1020
1013
  },
1014
+ applySelectorSelected = () => {
1015
+ if (disableSelectorSelected || !selectorId) {
1016
+ return
1017
+ }
1018
+
1019
+ if (previousSelectorId.current && selectorId !== previousSelectorId.current) {
1020
+ Repository.pauseEvents();
1021
+ Repository.clearFilters(previousSelectorId.current);
1022
+ Repository.resumeEvents();
1023
+ }
1024
+ previousSelectorId.current = selectorId;
1025
+
1026
+ let value = null;
1027
+ if (selectorSelected) {
1028
+ value = selectorSelected[selectorSelectedField];
1029
+ }
1030
+ if (noSelectorMeansNoResults && _.isEmpty(selectorSelected)) {
1031
+ value = 'NO_MATCHES';
1032
+ }
1033
+
1034
+ Repository.filter(selectorId, value, false); // false so it doesn't clear existing filters
1035
+ },
1036
+ onGridKeyDown = (e) => {
1037
+ if (isInlineEditorShown) {
1038
+ return;
1039
+ }
1040
+ if (disableWithSelection) {
1041
+ return;
1042
+ }
1043
+ const {
1044
+ shiftKey = false,
1045
+ } = e;
1046
+ if (selectionMode === SELECTION_MODE_MULTI && shiftKey) {
1047
+ switch(e.key) {
1048
+ case 'ArrowDown':
1049
+ e.preventDefault();
1050
+ addNextToSelection();
1051
+ break;
1052
+ case 'ArrowUp':
1053
+ e.preventDefault();
1054
+ addPrevToSelection();
1055
+ break;
1056
+ }
1057
+ } else {
1058
+ // selectionMode is SELECTION_MODE_SINGLE
1059
+ switch(e.key) {
1060
+ case 'Enter':
1061
+ // NOTE: This is never being reached.
1062
+ // The event is getting captured somwhere else,
1063
+ // but I can't find where.
1064
+ // e.preventDefault();
1065
+
1066
+ // launch inline or windowed editor
1067
+ // const p = props;
1068
+ // debugger;
1069
+ break;
1070
+ case 'ArrowDown':
1071
+ e.preventDefault();
1072
+ selectNext();
1073
+ break;
1074
+ case 'ArrowUp':
1075
+ e.preventDefault();
1076
+ selectPrev();
1077
+ break;
1078
+ }
1079
+ }
1080
+ },
1081
+ showColumnsSelector = () => {
1082
+ const
1083
+ modalItems = _.map(localColumnsConfig, (config, ix) => {
1084
+ return {
1085
+ name: config.id,
1086
+ label: config.header,
1087
+ type: config.isHidable ? 'Checkbox' : 'Text',
1088
+ isEditable: config.isHidable ?? false,
1089
+ };
1090
+ }),
1091
+ startingValues = (() => {
1092
+ const startingValues = {};
1093
+ _.each(localColumnsConfig, (config) => {
1094
+ const value = !config.isHidden; // checkbox implies to show it, so flip the polarity
1095
+ startingValues[config.id] = config.isHidable ? value : 'Always shown';
1096
+ });
1097
+ return startingValues;
1098
+ })();
1099
+
1100
+ showModal({
1101
+ title: 'Column Selector',
1102
+ includeReset: true,
1103
+ includeCancel: true,
1104
+ h: 800,
1105
+ w: styles.FORM_STACK_ROW_THRESHOLD + 10,
1106
+ body: <Form
1107
+ editorType={EDITOR_TYPE__PLAIN}
1108
+ columnDefaults={{
1109
+ labelWidth: '250px',
1110
+ }}
1111
+ items={[
1112
+ {
1113
+ name: 'instructions',
1114
+ type: 'DisplayField',
1115
+ text: 'Please select which columns to show in the grid.',
1116
+ className: 'mb-3',
1117
+ },
1118
+ {
1119
+ type: 'FieldSet',
1120
+ title: 'Columns',
1121
+ reference: 'columns',
1122
+ showToggleAllCheckbox: true,
1123
+ items: [
1124
+ ...modalItems,
1125
+ ],
1126
+ }
1127
+ ]}
1128
+ startingValues={startingValues}
1129
+ onSave={(values)=> {
1130
+ hideModal();
1131
+
1132
+ const newColumnsConfig = _.cloneDeep(localColumnsConfig);
1133
+ _.each(newColumnsConfig, (config, ix) => {
1134
+ if (config.isHidable) {
1135
+ newColumnsConfig[ix].isHidden = !values[config.id]; // checkbox implies to show it, so flip the polarity
1136
+ }
1137
+ });
1138
+ setLocalColumnsConfig(newColumnsConfig);
1139
+ }}
1140
+ />,
1141
+ });
1142
+ },
1143
+
1144
+ // These methods relate to auto-pageSize measurement and adjustment:
1145
+ getMeasurementPhase = () => {
1146
+ return measurementPhaseRaw.current;
1147
+ },
1148
+ setMeasurementPhase = (phase) => {
1149
+ measurementPhaseRaw.current = phase;
1150
+ forceUpdate();
1151
+ },
1152
+ getMeasuredRowHeight = () => {
1153
+ return measuredRowHeightRaw.current;
1154
+ },
1155
+ setMeasuredRowHeight = (height) => {
1156
+ measuredRowHeightRaw.current = height;
1157
+ forceUpdate();
1158
+ },
1021
1159
  calculatePageSize = (containerHeight, useActualMeasurements = false) => {
1022
1160
  if (DEBUG) {
1023
1161
  console.log(`${getMeasurementPhase()}, calculatePageSize A containerHeight=${containerHeight}, useActualMeasurements=${useActualMeasurements}, measuredRowHeight=${getMeasuredRowHeight()}`);
@@ -1202,6 +1340,7 @@ function GridComponent(props) {
1202
1340
  if (DEBUG) {
1203
1341
  console.log(`${getMeasurementPhase()}, applyMeasuredRowHeight B Repository.setPageSize(${newPageSize})`);
1204
1342
  }
1343
+ startAutoPageSizeSelectionGuard();
1205
1344
  Repository.setPageSize(newPageSize);
1206
1345
  }
1207
1346
  }
@@ -1261,6 +1400,7 @@ function GridComponent(props) {
1261
1400
  if (DEBUG) {
1262
1401
  console.log(`${getMeasurementPhase()}, adjustPageSizeToHeight D Repository.setPageSize(${pageSize})`);
1263
1402
  }
1403
+ startAutoPageSizeSelectionGuard();
1264
1404
  Repository.setPageSize(pageSize);
1265
1405
  }
1266
1406
  }
@@ -1279,136 +1419,51 @@ function GridComponent(props) {
1279
1419
  }
1280
1420
  },
1281
1421
  debouncedAdjustPageSizeToHeight = useCallback(_.debounce(adjustPageSizeToHeight, 200), []),
1282
- applySelectorSelected = () => {
1283
- if (disableSelectorSelected || !selectorId) {
1284
- return
1285
- }
1286
-
1287
- if (previousSelectorId.current && selectorId !== previousSelectorId.current) {
1288
- Repository.pauseEvents();
1289
- Repository.clearFilters(previousSelectorId.current);
1290
- Repository.resumeEvents();
1291
- }
1292
- previousSelectorId.current = selectorId;
1293
1422
 
1294
- let value = null;
1295
- if (selectorSelected) {
1296
- value = selectorSelected[selectorSelectedField];
1297
- }
1298
- if (noSelectorMeansNoResults && _.isEmpty(selectorSelected)) {
1299
- value = 'NO_MATCHES';
1300
- }
1301
-
1302
- Repository.filter(selectorId, value, false); // false so it doesn't clear existing filters
1423
+ // These methods guard for selection/pagination interaction
1424
+ // (If user makes a selection during the auto-pageSize adjustment,
1425
+ // we don't want to clear the selection if the current selection
1426
+ // would still be valid with the new page size):
1427
+ clearPaginationSelectionGuard = () => {
1428
+ paginationSelectionGuardRef.current = {
1429
+ source: null,
1430
+ pending: new Set(),
1431
+ expiresAt: 0,
1432
+ };
1303
1433
  },
1304
- onGridKeyDown = (e) => {
1305
- if (isInlineEditorShown) {
1434
+ startAutoPageSizeSelectionGuard = () => {
1435
+ if (disableWithSelection || !deselectAll) {
1306
1436
  return;
1307
1437
  }
1308
- if (disableWithSelection) {
1309
- return;
1438
+ paginationSelectionGuardRef.current = {
1439
+ source: 'autoPageSize',
1440
+ pending: new Set(['changePage', 'changePageSize',]),
1441
+ expiresAt: Date.now() + 5000,
1442
+ };
1443
+ },
1444
+ consumePaginationSelectionGuard = (eventType) => {
1445
+ const guard = paginationSelectionGuardRef.current;
1446
+ if (guard.source !== 'autoPageSize') {
1447
+ return false;
1310
1448
  }
1311
- const {
1312
- shiftKey = false,
1313
- } = e;
1314
- if (selectionMode === SELECTION_MODE_MULTI && shiftKey) {
1315
- switch(e.key) {
1316
- case 'ArrowDown':
1317
- e.preventDefault();
1318
- addNextToSelection();
1319
- break;
1320
- case 'ArrowUp':
1321
- e.preventDefault();
1322
- addPrevToSelection();
1323
- break;
1324
- }
1325
- } else {
1326
- // selectionMode is SELECTION_MODE_SINGLE
1327
- switch(e.key) {
1328
- case 'Enter':
1329
- // NOTE: This is never being reached.
1330
- // The event is getting captured somwhere else,
1331
- // but I can't find where.
1332
- // e.preventDefault();
1333
-
1334
- // launch inline or windowed editor
1335
- // const p = props;
1336
- // debugger;
1337
- break;
1338
- case 'ArrowDown':
1339
- e.preventDefault();
1340
- selectNext();
1341
- break;
1342
- case 'ArrowUp':
1343
- e.preventDefault();
1344
- selectPrev();
1345
- break;
1346
- }
1449
+ if (Date.now() > guard.expiresAt) {
1450
+ clearPaginationSelectionGuard();
1451
+ return false;
1452
+ }
1453
+ if (!guard.pending.has(eventType)) {
1454
+ return false;
1347
1455
  }
1348
- },
1349
- showColumnsSelector = () => {
1350
- const
1351
- modalItems = _.map(localColumnsConfig, (config, ix) => {
1352
- return {
1353
- name: config.id,
1354
- label: config.header,
1355
- type: config.isHidable ? 'Checkbox' : 'Text',
1356
- isEditable: config.isHidable ?? false,
1357
- };
1358
- }),
1359
- startingValues = (() => {
1360
- const startingValues = {};
1361
- _.each(localColumnsConfig, (config) => {
1362
- const value = !config.isHidden; // checkbox implies to show it, so flip the polarity
1363
- startingValues[config.id] = config.isHidable ? value : 'Always shown';
1364
- });
1365
- return startingValues;
1366
- })();
1367
-
1368
- showModal({
1369
- title: 'Column Selector',
1370
- includeReset: true,
1371
- includeCancel: true,
1372
- h: 800,
1373
- w: styles.FORM_STACK_ROW_THRESHOLD + 10,
1374
- body: <Form
1375
- editorType={EDITOR_TYPE__PLAIN}
1376
- columnDefaults={{
1377
- labelWidth: '250px',
1378
- }}
1379
- items={[
1380
- {
1381
- name: 'instructions',
1382
- type: 'DisplayField',
1383
- text: 'Please select which columns to show in the grid.',
1384
- className: 'mb-3',
1385
- },
1386
- {
1387
- type: 'FieldSet',
1388
- title: 'Columns',
1389
- reference: 'columns',
1390
- showToggleAllCheckbox: true,
1391
- items: [
1392
- ...modalItems,
1393
- ],
1394
- }
1395
- ]}
1396
- startingValues={startingValues}
1397
- onSave={(values)=> {
1398
- hideModal();
1399
1456
 
1400
- const newColumnsConfig = _.cloneDeep(localColumnsConfig);
1401
- _.each(newColumnsConfig, (config, ix) => {
1402
- if (config.isHidable) {
1403
- newColumnsConfig[ix].isHidden = !values[config.id]; // checkbox implies to show it, so flip the polarity
1404
- }
1405
- });
1406
- setLocalColumnsConfig(newColumnsConfig);
1407
- }}
1408
- />,
1409
- });
1457
+ guard.pending.delete(eventType);
1458
+
1459
+ if (!guard.pending.size) {
1460
+ clearPaginationSelectionGuard();
1461
+ }
1462
+
1463
+ return true;
1410
1464
  };
1411
1465
 
1466
+
1412
1467
  if (forceLoadOnRender && disableLoadOnRender) {
1413
1468
  throw new Error('incompatible config! forceLoadOnRender and disableLoadOnRender cannot both be true');
1414
1469
  }
@@ -1531,7 +1586,27 @@ function GridComponent(props) {
1531
1586
  // set up @onehat/data repository
1532
1587
  const
1533
1588
  setTrue = () => setIsLoading(true),
1534
- setFalse = () => setIsLoading(false),
1589
+ setFalse = () => {
1590
+ setIsLoading(false);
1591
+ clearPaginationSelectionGuard();
1592
+ },
1593
+ onPaginationEvent = (eventType) => {
1594
+ if (consumePaginationSelectionGuard(eventType)) {
1595
+ return;
1596
+ }
1597
+ if (!disableWithSelection && deselectAll) {
1598
+ deselectAll();
1599
+ }
1600
+ if (eventType === 'changePage' && showRowExpander) {
1601
+ expandedRowsRef.current = {}; // clear expanded rows
1602
+ }
1603
+ },
1604
+ onChangePageSize = () => {
1605
+ if (disableWithSelection || !deselectAll) {
1606
+ return;
1607
+ }
1608
+ onPaginationEvent('changePageSize');
1609
+ },
1535
1610
  onChangeFilters = () => {
1536
1611
  if (DEBUG) {
1537
1612
  console.log('onChangeFilters, reload and re-measure');
@@ -1546,20 +1621,16 @@ function GridComponent(props) {
1546
1621
  }
1547
1622
  },
1548
1623
  onChangePage = () => {
1549
- if (showRowExpander) {
1550
- expandedRowsRef.current = {}; // clear expanded rows
1551
- }
1624
+ onPaginationEvent('changePage');
1552
1625
  };
1553
1626
 
1554
1627
  Repository.on('beforeLoad', setTrue);
1555
1628
  Repository.on('load', setFalse);
1556
- if (!disableWithSelection) {
1557
- Repository.ons(['changePage', 'changePageSize',], deselectAll);
1558
- }
1629
+ Repository.on('changePage', onChangePage);
1630
+ Repository.on('changePageSize', onChangePageSize);
1559
1631
  Repository.ons(['changeData', 'change'], forceUpdate);
1560
1632
  Repository.on('changeFilters', onChangeFilters);
1561
1633
  Repository.on('changeSorters', onChangeSorters);
1562
- Repository.on('changePage', onChangePage);
1563
1634
 
1564
1635
  applySelectorSelected();
1565
1636
 
@@ -1578,13 +1649,11 @@ function GridComponent(props) {
1578
1649
  return () => {
1579
1650
  Repository.off('beforeLoad', setTrue);
1580
1651
  Repository.off('load', setFalse);
1581
- if (!disableWithSelection) {
1582
- Repository.offs(['changePage', 'changePageSize',], deselectAll);
1583
- }
1652
+ Repository.off('changePage', onChangePage);
1653
+ Repository.off('changePageSize', onChangePageSize);
1584
1654
  Repository.offs(['changeData', 'change'], forceUpdate);
1585
1655
  Repository.off('changeFilters', onChangeFilters);
1586
1656
  Repository.off('changeSorters', onChangeSorters);
1587
- Repository.off('changePage', onChangePage);
1588
1657
  };
1589
1658
  }, [isInited]);
1590
1659
 
@@ -1600,8 +1669,8 @@ function GridComponent(props) {
1600
1669
 
1601
1670
  }, [selectorId, selectorSelected]);
1602
1671
 
1603
- // Effect to trigger row height measurement after render
1604
1672
  useEffect(() => {
1673
+ // trigger row height measurement after render
1605
1674
  if (getMeasurementPhase() === PHASES__MEASURING) {
1606
1675
  // Small delay to ensure elements are fully rendered
1607
1676
  const timer = setTimeout(async () => {
@@ -1637,13 +1706,13 @@ function GridComponent(props) {
1637
1706
  }
1638
1707
  }, [autoAdjustPageSizeToHeight]);
1639
1708
 
1640
- // Reset measurement when rows were first empty then became populated
1641
1709
  useEffect(() => {
1710
+ // Reset measurement when rows were first empty then became populated
1642
1711
  const
1643
1712
  currentLength = entities?.length || 0,
1644
1713
  wasEmpty = previousEntitiesLength.current === 0,
1645
1714
  isNowPopulated = currentLength > 0,
1646
- hasPhantomRecord = entities?.some(entity => entity?.isPhantom);
1715
+ hasPhantomRecord = entities?.some(entity => !entity.isDestroyed && entity?.isPhantom);
1647
1716
 
1648
1717
  // NOTE: The Repository was reloading when a phantom record was added,
1649
1718
  // and this broke the Editor because selection was being reset to zero.
@@ -1674,6 +1743,15 @@ function GridComponent(props) {
1674
1743
  previousEntitiesLength.current = currentLength;
1675
1744
  }, [entities?.length, autoAdjustPageSizeToHeight]);
1676
1745
 
1746
+
1747
+ // Memoize footer toolbar items to avoid unnecessary re-renders, but only if they don't have dynamic properties
1748
+ const
1749
+ hasDynamicFooterToolbarItems = useMemo(() => _.some(additionalToolbarButtons, (config) => {
1750
+ return _.isFunction(config.getIsButtonDisabled) || _.isFunction(config.getText);
1751
+ }), [additionalToolbarButtons]),
1752
+ memoizedFooterToolbarItemComponents = useMemo(() => getFooterToolbarItems(), [Repository?.hash, additionalToolbarButtons, isReorderMode]),
1753
+ footerToolbarItemComponents = hasDynamicFooterToolbarItems ? getFooterToolbarItems() : memoizedFooterToolbarItemComponents;
1754
+
1677
1755
  if (canUser && !canUser('view')) {
1678
1756
  return <Unauthorized />;
1679
1757
  }
@@ -1685,8 +1763,6 @@ function GridComponent(props) {
1685
1763
 
1686
1764
  isAddingRaw.current = isAdding;
1687
1765
 
1688
- const footerToolbarItemComponents = useMemo(() => getFooterToolbarItems(), [Repository?.hash, additionalToolbarButtons, isReorderMode]);
1689
-
1690
1766
  if (!isInited) {
1691
1767
  // first time through, render a placeholder so we can get container dimensions
1692
1768
  return <VStackNative
@@ -39,7 +39,7 @@ const presetButtons = [
39
39
  DOWNLOAD,
40
40
  ];
41
41
 
42
- export default function withPresetButtons(WrappedComponent, isGrid = false) {
42
+ export default function withPresetButtons(WrappedComponent) {
43
43
  return forwardRef((props, ref) => {
44
44
 
45
45
  if (props.disablePresetButtons || props.alreadyHasWithPresetButtons) {
@@ -64,7 +64,7 @@ export default function withPresetButtons(WrappedComponent, isGrid = false) {
64
64
  {
65
65
  // extract and pass down
66
66
  isEditor = false,
67
- isTree = false,
67
+ isTree = false, // from withWindowedEditor or withSideEditor in Tree
68
68
  canDeleteRootNode = false,
69
69
  isSideEditor = false,
70
70
  canEditorViewOnly = false,
@@ -74,10 +74,10 @@ export default function withPresetButtons(WrappedComponent, isGrid = false) {
74
74
  disableAdd = !isEditor,
75
75
  disableEdit = !isEditor,
76
76
  disableDelete = !isEditor,
77
- disableView = !isGrid,
78
- disableCopy = !isGrid,
77
+ disableView = isTree,
78
+ disableCopy = isTree,
79
79
  disableDuplicate = !isEditor,
80
- disablePrint = !isGrid,
80
+ disablePrint = isTree,
81
81
  protectedValues, // records with these values cannot be edited or deleted
82
82
  addDisplayMsg,
83
83
  editDisplayMsg,
@@ -434,6 +434,18 @@ export default function withPresetButtons(WrappedComponent, isGrid = false) {
434
434
  }
435
435
  },
436
436
  onUploadDownload = () => {
437
+ const onUploadDecorator = async () => {
438
+ if (onUpload) {
439
+ await onUpload();
440
+ }
441
+ if (Repository && !Repository.isDestroyed) {
442
+ if (Repository.loadRootNodes) {
443
+ await Repository.loadRootNodes(1);
444
+ } else {
445
+ await Repository.reload();
446
+ }
447
+ }
448
+ };
437
449
  showModal({
438
450
  body: <UploadsDownloadsWindow
439
451
  reference="uploadsDownloads"
@@ -442,7 +454,7 @@ export default function withPresetButtons(WrappedComponent, isGrid = false) {
442
454
  columnsConfig={props.columnsConfig}
443
455
  uploadHeaders={uploadHeaders}
444
456
  uploadParams={uploadParams}
445
- onUpload={onUpload}
457
+ onUpload={onUploadDecorator}
446
458
  downloadHeaders={downloadHeaders}
447
459
  downloadParams={downloadParams}
448
460
  />,
@@ -0,0 +1,10 @@
1
+ import { createIcon } from "../Gluestack/icon";
2
+ import Svg, { Path } from 'react-native-svg';
3
+
4
+ const SvgComponent = createIcon({
5
+ Root: Svg,
6
+ viewBox: '0 0 512 512',
7
+ path: <Path d="M406.6 374.6l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l41.4 41.4H109.2l41.4-41.4c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 288h293.5l-41.4 41.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0z" />,
8
+ });
9
+
10
+ export default SvgComponent
@@ -0,0 +1,10 @@
1
+ import { createIcon } from "../Gluestack/icon";
2
+ import Svg, { Path } from 'react-native-svg';
3
+
4
+ const SvgComponent = createIcon({
5
+ Root: Svg,
6
+ viewBox: '0 0 228.6 32.7',
7
+ path: <Path d="M212.2 32.7c9 0 16.3-7.3 16.3-16.3S221.2.1 212.2.1H16.3C7.3 0 0 7.3 0 16.3s7.3 16.3 16.3 16.3h195.9z" />,
8
+ });
9
+
10
+ export default SvgComponent
@@ -0,0 +1,11 @@
1
+ // Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc.
2
+ import { createIcon } from "../Gluestack/icon";
3
+ import Svg, { Path } from 'react-native-svg';
4
+
5
+ const SvgComponent = createIcon({
6
+ Root: Svg,
7
+ viewBox: '0 0 448 512',
8
+ path: <Path d="M50.7 58.5L0 160h208V32H93.7c-18.2 0-34.8 10.3-43 26.5zM240 160h208L397.3 58.5c-8.2-16.2-24.8-26.5-43-26.5H240v128zm208 32H0v224c0 35.3 28.7 64 64 64h320c35.3 0 64-28.7 64-64V192z" />,
9
+ });
10
+
11
+ export default SvgComponent
@@ -0,0 +1,11 @@
1
+ // Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc.
2
+ import { createIcon } from "../Gluestack/icon";
3
+ import Svg, { Path } from 'react-native-svg';
4
+
5
+ const SvgComponent = createIcon({
6
+ Root: Svg,
7
+ viewBox: '0 0 640 512',
8
+ path: <Path d="M58.9 42.1c3-6.1 9.6-9.6 16.3-8.7L320 64l244.8-30.6c6.7-.8 13.3 2.7 16.3 8.7l41.7 83.4c9 17.9-.6 39.6-19.8 45.1l-163.4 46.7c-13.9 4-28.8-1.9-36.2-14.3L320 64l-83.4 139c-7.4 12.4-22.3 18.3-36.2 14.3L37.1 170.6c-19.3-5.5-28.8-27.2-19.8-45.1l41.6-83.4zM321.1 128l54.9 91.4c14.9 24.8 44.6 36.6 72.5 28.6L576 211.6v167c0 22-15 41.2-36.4 46.6l-204.1 51c-10.2 2.6-20.9 2.6-31 0l-204.1-51C79 419.7 64 400.5 64 378.5v-167L191.6 248c27.8 8 57.6-3.8 72.5-28.6l54.8-91.4h2.2z" />,
9
+ });
10
+
11
+ export default SvgComponent
@@ -0,0 +1,10 @@
1
+ import { createIcon } from "../Gluestack/icon";
2
+ import Svg, { Path } from 'react-native-svg';
3
+
4
+ const SvgComponent = createIcon({
5
+ Root: Svg,
6
+ viewBox: '0 0 448 512',
7
+ path: <Path d="M96 152v8H48v-8C48 68.1 116.1 0 200 0h48c83.9 0 152 68.1 152 152v8h-48v-8c0-57.4-46.6-104-104-104h-48C142.6 48 96 94.6 96 152zM0 224c0-17.7 14.3-32 32-32h384c17.7 0 32 14.3 32 32s-14.3 32-32 32h-5.1l-22.4 213c-2.6 24.4-23.2 43-47.7 43H107.2c-24.6 0-45.2-18.5-47.7-43L37.1 256H32c-17.7 0-32-14.3-32-32z" />,
8
+ });
9
+
10
+ export default SvgComponent
@@ -0,0 +1,21 @@
1
+ // from https://www.flaticon.com/free-icon/kick_1928
2
+ import { createIcon } from "../Gluestack/icon";
3
+ import Svg, { G, Path } from 'react-native-svg';
4
+
5
+ const SvgComponent = createIcon({
6
+ Root: Svg,
7
+ viewBox: '0 0 415.89 249.77',
8
+ path: <G>
9
+ <Path
10
+ d="M112.65 231.72c-.66-6.8-1.84-12.86-1.72-18.89.33-16.05 14.69-27.22 30.49-24.08 16.26 3.24 31.22 10.07 46.06 17.13 2.67 1.27 4.91 1.38 7.7.51 27.09-8.43 54.23-16.72 81.35-25.06 18.68-5.75 37.38-11.47 56.04-17.3 6.36-1.99 6.65-2.74 4.74-8.92-.6-1.95-1.16-3.9-1.81-5.84-3.21-9.63-5.67-19.61-9.84-28.8-6.8-14.96-20.99-21.74-37.12-19.8-13.07 1.57-26.23 2.48-39.35 3.65-2.91.26-5.84.4-9.18.62v31.62h-17.24v-32c-5.36-.35-10.43-.67-16.02-1.04v28.89h-17.41v-31.17c-5.27-1.02-10.13-1.95-15.52-2.99v26.04h-17.14v-21.87c0-9.08.1-9.38-8.62-12.19-10.91-3.51-19.56-9.1-22.74-20.89-.49-1.82-1.44-3.51-2.18-5.26-8.4-19.74-16.75-39.5-25.25-59.2C95.44-.8 95.24-.7 89.56 1.09 61.6 9.89 33.62 18.7 5.66 27.51c-1.89.6-3.75 1.27-5.66 1.92 4.29 26.31 8.49 52.19 12.75 78.06.67 4.05 1.17 7.71-1.81 11.42-1.94 2.41-2.86 5.85-3.62 8.98-2.48 10.16-1.27 20.26 1.25 30.23 4.98 19.73 14.07 37.71 25.15 54.52 6.63 10.05 11.26 20.62 14.48 32.04 1.51 5.36 2.32 5.86 7.86 4.36 6.94-1.88 13.79-4.1 20.67-6.21 12.17-3.74 24.34-7.52 35.94-11.11zm265.05-54.59c-3.46-6.2-6.98-11.72-9.73-17.6-9.46-20.18-4.21-36.18 15.57-46.3 6.45-3.3 13.71-5.05 20.63-7.43 3.88-1.33 7.81-2.5 11.72-3.74-3.25-1.48-6.41-2.02-9.5-2.8-11.7-2.92-23.75-4.93-34.98-9.13-16.55-6.19-25.42-18.84-25.73-36.94-.16-9.73 2.56-18.76 6.39-27.57 1.74-4 3.24-8.11 5.26-13.23-3.27 2.05-5.42 3.46-7.62 4.77-7.11 4.24-13.98 8.99-21.42 12.58-19.72 9.5-38.29 5.49-52.49-11.15-4.47-5.23-8.15-11.13-12.33-16.91-4.01 1.74-8.35 3.63-12.9 5.61 7.09 14.48 16.55 26.54 30.26 34.76 15.95 9.57 32.7 9.59 50.24 2.79-2.22 29.1 9.78 49.09 36.23 59.96-.26.63-.29.94-.46 1.09-.9.83-1.84 1.61-2.75 2.43-8.16 7.33-13.65 16.18-14.99 27.22-2.33 19.23 6.48 34.69 17.05 50.05 4.05-2.98 7.85-5.76 11.54-8.48z"
11
+ />
12
+ <Path
13
+ d="M112.65 231.72c-11.6 3.59-23.76 7.36-35.94 11.11-6.88 2.11-13.73 4.33-20.67 6.21-5.53 1.5-6.34 1-7.86-4.36-3.22-11.42-7.85-21.99-14.48-32.04-11.08-16.81-20.17-34.79-25.15-54.52-2.52-9.98-3.73-20.07-1.25-30.23.76-3.13 1.68-6.56 3.62-8.98 2.98-3.71 2.48-7.37 1.81-11.42C8.49 81.62 4.29 55.75 0 29.43c1.9-.65 3.77-1.33 5.66-1.92C33.62 18.7 61.6 9.89 89.56 1.09 95.24-.7 95.44-.8 97.89 4.88c8.5 19.7 16.84 39.46 25.25 59.2.74 1.75 1.69 3.45 2.18 5.26 3.18 11.8 11.83 17.38 22.74 20.89 8.71 2.81 8.62 3.11 8.62 12.19v21.87h17.14V98.25c5.39 1.04 10.25 1.97 15.52 2.99v31.17h17.41v-28.89c5.59.36 10.66.69 16.02 1.04v32h17.24v-31.62c3.34-.22 6.27-.36 9.18-.62 13.12-1.17 26.27-2.08 39.35-3.65 16.13-1.94 30.32 4.84 37.12 19.8 4.18 9.19 6.63 19.17 9.84 28.8.64 1.93 1.21 3.89 1.81 5.84 1.91 6.18 1.62 6.93-4.74 8.92-18.66 5.83-37.35 11.55-56.04 17.3-27.12 8.34-54.25 16.63-81.35 25.06-2.79.87-5.03.76-7.7-.51-14.84-7.06-29.8-13.89-46.06-17.13-15.8-3.14-30.16 8.03-30.49 24.08-.12 6.03 1.06 12.09 1.72 18.89z"
14
+ />
15
+ <Path
16
+ d="M377.7 177.13c-3.69 2.71-7.49 5.5-11.54 8.48-10.57-15.37-19.38-30.82-17.05-50.05 1.34-11.04 6.83-19.89 14.99-27.22.91-.82 1.85-1.6 2.75-2.43.17-.15.2-.46.46-1.09-26.44-10.87-38.45-30.86-36.23-59.96-17.54 6.8-34.29 6.78-50.24-2.79-13.71-8.22-23.17-20.28-30.26-34.76 4.55-1.98 8.89-3.87 12.9-5.61 4.18 5.78 7.86 11.68 12.33 16.91 14.2 16.64 32.76 20.65 52.49 11.15 7.43-3.58 14.3-8.33 21.42-12.58 2.21-1.32 4.36-2.72 7.62-4.77-2.03 5.12-3.52 9.23-5.26 13.23-3.83 8.81-6.55 17.84-6.39 27.57.3 18.09 9.17 30.74 25.73 36.94 11.23 4.2 23.28 6.21 34.98 9.13 3.1.77 6.25 1.31 9.5 2.8-3.91 1.24-7.84 2.4-11.72 3.74-6.92 2.38-14.17 4.13-20.63 7.43-19.78 10.12-25.03 26.13-15.57 46.3 2.76 5.88 6.28 11.4 9.73 17.6z"
17
+ />
18
+ </G>,
19
+ });
20
+
21
+ export default SvgComponent
@@ -0,0 +1,12 @@
1
+ // Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc.
2
+ import { createIcon } from "../Gluestack/icon";
3
+ import Svg, { Path } from 'react-native-svg';
4
+
5
+ const SvgComponent = createIcon({
6
+ Root: Svg,
7
+ viewBox: '0 0 384 512',
8
+ path: <Path d="M64 0C28.7 0 0 28.7 0 64v384c0 35.3 28.7 64 64 64h256c35.3 0 64-28.7 64-64V64c0-35.3-28.7-64-64-64H64zm32 64h192c17.7 0 32 14.3 32 32v32c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V96c0-17.7 14.3-32 32-32zm32 160a32 32 0 11-64 0 32 32 0 1164 0zM96 352a32 32 0 110-64 32 32 0 110 64zm-32 64c0-17.7 14.3-32 32-32h96c17.7 0 32 14.3 32 32s-14.3 32-32 32H96c-17.7 0-32-14.3-32-32zm128-160a32 32 0 110-64 32 32 0 110 64zm32 64a32 32 0 11-64 0 32 32 0 1164 0zm64-64a32 32 0 110-64 32 32 0 110 64zm32 64a32 32 0 11-64 0 32 32 0 1164 0zm-32 128a32 32 0 110-64 32 32 0 110 64z" />,
9
+ });
10
+
11
+ export default SvgComponent
12
+