@onehat/ui 0.2.41 → 0.2.42

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.2.41",
3
+ "version": "0.2.42",
4
4
  "description": "Base UI for OneHat apps",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -5,10 +5,13 @@ import {
5
5
  import UiGlobals from '../../../UiGlobals.js';
6
6
  import withTooltip from '../../Hoc/withTooltip.js';
7
7
  import withValue from '../../Hoc/withValue.js';
8
+ import _ from 'lodash';
8
9
 
9
10
  const
10
11
  TextAreaElement = (props) => {
11
- const styles = UiGlobals.styles;
12
+ const
13
+ styles = UiGlobals.styles,
14
+ value = _.isNil(props.value) ? '' : props.value; // null value may not actually reset this TextArea, so set it explicitly to empty string
12
15
  return <TextArea
13
16
  ref={props.outerRef}
14
17
  onChangeText={props.setValue}
@@ -17,6 +20,7 @@ const
17
20
  fontSize={styles.FORM_TEXTAREA_FONTSIZE}
18
21
  h={styles.FORM_TEXTAREA_HEIGHT}
19
22
  {...props}
23
+ value={value}
20
24
  />;
21
25
  },
22
26
  TextAreaField = withValue(TextAreaElement);
@@ -14,6 +14,9 @@ import {
14
14
  EDITOR_TYPE__SIDE,
15
15
  EDITOR_TYPE__SMART,
16
16
  EDITOR_TYPE__PLAIN,
17
+ EDITOR_MODE__VIEW,
18
+ EDITOR_MODE__ADD,
19
+ EDITOR_MODE__EDIT,
17
20
  } from '../../Constants/Editor.js';
18
21
  import { useForm, Controller } from 'react-hook-form'; // https://react-hook-form.com/api/
19
22
  import * as yup from 'yup'; // https://github.com/jquense/yup#string
@@ -74,6 +77,7 @@ function Form(props) {
74
77
 
75
78
  // withEditor
76
79
  isViewOnly = false,
80
+ editorMode,
77
81
  onCancel,
78
82
  onEditorSave,
79
83
  onSave = onEditorSave,
@@ -456,18 +460,32 @@ function Form(props) {
456
460
  <Row flex={1}>{formComponents}</Row>
457
461
  </ScrollView>;
458
462
  }
463
+
464
+ let editorModeF;
465
+ switch(editorMode) {
466
+ case EDITOR_MODE__VIEW:
467
+ editorModeF = 'View';
468
+ break;
469
+ case EDITOR_MODE__ADD:
470
+ editorModeF = 'Add';
471
+ break;
472
+ case EDITOR_MODE__EDIT:
473
+ editorModeF = isMultiple ? 'Edit Multiple' : 'Edit';
474
+ break;
475
+ }
459
476
 
460
477
  return <Column {...sizeProps} onLayout={onLayout}>
461
478
 
462
- {onBack && <Row p={2} alignItems="center">
463
- <Button
464
- key="backBtn"
465
- onPress={onBack}
466
- leftIcon={<Icon as={AngleLeft} color="#fff" size="sm" />}
467
- color="#fff"
468
- >Back</Button>
469
- <Text ml={2} fontSize={18}>Edit Mode</Text>
470
- </Row>}
479
+ <Row p={2} alignItems="center">
480
+ {isSingle && editorMode === EDITOR_MODE__EDIT && onBack &&
481
+ <Button
482
+ key="backBtn"
483
+ onPress={onBack}
484
+ leftIcon={<Icon as={AngleLeft} color="#fff" size="sm" />}
485
+ color="#fff"
486
+ >Back</Button>}
487
+ <Text ml={2} fontSize={18}>{editorModeF} Mode</Text>
488
+ </Row>
471
489
 
472
490
  {editor}
473
491
 
@@ -475,7 +493,7 @@ function Form(props) {
475
493
  <Button.Group space={2} {...buttonGroupProps}>
476
494
  {!isViewOnly && <IconButton
477
495
  key="resetBtn"
478
- onPress={reset}
496
+ onPress={() => reset()}
479
497
  icon={<Rotate color="#fff" />}
480
498
  />}
481
499
  {!isViewOnly && onCancel && <Button
@@ -495,7 +513,7 @@ function Form(props) {
495
513
  onPress={(e) => handleSubmit(onSave, onSubmitError)(e)}
496
514
  isDisabled={!_.isEmpty(formState.errors) || (!isSingle && !record?.isPhantom && !formState.isDirty)}
497
515
  color="#fff"
498
- >Save</Button>}
516
+ >{editorMode === EDITOR_MODE__ADD ? 'Add' : 'Save'}</Button>}
499
517
  {isViewOnly && onClose && <Button
500
518
  key="closeBtn"
501
519
  onPress={onClose}
@@ -8,6 +8,8 @@ import _ from 'lodash';
8
8
 
9
9
  export default function withEditor(WrappedComponent) {
10
10
  return (props) => {
11
+
12
+ let [editorMode, setEditorMode] = useState(EDITOR_MODE__VIEW); // Can change below, so use 'let'
11
13
  const {
12
14
  useEditor = false,
13
15
  userCanEdit = true,
@@ -38,9 +40,9 @@ export default function withEditor(WrappedComponent) {
38
40
  [currentRecord, setCurrentRecord] = useState(null),
39
41
  [isEditorShown, setIsEditorShown] = useState(false),
40
42
  [isEditorViewOnly, setIsEditorViewOnly] = useState(false),
41
- [editorMode, setEditorMode] = useState(EDITOR_MODE__VIEW),
43
+ [lastSelection, setLastSelection] = useState(),
42
44
  addRecord = async () => {
43
- if (!userCanEdit) {
45
+ if (!userCanEdit || disableAdd) {
44
46
  return;
45
47
  }
46
48
  const
@@ -52,7 +54,7 @@ export default function withEditor(WrappedComponent) {
52
54
  setIsEditorShown(true);
53
55
  },
54
56
  editRecord = () => {
55
- if (!userCanEdit) {
57
+ if (!userCanEdit || disableEdit) {
56
58
  return;
57
59
  }
58
60
  setIsEditorViewOnly(false);
@@ -60,7 +62,7 @@ export default function withEditor(WrappedComponent) {
60
62
  setIsEditorShown(true);
61
63
  },
62
64
  deleteRecord = (e) => {
63
- if (!userCanEdit) {
65
+ if (!userCanEdit || disableDelete) {
64
66
  return;
65
67
  }
66
68
  const
@@ -74,11 +76,9 @@ export default function withEditor(WrappedComponent) {
74
76
  confirm('Are you sure you want to delete the ' + identifier, onDelete);
75
77
  }
76
78
  },
77
- onDelete = () => {
79
+ onDelete = async () => {
78
80
  Repository.delete(selection);
79
- if (!Repository.isAutoSave) {
80
- Repository.save();
81
- }
81
+ await Repository.save();
82
82
  },
83
83
  viewRecord = () => {
84
84
  if (!userCanView) {
@@ -92,7 +92,7 @@ export default function withEditor(WrappedComponent) {
92
92
  setIsEditorShown(true);
93
93
  },
94
94
  duplicateRecord = async () => {
95
- if (!userCanEdit) {
95
+ if (!userCanEdit || disableDuplicate) {
96
96
  return;
97
97
  }
98
98
  if (selection.length !== 1) {
@@ -104,9 +104,10 @@ export default function withEditor(WrappedComponent) {
104
104
  rawValues = _.omit(entity.rawValues, idProperty),
105
105
  duplicate = await Repository.add(rawValues, false, true);
106
106
  setSelection([duplicate]);
107
+ setEditorMode(EDITOR_MODE__EDIT);
107
108
  setIsEditorShown(true);
108
109
  },
109
- onEditorSave = (data, e) => {
110
+ onEditorSave = async (data, e) => {
110
111
  const
111
112
  what = record || selection,
112
113
  isSingle = what.length === 1;
@@ -123,36 +124,53 @@ export default function withEditor(WrappedComponent) {
123
124
 
124
125
 
125
126
  }
126
- if (!Repository.isAutoSave) {
127
- Repository.save();
128
- }
127
+ await Repository.save();
129
128
  setIsEditorShown(false);
130
129
  },
131
- onEditorCancel = () => {
130
+ onEditorCancel = async () => {
132
131
  const
133
132
  isSingle = selection.length === 1,
134
133
  isPhantom = selection[0] && selection[0].isPhantom;
135
134
  if (isSingle && isPhantom) {
136
- onDelete();
135
+ await onDelete();
137
136
  }
137
+ setEditorMode(EDITOR_MODE__VIEW);
138
138
  setIsEditorShown(false);
139
139
  },
140
140
  onEditorClose = () => {
141
141
  setIsEditorShown(false);
142
+ },
143
+ calculateEditorMode = () => {
144
+ let mode = EDITOR_MODE__VIEW;
145
+ if (userCanEdit) {
146
+ if (selection.length > 1) {
147
+ if (!disableEdit) {
148
+ // For multiple entities selected, change it to edit multiple mode
149
+ mode = EDITOR_MODE__EDIT;
150
+ }
151
+ } else if (selection.length === 1 && selection.isPhantom) {
152
+ if (!disableAdd) {
153
+ // When a phantom entity is selected, change it to add mode.
154
+ mode = EDITOR_MODE__ADD;
155
+ }
156
+ }
157
+ }
158
+ return mode;
142
159
  };
143
160
 
144
161
  useEffect(() => {
145
- if (selection.length === 1 && selection.isPhantom && userCanEdit) {
146
- if (editorMode !== EDITOR_MODE__ADD) {
147
- setEditorMode(EDITOR_MODE__ADD);
148
- }
149
- } else {
150
- if (editorMode !== EDITOR_MODE__VIEW) {
151
- setEditorMode(EDITOR_MODE__VIEW);
152
- }
153
- }
162
+ // When selection changes, set the mode appropriately
163
+ const mode = calculateEditorMode();
164
+ setEditorMode(mode);
165
+ setLastSelection(selection);
154
166
  }, [selection]);
155
167
 
168
+ if (lastSelection !== selection) {
169
+ // NOTE: If I don't calculate this on the fly for selection changes,
170
+ // we see a flash of the previous state, since useEffect hasn't yet run.
171
+ editorMode = calculateEditorMode();
172
+ }
173
+
156
174
  return <WrappedComponent
157
175
  {...props}
158
176
  currentRecord={currentRecord}