@onehat/ui 0.3.31 → 0.3.33

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.
Files changed (51) hide show
  1. package/package.json +1 -1
  2. package/src/Components/Buttons/Button.js +20 -0
  3. package/src/Components/Buttons/IconButton.js +68 -51
  4. package/src/Components/Buttons/SquareButton.js +6 -4
  5. package/src/Components/Container/Container.js +4 -1
  6. package/src/Components/Container/ScreenContainer.js +4 -1
  7. package/src/Components/Editor/Editor.js +15 -1
  8. package/src/Components/Form/Field/CKEditor/CKEditor.js +2 -1
  9. package/src/Components/Form/Field/Checkbox/Checkbox.js +2 -1
  10. package/src/Components/Form/Field/Color.js +2 -1
  11. package/src/Components/Form/Field/Combo/Combo.js +7 -4
  12. package/src/Components/Form/Field/Date.js +2 -1
  13. package/src/Components/Form/Field/DisplayField.js +2 -1
  14. package/src/Components/Form/Field/File.js +2 -1
  15. package/src/Components/Form/Field/Input.js +2 -1
  16. package/src/Components/Form/Field/Number.js +2 -1
  17. package/src/Components/Form/Field/RadioGroup/RadioGroup.js +2 -1
  18. package/src/Components/Form/Field/Text.js +2 -1
  19. package/src/Components/Form/Field/TextArea.js +3 -2
  20. package/src/Components/Form/Field/Toggle.js +2 -1
  21. package/src/Components/Form/Form.js +93 -45
  22. package/src/Components/Grid/Grid.js +67 -53
  23. package/src/Components/Grid/GridHeaderRow.js +5 -2
  24. package/src/Components/Grid/GridRow.js +8 -2
  25. package/src/Components/Hoc/withAlert.js +1 -3
  26. package/src/Components/Hoc/withComponent.js +65 -0
  27. package/src/Components/Hoc/withData.js +6 -0
  28. package/src/Components/Hoc/withEditor.js +54 -4
  29. package/src/Components/Hoc/withFilters.js +35 -5
  30. package/src/Components/Hoc/withInlineEditor.js +4 -0
  31. package/src/Components/Hoc/withPdfButton.js +12 -13
  32. package/src/Components/Hoc/withPresetButtons.js +14 -1
  33. package/src/Components/Hoc/withSelection.js +16 -0
  34. package/src/Components/Hoc/withSideEditor.js +7 -1
  35. package/src/Components/Hoc/withWindowedEditor.js +7 -1
  36. package/src/Components/Icons/HighPriority.js +20 -0
  37. package/src/Components/Icons/LowPriority.js +20 -0
  38. package/src/Components/Icons/MedPriority.js +20 -0
  39. package/src/Components/Icons/Pdf.js +14 -0
  40. package/src/Components/Screens/Manager.js +5 -2
  41. package/src/Components/Tab/TabBar.js +5 -2
  42. package/src/Components/Toolbar/Pagination.js +2 -1
  43. package/src/Components/Tree/Tree.js +47 -40
  44. package/src/Components/Viewer/TagViewer.js +3 -1
  45. package/src/Components/Viewer/Viewer.js +57 -14
  46. package/src/Components/index.js +2 -0
  47. package/src/Functions/getIconButtonFromConfig.js +3 -1
  48. package/src/Components/Form/Field/Field.js +0 -14
  49. package/src/Components/Grid/ReactGrid.js +0 -468
  50. package/src/Components/Grid/SenchaGrid.js +0 -421
  51. package/src/Components/Grid/reactgrid.css +0 -6
@@ -1,7 +1,6 @@
1
1
  import { useEffect, useState, isValidElement, } from 'react';
