@onehat/ui 0.2.64 → 0.2.66

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.64",
3
+ "version": "0.2.66",
4
4
  "description": "Base UI for OneHat apps",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -14,6 +14,7 @@ export default function Editor(props) {
14
14
  onEditorCancel: onCancel,
15
15
  onEditorSave: onSave,
16
16
  onEditorClose: onClose,
17
+ onEditorDelete: onDelete,
17
18
  editorMode,
18
19
  setEditorMode,
19
20
 
@@ -41,6 +42,7 @@ export default function Editor(props) {
41
42
  Repository={Repository}
42
43
  onEditMode={isViewOnly ? null : onEditMode}
43
44
  onClose={onClose}
45
+ onDelete={onDelete}
44
46
  {...props}
45
47
  />;
46
48
  }
@@ -49,11 +51,12 @@ export default function Editor(props) {
49
51
  // and only show in one column when it's not.
50
52
 
51
53
  return <Form
54
+ {...props}
52
55
  record={selection}
53
56
  onViewMode={onViewMode}
54
57
  onCancel={onCancel}
55
58
  onSave={onSave}
56
59
  onClose={onClose}
57
- {...props}
60
+ onDelete={onDelete}
58
61
  />;
59
62
  }
@@ -0,0 +1,71 @@
1
+ import {
2
+ Button,
3
+ Column,
4
+ Icon,
5
+ ScrollView,
6
+ Row,
7
+ Text,
8
+ } from 'native-base';
9
+ import Label from '../Form/Label.js';
10
+ import Pencil from '../Icons/Pencil.js';
11
+ import Footer from '../Layout/Footer.js';
12
+ import _ from 'lodash';
13
+
14
+ // This is a wrapper for the Viewer subcomponent passed to props,]
15
+ // that adds
16
+
17
+
18
+ export default function Viewer(props) {
19
+ const {
20
+ Viewer, // Subcomponent
21
+ additionalViewButtons = [],
22
+ onEditMode,
23
+ onClose,
24
+ onDelete,
25
+ } = props;
26
+
27
+ return <Column flex={1} w="100%">
28
+ <ScrollView flex={1} w="100%">
29
+ <Column m={2}>
30
+ {onEditMode && <Row mb={4} justifyContent="flex-end">
31
+ <Button
32
+ key="editBtn"
33
+ onPress={onEditMode}
34
+ leftIcon={<Icon as={Pencil} color="#fff" size="sm" />}
35
+ color="#fff"
36
+ >To Edit</Button>
37
+ </Row>}
38
+
39
+ {!_.isEmpty(additionalViewButtons) &&
40
+ <Row p={2} alignItems="center" justifyContent="flex-end">
41
+ {additionalViewButtons}
42
+ </Row>}
43
+
44
+ <Viewer {...props} />
45
+
46
+ </Column>
47
+ </ScrollView>
48
+ <Footer justifyContent="flex-end">
49
+ {onDelete && <Row flex={1} justifyContent="flex-start">
50
+ <Button
51
+ key="deleteBtn"
52
+ onPress={() => {
53
+ confirm('Are you sure you want to delete this record?', onDelete);
54
+ }}
55
+ bg="warning"
56
+ _hover={{
57
+ bg: 'warningHover',
58
+ }}
59
+ color="#fff"
60
+ >Delete</Button>
61
+ </Row>}
62
+ <Button.Group space={2}>
63
+ <Button
64
+ key="closeBtn"
65
+ onPress={onClose}
66
+ color="#fff"
67
+ >Close</Button>
68
+ </Button.Group>
69
+ </Footer>
70
+ </Column>;
71
+ }
@@ -65,7 +65,7 @@ function Form(props) {
65
65
  onBack,
66
66
  onReset,
67
67
  onViewMode,
68
- additionalButtons = [],
68
+ additionalEditButtons = [],
69
69
  ancillaryComponents = [],
70
70
 
71
71
  // sizing of outer container
@@ -83,9 +83,9 @@ function Form(props) {
83
83
  isViewOnly = false,
84
84
  editorMode,
85
85
  onCancel,
86
- onEditorSave,
87
- onSave = onEditorSave,
86
+ onSave,
88
87
  onClose,
88
+ onDelete,
89
89
 
90
90
  // DataMgt
91
91
  selectorId,
@@ -121,7 +121,7 @@ function Form(props) {
121
121
  mode: 'onChange', // onChange | onBlur | onSubmit | onTouched | all
122
122
  // reValidateMode: 'onChange', // onChange | onBlur | onSubmit
123
123
  defaultValues,
124
- // values: defaultValues, // NOTE: This will cause a looping re-render if not used carefully!
124
+ // values: defaultValues,
125
125
  // resetOptions: {
126
126
  // keepDirtyValues: false, // user-interacted input will be retained
127
127
  // keepErrors: false, // input errors will be retained with value update
@@ -478,6 +478,14 @@ function Form(props) {
478
478
  editorModeF = isMultiple ? 'Edit Multiple' : 'Edit';
479
479
  break;
480
480
  }
481
+
482
+ let isSaveDisabled = false;
483
+ if (!_.isEmpty(formState.errors)) {
484
+ isSaveDisabled = true;
485
+ }
486
+ if (_.isEmpty(formState.dirtyFields) && !record?.isRemotePhantom) {
487
+ isSaveDisabled = true;
488
+ }
481
489
 
482
490
  return <Column {...sizeProps} onLayout={onLayout}>
483
491
 
@@ -493,20 +501,40 @@ function Form(props) {
493
501
  {isSingle && editorMode === EDITOR_MODE__EDIT && onViewMode &&
494
502
  <Button
495
503
  key="viewBtn"
496
- onPress={onViewMode}
504
+ onPress={() => {
505
+ if (!_.isEmpty(formState.dirtyFields)) {
506
+ confirm('This record has unsaved changes. Are you sure you want to switch to "View" mode? Changes will be lost.', onViewMode);
507
+ } else {
508
+ onViewMode();
509
+ }
510
+ }}
497
511
  leftIcon={<Icon as={Eye} color="#fff" size="sm" />}
498
512
  color="#fff"
499
513
  >To View</Button>}
500
514
  </Row>
501
- {!_.isEmpty(additionalButtons) &&
515
+ {editorMode === EDITOR_MODE__EDIT && !_.isEmpty(additionalEditButtons) &&
502
516
  <Row p={2} alignItems="center" justifyContent="flex-end">
503
- {additionalButtons}
517
+ {additionalEditButtons}
504
518
  </Row>}
505
519
 
506
520
  {editor}
507
521
 
508
522
  <Footer justifyContent="flex-end" {...footerProps}>
523
+ {onDelete && <Row flex={1} justifyContent="flex-start">
524
+ <Button
525
+ key="deleteBtn"
526
+ onPress={() => {
527
+ confirm('Are you sure you want to delete this record?', onDelete);
528
+ }}
529
+ bg="warning"
530
+ _hover={{
531
+ bg: 'warningHover',
532
+ }}
533
+ color="#fff"
534
+ >Delete</Button>
535
+ </Row>}
509
536
  <Button.Group space={2} {...buttonGroupProps}>
537
+
510
538
  {!isViewOnly && <IconButton
511
539
  key="resetBtn"
512
540
  onPress={() => {
@@ -521,7 +549,7 @@ function Form(props) {
521
549
  key="cancelBtn"
522
550
  variant="ghost"
523
551
  onPress={() => {
524
- if (formState.isDirty) {
552
+ if (!_.isEmpty(formState.dirtyFields)) {
525
553
  confirm('This record has unsaved changes. Are you sure you want to cancel editing? Changes will be lost.', onCancel);
526
554
  } else {
527
555
  onCancel();
@@ -532,7 +560,7 @@ function Form(props) {
532
560
  {!isViewOnly && onSave && <Button
533
561
  key="saveBtn"
534
562
  onPress={(e) => handleSubmit(onSave, onSubmitError)(e)}
535
- isDisabled={!_.isEmpty(formState.errors) || (!isSingle && !record?.isPhantom && !formState.isDirty)}
563
+ isDisabled={isSaveDisabled}
536
564
  color="#fff"
537
565
  >{editorMode === EDITOR_MODE__ADD ? 'Add' : 'Save'}</Button>}
538
566
  {isViewOnly && onClose && <Button
@@ -155,16 +155,16 @@ export default function withAlert(WrappedComponent) {
155
155
  <Panel
156
156
  title={title}
157
157
  isCollapsible={false}
158
- p={5}
158
+ p={0}
159
159
  footer={<Footer justifyContent="flex-end" >
160
160
  <Button.Group space={2}>
161
161
  {buttons}
162
162
  </Button.Group>
163
163
  </Footer>}
164
164
  >
165
- <Row flex={1}>
166
- <Column w={50} p={0} mr={5}>
167
- <Icon as={TriangleExclamation} size={10}/>
165
+ <Row flex={1} p={5}>
166
+ <Column w="40px" p={0} mr={5}>
167
+ <Icon as={TriangleExclamation} size={10} color="#f00" />
168
168
  </Column>
169
169
  <Text>{message}</Text>
170
170
  </Row>
@@ -23,7 +23,7 @@ export default function withEditor(WrappedComponent) {
23
23
  if (selection.length > 1) {
24
24
  return 'records?';
25
25
  }
26
- return 'record?';
26
+ return 'record' + (selection[0].displayValue ? ' "' + selection[0].displayValue + '"' : '') + '?';
27
27
  },
28
28
  record,
29
29
 
@@ -45,10 +45,7 @@ export default function withEditor(WrappedComponent) {
45
45
  [isEditorShown, setIsEditorShown] = useState(false),
46
46
  [isEditorViewOnly, setIsEditorViewOnly] = useState(false),
47
47
  [lastSelection, setLastSelection] = useState(),
48
- addRecord = async () => {
49
- if (!userCanEdit || disableAdd) {
50
- return;
51
- }
48
+ onAdd = async () => {
52
49
  const defaultValues = Repository.getSchema().model.defaultValues;
53
50
  let addValues = _.clone(defaultValues);
54
51
 
@@ -75,31 +72,25 @@ export default function withEditor(WrappedComponent) {
75
72
  setEditorMode(EDITOR_MODE__ADD);
76
73
  setIsEditorShown(true);
77
74
  },
78
- editRecord = () => {
79
- if (!userCanEdit || disableEdit) {
80
- return;
81
- }
75
+ onEdit = () => {
82
76
  setIsEditorViewOnly(false);
83
77
  setEditorMode(EDITOR_MODE__EDIT);
84
78
  setIsEditorShown(true);
85
79
  },
86
- deleteRecord = (e) => {
87
- if (!userCanEdit || disableDelete) {
88
- return;
89
- }
80
+ onDelete = () => {
90
81
  const
91
82
  isSingle = selection.length === 1,
92
83
  isPhantom = selection[0] && selection[0].isPhantom;
93
84
 
94
85
  if (isSingle && isPhantom) {
95
- onDelete();
86
+ deleteRecord();
96
87
  } else {
97
88
  const identifier = getRecordIdentifier(selection);
98
- confirm('Are you sure you want to delete the ' + identifier, onDelete);
89
+ confirm('Are you sure you want to delete the ' + identifier, deleteRecord);
99
90
  }
100
91
  },
101
- onDelete = async () => {
102
- Repository.delete(selection);
92
+ deleteRecord = async () => {
93
+ await Repository.delete(selection);
103
94
  if (!Repository.isAutoSave) {
104
95
  await Repository.save();
105
96
  }
@@ -160,7 +151,7 @@ export default function withEditor(WrappedComponent) {
160
151
  isSingle = selection.length === 1,
161
152
  isPhantom = selection[0] && selection[0].isPhantom;
162
153
  if (isSingle && isPhantom) {
163
- await onDelete();
154
+ await deleteRecord();
164
155
  }
165
156
  setEditorMode(EDITOR_MODE__VIEW);
166
157
  setIsEditorShown(false);
@@ -168,6 +159,11 @@ export default function withEditor(WrappedComponent) {
168
159
  onEditorClose = () => {
169
160
  setIsEditorShown(false);
170
161
  },
162
+ onEditorDelete = async () => {
163
+ await deleteRecord();
164
+ setEditorMode(EDITOR_MODE__VIEW);
165
+ setIsEditorShown(false);
166
+ },
171
167
  calculateEditorMode = () => {
172
168
  let mode = EDITOR_MODE__VIEW;
173
169
  if (userCanEdit) {
@@ -208,13 +204,14 @@ export default function withEditor(WrappedComponent) {
208
204
  editorMode={editorMode}
209
205
  setEditorMode={setEditorMode}
210
206
  setIsEditorShown={setIsEditorShown}
211
- onAdd={addRecord}
212
- onEdit={editRecord}
213
- onDelete={deleteRecord}
207
+ onAdd={(!userCanEdit || disableAdd) ? null : onAdd}
208
+ onEdit={(!userCanEdit || disableEdit) ? null : onEdit}
209
+ onDelete={(!userCanEdit || disableDelete || (editorMode === EDITOR_MODE__ADD && (selection[0]?.isPhantom || currentRecord?.isPhantom))) ? null : onDelete}
214
210
  onView={viewRecord}
215
211
  onDuplicate={duplicateRecord}
216
212
  onEditorSave={onEditorSave}
217
213
  onEditorCancel={onEditorCancel}
214
+ onEditorDelete={(!userCanEdit || disableDelete || (editorMode === EDITOR_MODE__ADD && (selection[0]?.isPhantom || currentRecord?.isPhantom))) ? null : onEditorDelete}
218
215
  onEditorClose={onEditorClose}
219
216
  useEditor={useEditor}
220
217
  userCanEdit={userCanEdit}
@@ -23,6 +23,7 @@ const ThemeOverrides = {
23
23
  vip: '#3a78bc',
24
24
  navBlue: '#3b82f6',
25
25
  warning: '#d92b2b',
26
+ warningHover: '#af1313',
26
27
  orange: '#de9000',
27
28
  greens: {
28
29
  100: '#4CAF50',