@onehat/ui 0.3.148 → 0.3.150
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 +2 -2
- package/src/Components/Form/Field/Combo/Combo.js +9 -4
- package/src/Components/Form/Field/Tag/Tag.js +68 -0
- package/src/Components/Grid/Grid.js +3 -2
- package/src/Components/Hoc/Secondary/withSecondaryEditor.js +84 -64
- package/src/Components/Hoc/withEditor.js +85 -65
- package/src/Components/Toolbar/Pagination.js +1 -1
- package/src/Components/Tree/Tree.js +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onehat/ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.150",
|
|
4
4
|
"description": "Base UI for OneHat apps",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"@gluestack-ui/themed": "^0.1.53",
|
|
30
30
|
"@hookform/resolvers": "^3.3.1",
|
|
31
31
|
"@k-renwick/colour-mixer": "^1.2.1",
|
|
32
|
-
"@onehat/data": "^1.
|
|
32
|
+
"@onehat/data": "^1.20.0",
|
|
33
33
|
"@reduxjs/toolkit": "^1.9.5",
|
|
34
34
|
"inflector-js": "^1.0.1",
|
|
35
35
|
"js-cookie": "^3.0.5",
|
|
@@ -46,12 +46,15 @@ export function ComboComponent(props) {
|
|
|
46
46
|
_input = {},
|
|
47
47
|
isEditor = false,
|
|
48
48
|
isDisabled = false,
|
|
49
|
+
isInTag = false,
|
|
49
50
|
tooltipPlacement = 'bottom',
|
|
50
51
|
placeholder,
|
|
51
52
|
onRowPress,
|
|
52
53
|
icon,
|
|
53
54
|
Editor, // only used for the eyeButton
|
|
54
|
-
|
|
55
|
+
onGridAdd, // to hook into when menu adds (ComboEditor only)
|
|
56
|
+
onGridSave, // to hook into when menu saves (ComboEditor only)
|
|
57
|
+
onGridDelete, // to hook into when menu deletes (ComboEditor only)
|
|
55
58
|
|
|
56
59
|
// withComponent
|
|
57
60
|
self,
|
|
@@ -735,19 +738,21 @@ export function ComboComponent(props) {
|
|
|
735
738
|
}
|
|
736
739
|
|
|
737
740
|
}}
|
|
741
|
+
onAdd={onGridAdd}
|
|
738
742
|
onSave={(selection) => {
|
|
739
743
|
const entity = selection[0];
|
|
740
|
-
if (entity?.id !== value) {
|
|
744
|
+
if (entity?.id !== value && !isInTag) { // Tag doesn't use value, so don't do this comparison in the Tag
|
|
741
745
|
// Either a phantom record was just solidified into a real record, or a new (non-phantom) record was added.
|
|
742
746
|
// Select it and set the value of the combo.
|
|
743
747
|
setGridSelection([entity]);
|
|
744
748
|
const id = entity.id;
|
|
745
749
|
setValue(id);
|
|
746
750
|
}
|
|
747
|
-
if (
|
|
748
|
-
|
|
751
|
+
if (onGridSave) {
|
|
752
|
+
onGridSave(selection);
|
|
749
753
|
}
|
|
750
754
|
}}
|
|
755
|
+
onDelete={onGridDelete}
|
|
751
756
|
onRowPress={(item, e) => {
|
|
752
757
|
if (onRowPress) {
|
|
753
758
|
onRowPress(item, e);
|
|
@@ -40,6 +40,7 @@ function TagComponent(props) {
|
|
|
40
40
|
setValue,
|
|
41
41
|
...propsToPass // break connection between Tag and Combo props
|
|
42
42
|
} = props,
|
|
43
|
+
valueRef = useRef(value),
|
|
43
44
|
ignoreNextComboValueChangeRef = useRef(false),
|
|
44
45
|
[isViewerShown, setIsViewerShown] = useState(false),
|
|
45
46
|
[viewerSelection, setViewerSelection] = useState([]),
|
|
@@ -138,6 +139,67 @@ function TagComponent(props) {
|
|
|
138
139
|
});
|
|
139
140
|
setValue(newValue);
|
|
140
141
|
},
|
|
142
|
+
onGridAdd = (selection) => {
|
|
143
|
+
// underlying GridEditor added a record.
|
|
144
|
+
// add it to this Tag's value
|
|
145
|
+
const
|
|
146
|
+
entity = selection[0],
|
|
147
|
+
id = entity.id,
|
|
148
|
+
newValue = _.clone(valueRef.current);
|
|
149
|
+
newValue.push({
|
|
150
|
+
id,
|
|
151
|
+
text: entity.displayValue,
|
|
152
|
+
});
|
|
153
|
+
setValue(newValue);
|
|
154
|
+
},
|
|
155
|
+
onGridSave = (selection) => {
|
|
156
|
+
// underlying GridEditor has changed a record.
|
|
157
|
+
// Check if that value exists, and if so, update its displayValue
|
|
158
|
+
if (_.isEmpty(valueRef.current)) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const
|
|
163
|
+
entity = selection[0],
|
|
164
|
+
id = entity.id,
|
|
165
|
+
ix = _.findIndex(valueRef.current, (item) => {
|
|
166
|
+
return item.id === id;
|
|
167
|
+
}),
|
|
168
|
+
isFound = ix !== -1;
|
|
169
|
+
if (!isFound) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const newValue = _.clone(valueRef.current);
|
|
174
|
+
newValue[ix] = {
|
|
175
|
+
id,
|
|
176
|
+
text: entity.displayValue,
|
|
177
|
+
};
|
|
178
|
+
setValue(newValue);
|
|
179
|
+
},
|
|
180
|
+
onGridDelete = (selection) => {
|
|
181
|
+
// underlying GridEditor has deleted a value.
|
|
182
|
+
// Check if that value exists, and if so delete it
|
|
183
|
+
if (_.isEmpty(valueRef.current)) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const
|
|
188
|
+
entity = selection[0],
|
|
189
|
+
id = entity.id,
|
|
190
|
+
ix = _.findIndex(valueRef.current, (item) => {
|
|
191
|
+
return item.id === id;
|
|
192
|
+
}),
|
|
193
|
+
isFound = ix !== -1;
|
|
194
|
+
if (!isFound) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const newValue = _.filter(valueRef.current, (item) => {
|
|
199
|
+
return item.id !== id;
|
|
200
|
+
});
|
|
201
|
+
setValue(newValue);
|
|
202
|
+
},
|
|
141
203
|
valueBoxes = _.map(value, (val, ix) => {
|
|
142
204
|
return <ValueBox
|
|
143
205
|
key={ix}
|
|
@@ -146,6 +208,8 @@ function TagComponent(props) {
|
|
|
146
208
|
onDelete={!isViewOnly ? () => onDelete(val) : null}
|
|
147
209
|
/>;
|
|
148
210
|
});
|
|
211
|
+
|
|
212
|
+
valueRef.current = value; // the onGrid* methods were dealing with stale data, so use a ref, and update it here
|
|
149
213
|
|
|
150
214
|
let WhichCombo = Combo;
|
|
151
215
|
if (_combo.isEditor) {
|
|
@@ -193,6 +257,10 @@ function TagComponent(props) {
|
|
|
193
257
|
onChangeValue={onChangeComboValue}
|
|
194
258
|
parent={self}
|
|
195
259
|
reference="combo"
|
|
260
|
+
isInTag={true}
|
|
261
|
+
onGridAdd={onGridAdd}
|
|
262
|
+
onGridSave={onGridSave}
|
|
263
|
+
onGridDelete={onGridDelete}
|
|
196
264
|
{..._combo}
|
|
197
265
|
/>}
|
|
198
266
|
</Column>
|
|
@@ -287,6 +287,7 @@ function GridComponent(props) {
|
|
|
287
287
|
reference="reorderBtn"
|
|
288
288
|
onPress={() => setIsDragMode(!isDragMode)}
|
|
289
289
|
icon={<Icon as={isDragMode ? NoReorderRows : ReorderRows} color={styles.GRID_TOOLBAR_ITEMS_COLOR} />}
|
|
290
|
+
tooltip="Reorder Rows"
|
|
290
291
|
/>);
|
|
291
292
|
}
|
|
292
293
|
return items;
|
|
@@ -618,7 +619,7 @@ function GridComponent(props) {
|
|
|
618
619
|
}
|
|
619
620
|
|
|
620
621
|
setDragRowSlot({ ix: newIx, marker, useBottom, });
|
|
621
|
-
// console.log('onRowReorderDrag', newIx);
|
|
622
|
+
// console.log('onRowReorderDrag slot', newIx);
|
|
622
623
|
|
|
623
624
|
},
|
|
624
625
|
onRowReorderDragStop = (delta, e, config) => {
|
|
@@ -887,7 +888,7 @@ function GridComponent(props) {
|
|
|
887
888
|
|
|
888
889
|
isAddingRef.current = isAdding;
|
|
889
890
|
|
|
890
|
-
const footerToolbarItemComponents = useMemo(() => getFooterToolbarItems(), [additionalToolbarButtons, isDragMode]);
|
|
891
|
+
const footerToolbarItemComponents = useMemo(() => getFooterToolbarItems(), [Repository?.hash, additionalToolbarButtons, isDragMode]);
|
|
891
892
|
|
|
892
893
|
if (!isInited) {
|
|
893
894
|
// first time through, render a placeholder so we can get container dimensions
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
EDITOR_MODE__ADD,
|
|
8
8
|
EDITOR_MODE__EDIT,
|
|
9
9
|
} from '../../../Constants/Editor.js';
|
|
10
|
-
import UiGlobals from '../../../UiGlobals.js';
|
|
11
10
|
import _ from 'lodash';
|
|
12
11
|
|
|
13
12
|
// NOTE: This is a modified version of @onehat/ui/src/Hoc/withEditor
|
|
@@ -38,8 +37,10 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
38
37
|
return 'record' + (secondarySelection[0].displayValue ? ' "' + secondarySelection[0].displayValue + '"' : '') + '?';
|
|
39
38
|
},
|
|
40
39
|
secondaryRecord,
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
secondaryOnAdd,
|
|
41
|
+
secondaryOnChange, // any kind of crud change
|
|
42
|
+
secondaryOnDelete,
|
|
43
|
+
secondaryOnSave, // this could also be called 'onEdit'
|
|
43
44
|
secondaryNewEntityDisplayValue,
|
|
44
45
|
secondaryDefaultValues,
|
|
45
46
|
|
|
@@ -93,12 +94,12 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
93
94
|
getNewEntityDisplayValue = () => {
|
|
94
95
|
return secondaryNewEntityDisplayValueRef.current;
|
|
95
96
|
},
|
|
96
|
-
|
|
97
|
+
secondaryDoAdd = async (e, values) => {
|
|
97
98
|
let addValues = values;
|
|
98
99
|
|
|
99
100
|
if (!values) {
|
|
100
101
|
// you can either:
|
|
101
|
-
// 1. directlty submit 'values' to use in
|
|
102
|
+
// 1. directlty submit 'values' to use in secondaryDoAdd(), or
|
|
102
103
|
// 2. Use the repository's default values (defined on each property as 'defaultValue'), or
|
|
103
104
|
// 3. Individually override the repository's default values with submitted 'defaultValues' (given as a prop to this HOC)
|
|
104
105
|
let defaultValuesToUse = Repository.getSchema().getDefaultValues();
|
|
@@ -151,18 +152,20 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
151
152
|
setIsSaving(false);
|
|
152
153
|
setSecondaryIsIgnoreNextSelectionChange(true);
|
|
153
154
|
secondarySetSelection([entity]);
|
|
155
|
+
if (SecondaryRepository.isAutoSave) {
|
|
156
|
+
// for isAutoSave Repositories, submit the handers right away
|
|
157
|
+
if (getListeners().onAfterAdd) {
|
|
158
|
+
await getListeners().onAfterAdd(entity);
|
|
159
|
+
}
|
|
160
|
+
if (onAdd) {
|
|
161
|
+
await secondaryOnAdd(entity);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
154
164
|
setIsEditorViewOnly(false);
|
|
155
|
-
|
|
165
|
+
setEditorMode(SecondaryRepository.isAutoSave ? EDITOR_MODE__EDIT : EDITOR_MODE__ADD);
|
|
156
166
|
secondarySetIsEditorShown(true);
|
|
157
|
-
|
|
158
|
-
if (getListeners().onAfterAdd) {
|
|
159
|
-
await getListeners().onAfterAdd(entity);
|
|
160
|
-
}
|
|
161
|
-
if (secondaryOnChange) {
|
|
162
|
-
secondaryOnChange();
|
|
163
|
-
}
|
|
164
167
|
},
|
|
165
|
-
|
|
168
|
+
secondaryDoEdit = async () => {
|
|
166
169
|
if (_.isEmpty(secondarySelection) || (_.isArray(secondarySelection) && (secondarySelection.length > 1 || secondarySelection[0]?.isDestroyed))) {
|
|
167
170
|
return;
|
|
168
171
|
}
|
|
@@ -176,7 +179,7 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
176
179
|
secondarySetEditorMode(EDITOR_MODE__EDIT);
|
|
177
180
|
secondarySetIsEditorShown(true);
|
|
178
181
|
},
|
|
179
|
-
|
|
182
|
+
secondaryDoDelete = async (args) => {
|
|
180
183
|
let cb = null;
|
|
181
184
|
if (_.isFunction(args)) {
|
|
182
185
|
cb = args;
|
|
@@ -203,10 +206,10 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
203
206
|
message: 'The node you have selected for deletion has children. ' +
|
|
204
207
|
'Should these children be moved up to this node\'s parent, or be deleted?',
|
|
205
208
|
buttons: [
|
|
206
|
-
<Button colorScheme="danger" onPress={() =>
|
|
209
|
+
<Button colorScheme="danger" onPress={() => secondaryDoMoveChildren(cb)} key="moveBtn">
|
|
207
210
|
Move Children
|
|
208
211
|
</Button>,
|
|
209
|
-
<Button colorScheme="danger" onPress={() =>
|
|
212
|
+
<Button colorScheme="danger" onPress={() => secondaryDoDeleteChildren(cb)} key="deleteBtn">
|
|
210
213
|
Delete Children
|
|
211
214
|
</Button>
|
|
212
215
|
],
|
|
@@ -220,17 +223,20 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
220
223
|
confirm('Are you sure you want to delete the ' + identifier, () => deleteRecord(null, cb));
|
|
221
224
|
}
|
|
222
225
|
},
|
|
223
|
-
|
|
226
|
+
secondaryDoMoveChildren = (cb) => {
|
|
224
227
|
hideAlert();
|
|
225
228
|
deleteRecord(true, cb);
|
|
226
229
|
},
|
|
227
|
-
|
|
230
|
+
secondaryDoDeleteChildren = (cb) => {
|
|
228
231
|
hideAlert();
|
|
229
232
|
deleteRecord(false, cb);
|
|
230
233
|
},
|
|
231
234
|
deleteRecord = async (moveSubtreeUp, cb) => {
|
|
232
|
-
if (getListeners().
|
|
233
|
-
await getListeners().
|
|
235
|
+
if (getListeners().onBeforeDelete) {
|
|
236
|
+
const listenerResult = await getListeners().onBeforeDelete(secondarySelection);
|
|
237
|
+
if (listenerResult === false) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
234
240
|
}
|
|
235
241
|
|
|
236
242
|
await SecondaryRepository.delete(secondarySelection, moveSubtreeUp);
|
|
@@ -242,13 +248,16 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
242
248
|
}
|
|
243
249
|
secondarySetSelection([]);
|
|
244
250
|
if (cb) {
|
|
245
|
-
cb();
|
|
251
|
+
cb(secondarySelection);
|
|
246
252
|
}
|
|
247
253
|
if (secondaryOnChange) {
|
|
248
|
-
secondaryOnChange();
|
|
254
|
+
secondaryOnChange(secondarySelection);
|
|
255
|
+
}
|
|
256
|
+
if (secondaryOnDelete) {
|
|
257
|
+
secondaryOnDelete(secondarySelection);
|
|
249
258
|
}
|
|
250
259
|
},
|
|
251
|
-
|
|
260
|
+
secondaryDoView = async () => {
|
|
252
261
|
if (!secondaryUserCanView) {
|
|
253
262
|
return;
|
|
254
263
|
}
|
|
@@ -263,7 +272,7 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
263
272
|
await getListeners().onAfterView();
|
|
264
273
|
}
|
|
265
274
|
},
|
|
266
|
-
|
|
275
|
+
secondaryDoDuplicate = async () => {
|
|
267
276
|
if (!secondaryUserCanEdit || secondaryDisableDuplicate) {
|
|
268
277
|
return;
|
|
269
278
|
}
|
|
@@ -290,9 +299,10 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
290
299
|
|
|
291
300
|
setSecondaryIsIgnoreNextSelectionChange(true);
|
|
292
301
|
secondarySetSelection([duplicateEntity]);
|
|
293
|
-
|
|
302
|
+
secondaryDoEdit();
|
|
294
303
|
},
|
|
295
|
-
|
|
304
|
+
secondaryDoEditorSave = async (data, e) => {
|
|
305
|
+
// NOTE: The Form submits onSave for both adds (when not isAutoSsave) and edits.
|
|
296
306
|
const
|
|
297
307
|
what = secondaryRecord || secondarySelection,
|
|
298
308
|
isSingle = what.length === 1;
|
|
@@ -314,8 +324,11 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
314
324
|
});
|
|
315
325
|
}
|
|
316
326
|
|
|
317
|
-
if (getListeners().
|
|
318
|
-
await getListeners().
|
|
327
|
+
if (getListeners().onBeforeSave) {
|
|
328
|
+
const listenerResult = await getListeners().onBeforeSave(what);
|
|
329
|
+
if (listenerResult === false) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
319
332
|
}
|
|
320
333
|
|
|
321
334
|
setIsSaving(true);
|
|
@@ -330,25 +343,32 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
330
343
|
setIsSaving(false);
|
|
331
344
|
|
|
332
345
|
if (success) {
|
|
333
|
-
setIsAdding(false);
|
|
334
|
-
|
|
335
|
-
secondarySetEditorMode(EDITOR_MODE__EDIT);
|
|
336
|
-
// secondarySetIsEditorShown(false);
|
|
337
|
-
|
|
338
|
-
if (getListeners().onAfterEdit) {
|
|
339
|
-
await getListeners().onAfterEdit(what);
|
|
340
|
-
}
|
|
341
346
|
if (secondaryOnChange) {
|
|
342
|
-
secondaryOnChange();
|
|
347
|
+
secondaryOnChange(what);
|
|
343
348
|
}
|
|
344
|
-
if (
|
|
345
|
-
|
|
349
|
+
if (editorMode === EDITOR_MODE__ADD) {
|
|
350
|
+
if (onAdd) {
|
|
351
|
+
await onAdd(what);
|
|
352
|
+
}
|
|
353
|
+
if (getListeners().onAfterAdd) {
|
|
354
|
+
await getListeners().onAfterAdd(what);
|
|
355
|
+
}
|
|
356
|
+
setIsAdding(false);
|
|
357
|
+
setEditorMode(EDITOR_MODE__EDIT);
|
|
358
|
+
} else if (editorMode === EDITOR_MODE__EDIT) {
|
|
359
|
+
if (getListeners().onAfterEdit) {
|
|
360
|
+
await getListeners().onAfterEdit(what);
|
|
361
|
+
}
|
|
362
|
+
if (secondaryOnSave) {
|
|
363
|
+
secondaryOnSave(what);
|
|
364
|
+
}
|
|
346
365
|
}
|
|
366
|
+
// secondarySetIsEditorShown(false);
|
|
347
367
|
}
|
|
348
368
|
|
|
349
369
|
return success;
|
|
350
370
|
},
|
|
351
|
-
|
|
371
|
+
secondaryDoEditorCancel = () => {
|
|
352
372
|
async function doIt() {
|
|
353
373
|
const
|
|
354
374
|
isSingle = secondarySelection.length === 1,
|
|
@@ -367,14 +387,14 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
367
387
|
doIt();
|
|
368
388
|
}
|
|
369
389
|
},
|
|
370
|
-
|
|
390
|
+
secondaryDoEditorClose = () => {
|
|
371
391
|
if (secondaryIsAdding) {
|
|
372
|
-
|
|
392
|
+
secondaryDoEditorCancel();
|
|
373
393
|
}
|
|
374
394
|
secondarySetIsEditorShown(false);
|
|
375
395
|
},
|
|
376
|
-
|
|
377
|
-
|
|
396
|
+
secondaryDoEditorDelete = async () => {
|
|
397
|
+
secondaryDoDelete(() => {
|
|
378
398
|
secondarySetEditorMode(EDITOR_MODE__VIEW);
|
|
379
399
|
secondarySetIsEditorShown(false);
|
|
380
400
|
});
|
|
@@ -396,10 +416,10 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
396
416
|
}
|
|
397
417
|
return mode;
|
|
398
418
|
},
|
|
399
|
-
|
|
419
|
+
secondarySetEditMode = () => {
|
|
400
420
|
secondarySetEditorMode(EDITOR_MODE__EDIT);
|
|
401
421
|
},
|
|
402
|
-
|
|
422
|
+
secondarySetViewMode = () => {
|
|
403
423
|
function doIt() {
|
|
404
424
|
secondarySetEditorMode(EDITOR_MODE__VIEW);
|
|
405
425
|
}
|
|
@@ -428,12 +448,12 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
428
448
|
}, [secondarySelection]);
|
|
429
449
|
|
|
430
450
|
if (self) {
|
|
431
|
-
self.secondaryAdd =
|
|
432
|
-
self.secondaryEdit =
|
|
433
|
-
self.secondaryDelete =
|
|
434
|
-
self.secondarnMoveChildren =
|
|
435
|
-
self.secondaryDeleteChildren =
|
|
436
|
-
self.secondaryDuplicate =
|
|
451
|
+
self.secondaryAdd = secondaryDoAdd;
|
|
452
|
+
self.secondaryEdit = secondaryDoEdit;
|
|
453
|
+
self.secondaryDelete = secondaryDoDelete;
|
|
454
|
+
self.secondarnMoveChildren = secondaryDoMoveChildren;
|
|
455
|
+
self.secondaryDeleteChildren = secondaryDoDeleteChildren;
|
|
456
|
+
self.secondaryDuplicate = secondaryDoDuplicate;
|
|
437
457
|
}
|
|
438
458
|
secondaryNewEntityDisplayValueRef.current = secondaryNewEntityDisplayValue;
|
|
439
459
|
|
|
@@ -458,19 +478,19 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
458
478
|
secondaryIsAdding={secondaryIsAdding}
|
|
459
479
|
secondaryIsSaving={secondaryIsSaving}
|
|
460
480
|
secondaryEditorMode={secondaryEditorMode}
|
|
461
|
-
secondaryOnEditMode={
|
|
462
|
-
secondaryOnViewMode={
|
|
481
|
+
secondaryOnEditMode={secondarySetEditMode}
|
|
482
|
+
secondaryOnViewMode={secondarySetViewMode}
|
|
463
483
|
secondaryEditorStateRef={secondaryEditorStateRef}
|
|
464
484
|
secondarySetIsEditorShown={secondarySetIsEditorShown}
|
|
465
|
-
secondaryOnAdd={(!secondaryUserCanEdit || secondaryDisableAdd) ? null :
|
|
466
|
-
secondaryOnEdit={(!secondaryUserCanEdit || secondaryDisableEdit) ? null :
|
|
467
|
-
secondaryOnDelete={(!secondaryUserCanEdit || secondaryDisableDelete) ? null :
|
|
468
|
-
secondaryOnView={
|
|
469
|
-
secondaryOnDuplicate={
|
|
470
|
-
secondaryOnEditorSave={
|
|
471
|
-
secondaryOnEditorCancel={
|
|
472
|
-
secondaryOnEditorDelete={(!secondaryUserCanEdit || secondaryDisableDelete) ? null :
|
|
473
|
-
secondaryOnEditorClose={
|
|
485
|
+
secondaryOnAdd={(!secondaryUserCanEdit || secondaryDisableAdd) ? null : secondaryDoAdd}
|
|
486
|
+
secondaryOnEdit={(!secondaryUserCanEdit || secondaryDisableEdit) ? null : secondaryDoEdit}
|
|
487
|
+
secondaryOnDelete={(!secondaryUserCanEdit || secondaryDisableDelete) ? null : secondaryDoDelete}
|
|
488
|
+
secondaryOnView={secondaryDoView}
|
|
489
|
+
secondaryOnDuplicate={secondaryDoDuplicate}
|
|
490
|
+
secondaryOnEditorSave={secondaryDoEditorSave}
|
|
491
|
+
secondaryOnEditorCancel={secondaryDoEditorCancel}
|
|
492
|
+
secondaryOnEditorDelete={(!secondaryUserCanEdit || secondaryDisableDelete) ? null : secondaryDoEditorDelete}
|
|
493
|
+
secondaryOnEditorClose={secondaryDoEditorClose}
|
|
474
494
|
secondarySetWithEditListeners={setListeners}
|
|
475
495
|
secondaryIsEditor={true}
|
|
476
496
|
secondaryUserCanEdit={secondaryUserCanEdit}
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
EDITOR_MODE__ADD,
|
|
8
8
|
EDITOR_MODE__EDIT,
|
|
9
9
|
} from '../../Constants/Editor.js';
|
|
10
|
-
import UiGlobals from '../../UiGlobals.js';
|
|
11
10
|
import _ from 'lodash';
|
|
12
11
|
|
|
13
12
|
export default function withEditor(WrappedComponent, isTree = false) {
|
|
@@ -35,8 +34,10 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
35
34
|
return 'record' + (selection[0].displayValue ? ' "' + selection[0].displayValue + '"' : '') + '?';
|
|
36
35
|
},
|
|
37
36
|
record,
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
onAdd,
|
|
38
|
+
onChange, // any kind of crud change
|
|
39
|
+
onDelete,
|
|
40
|
+
onSave, // this could also be called 'onEdit'
|
|
40
41
|
newEntityDisplayValue,
|
|
41
42
|
defaultValues,
|
|
42
43
|
|
|
@@ -95,12 +96,12 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
95
96
|
getNewEntityDisplayValue = () => {
|
|
96
97
|
return newEntityDisplayValueRef.current;
|
|
97
98
|
},
|
|
98
|
-
|
|
99
|
+
doAdd = async (e, values) => {
|
|
99
100
|
let addValues = values;
|
|
100
101
|
|
|
101
102
|
if (!values) {
|
|
102
103
|
// you can either:
|
|
103
|
-
// 1. directlty submit 'values' to use in
|
|
104
|
+
// 1. directlty submit 'values' to use in doAdd(), or
|
|
104
105
|
// 2. Use the repository's default values (defined on each property as 'defaultValue'), or
|
|
105
106
|
// 3. Individually override the repository's default values with submitted 'defaultValues' (given as a prop to this HOC)
|
|
106
107
|
let defaultValuesToUse = Repository.getSchema().getDefaultValues();
|
|
@@ -153,18 +154,20 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
153
154
|
setIsSaving(false);
|
|
154
155
|
setIsIgnoreNextSelectionChange(true);
|
|
155
156
|
setSelection([entity]);
|
|
157
|
+
if (Repository.isAutoSave) {
|
|
158
|
+
// for isAutoSave Repositories, submit the handers right away
|
|
159
|
+
if (getListeners().onAfterAdd) {
|
|
160
|
+
await getListeners().onAfterAdd(entity);
|
|
161
|
+
}
|
|
162
|
+
if (onAdd) {
|
|
163
|
+
await onAdd(entity);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
156
166
|
setIsEditorViewOnly(false);
|
|
157
|
-
setEditorMode(EDITOR_MODE__ADD);
|
|
167
|
+
setEditorMode(Repository.isAutoSave ? EDITOR_MODE__EDIT : EDITOR_MODE__ADD);
|
|
158
168
|
setIsEditorShown(true);
|
|
159
|
-
|
|
160
|
-
if (getListeners().onAfterAdd) {
|
|
161
|
-
await getListeners().onAfterAdd(entity);
|
|
162
|
-
}
|
|
163
|
-
if (onChange) {
|
|
164
|
-
onChange();
|
|
165
|
-
}
|
|
166
169
|
},
|
|
167
|
-
|
|
170
|
+
doEdit = async () => {
|
|
168
171
|
if (_.isEmpty(selection) || (_.isArray(selection) && (selection.length > 1 || selection[0]?.isDestroyed))) {
|
|
169
172
|
return;
|
|
170
173
|
}
|
|
@@ -178,7 +181,7 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
178
181
|
setEditorMode(EDITOR_MODE__EDIT);
|
|
179
182
|
setIsEditorShown(true);
|
|
180
183
|
},
|
|
181
|
-
|
|
184
|
+
doDelete = async (args) => {
|
|
182
185
|
let cb = null;
|
|
183
186
|
if (_.isFunction(args)) {
|
|
184
187
|
cb = args;
|
|
@@ -205,10 +208,10 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
205
208
|
message: 'The node you have selected for deletion has children. ' +
|
|
206
209
|
'Should these children be moved up to this node\'s parent, or be deleted?',
|
|
207
210
|
buttons: [
|
|
208
|
-
<Button colorScheme="danger" onPress={() =>
|
|
211
|
+
<Button colorScheme="danger" onPress={() => doMoveChildren(cb)} key="moveBtn">
|
|
209
212
|
Move Children
|
|
210
213
|
</Button>,
|
|
211
|
-
<Button colorScheme="danger" onPress={() =>
|
|
214
|
+
<Button colorScheme="danger" onPress={() => doDeleteChildren(cb)} key="deleteBtn">
|
|
212
215
|
Delete Children
|
|
213
216
|
</Button>
|
|
214
217
|
],
|
|
@@ -222,17 +225,20 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
222
225
|
confirm('Are you sure you want to delete the ' + identifier, () => deleteRecord(null, cb));
|
|
223
226
|
}
|
|
224
227
|
},
|
|
225
|
-
|
|
228
|
+
doMoveChildren = (cb) => {
|
|
226
229
|
hideAlert();
|
|
227
230
|
deleteRecord(true, cb);
|
|
228
231
|
},
|
|
229
|
-
|
|
232
|
+
doDeleteChildren = (cb) => {
|
|
230
233
|
hideAlert();
|
|
231
234
|
deleteRecord(false, cb);
|
|
232
235
|
},
|
|
233
236
|
deleteRecord = async (moveSubtreeUp, cb) => {
|
|
234
|
-
if (getListeners().
|
|
235
|
-
await getListeners().
|
|
237
|
+
if (getListeners().onBeforeDelete) {
|
|
238
|
+
const listenerResult = await getListeners().onBeforeDelete(selection);
|
|
239
|
+
if (listenerResult === false) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
236
242
|
}
|
|
237
243
|
|
|
238
244
|
await Repository.delete(selection, moveSubtreeUp);
|
|
@@ -244,13 +250,16 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
244
250
|
}
|
|
245
251
|
setSelection([]);
|
|
246
252
|
if (cb) {
|
|
247
|
-
cb();
|
|
253
|
+
cb(selection);
|
|
248
254
|
}
|
|
249
255
|
if (onChange) {
|
|
250
|
-
onChange();
|
|
256
|
+
onChange(selection);
|
|
257
|
+
}
|
|
258
|
+
if (onDelete) {
|
|
259
|
+
onDelete(selection);
|
|
251
260
|
}
|
|
252
261
|
},
|
|
253
|
-
|
|
262
|
+
doView = async () => {
|
|
254
263
|
if (!userCanView) {
|
|
255
264
|
return;
|
|
256
265
|
}
|
|
@@ -265,7 +274,7 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
265
274
|
await getListeners().onAfterView();
|
|
266
275
|
}
|
|
267
276
|
},
|
|
268
|
-
|
|
277
|
+
doDuplicate = async () => {
|
|
269
278
|
if (!userCanEdit || disableDuplicate) {
|
|
270
279
|
return;
|
|
271
280
|
}
|
|
@@ -292,9 +301,10 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
292
301
|
|
|
293
302
|
setIsIgnoreNextSelectionChange(true);
|
|
294
303
|
setSelection([duplicateEntity]);
|
|
295
|
-
|
|
304
|
+
doEdit();
|
|
296
305
|
},
|
|
297
|
-
|
|
306
|
+
doEditorSave = async (data, e) => {
|
|
307
|
+
// NOTE: The Form submits onSave for both adds (when not isAutoSsave) and edits.
|
|
298
308
|
const
|
|
299
309
|
what = record || selection,
|
|
300
310
|
isSingle = what.length === 1;
|
|
@@ -316,8 +326,11 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
316
326
|
});
|
|
317
327
|
}
|
|
318
328
|
|
|
319
|
-
if (getListeners().
|
|
320
|
-
await getListeners().
|
|
329
|
+
if (getListeners().onBeforeSave) {
|
|
330
|
+
const listenerResult = await getListeners().onBeforeSave(what);
|
|
331
|
+
if (listenerResult === false) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
321
334
|
}
|
|
322
335
|
|
|
323
336
|
setIsSaving(true);
|
|
@@ -332,25 +345,32 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
332
345
|
setIsSaving(false);
|
|
333
346
|
|
|
334
347
|
if (success) {
|
|
335
|
-
setIsAdding(false);
|
|
336
|
-
|
|
337
|
-
setEditorMode(EDITOR_MODE__EDIT);
|
|
338
|
-
// setIsEditorShown(false);
|
|
339
|
-
|
|
340
|
-
if (getListeners().onAfterEdit) {
|
|
341
|
-
await getListeners().onAfterEdit(what);
|
|
342
|
-
}
|
|
343
348
|
if (onChange) {
|
|
344
|
-
onChange();
|
|
349
|
+
onChange(what);
|
|
345
350
|
}
|
|
346
|
-
if (
|
|
347
|
-
|
|
351
|
+
if (editorMode === EDITOR_MODE__ADD) {
|
|
352
|
+
if (onAdd) {
|
|
353
|
+
await onAdd(what);
|
|
354
|
+
}
|
|
355
|
+
if (getListeners().onAfterAdd) {
|
|
356
|
+
await getListeners().onAfterAdd(what);
|
|
357
|
+
}
|
|
358
|
+
setIsAdding(false);
|
|
359
|
+
setEditorMode(EDITOR_MODE__EDIT);
|
|
360
|
+
} else if (editorMode === EDITOR_MODE__EDIT) {
|
|
361
|
+
if (getListeners().onAfterEdit) {
|
|
362
|
+
await getListeners().onAfterEdit(what);
|
|
363
|
+
}
|
|
364
|
+
if (onSave) {
|
|
365
|
+
onSave(what);
|
|
366
|
+
}
|
|
348
367
|
}
|
|
368
|
+
// setIsEditorShown(false);
|
|
349
369
|
}
|
|
350
370
|
|
|
351
371
|
return success;
|
|
352
372
|
},
|
|
353
|
-
|
|
373
|
+
doEditorCancel = () => {
|
|
354
374
|
async function doIt() {
|
|
355
375
|
const
|
|
356
376
|
isSingle = selection.length === 1,
|
|
@@ -369,14 +389,14 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
369
389
|
doIt();
|
|
370
390
|
}
|
|
371
391
|
},
|
|
372
|
-
|
|
392
|
+
doEditorClose = () => {
|
|
373
393
|
if (isAdding) {
|
|
374
|
-
|
|
394
|
+
doEditorCancel();
|
|
375
395
|
}
|
|
376
396
|
setIsEditorShown(false);
|
|
377
397
|
},
|
|
378
|
-
|
|
379
|
-
|
|
398
|
+
doEditorDelete = async () => {
|
|
399
|
+
doDelete(() => {
|
|
380
400
|
setEditorMode(EDITOR_MODE__VIEW);
|
|
381
401
|
setIsEditorShown(false);
|
|
382
402
|
});
|
|
@@ -398,10 +418,10 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
398
418
|
}
|
|
399
419
|
return mode;
|
|
400
420
|
},
|
|
401
|
-
|
|
421
|
+
setEditMode = () => {
|
|
402
422
|
setEditorMode(EDITOR_MODE__EDIT);
|
|
403
423
|
},
|
|
404
|
-
|
|
424
|
+
setViewMode = () => {
|
|
405
425
|
function doIt() {
|
|
406
426
|
setEditorMode(EDITOR_MODE__VIEW);
|
|
407
427
|
}
|
|
@@ -417,7 +437,7 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
417
437
|
// When selection changes, set the mode appropriately
|
|
418
438
|
let mode;
|
|
419
439
|
if (isIgnoreNextSelectionChange) {
|
|
420
|
-
// on selection change from
|
|
440
|
+
// on selection change from doAdd/doDuplicate/etc, calculate whether to put Editor in "add" or "edit" mode
|
|
421
441
|
mode = calculateEditorMode();
|
|
422
442
|
} else {
|
|
423
443
|
// Most of the time, if selection changed, put the Editor in "view" mode
|
|
@@ -430,12 +450,12 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
430
450
|
}, [selection]);
|
|
431
451
|
|
|
432
452
|
if (self) {
|
|
433
|
-
self.add =
|
|
434
|
-
self.edit =
|
|
435
|
-
self.delete =
|
|
436
|
-
self.moveChildren =
|
|
437
|
-
self.deleteChildren =
|
|
438
|
-
self.duplicate =
|
|
453
|
+
self.add = doAdd;
|
|
454
|
+
self.edit = doEdit;
|
|
455
|
+
self.delete = doDelete;
|
|
456
|
+
self.moveChildren = doMoveChildren;
|
|
457
|
+
self.deleteChildren = doDeleteChildren;
|
|
458
|
+
self.duplicate = doDuplicate;
|
|
439
459
|
}
|
|
440
460
|
newEntityDisplayValueRef.current = newEntityDisplayValue;
|
|
441
461
|
|
|
@@ -460,19 +480,19 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
460
480
|
isAdding={isAdding}
|
|
461
481
|
isSaving={isSaving}
|
|
462
482
|
editorMode={editorMode}
|
|
463
|
-
onEditMode={
|
|
464
|
-
onViewMode={
|
|
483
|
+
onEditMode={setEditMode}
|
|
484
|
+
onViewMode={setViewMode}
|
|
465
485
|
editorStateRef={editorStateRef}
|
|
466
486
|
setIsEditorShown={setIsEditorShown}
|
|
467
|
-
onAdd={(!userCanEdit || disableAdd) ? null :
|
|
468
|
-
onEdit={(!userCanEdit || disableEdit) ? null :
|
|
469
|
-
onDelete={(!userCanEdit || disableDelete) ? null :
|
|
470
|
-
onView={
|
|
471
|
-
onDuplicate={
|
|
472
|
-
onEditorSave={
|
|
473
|
-
onEditorCancel={
|
|
474
|
-
onEditorDelete={(!userCanEdit || disableDelete) ? null :
|
|
475
|
-
onEditorClose={
|
|
487
|
+
onAdd={(!userCanEdit || disableAdd) ? null : doAdd}
|
|
488
|
+
onEdit={(!userCanEdit || disableEdit) ? null : doEdit}
|
|
489
|
+
onDelete={(!userCanEdit || disableDelete) ? null : doDelete}
|
|
490
|
+
onView={doView}
|
|
491
|
+
onDuplicate={doDuplicate}
|
|
492
|
+
onEditorSave={doEditorSave}
|
|
493
|
+
onEditorCancel={doEditorCancel}
|
|
494
|
+
onEditorDelete={(!userCanEdit || disableDelete) ? null : doEditorDelete}
|
|
495
|
+
onEditorClose={doEditorClose}
|
|
476
496
|
setWithEditListeners={setListeners}
|
|
477
497
|
isEditor={true}
|
|
478
498
|
userCanEdit={userCanEdit}
|
|
@@ -1079,8 +1079,8 @@ function TreeComponent(props) {
|
|
|
1079
1079
|
});
|
|
1080
1080
|
|
|
1081
1081
|
const
|
|
1082
|
-
headerToolbarItemComponents = useMemo(() => getHeaderToolbarItems(), [treeSearchValue, isDragMode, getTreeNodeData()]),
|
|
1083
|
-
footerToolbarItemComponents = useMemo(() => getFooterToolbarItems(), [additionalToolbarButtons, isDragMode, getTreeNodeData()]);
|
|
1082
|
+
headerToolbarItemComponents = useMemo(() => getHeaderToolbarItems(), [Repository?.hash, treeSearchValue, isDragMode, getTreeNodeData()]),
|
|
1083
|
+
footerToolbarItemComponents = useMemo(() => getFooterToolbarItems(), [Repository?.hash, additionalToolbarButtons, isDragMode, getTreeNodeData()]);
|
|
1084
1084
|
|
|
1085
1085
|
if (!isReady) {
|
|
1086
1086
|
return null;
|