@onehat/ui 0.3.221 → 0.3.222

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onehat/ui",
3
- "version": "0.3.221",
3
+ "version": "0.3.222",
4
4
  "description": "Base UI for OneHat apps",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -36,12 +36,13 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
36
36
  }
37
37
  return 'record' + (secondarySelection[0].displayValue ? ' "' + secondarySelection[0].displayValue + '"' : '') + '?';
38
38
  },
39
- secondaryRecord,
40
39
  secondaryOnAdd,
41
40
  secondaryOnChange, // any kind of crud change
42
41
  secondaryOnDelete,
43
42
  secondaryOnSave, // this could also be called 'onEdit'
43
+ secondaryOnEditorClose,
44
44
  secondaryNewEntityDisplayValue,
45
+ secondaryNewEntityDisplayProperty, // in case the field to set for newEntityDisplayValue is different from model
45
46
  secondaryDefaultValues,
46
47
 
47
48
  // withComponent
@@ -69,10 +70,16 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
69
70
  [secondaryCurrentRecord, secondarySetCurrentRecord] = useState(null),
70
71
  [secondaryIsAdding, setIsAdding] = useState(false),
71
72
  [secondaryIsSaving, setIsSaving] = useState(false),
72
- [secondaryIsEditorShown, secondarySetIsEditorShown] = useState(false),
73
+ [secondaryIsEditorShown, secondarySetIsEditorShownRaw] = useState(false),
73
74
  [secondaryIsEditorViewOnly, setIsEditorViewOnly] = useState(secondaryCanEditorViewOnly), // current state of whether editor is in view-only mode
74
75
  [secondaryIsIgnoreNextSelectionChange, setSecondaryIsIgnoreNextSelectionChange] = useState(false),
75
76
  [secondaryLastSelection, setLastSelection] = useState(),
77
+ secondarySetIsEditorShown = (bool) => {
78
+ secondarySetIsEditorShownRaw(bool);
79
+ if (!bool && secondaryOnEditorClose) {
80
+ secondaryOnEditorClose();
81
+ }
82
+ },
76
83
  secondarySetSelectionDecorated = (newSelection) => {
77
84
  function doIt() {
78
85
  secondarySetSelection(newSelection);
@@ -107,7 +114,7 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
107
114
  // 1. directlty submit 'values' to use in secondaryDoAdd(), or
108
115
  // 2. Use the repository's default values (defined on each property as 'defaultValue'), or
109
116
  // 3. Individually override the repository's default values with submitted 'defaultValues' (given as a prop to this HOC)
110
- let defaultValuesToUse = Repository.getSchema().getDefaultValues();
117
+ let defaultValuesToUse = SecondaryRepository.getSchema().getDefaultValues();
111
118
  if (secondaryDefaultValues) {
112
119
  _.merge(defaultValuesToUse, secondaryDefaultValues);
113
120
  }
@@ -119,7 +126,7 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
119
126
  }
120
127
 
121
128
  if (getNewEntityDisplayValue()) {
122
- const displayPropertyName = SecondaryRepository.getSchema().model.displayProperty;
129
+ const displayPropertyName = secondaryNewEntityDisplayProperty || SecondaryRepository.getSchema().model.displayProperty;
123
130
  addValues[displayPropertyName] = getNewEntityDisplayValue();
124
131
  }
125
132
 
@@ -170,12 +177,12 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
170
177
  if (getListeners().onAfterAdd) {
171
178
  await getListeners().onAfterAdd(entity);
172
179
  }
173
- if (onAdd) {
180
+ if (secondaryOnAdd) {
174
181
  await secondaryOnAdd(entity);
175
182
  }
176
183
  }
177
184
  setIsEditorViewOnly(false);
178
- setEditorMode(SecondaryRepository.isAutoSave ? EDITOR_MODE__EDIT : EDITOR_MODE__ADD);
185
+ secondarySetEditorMode(SecondaryRepository.isAutoSave ? EDITOR_MODE__EDIT : EDITOR_MODE__ADD);
179
186
  secondarySetIsEditorShown(true);
180
187
  },
181
188
  secondaryDoEdit = async () => {
@@ -270,14 +277,14 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
270
277
  secondaryOnDelete(secondarySelection);
271
278
  }
272
279
  },
