@onehat/ui 0.3.27 → 0.3.29

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.27",
3
+ "version": "0.3.29",
4
4
  "description": "Base UI for OneHat apps",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -0,0 +1,26 @@
1
+ import CheckboxButton from '../../../Buttons/CheckboxButton.js';
2
+ import withValue from '../../../Hoc/withValue.js';
3
+ import _ from 'lodash';
4
+
5
+ const
6
+ CheckboxElement = (props) => {
7
+ const {
8
+ value,
9
+ setValue,
10
+ } = props,
11
+ onToggle = () => {
12
+ setValue(!value);
13
+ };
14
+
15
+ return <CheckboxButton
16
+ isChecked={value}
17
+ onPress={onToggle}
18
+ _icon={{
19
+ size: 'lg',
20
+ }}
21
+ />;
22
+
23
+ },
24
+ CheckboxEField = withValue(CheckboxElement);
25
+
26
+ export default CheckboxEField;
@@ -25,6 +25,7 @@ import useForceUpdate from '../../Hooks/useForceUpdate.js';
25
25
  import UiGlobals from '../../UiGlobals.js';
26
26
  import withAlert from '../Hoc/withAlert.js';
27
27
  import withEditor from '../Hoc/withEditor.js';
28
+ import withPdfButton from '../Hoc/withPdfButton.js';
28
29
  import inArray from '../../Functions/inArray.js';
29
30
  import getComponentFromType from '../../Functions/getComponentFromType.js';
30
31
  import IconButton from '../Buttons/IconButton.js';