2
2
  import {
3
3
  Box,
4
- Button,
5
4
  Column,
6
5
  Icon,
7
6
  Row,
@@ -24,10 +23,12 @@ import { yupResolver } from '@hookform/resolvers/yup';
24
23
  import useForceUpdate from '../../Hooks/useForceUpdate.js';
25
24
  import UiGlobals from '../../UiGlobals.js';
26
25
  import withAlert from '../Hoc/withAlert.js';
26
+ import withComponent from '../Hoc/withComponent.js';
27
27
  import withEditor from '../Hoc/withEditor.js';
28
28
  import withPdfButton from '../Hoc/withPdfButton.js';
29
29
  import inArray from '../../Functions/inArray.js';
30
30
  import getComponentFromType from '../../Functions/getComponentFromType.js';
31
+ import Button from '../Buttons/Button.js';
31
32
  import IconButton from '../Buttons/IconButton.js';
32
33
  import AngleLeft from '../Icons/AngleLeft.js';
33
34
  import Eye from '../Icons/Eye.js';
@@ -71,16 +72,20 @@ function Form(props) {
71
72
  onViewMode,
72
73
  submitBtnLabel,
73
74
  onSubmit,
74
- additionalEditButtons = [],
75
+ additionalEditButtons,
75
76
 
76
77
  // sizing of outer container
77
78
  h,
78
79
  maxHeight,
80
+ minHeight = 0,
79
81
  w,
80
82
  maxWidth,
81
83
  flex,
82
84
  onLayout, // onLayout handler for main view
83
85
 
86
+ // withComponent
87
+ self,
88
+
84
89
  // withData
85
90
  Repository,
86
91
 
@@ -236,6 +241,8 @@ function Form(props) {
236
241
  onBlur={onBlur}
237
242
  flex={1}
238
243
  {...editorProps}
244
+ parent={self}
245
+ reference={fieldName}
239
246
  // {...defaults}
240
247
  // {...propsToPass}
241
248
  />;
@@ -294,7 +301,7 @@ function Form(props) {
294
301
  type: t,
295
302
  ...p
296
303
  } = propertyDef.viewerType;
297
- type = t
304
+ type = t;
298
305
  } else {
299
306
  type = 'Text';
300
307
  }
@@ -324,6 +331,8 @@ function Form(props) {
324
331
  const value = (record && record[name]) || (startingValues && startingValues[name]) || null;
325
332
  let element = <Element
326
333
  value={value}
334
+ parent={self}
335
+ reference={name}
327
336
  {...propsToPass}
328
337
  />;
329
338
  if (label) {
@@ -400,6 +409,8 @@ function Form(props) {
400
409
  }}
401
410
  onBlur={onBlur}
402
411
  flex={1}
412
+ parent={self}
413
+ reference={name}
403
414
  {...defaults}
404
415
  {...propsToPass}
405
416
  {...editorTypeProps}
@@ -455,6 +466,7 @@ function Form(props) {
455
466
  selectorSelected={selectorSelected || record}
456
467
  flex={1}
457
468
  uniqueRepository={true}
469
+ parent={self}
458
470
  {...propsToPass}
459
471
  />;
460
472
  if (title) {
@@ -468,6 +480,43 @@ function Form(props) {
468
480
  }
469
481
  return components;
470
482
  },
483
+ buildAdditionalButtons = (configs) => {
484
+ const additionalButtons = [];
485
+ _.each(additionalEditButtons, (config) => {
486
+ const {
487
+ key,
488
+ text,
489
+ handler,
490
+ icon,
491
+ isDisabled,
492
+ color = '#fff',
493
+ } = config,
494
+ buttonProps = {};
495
+ if (key) {
496
+ buttonProps.key = key;
497
+ buttonProps.reference = key;
498
+ }
499
+ if (handler) {
500
+ buttonProps.onPress = handler;
501
+ }
502
+ if (icon) {
503
+ buttonProps.leftIcon = <Icon as={icon} color="#fff" size="sm" />;
504
+ }
505
+ if (isDisabled) {
506
+ buttonProps.isDisabled = isDisabled;
507
+ }
508
+
509
+ const button = <Button
510
+ color={color}
511
+ ml={2}
512
+ parent={self}
513
+ reference={key}
514
+ {...buttonProps}
515
+ >{text}</Button>;
516
+ additionalButtons.push(button);
517
+ });
518
+ return additionalButtons;
519
+ },
471
520
  onSubmitError = (errors, e) => {
472
521
  debugger;
473
522
  if (editorType === EDITOR_TYPE__INLINE) {
@@ -569,7 +618,7 @@ function Form(props) {
569
618
  } else {
570
619
  formComponents = buildFromItems();
571
620
  const formAncillaryComponents = buildAncillary();
572
- editor = <ScrollView _web={{ height: 1 }} width="100%" pb={1}>
621
+ editor = <ScrollView _web={{ minHeight, }} width="100%" pb={1}>
573
622
  <Column p={4}>{formComponents}</Column>
574
623
  <Column m={2} pt={4}>{formAncillaryComponents}</Column>
575
624
  </ScrollView>;
@@ -603,11 +652,12 @@ function Form(props) {
603
652
  buttonGroupProps.left = 10; // TODO: I would prefer to have this be centered, but it's a lot more complex than just making it stick to the left
604
653
  footerProps.alignItems = 'flex-start';
605
654
  }
655
+
656
+ const additionalButtons = buildAdditionalButtons(additionalEditButtons);
606
657
 
607
658
  return <Column {...sizeProps} onLayout={onLayout}>
608
659
 
609
660
  <Row px={4} pt={4} alignItems="center" justifyContent="flex-end">
610
- {/* <Text mr={2} fontSize={18}>{editorModeF} Mode</Text> */}
611
661
  {isSingle && editorMode === EDITOR_MODE__EDIT && onBack &&
612
662
  <Button
613
663
  key="backBtn"
@@ -623,9 +673,9 @@ function Form(props) {
623
673
  color="#fff"
624
674
  >To View</Button>}
625
675
  </Row>
626
- {editorMode === EDITOR_MODE__EDIT && !_.isEmpty(additionalEditButtons) &&
676
+ {editorMode === EDITOR_MODE__EDIT && !_.isEmpty(additionalButtons) &&
627
677
  <Row p={4} alignItems="center" justifyContent="flex-end">
628
- {additionalEditButtons}
678
+ {additionalButtons}
629
679
  </Row>}
630
680
 
631
681
  {editor}
@@ -643,43 +693,41 @@ function Form(props) {
643
693
  color="#fff"
644
694
  >Delete</Button>
645
695
  </Row>}
646
- <Button.Group space={2} {...buttonGroupProps}>
647
696
 
648
- {!isEditorViewOnly && <IconButton
649
- key="resetBtn"
650
- onPress={() => {
651
- if (onReset) {
652
- onReset();
653
- }
654
- reset();
655
- }}
656
- icon={<Rotate color="#fff" />}
657
- />}
658
- {!isEditorViewOnly && isSingle && onCancel && <Button
659
- key="cancelBtn"
660
- variant="ghost"
661
- onPress={onCancel}
662
- color="#fff"
663
- >Cancel</Button>}
664
- {!isEditorViewOnly && onSave && <Button
665
- key="saveBtn"
666
- onPress={(e) => handleSubmit(onSaveDecorated, onSubmitError)(e)}
667
- isDisabled={isSaveDisabled}
668
- color="#fff"
669
- >{editorMode === EDITOR_MODE__ADD ? 'Add' : 'Save'}</Button>}
670
- {onSubmit && <Button
671
- key="submitBtn"
672
- onPress={(e) => handleSubmit(onSubmitDecorated, onSubmitError)(e)}
673
- isDisabled={isSubmitDisabled}
674
- color="#fff"
675
- >{submitBtnLabel || 'Submit'}</Button>}
676
-
677
- {isEditorViewOnly && onClose && editorType !== EDITOR_TYPE__SIDE && <Button
678
- key="closeBtn"
679
- onPress={onClose}
680
- color="#fff"
681
- >Close</Button>}
682
- </Button.Group>
697
+ {!isEditorViewOnly && <IconButton
698
+ key="resetBtn"
699
+ onPress={() => {
700
+ if (onReset) {
701
+ onReset();
702
+ }
703
+ reset();
704
+ }}
705
+ icon={<Rotate color="#fff" />}
706
+ />}
707
+ {!isEditorViewOnly && isSingle && onCancel && <Button
708
+ key="cancelBtn"
709
+ variant="ghost"
710
+ onPress={onCancel}
711
+ color="#fff"
712
+ >Cancel</Button>}
713
+ {!isEditorViewOnly && onSave && <Button
714
+ key="saveBtn"
715
+ onPress={(e) => handleSubmit(onSaveDecorated, onSubmitError)(e)}
716
+ isDisabled={isSaveDisabled}
717
+ color="#fff"
718
+ >{editorMode === EDITOR_MODE__ADD ? 'Add' : 'Save'}</Button>}
719
+ {onSubmit && <Button
720
+ key="submitBtn"
721
+ onPress={(e) => handleSubmit(onSubmitDecorated, onSubmitError)(e)}
722
+ isDisabled={isSubmitDisabled}
723
+ color="#fff"
724
+ >{submitBtnLabel || 'Submit'}</Button>}
725
+
726
+ {isEditorViewOnly && onClose && editorType !== EDITOR_TYPE__SIDE && <Button
727
+ key="closeBtn"
728
+ onPress={onClose}
729
+ color="#fff"
730
+ >Close</Button>}
683
731
  </Footer>
684
732
  </Column>;
685
733
  }
@@ -728,6 +776,6 @@ function getNullFieldValues(initialValues, Repository) {
728
776
  return ret;
729
777
  }
730
778
 
731
- export const FormEditor = withAlert(withEditor(withPdfButton(Form)));
779
+ export const FormEditor = withComponent(withAlert(withEditor(withPdfButton(Form))));
732
780
 
733
- export default withAlert(withPdfButton(Form));
781
+ export default withComponent(withAlert(withPdfButton(Form)));
@@ -31,6 +31,7 @@ import UiGlobals from '../../UiGlobals.js';
31
31
  import useForceUpdate from '../../Hooks/useForceUpdate.js';
32
32
  import withContextMenu from '../Hoc/withContextMenu.js';
33
33
  import withAlert from '../Hoc/withAlert.js';
34
+ import withComponent from '../Hoc/withComponent.js';
34
35
  import withData from '../Hoc/withData.js';
35
36
  import withEvents from '../Hoc/withEvents.js';
36
37
  import withSideEditor from '../Hoc/withSideEditor.js';
@@ -96,6 +97,9 @@ function GridComponent(props) {
96
97
  flex,
97
98
  bg,
98
99
 
100
+ // withComponent
101
+ self,
102
+
99
103
  // withEditor
100
104
  onAdd,
101
105
  onEdit,
@@ -224,11 +228,13 @@ function GridComponent(props) {
224
228
  }
225
229
  },
226
230
  getFooterToolbarItems = () => {
227
- const items = _.map(additionalToolbarButtons, getIconButtonFromConfig);
231
+ const items = _.map(additionalToolbarButtons, (config, ix) => getIconButtonFromConfig(config, ix, self));
228
232
 
229
233
  if (canRowsReorder) {
230
234
  items.unshift(<IconButton
231
235
  key="reorderBtn"
236
+ parent={self}
237
+ reference="reorderBtn"
232
238
  onPress={() => setIsDragMode(!isDragMode)}
233
239
  icon={<Icon as={isDragMode ? NoReorderRows : ReorderRows} color={styles.GRID_TOOLBAR_ITEMS_COLOR} />}
234
240
  />);
@@ -866,37 +872,41 @@ function GridComponent(props) {
866
872
 
867
873
  }
868
874
 
869
- export const Grid = withAlert(
870
- withEvents(
871
- withData(
872
- withMultiSelection(
873
- withSelection(
874
- withFilters(
875
- withPresetButtons(
876
- withContextMenu(
877
- GridComponent
878
- ),
879
- true // isGrid
875
+ export const Grid = withComponent(
876
+ withAlert(
877
+ withEvents(
878
+ withData(
879
+ withMultiSelection(
880
+ withSelection(
881
+ withFilters(
882
+ withPresetButtons(
883
+ withContextMenu(
884
+ GridComponent
885
+ ),
886
+ true // isGrid
887
+ )
888
+ )
889
+ )
880
890
  )
881
891
  )
882
892
  )
883
893
  )
884
- )
885
- )
886
- );
887
-
888
- export const SideGridEditor = withAlert(
889
- withEvents(
890
- withData(
891
- withMultiSelection(
892
- withSelection(
893
- withSideEditor(
894
- withFilters(
895
- withPresetButtons(
896
- withContextMenu(
897
- GridComponent
898
- ),
899
- true // isGrid
894
+ );
895
+
896
+ export const SideGridEditor = withComponent(
897
+ withAlert(
898
+ withEvents(
899
+ withData(
900
+ withMultiSelection(
901
+ withSelection(
902
+ withSideEditor(
903
+ withFilters(
904
+ withPresetButtons(
905
+ withContextMenu(
906
+ GridComponent
907
+ ),
908
+ true // isGrid
909
+ )
900
910
  )
901
911
  )
902
912
  )
@@ -906,18 +916,20 @@ export const SideGridEditor = withAlert(
906
916
  )
907
917
  );
908
918
 
909
- export const WindowedGridEditor = withAlert(
910
- withEvents(
911
- withData(
912
- withMultiSelection(
913
- withSelection(
914
- withWindowedEditor(
915
- withFilters(
916
- withPresetButtons(
917
- withContextMenu(
918
- GridComponent
919
- ),
920
- true // isGrid
919
+ export const WindowedGridEditor = withComponent(
920
+ withAlert(
921
+ withEvents(
922
+ withData(
923
+ withMultiSelection(
924
+ withSelection(
925
+ withWindowedEditor(
926
+ withFilters(
927
+ withPresetButtons(
928
+ withContextMenu(
929
+ GridComponent
930
+ ),
931
+ true // isGrid
932
+ )
921
933
  )
922
934
  )
923
935
  )
@@ -927,19 +939,21 @@ export const WindowedGridEditor = withAlert(
927
939
  )
928
940
  );
929
941
 
930
- export const InlineGridEditor = withAlert(
931
- withEvents(
932
- withData(
933
- withMultiSelection(
934
- withSelection(
935
- withInlineEditor(
936
- withFilters(
937
- withPresetButtons(
938
- withContextMenu(
939
- GridComponent
940
- )
941
- ),
942
- true // isGrid
942
+ export const InlineGridEditor = withComponent(
943
+ withAlert(
944
+ withEvents(
945
+ withData(
946
+ withMultiSelection(
947
+ withSelection(
948
+ withInlineEditor(
949
+ withFilters(
950
+ withPresetButtons(
951
+ withContextMenu(
952
+ GridComponent
953
+ )
954
+ ),
955
+ true // isGrid
956
+ )
943
957
  )
944
958
  )
945
959
  )
@@ -327,6 +327,10 @@ export default function GridHeaderRow(props) {
327
327
  propsToPass.minWidth = styles.INLINE_EDITOR_MIN_WIDTH;
328
328
  }
329
329
 
330
+ const textProps = {};
331
+ if (UiGlobals.mode === UI_MODE_WEB) {
332
+ textProps.textOverflow = 'ellipsis';
333
+ }
330
334
  return <Pressable
331
335
  key={ix}
332
336
  onPress={(e) => {
@@ -375,12 +379,10 @@ export default function GridHeaderRow(props) {
375
379
  return proxy;
376
380
  }}
377
381
  />}
378
-
379
382
  <Text
380
383
  key="Text"
381
384
  fontSize={styles.GRID_HEADER_FONTSIZE}
382
385
  overflow="hidden"
383
- textOverflow="ellipsis"
384
386
  flex={1}
385
387
  h="100%"
386
388
  px={styles.GRID_HEADER_CELL_PX}
@@ -389,6 +391,7 @@ export default function GridHeaderRow(props) {
389
391
  justifyContent="center"
390
392
  numberOfLines={1}
391
393
  ellipsizeMode="head"
394
+ {...textProps}
392
395
  >{header}</Text>
393
396
 
394
397
  {isSorter && <Icon key="Icon" as={isSortDirectionAsc ? SortDown : SortUp} textAlign="center" size="sm" mt={3} mr={2} color="trueGray.500" />}
@@ -7,6 +7,9 @@ import {
7
7
  import {
8
8
  VERTICAL,
9
9
  } from '../../Constants/Directions.js';
10
+ import {
11
+ UI_MODE_WEB,
12
+ } from '../../Constants/UiModes.js';
10
13
  import getComponentFromType from '../../Functions/getComponentFromType.js';
11
14
  import UiGlobals from '../../UiGlobals.js';
12
15
  import withDraggable from '../Hoc/withDraggable.js';
@@ -100,11 +103,14 @@ export default function GridRow(props) {
100
103
 
101
104
  if (property?.viewerType?.type) {
102
105
  const Element = getComponentFromType(property?.viewerType?.type);
106
+ const elementProps = {};
107
+ if (UiGlobals.mode === UI_MODE_WEB) {
108
+ elementProps.textOverflow = 'ellipsis';
109
+ }
103
110
  return <Element
104
111
  value={value}
105
112
  key={key}
106
113
  overflow="hidden"
107
- textOverflow="ellipsis"
108
114
  alignSelf="center"
109
115
  style={{
110
116
  userSelect: 'none',
@@ -115,7 +121,7 @@ export default function GridRow(props) {
115
121
  numberOfLines={1}
116
122
  ellipsizeMode="head"
117
123
  {...propsToPass}
118
- {...propsToPass}
124
+ {...elementProps}
119
125
  />;
120
126
  }
121
127
  } else if (item[config.fieldName]) {
@@ -168,9 +168,7 @@ export default function withAlert(WrappedComponent) {
168
168
  </Row>
169
169
  </AlertDialog.Body>
170
170
  <AlertDialog.Footer>
171
- <Button.Group space={2}>
172
- {buttons}
173
- </Button.Group>
171
+ {buttons}
174
172
  </AlertDialog.Footer>
175
173
  </AlertDialog.Content>
176
174
  </AlertDialog>
@@ -0,0 +1,65 @@
1
+ import React, { useState, useRef, useEffect, } from 'react';
2
+ import _ from 'lodash';
3
+
4
+ // This HOC establishes a parent-child relationship between components.
5
+ // Basically anything wrapped in withComponent registers itself with a parent
6
+ // and allows children to register.
7
+
8
+ export default function withComponent(WrappedComponent) {
9
+ return (props) => {
10
+ const {
11
+ // self: parent,
12
+ parent,
13
+ componentMethods,
14
+ ...propsToPass
15
+ } = props,
16
+ { reference } = props,
17
+ childrenRef = useRef({}),
18
+ selfRef = useRef({
19
+ parent,
20
+ reference,
21
+ registerChild: (childRef) => {
22
+ const {
23
+ reference,
24
+ } = childRef;
25
+ if (typeof childrenRef.current[reference] !== 'undefined') {
26
+ throw Error('reference already exists!');
27
+ }
28
+ childrenRef.current[reference] = childRef; // so we can do component addresses like self.children.workOrdersGridEditor
29
+ },
30
+ unregisterChild: (childRef) => {
31
+ const {
32
+ reference,
33
+ } = childRef;
34
+ if (typeof childrenRef.current[reference] !== 'undefined') {
35
+ delete childrenRef.current[reference];
36
+ }
37
+ },
38
+ children: childrenRef.current,
39
+ });
40
+
41
+ useEffect(() => {
42
+ if (componentMethods) {
43
+ _.each(componentMethods, (method, name) => {
44
+ selfRef.current[name] = method;
45
+ });
46
+ }
47
+ if (parent && reference) {
48
+ parent.registerChild(selfRef.current);
49
+ }
50
+ return () => {
51
+ if (parent && reference) {
52
+ parent.unregisterChild(selfRef.current);
53
+ }
54
+ childrenRef.current = {};
55
+ };
56
+ }, []);
57
+
58
+ return <WrappedComponent
59
+ // parent={parent}
60
+ self={selfRef.current}
61
+ {...propsToPass}
62
+ />;
63
+
64
+ };
65
+ }
@@ -28,6 +28,9 @@ export default function withData(WrappedComponent) {
28
28
  displayField = 'value',
29
29
  idIx,
30
30
  displayIx,
31
+
32
+ // withComponent
33
+ self,
31
34
  } = props,
32
35
  propsToPass = _.omit(props, ['model']), // passing 'model' would mess things up if withData gets called twice (e.g. withData(...withData(...)) ), as we'd be trying to recreate Repository twice
33
36
  localIdIx = idIx || (fields && idField ? fields.indexOf(idField) : null),
@@ -64,6 +67,9 @@ export default function withData(WrappedComponent) {
64
67
  if (setRepository) { // pass it on up to higher components
65
68
  setRepository(Repository);
66
69
  }
70
+ if (self) {
71
+ self.repository = Repository;
72
+ }
67
73
  setIsReady(true);
68
74
  })();
69
75