273
- secondaryDoView = async () => {
280
+ secondaryDoView = async (allowEditing = false) => {
274
281
  if (!secondaryUserCanView) {
275
282
  return;
276
283
  }
277
284
  if (secondarySelection.length !== 1) {
278
285
  return;
279
286
  }
280
- setIsEditorViewOnly(true);
287
+ setIsEditorViewOnly(!allowEditing);
281
288
  secondarySetEditorMode(EDITOR_MODE__VIEW);
282
289
  secondarySetIsEditorShown(true);
283
290
 
@@ -316,12 +323,17 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
316
323
  },
317
324
  secondaryDoEditorSave = async (data, e) => {
318
325
  // NOTE: The Form submits onSave for both adds (when not isAutoSsave) and edits.
319
- const
320
- what = secondaryRecord || secondarySelection,
321
- isSingle = what.length === 1;
326
+ const isSingle = secondarySelection.length === 1;
327
+ let useStaged = false;
322
328
  if (isSingle) {
323
329
  // just update this one entity
324
- what[0].setValues(data);
330
+ secondarySelection[0].setValues(data);
331
+
332
+ // If this is a remote phantom, and nothing is dirty, stage it so it actually gets saved to server and solidified
333
+ if (secondarySelection[0].isRemotePhantom && !secondarySelection[0].isDirty) {
334
+ secondarySelection[0].markStaged();
335
+ useStaged = true;
336
+ }
325
337
 
326
338
  } else if (secondarySelection.length > 1) {
327
339
  // Edit multiple entities
@@ -330,7 +342,7 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
330
342
  const propertyNames = Object.getOwnPropertyNames(data);
331
343
  _.each(propertyNames, (propertyName) => {
332
344
  if (!_.isNil(data[propertyName])) {
333
- _.each(what, (rec) => {
345
+ _.each(secondarySelection, (rec) => {
334
346
  rec[propertyName] = data[propertyName]
335
347
  });
336
348
  }
@@ -338,7 +350,7 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
338
350
  }
339
351
 
340
352
  if (getListeners().onBeforeSave) {
341
- const listenerResult = await getListeners().onBeforeSave(what);
353
+ const listenerResult = await getListeners().onBeforeSave(secondarySelection);
342
354
  if (listenerResult === false) {
343
355
  return;
344
356
  }
@@ -347,36 +359,36 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
347
359
  setIsSaving(true);
348
360
  let success;
349
361
  try {
350
- await SecondaryRepository.save();
362
+ await SecondaryRepository.save(null, useStaged);
351
363
  success = true;
352
364
  } catch (e) {
353
- alert(e.context);
365
+ // alert(e.context);
354
366
  success = false;
355
367
  }
356
368
  setIsSaving(false);
357
369
 
358
370
  if (success) {
359
371
  if (secondaryOnChange) {
360
- secondaryOnChange(what);
372
+ secondaryOnChange(secondarySelection);
361
373
  }
362
- if (editorMode === EDITOR_MODE__ADD) {
363
- if (onAdd) {
364
- await onAdd(what);
374
+ if (secondaryEditorMode === EDITOR_MODE__ADD) {
375
+ if (secondaryOnAdd) {
376
+ await secondaryOnAdd(secondarySelection);
365
377
  }
366
378
  if (getListeners().onAfterAdd) {
367
- await getListeners().onAfterAdd(what);
379
+ await getListeners().onAfterAdd(secondarySelection);
368
380
  }
369
381
  setIsAdding(false);
370
- setEditorMode(EDITOR_MODE__EDIT);
371
- } else if (editorMode === EDITOR_MODE__EDIT) {
382
+ secondarySetEditorMode(EDITOR_MODE__EDIT);
383
+ } else if (secondaryEditorMode === EDITOR_MODE__EDIT) {
372
384
  if (getListeners().onAfterEdit) {
373
- await getListeners().onAfterEdit(what);
385
+ await getListeners().onAfterEdit(secondarySelection);
374
386
  }
375
387
  if (secondaryOnSave) {
376
- secondaryOnSave(what);
388
+ secondaryOnSave(secondarySelection);
377
389
  }
378
390
  }
379
- // secondarySetIsEditorShown(false);
391
+ // setIsEditorShown(false);
380
392
  }
381
393
 
382
394
  return success;
@@ -412,20 +424,26 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
412
424
  secondarySetIsEditorShown(false);
413
425
  });
414
426
  },
415
- calculateEditorMode = () => {
416
- let mode = secondaryEditorMode;
417
- if (!secondaryCanEditorViewOnly && secondaryUserCanEdit) {
418
- if (secondarySelection.length > 1) {
419
- if (!secondaryDisableEdit) {
420
- // For multiple entities selected, change it to edit multiple mode
421
- mode = EDITOR_MODE__EDIT;
422
- }
423
- } else if (secondarySelection.length === 1 && !secondarySelection[0].isDestroyed && secondarySelection[0].isPhantom) {
424
- if (!secondaryDisableAdd) {
425
- // When a phantom entity is selected, change it to add mode.
426
- mode = EDITOR_MODE__ADD;
427
+ calculateEditorMode = (secondaryIsIgnoreNextSelectionChange = false) => {
428
+ // calculateEditorMode gets called only on selection changes
429
+ let mode;
430
+ if (secondaryIsIgnoreNextSelectionChange) {
431
+ mode = secondaryEditorMode;
432
+ if (!secondaryCanEditorViewOnly && secondaryUserCanEdit) {
433
+ if (secondarySelection.length > 1) {
434
+ if (!secondaryDisableEdit) {
435
+ // For multiple entities selected, change it to edit multiple mode
436
+ mode = EDITOR_MODE__EDIT;
437
+ }
438
+ } else if (secondarySelection.length === 1 && !secondarySelection[0].isDestroyed && secondarySelection[0].isPhantom) {
439
+ if (!secondaryDisableAdd) {
440
+ // When a phantom entity is selected, change it to add mode.
441
+ mode = EDITOR_MODE__ADD;
442
+ }
427
443
  }
428
444
  }
445
+ } else {
446
+ mode = secondarySelection.length > 1 ? EDITOR_MODE__EDIT : EDITOR_MODE__VIEW;
429
447
  }
430
448
  return mode;
431
449
  },
@@ -445,16 +463,22 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
445
463
  };
446
464
 
447
465
  useEffect(() => {
448
- // When secondarySelection changes, set the mode appropriately
449
- let mode;
450
- if (secondaryIsIgnoreNextSelectionChange) {
451
- // on secondarySelection change from onAdd/onDuplicate/etc, calculate whether to put Editor in "add" or "edit" mode
452
- mode = calculateEditorMode();
453
- } else {
454
- // Most of the time, if secondarySelection changed, put the Editor in "view" mode
455
- mode = EDITOR_MODE__VIEW;
466
+ if (!SecondaryRepository) {
467
+ return () => {};
468
+ }
469
+
470
+ function handleError(msg) {
471
+ alert(msg);
456
472
  }
457
- secondarySetEditorMode(mode);
473
+
474
+ SecondaryRepository.on('error', handleError);
475
+ return () => {
476
+ SecondaryRepository.off('error', handleError);
477
+ };
478
+ }, []);
479
+
480
+ useEffect(() => {
481
+ secondarySetEditorMode(calculateEditorMode(secondaryIsIgnoreNextSelectionChange));
458
482
 
459
483
  setSecondaryIsIgnoreNextSelectionChange(false);
460
484
  setLastSelection(secondarySelection);
@@ -467,18 +491,15 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
467
491
  self.secondarnMoveChildren = secondaryDoMoveChildren;
468
492
  self.secondaryDeleteChildren = secondaryDoDeleteChildren;
469
493
  self.secondaryDuplicate = secondaryDoDuplicate;
494
+ self.secondarySetIsEditorShown = secondarySetIsEditorShown;
470
495
  }
471
496
  secondaryNewEntityDisplayValueRef.current = secondaryNewEntityDisplayValue;
472
497
 
473
498
  if (secondaryLastSelection !== secondarySelection) {
474
- // NOTE: If I don't calculate this on the fly for secondarySelection changes,
499
+ // NOTE: If I don't calculate this on the fly for selection changes,
475
500
  // we see a flash of the previous state, since useEffect hasn't yet run.
476
501
  // (basically redo what's in the useEffect, above)
477
- if (secondaryIsIgnoreNextSelectionChange) {
478
- secondaryEditorMode = calculateEditorMode();
479
- } else {
480
- secondaryEditorMode = EDITOR_MODE__VIEW;
481
- }
502
+ secondaryEditorMode = calculateEditorMode(secondaryIsIgnoreNextSelectionChange);
482
503
  }
483
504
 
484
505
  return <WrappedComponent