@@ -67,6 +68,7 @@ function Form(props) {
67
68
  onBack,
68
69
  onReset,
69
70
  onViewMode,
71
+ saveBtnLabel,
70
72
  additionalEditButtons = [],
71
73
 
72
74
  // sizing of outer container
@@ -305,14 +307,14 @@ function Form(props) {
305
307
  if (_.isEmpty(items)) {
306
308
  return null;
307
309
  }
308
- const defaults = item.defaults;
310
+ const itemDefaults = item.defaults;
309
311
  children = _.map(items, (item, ix) => {
310
- return buildNextLayer(item, ix, defaults);
312
+ return buildNextLayer(item, ix, itemDefaults);
311
313
  });
312
- return <Element key={ix} title={title} {...defaults} {...propsToPass} {...editorTypeProps}>{children}</Element>;
314
+ return <Element key={ix} title={title} {...itemDefaults} {...propsToPass} {...editorTypeProps}>{children}</Element>;
313
315
  }
314
316
 
315
- if (!label && Repository && propertyDef.title) {
317
+ if (!label && Repository && propertyDef?.title) {
316
318
  label = propertyDef.title;
317
319
  }
318
320
 
@@ -548,13 +550,13 @@ function Form(props) {
548
550
  borderTopColor="primary.100"
549
551
  borderBottomColor="primary.100"
550
552
  >{formComponents}</ScrollView>;
551
- } else if (editorType === EDITOR_TYPE__PLAIN) {
552
- formComponents = buildFromItems();
553
- const formAncillaryComponents = buildAncillary();
554
- editor = <>
555
- <Column p={4}>{formComponents}</Column>
556
- <Column pt={4}>{formAncillaryComponents}</Column>
557
- </>;
553
+ // } else if (editorType === EDITOR_TYPE__PLAIN) {
554
+ // formComponents = buildFromItems();
555
+ // const formAncillaryComponents = buildAncillary();
556
+ // editor = <>
557
+ // <Column p={4}>{formComponents}</Column>
558
+ // <Column pt={4}>{formAncillaryComponents}</Column>
559
+ // </>;
558
560
  } else {
559
561
  formComponents = buildFromItems();
560
562
  const formAncillaryComponents = buildAncillary();
@@ -653,7 +655,7 @@ function Form(props) {
653
655
  onPress={(e) => handleSubmit(onSaveDecorated, onSubmitError)(e)}
654
656
  isDisabled={isSaveDisabled}
655
657
  color="#fff"
656
- >{editorMode === EDITOR_MODE__ADD ? 'Add' : 'Save'}</Button>}
658
+ >{saveBtnLabel || (editorMode === EDITOR_MODE__ADD ? 'Add' : 'Save')}</Button>}
657
659
  {isEditorViewOnly && onClose && editorType !== EDITOR_TYPE__SIDE && <Button
658
660
  key="closeBtn"
659
661
  onPress={onClose}
@@ -708,6 +710,6 @@ function getNullFieldValues(initialValues, Repository) {
708
710
  return ret;
709
711
  }
710
712
 
711
- export const FormEditor = withAlert(withEditor(Form));
713
+ export const FormEditor = withAlert(withEditor(withPdfButton(Form)));
712
714
 
713
- export default withAlert(Form);
715
+ export default withAlert(withPdfButton(Form));
@@ -11,7 +11,7 @@ export default function Label(props) {
11
11
  return <Row
12
12
  w={w}
13
13
  minWidth="120px"
14
- maxWidth="50%"
14
+ // maxWidth="50%"
15
15
  alignItems="center"
16
16
  pl={2}
17
17
  {...props}
@@ -0,0 +1,180 @@
1
+ import { useState, } from 'react';
2
+ import {
3
+ Column,
4
+ Button,
5
+ Modal,
6
+ Row,
7
+ } from 'native-base';
8
+ import Inflector from 'inflector-js';
9
+ import qs from 'qs';
10
+ import FormPanel from '../Panel/FormPanel.js';
11
+ import inArray from '../../Functions/inArray.js';
12
+ import useAdjustedWindowSize from '../../Hooks/useAdjustedWindowSize.js';
13
+ import { EDITOR_TYPE__PLAIN } from '@onehat/ui/src/Constants/Editor.js';
14
+ import UiGlobals from '../../UiGlobals.js';
15
+ import _ from 'lodash';
16
+
17
+ export default function withPdfButton(WrappedComponent) {
18
+ return (props) => {
19
+
20
+ if (!props.showViewPdfBtn) {
21
+ // bypass everything.
22
+ // If we don't do this, we get an infinite recursion with Form
23
+ // because this HOC wraps Form and uses Form itself.
24
+ return <WrappedComponent {...props} />;
25
+ }
26
+
27
+ const
28
+ {
29
+ additionalEditButtons = [],
30
+ additionalViewButtons = [],
31
+ items = [],
32
+ ancillaryItems = [],
33
+ columnDefaults = {},
34
+
35
+ // withData
36
+ Repository,
37
+ model,
38
+ } = props,
39
+ [isModalShown, setIsModalShown] = useState(false),
40
+ [width, height] = useAdjustedWindowSize(500, 800);
41
+ buildModalItems = () => {
42
+ const modalItems = _.map(_.cloneDeep(items), (item, ix) => buildNextLayer(item, ix, columnDefaults)); // clone, as we don't want to alter the item by reference
43
+
44
+ if (!_.isEmpty(ancillaryItems)) {
45
+ modalItems.push({
46
+ type: 'FieldSet',
47
+ title: 'Ancillary Items',
48
+ defaults: {
49
+ labelWidth: '90%',
50
+ },
51
+ items: _.map(_.cloneDeep(ancillaryItems), (ancillaryItem) => { // clone, as we don't want to alter the item by reference
52
+ let name;
53
+ if (ancillaryItem.model) {
54
+ name = Inflector.underscore(ancillaryItem.model);
55
+ } else {
56
+ name = ancillaryItem.title;
57
+ }
58
+ name = 'ancillary___' + name;
59
+ return {
60
+ title: ancillaryItem.title,
61
+ label: ancillaryItem.title,
62
+ name,
63
+ type: 'Checkbox',
64
+ };
65
+ }),
66
+ });
67
+ }
68
+
69
+ return modalItems;
70
+ },
71
+ buildNextLayer = (item, ix, defaults) => {
72
+ let {
73
+ type,
74
+ name,
75
+ items,
76
+ } = item;
77
+ if (inArray(type, ['Column', 'FieldSet'])) {
78
+ if (!item.defaults) {
79
+ item.defaults = {};
80
+ }
81
+ item.defaults.labelWidth = '90%';
82
+ if (!_.isEmpty(items)) {
83
+ const defaults = item.defaults;
84
+ item.children = _.map(items, (item, ix) => {
85
+ return buildNextLayer(item, ix, defaults);
86
+ });
87
+ }
88
+ return item;
89
+ }
90
+
91
+ if (!item.title) {
92
+ const propertyDef = name && Repository?.getSchema().getPropertyDefinition(name);
93
+ if (propertyDef.title) {
94
+ item.title = propertyDef.title;
95
+ }
96
+ }
97
+ item.type = 'Checkbox';
98
+ return item;
99
+ },
100
+ getStartingValues = (modalItems) => {
101
+ const startingValues = {};
102
+ function walkTree(item) {
103
+ let {
104
+ name,
105
+ items,
106
+ } = item;
107
+ if (!_.isEmpty(items)) {
108
+ _.each(items, (item) => {
109
+ walkTree(item);
110
+ });
111
+ }
112
+ if (name) {
113
+ startingValues[name] = true;
114
+ }
115
+ }
116
+ _.each(modalItems, walkTree);
117
+ return startingValues;
118
+ },
119
+ getPdf = (data) => {
120
+ const
121
+ url = UiGlobals.baseURL + model + '/viewPdf?',
122
+ queryString = qs.stringify(data);
123
+ window.open(url + queryString, '_blank');
124
+ };
125
+
126
+ const button = <Button
127
+ key="viewPdfBtn"
128
+ borderRadius="md"
129
+ colorScheme="primary"
130
+ flexDirection="row"
131
+ justifyContent="center"
132
+ alignItems="center"
133
+ px={4}
134
+ onPress={(e) => setIsModalShown(true)}
135
+ >View PDF</Button>;
136
+ additionalEditButtons.unshift(button);
137
+ if (additionalEditButtons !== additionalViewButtons) { // Ensure they're NOT the same object, otherwise this would be adding it twice!
138
+ additionalViewButtons.unshift(button);
139
+ }
140
+
141
+ let modal = null;
142
+ if (isModalShown) {
143
+ const
144
+ modalItems = buildModalItems(),
145
+ startingValues = getStartingValues(modalItems);
146
+ modal = <Modal
147
+ isOpen={true}
148
+ onClose={() => setIsModalShown(false)}
149
+ >
150
+ <Column bg="#fff" w={width} h={height}>
151
+ <FormPanel
152
+ title="PDF Fields to Show"
153
+ instructions="Please select which fields to show in the PDF."
154
+ editorType={EDITOR_TYPE__PLAIN}
155
+ flex={1}
156
+ Repository={Repository}
157
+ items={modalItems}
158
+ startingValues={startingValues}
159
+ onCancel={(e) => {
160
+ setIsModalShown(false);
161
+ }}
162
+ onSave={(data, e) => {
163
+ getPdf(data);
164
+ setIsModalShown(false);
165
+ }}
166
+ saveBtnLabel="View PDF"
167
+ />
168
+ </Column>
169
+ </Modal>;
170
+ }
171
+ return <>
172
+ <WrappedComponent
173
+ {...props}
174
+ additionalEditButtons={additionalEditButtons}
175
+ additionalViewButtons={additionalViewButtons}
176
+ />;
177
+ {modal}
178
+ </>;
179
+ };
180
+ }
@@ -10,6 +10,7 @@ import {
10
10
  EDITOR_TYPE__SIDE,
11
11
  } from '../../Constants/Editor.js';
12
12
  import UiGlobals from '../../UiGlobals.js';
13
+ import withPdfButton from '../Hoc/withPdfButton.js';
13
14
  import inArray from '../../Functions/inArray.js';
14
15
  import getComponentFromType from '../../Functions/getComponentFromType.js';
15
16
  import Label from '../Form/Label.js';
@@ -17,7 +18,7 @@ import Pencil from '../Icons/Pencil.js';
17
18
  import Footer from '../Layout/Footer.js';
18
19
  import _ from 'lodash';
19
20
 
20
- export default function Viewer(props) {
21
+ function Viewer(props) {
21
22
  const {
22
23
  viewerCanDelete = false,
23
24
  items = [], // Columns, FieldSets, Fields, etc to define the form
@@ -210,3 +211,5 @@ export default function Viewer(props) {
210
211
  </Footer>}
211
212
  </Column>;
212
213
  }
214
+
215
+ export default withPdfButton(Viewer);
@@ -2,7 +2,7 @@ import {
2
2
  Column,
3
3
  } from 'native-base';
4
4
  // import AccordionGridPanel from '../Components/Panel/AccordionGridPanel.js';
5
- import ArrayCheckboxGroup from './Form/Field/CheckboxGroup/ArrayCheckboxGroup.js';
5
+ import ArrayCheckboxGroup from './Form/Field/Checkbox/ArrayCheckboxGroup.js';
6
6
  import ArrayCombo from './Form/Field/Combo/ArrayCombo.js';
7
7
  import ArrayRadioGroup from './Form/Field/RadioGroup/ArrayRadioGroup.js';
8
8
  // import BackButton from '../Components/Buttons/BackButton.js';
@@ -10,7 +10,8 @@ import Blank from './Blank.js';
10
10
  import BooleanCombo from './Form/Field/Combo/BooleanCombo.js';
11
11
  // import CartButtonWithBadge from '../Components/Buttons/CartButtonWithBadge.js';
12
12
  // import CKEditor from './Form/Field/CKEditor/CKEditor.js'; // web only
13
- import CheckboxGroup from './Form/Field/CheckboxGroup/CheckboxGroup.js';
13
+ import Checkbox from './Form/Field/Checkbox/Checkbox.js';
14
+ import CheckboxGroup from './Form/Field/Checkbox/CheckboxGroup.js';
14
15
  import Color from './Form/Field/Color.js';
15
16
  import Combo from './Form/Field/Combo/Combo.js';
16
17
  // import { ComboEditor } from '../Components/Form/Field/Combo/Combo.js';
@@ -58,6 +59,7 @@ const components = {
58
59
  Blank,
59
60
  BooleanCombo,
60
61
  // CartButtonWithBadge,
62
+ Checkbox,
61
63
  CheckboxGroup,
62
64
  // CKEditor,
63
65
  Color,