@onehat/ui 0.4.101 → 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.
- package/package.json +1 -1
- package/src/Components/Accordion/Accordion.js +65 -6
- package/src/Components/Container/Container.js +10 -4
- package/src/Components/Form/Field/Combo/Combo.js +10 -4
- package/src/Components/Form/Field/Tag/Tag.js +6 -0
- package/src/Components/Form/Form.js +8 -3
- package/src/Components/Grid/Grid.js +232 -154
- package/src/Components/Grid/GridRow.js +7 -3
- package/src/Components/Hoc/withPresetButtons.js +18 -6
- package/src/Components/Icons/ArrowsLeftRight.js +10 -0
- package/src/Components/Icons/Bar.js +10 -0
- package/src/Components/Icons/Box.js +11 -0
- package/src/Components/Icons/BoxOpen.js +11 -0
- package/src/Components/Icons/Bucket.js +10 -0
- package/src/Components/Icons/Bump.js +21 -0
- package/src/Components/Icons/Calculator.js +12 -0
- package/src/Components/Icons/Dots.js +20 -0
- package/src/Components/Icons/Fleets.js +26 -0
- package/src/Components/Icons/Lock.js +11 -0
- package/src/Components/Icons/Microchip.js +12 -0
- package/src/Components/Icons/Num1.js +10 -0
- package/src/Components/Icons/Num2.js +10 -0
- package/src/Components/Icons/Num3.js +10 -0
- package/src/Components/Icons/Num4.js +10 -0
- package/src/Components/Icons/OilCan.js +11 -0
- package/src/Components/Icons/Operations.js +10 -0
- package/src/Components/Icons/OverduePms.js +10 -0
- package/src/Components/Icons/SackDollar.js +11 -0
- package/src/Components/Icons/ShortBar.js +15 -0
- package/src/Components/Icons/Tower.js +10 -0
- package/src/Components/Icons/UpcomingPms.js +10 -0
- package/src/Components/Layout/ScreenHeader.js +35 -3
- package/src/Components/Layout/SetupButton.js +31 -0
- package/src/Components/Layout/UserIndicator.js +35 -0
- package/src/Components/Pms/Editor/BumpPmsEditor.js +9 -0
- package/src/Components/Pms/Editor/MetersEditor.js +173 -0
- package/src/Components/Pms/Editor/PmEventsEditor.js +291 -0
- package/src/Components/Pms/Grid/UpcomingPmsGrid.js +569 -0
- package/src/Components/Pms/Layout/TreeSpecific/MakeTreeSelection.js +11 -0
- package/src/Components/Pms/Layout/TreeSpecific/TreeSpecific.js +30 -0
- package/src/Components/Pms/Modals/BulkAssignTechnician.js +104 -0
- package/src/Components/Pms/Screens/PmsManager.js +136 -0
- package/src/Components/Pms/Window/BumpPmsEditorWindow.js +25 -0
- package/src/Components/Screens/Manager.js +3 -0
- package/src/Components/Screens/ReportsManager.js +51 -26
- package/src/Components/Tree/Tree.js +15 -6
- package/src/Components/Viewer/PmCalcDebugViewer.js +164 -146
- package/src/Components/Viewer/TextWithLinks.js +9 -1
- package/src/Components/Viewer/Viewer.js +38 -30
- package/src/Functions/flatten.js +39 -0
- package/src/Functions/verifyCanCrudPmEvents.js +33 -0
|
@@ -147,6 +147,7 @@ function GridComponent(props) {
|
|
|
147
147
|
showHeaders = true,
|
|
148
148
|
showHovers = true,
|
|
149
149
|
showSelectHandle = true,
|
|
150
|
+
isRowTextSelectable, // if false, user can't select text in rows (e.g. to copy/paste)
|
|
150
151
|
isRowSelectable = true,
|
|
151
152
|
isRowHoverable = true,
|
|
152
153
|
isDisabled = false,
|
|
@@ -295,6 +296,11 @@ function GridComponent(props) {
|
|
|
295
296
|
footerToolbarRef = useRef(null),
|
|
296
297
|
rowRefs = useRef([]),
|
|
297
298
|
previousEntitiesLength = useRef(0),
|
|
299
|
+
paginationSelectionGuardRef = useRef({
|
|
300
|
+
source: null,
|
|
301
|
+
pending: new Set(),
|
|
302
|
+
expiresAt: 0,
|
|
303
|
+
}),
|
|
298
304
|
hasRemeasuredAfterRowsAppeared = useRef(false),
|
|
299
305
|
[isInited, setIsInited] = useState(false),
|
|
300
306
|
[isReady, setIsReady] = useState(false),
|
|
@@ -304,20 +310,6 @@ function GridComponent(props) {
|
|
|
304
310
|
showRowHandle = showSelectHandle || areRowsDragSource || (canRowsReorder && isReorderMode),
|
|
305
311
|
rowLongPressDelay = rowLongPressDelayMs ?? ((areRowsDragSource || canRowsReorder) ? 800 : undefined),
|
|
306
312
|
[lastMeasuredContainerHeight, setLastMeasuredContainerHeight] = useState(0),
|
|
307
|
-
getMeasurementPhase = () => {
|
|
308
|
-
return measurementPhaseRaw.current;
|
|
309
|
-
},
|
|
310
|
-
setMeasurementPhase = (phase) => {
|
|
311
|
-
measurementPhaseRaw.current = phase;
|
|
312
|
-
forceUpdate();
|
|
313
|
-
},
|
|
314
|
-
getMeasuredRowHeight = () => {
|
|
315
|
-
return measuredRowHeightRaw.current;
|
|
316
|
-
},
|
|
317
|
-
setMeasuredRowHeight = (height) => {
|
|
318
|
-
measuredRowHeightRaw.current = height;
|
|
319
|
-
forceUpdate();
|
|
320
|
-
},
|
|
321
313
|
getIsExpanded = (index) => {
|
|
322
314
|
return !!expandedRowsRef.current[index];
|
|
323
315
|
},
|
|
@@ -426,13 +418,15 @@ function GridComponent(props) {
|
|
|
426
418
|
}
|
|
427
419
|
},
|
|
428
420
|
getFooterToolbarItems = () => {
|
|
429
|
-
// Process additionalToolbarButtons to evaluate
|
|
421
|
+
// Process additionalToolbarButtons to evaluate functions
|
|
430
422
|
const processedButtons = _.map(additionalToolbarButtons, (config) => {
|
|
431
423
|
const processedConfig = { ...config };
|
|
432
|
-
// If the button has an getIsButtonDisabled function, evaluate it with current selection
|
|
433
424
|
if (_.isFunction(config.getIsButtonDisabled)) {
|
|
434
425
|
processedConfig.isDisabled = config.getIsButtonDisabled(selection);
|
|
435
426
|
}
|
|
427
|
+
if (_.isFunction(config.getText)) {
|
|
428
|
+
processedConfig.text = config.getText(selection);
|
|
429
|
+
}
|
|
436
430
|
return processedConfig;
|
|
437
431
|
});
|
|
438
432
|
const items = _.map(processedButtons, (config, ix) => getIconButtonFromConfig(config, ix, self));
|
|
@@ -789,6 +783,7 @@ function GridComponent(props) {
|
|
|
789
783
|
areCellsScrollable={areCellsScrollable}
|
|
790
784
|
showHovers={showHovers}
|
|
791
785
|
showRowHandle={showRowHandle}
|
|
786
|
+
isRowTextSelectable={isRowTextSelectable}
|
|
792
787
|
rowCanSelect={rowCanSelect}
|
|
793
788
|
rowCanDrag={rowCanDrag}
|
|
794
789
|
index={index}
|
|
@@ -1016,6 +1011,151 @@ function GridComponent(props) {
|
|
|
1016
1011
|
marker.remove();
|
|
1017
1012
|
cachedDragElements.current = null;
|
|
1018
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
|
+
},
|
|
1019
1159
|
calculatePageSize = (containerHeight, useActualMeasurements = false) => {
|
|
1020
1160
|
if (DEBUG) {
|
|
1021
1161
|
console.log(`${getMeasurementPhase()}, calculatePageSize A containerHeight=${containerHeight}, useActualMeasurements=${useActualMeasurements}, measuredRowHeight=${getMeasuredRowHeight()}`);
|
|
@@ -1200,6 +1340,7 @@ function GridComponent(props) {
|
|
|
1200
1340
|
if (DEBUG) {
|
|
1201
1341
|
console.log(`${getMeasurementPhase()}, applyMeasuredRowHeight B Repository.setPageSize(${newPageSize})`);
|
|
1202
1342
|
}
|
|
1343
|
+
startAutoPageSizeSelectionGuard();
|
|
1203
1344
|
Repository.setPageSize(newPageSize);
|
|
1204
1345
|
}
|
|
1205
1346
|
}
|
|
@@ -1259,6 +1400,7 @@ function GridComponent(props) {
|
|
|
1259
1400
|
if (DEBUG) {
|
|
1260
1401
|
console.log(`${getMeasurementPhase()}, adjustPageSizeToHeight D Repository.setPageSize(${pageSize})`);
|
|
1261
1402
|
}
|
|
1403
|
+
startAutoPageSizeSelectionGuard();
|
|
1262
1404
|
Repository.setPageSize(pageSize);
|
|
1263
1405
|
}
|
|
1264
1406
|
}
|
|
@@ -1277,136 +1419,51 @@ function GridComponent(props) {
|
|
|
1277
1419
|
}
|
|
1278
1420
|
},
|
|
1279
1421
|
debouncedAdjustPageSizeToHeight = useCallback(_.debounce(adjustPageSizeToHeight, 200), []),
|
|
1280
|
-
applySelectorSelected = () => {
|
|
1281
|
-
if (disableSelectorSelected || !selectorId) {
|
|
1282
|
-
return
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
if (previousSelectorId.current && selectorId !== previousSelectorId.current) {
|
|
1286
|
-
Repository.pauseEvents();
|
|
1287
|
-
Repository.clearFilters(previousSelectorId.current);
|
|
1288
|
-
Repository.resumeEvents();
|
|
1289
|
-
}
|
|
1290
|
-
previousSelectorId.current = selectorId;
|
|
1291
1422
|
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
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
|
+
};
|
|
1301
1433
|
},
|
|
1302
|
-
|
|
1303
|
-
if (
|
|
1434
|
+
startAutoPageSizeSelectionGuard = () => {
|
|
1435
|
+
if (disableWithSelection || !deselectAll) {
|
|
1304
1436
|
return;
|
|
1305
1437
|
}
|
|
1306
|
-
|
|
1307
|
-
|
|
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;
|
|
1308
1448
|
}
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
e.preventDefault();
|
|
1316
|
-
addNextToSelection();
|
|
1317
|
-
break;
|
|
1318
|
-
case 'ArrowUp':
|
|
1319
|
-
e.preventDefault();
|
|
1320
|
-
addPrevToSelection();
|
|
1321
|
-
break;
|
|
1322
|
-
}
|
|
1323
|
-
} else {
|
|
1324
|
-
// selectionMode is SELECTION_MODE_SINGLE
|
|
1325
|
-
switch(e.key) {
|
|
1326
|
-
case 'Enter':
|
|
1327
|
-
// NOTE: This is never being reached.
|
|
1328
|
-
// The event is getting captured somwhere else,
|
|
1329
|
-
// but I can't find where.
|
|
1330
|
-
// e.preventDefault();
|
|
1331
|
-
|
|
1332
|
-
// launch inline or windowed editor
|
|
1333
|
-
// const p = props;
|
|
1334
|
-
// debugger;
|
|
1335
|
-
break;
|
|
1336
|
-
case 'ArrowDown':
|
|
1337
|
-
e.preventDefault();
|
|
1338
|
-
selectNext();
|
|
1339
|
-
break;
|
|
1340
|
-
case 'ArrowUp':
|
|
1341
|
-
e.preventDefault();
|
|
1342
|
-
selectPrev();
|
|
1343
|
-
break;
|
|
1344
|
-
}
|
|
1449
|
+
if (Date.now() > guard.expiresAt) {
|
|
1450
|
+
clearPaginationSelectionGuard();
|
|
1451
|
+
return false;
|
|
1452
|
+
}
|
|
1453
|
+
if (!guard.pending.has(eventType)) {
|
|
1454
|
+
return false;
|
|
1345
1455
|
}
|
|
1346
|
-
},
|
|
1347
|
-
showColumnsSelector = () => {
|
|
1348
|
-
const
|
|
1349
|
-
modalItems = _.map(localColumnsConfig, (config, ix) => {
|
|
1350
|
-
return {
|
|
1351
|
-
name: config.id,
|
|
1352
|
-
label: config.header,
|
|
1353
|
-
type: config.isHidable ? 'Checkbox' : 'Text',
|
|
1354
|
-
isEditable: config.isHidable ?? false,
|
|
1355
|
-
};
|
|
1356
|
-
}),
|
|
1357
|
-
startingValues = (() => {
|
|
1358
|
-
const startingValues = {};
|
|
1359
|
-
_.each(localColumnsConfig, (config) => {
|
|
1360
|
-
const value = !config.isHidden; // checkbox implies to show it, so flip the polarity
|
|
1361
|
-
startingValues[config.id] = config.isHidable ? value : 'Always shown';
|
|
1362
|
-
});
|
|
1363
|
-
return startingValues;
|
|
1364
|
-
})();
|
|
1365
|
-
|
|
1366
|
-
showModal({
|
|
1367
|
-
title: 'Column Selector',
|
|
1368
|
-
includeReset: true,
|
|
1369
|
-
includeCancel: true,
|
|
1370
|
-
h: 800,
|
|
1371
|
-
w: styles.FORM_STACK_ROW_THRESHOLD + 10,
|
|
1372
|
-
body: <Form
|
|
1373
|
-
editorType={EDITOR_TYPE__PLAIN}
|
|
1374
|
-
columnDefaults={{
|
|
1375
|
-
labelWidth: '250px',
|
|
1376
|
-
}}
|
|
1377
|
-
items={[
|
|
1378
|
-
{
|
|
1379
|
-
name: 'instructions',
|
|
1380
|
-
type: 'DisplayField',
|
|
1381
|
-
text: 'Please select which columns to show in the grid.',
|
|
1382
|
-
className: 'mb-3',
|
|
1383
|
-
},
|
|
1384
|
-
{
|
|
1385
|
-
type: 'FieldSet',
|
|
1386
|
-
title: 'Columns',
|
|
1387
|
-
reference: 'columns',
|
|
1388
|
-
showToggleAllCheckbox: true,
|
|
1389
|
-
items: [
|
|
1390
|
-
...modalItems,
|
|
1391
|
-
],
|
|
1392
|
-
}
|
|
1393
|
-
]}
|
|
1394
|
-
startingValues={startingValues}
|
|
1395
|
-
onSave={(values)=> {
|
|
1396
|
-
hideModal();
|
|
1397
1456
|
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
}}
|
|
1406
|
-
/>,
|
|
1407
|
-
});
|
|
1457
|
+
guard.pending.delete(eventType);
|
|
1458
|
+
|
|
1459
|
+
if (!guard.pending.size) {
|
|
1460
|
+
clearPaginationSelectionGuard();
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
return true;
|
|
1408
1464
|
};
|
|
1409
1465
|
|
|
1466
|
+
|
|
1410
1467
|
if (forceLoadOnRender && disableLoadOnRender) {
|
|
1411
1468
|
throw new Error('incompatible config! forceLoadOnRender and disableLoadOnRender cannot both be true');
|
|
1412
1469
|
}
|
|
@@ -1529,7 +1586,27 @@ function GridComponent(props) {
|
|
|
1529
1586
|
// set up @onehat/data repository
|
|
1530
1587
|
const
|
|
1531
1588
|
setTrue = () => setIsLoading(true),
|
|
1532
|
-
setFalse = () =>
|
|
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
|
+
},
|
|
1533
1610
|
onChangeFilters = () => {
|
|
1534
1611
|
if (DEBUG) {
|
|
1535
1612
|
console.log('onChangeFilters, reload and re-measure');
|
|
@@ -1544,20 +1621,16 @@ function GridComponent(props) {
|
|
|
1544
1621
|
}
|
|
1545
1622
|
},
|
|
1546
1623
|
onChangePage = () => {
|
|
1547
|
-
|
|
1548
|
-
expandedRowsRef.current = {}; // clear expanded rows
|
|
1549
|
-
}
|
|
1624
|
+
onPaginationEvent('changePage');
|
|
1550
1625
|
};
|
|
1551
1626
|
|
|
1552
1627
|
Repository.on('beforeLoad', setTrue);
|
|
1553
1628
|
Repository.on('load', setFalse);
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
}
|
|
1629
|
+
Repository.on('changePage', onChangePage);
|
|
1630
|
+
Repository.on('changePageSize', onChangePageSize);
|
|
1557
1631
|
Repository.ons(['changeData', 'change'], forceUpdate);
|
|
1558
1632
|
Repository.on('changeFilters', onChangeFilters);
|
|
1559
1633
|
Repository.on('changeSorters', onChangeSorters);
|
|
1560
|
-
Repository.on('changePage', onChangePage);
|
|
1561
1634
|
|
|
1562
1635
|
applySelectorSelected();
|
|
1563
1636
|
|
|
@@ -1576,13 +1649,11 @@ function GridComponent(props) {
|
|
|
1576
1649
|
return () => {
|
|
1577
1650
|
Repository.off('beforeLoad', setTrue);
|
|
1578
1651
|
Repository.off('load', setFalse);
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
}
|
|
1652
|
+
Repository.off('changePage', onChangePage);
|
|
1653
|
+
Repository.off('changePageSize', onChangePageSize);
|
|
1582
1654
|
Repository.offs(['changeData', 'change'], forceUpdate);
|
|
1583
1655
|
Repository.off('changeFilters', onChangeFilters);
|
|
1584
1656
|
Repository.off('changeSorters', onChangeSorters);
|
|
1585
|
-
Repository.off('changePage', onChangePage);
|
|
1586
1657
|
};
|
|
1587
1658
|
}, [isInited]);
|
|
1588
1659
|
|
|
@@ -1598,8 +1669,8 @@ function GridComponent(props) {
|
|
|
1598
1669
|
|
|
1599
1670
|
}, [selectorId, selectorSelected]);
|
|
1600
1671
|
|
|
1601
|
-
// Effect to trigger row height measurement after render
|
|
1602
1672
|
useEffect(() => {
|
|
1673
|
+
// trigger row height measurement after render
|
|
1603
1674
|
if (getMeasurementPhase() === PHASES__MEASURING) {
|
|
1604
1675
|
// Small delay to ensure elements are fully rendered
|
|
1605
1676
|
const timer = setTimeout(async () => {
|
|
@@ -1635,13 +1706,13 @@ function GridComponent(props) {
|
|
|
1635
1706
|
}
|
|
1636
1707
|
}, [autoAdjustPageSizeToHeight]);
|
|
1637
1708
|
|
|
1638
|
-
// Reset measurement when rows were first empty then became populated
|
|
1639
1709
|
useEffect(() => {
|
|
1710
|
+
// Reset measurement when rows were first empty then became populated
|
|
1640
1711
|
const
|
|
1641
1712
|
currentLength = entities?.length || 0,
|
|
1642
1713
|
wasEmpty = previousEntitiesLength.current === 0,
|
|
1643
1714
|
isNowPopulated = currentLength > 0,
|
|
1644
|
-
hasPhantomRecord = entities?.some(entity => entity?.isPhantom);
|
|
1715
|
+
hasPhantomRecord = entities?.some(entity => !entity.isDestroyed && entity?.isPhantom);
|
|
1645
1716
|
|
|
1646
1717
|
// NOTE: The Repository was reloading when a phantom record was added,
|
|
1647
1718
|
// and this broke the Editor because selection was being reset to zero.
|
|
@@ -1672,6 +1743,15 @@ function GridComponent(props) {
|
|
|
1672
1743
|
previousEntitiesLength.current = currentLength;
|
|
1673
1744
|
}, [entities?.length, autoAdjustPageSizeToHeight]);
|
|
1674
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
|
+
|
|
1675
1755
|
if (canUser && !canUser('view')) {
|
|
1676
1756
|
return <Unauthorized />;
|
|
1677
1757
|
}
|
|
@@ -1683,8 +1763,6 @@ function GridComponent(props) {
|
|
|
1683
1763
|
|
|
1684
1764
|
isAddingRaw.current = isAdding;
|
|
1685
1765
|
|
|
1686
|
-
const footerToolbarItemComponents = useMemo(() => getFooterToolbarItems(), [Repository?.hash, additionalToolbarButtons, isReorderMode]);
|
|
1687
|
-
|
|
1688
1766
|
if (!isInited) {
|
|
1689
1767
|
// first time through, render a placeholder so we can get container dimensions
|
|
1690
1768
|
return <VStackNative
|
|
@@ -38,6 +38,7 @@ const GridRow = forwardRef((props, ref) => {
|
|
|
38
38
|
rowProps,
|
|
39
39
|
hideNavColumn,
|
|
40
40
|
showRowHandle,
|
|
41
|
+
isRowTextSelectable,
|
|
41
42
|
areCellsScrollable,
|
|
42
43
|
rowCanSelect,
|
|
43
44
|
rowCanDrag,
|
|
@@ -126,6 +127,8 @@ const GridRow = forwardRef((props, ref) => {
|
|
|
126
127
|
const
|
|
127
128
|
visibleColumns = _.filter(columnsConfig, (config) => !config.isHidden),
|
|
128
129
|
isOnlyOneVisibleColumn = visibleColumns.length === 1,
|
|
130
|
+
canSelectTextOnRow = isRowTextSelectable === false ? false : isDragFromHandleOnly,
|
|
131
|
+
shouldUseTextCursor = showRowHandle && canSelectTextOnRow,
|
|
129
132
|
rowShouldHaveDragRef = !isDragFromHandleOnly && (isDragSource || isDraggable) && !!dragSourceRef;
|
|
130
133
|
const setRowRef = (node) => {
|
|
131
134
|
if (typeof ref === 'function') {
|
|
@@ -152,7 +155,7 @@ const GridRow = forwardRef((props, ref) => {
|
|
|
152
155
|
const
|
|
153
156
|
propsToPass = columnProps[key] || {},
|
|
154
157
|
colStyle = {},
|
|
155
|
-
whichCursor =
|
|
158
|
+
whichCursor = shouldUseTextCursor ? 'cursor-text' : 'cursor-pointer';
|
|
156
159
|
let colClassName = clsx(
|
|
157
160
|
'GridRow-column',
|
|
158
161
|
'p-1',
|
|
@@ -160,7 +163,7 @@ const GridRow = forwardRef((props, ref) => {
|
|
|
160
163
|
'border-r-black-100',
|
|
161
164
|
'block',
|
|
162
165
|
areCellsScrollable ? 'overflow-auto' : 'overflow-hidden',
|
|
163
|
-
|
|
166
|
+
canSelectTextOnRow ? null : 'select-none',
|
|
164
167
|
whichCursor,
|
|
165
168
|
styles.GRID_ROW_MAX_HEIGHT_EXTRA,
|
|
166
169
|
);
|
|
@@ -465,7 +468,7 @@ const GridRow = forwardRef((props, ref) => {
|
|
|
465
468
|
let rowClassName = clsx(
|
|
466
469
|
'GridRow-HStackNative',
|
|
467
470
|
'items-center',
|
|
468
|
-
|
|
471
|
+
canSelectTextOnRow ? null : 'select-none',
|
|
469
472
|
);
|
|
470
473
|
if (isOnlyOneVisibleColumn) {
|
|
471
474
|
rowClassName += ' w-full';
|
|
@@ -514,6 +517,7 @@ const GridRow = forwardRef((props, ref) => {
|
|
|
514
517
|
dragPreviewRef,
|
|
515
518
|
dropTargetRef,
|
|
516
519
|
showRowHandle,
|
|
520
|
+
isRowTextSelectable,
|
|
517
521
|
rowCanSelect,
|
|
518
522
|
rowCanDrag,
|
|
519
523
|
isDragFromHandleOnly,
|
|
@@ -39,7 +39,7 @@ const presetButtons = [
|
|
|
39
39
|
DOWNLOAD,
|
|
40
40
|
];
|
|
41
41
|
|
|
42
|
-
export default function withPresetButtons(WrappedComponent
|
|
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 =
|
|
78
|
-
disableCopy =
|
|
77
|
+
disableView = isTree,
|
|
78
|
+
disableCopy = isTree,
|
|
79
79
|
disableDuplicate = !isEditor,
|
|
80
|
-
disablePrint =
|
|
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={
|
|
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
|