@onehat/ui 0.4.64 → 0.4.65

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.4.64",
3
+ "version": "0.4.65",
4
4
  "description": "Base UI for OneHat apps",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -0,0 +1,21 @@
1
+ import {
2
+ VStack,
3
+ } from '@project-components/Gluestack';
4
+ import _ from 'lodash';
5
+
6
+ // This component allows us to stack multiple children in a Container slot (e.g. east)
7
+ // such that the ContainerColumn can be passed props like isResizable,
8
+ // which the Container will translate into classNames for the VStack component.
9
+
10
+ export default function ContainerColumn(props) {
11
+ let className = `
12
+ ContainerColumn
13
+ `;
14
+ if (props.className) {
15
+ className += ` ${props.className}`;
16
+ }
17
+
18
+ return <VStack className={className}>
19
+ {props.children}
20
+ </VStack>;
21
+ }
@@ -767,6 +767,7 @@ export const ComboComponent = forwardRef((props, ref) => {
767
767
  newEntityDisplayProperty={newEntityDisplayProperty}
768
768
  disablePresetButtons={!isEditor}
769
769
  alternateRowBackgrounds={false}
770
+ showSelectHandle={false}
770
771
  onChangeSelection={(selection) => {
771
772
 
772
773
  if (Repository && selection[0]?.isPhantom) {
@@ -46,12 +46,12 @@ export function JsonElement(props) {
46
46
  ${testID}
47
47
  `;
48
48
  if (props.className) {
49
- className += ' ' + props.className;
49
+ className += ' ' + propsToPass.className;
50
50
  }
51
51
  // if (UiGlobals.mode === UI_MODE_WEB) {
52
52
  const src = value ? JSON.parse(value) : {};
53
53
  assembledComponents =
54
- <HStack style={props.style} className={className}>
54
+ <HStack style={propsToPass.style} className={className}>
55
55
  <JsonEditor
56
56
  width="100%"
57
57
  editable={!isViewOnly}
@@ -61,7 +61,7 @@ export function JsonElement(props) {
61
61
  onEdit={(obj) => {
62
62
  setValue(JSON.stringify(obj.updated_src));
63
63
  }}
64
- {...props}
64
+ {...propsToPass}
65
65
  />
66
66
  </HStack>;
67
67
  // }
@@ -132,6 +132,7 @@ function GridComponent(props) {
132
132
  getExpandedRowContent,
133
133
  showHeaders = true,
134
134
  showHovers = true,
135
+ showSelectHandle = true,
135
136
  canColumnsSort = true,
136
137
  canColumnsReorder = true,
137
138
  canColumnsResize = true,
@@ -424,10 +425,10 @@ function GridComponent(props) {
424
425
  } else {
425
426
  let canDoEdit = false,
426
427
  canDoView = false;
427
- if (onEdit && canUser && canUser(EDIT) && (!canRecordBeEdited || canRecordBeEdited(selection))) {
428
+ if (onEdit && canUser && canUser(EDIT) && (!canRecordBeEdited || canRecordBeEdited(selection)) && !props.disableEdit) {
428
429
  canDoEdit = true;
429
430
  } else
430
- if (onView && canUser && canUser(VIEW)) {
431
+ if (onView && canUser && canUser(VIEW) && !props.disableView) {
431
432
  canDoView = true;
432
433
  }
433
434
 
@@ -493,6 +494,7 @@ function GridComponent(props) {
493
494
  isInlineEditorShown={isInlineEditorShown}
494
495
  areRowsDragSource={areRowsDragSource}
495
496
  showColumnsSelector={showColumnsSelector}
497
+ showSelectHandle={showSelectHandle}
496
498
  />;
497
499
  if (showRowExpander) {
498
500
  // align the header row to content rows by adding a spacer that matches the width of the Grid-rowExpander-expandBtn
@@ -570,6 +572,7 @@ function GridComponent(props) {
570
572
  isSelected={isSelected}
571
573
  isHovered={hovered}
572
574
  showHovers={showHovers}
575
+ showSelectHandle={showSelectHandle}
573
576
  index={index}
574
577
  alternatingInterval={alternatingInterval}
575
578
  alternateRowBackgrounds={alternateRowBackgrounds}
@@ -20,6 +20,7 @@ import UiGlobals from '../../UiGlobals.js';
20
20
  import useBlocking from '../../Hooks/useBlocking.js';
21
21
  import testProps from '../../Functions/testProps.js';
22
22
  import AngleRight from '../Icons/AngleRight.js';
23
+ import ArrowPointer from '../Icons/ArrowPointer.js';
23
24
  import HeaderReorderHandle from './HeaderReorderHandle.js';
24
25
  import HeaderResizeHandle from './HeaderResizeHandle.js';
25
26
  import HeaderColumnSelectorHandle from './HeaderColumnSelectorHandle.js';
@@ -46,6 +47,7 @@ export default function GridHeaderRow(props) {
46
47
  isInlineEditorShown,
47
48
  areRowsDragSource,
48
49
  showColumnsSelector,
50
+ showSelectHandle,
49
51
  } = props,
50
52
  styles = UiGlobals.styles,
51
53
  sortFn = Repository && Repository.getSortFn(),
@@ -462,6 +464,14 @@ export default function GridHeaderRow(props) {
462
464
  />}
463
465
  </Pressable>;
464
466
  });
467
+ if (showSelectHandle) {
468
+ headerColumns.unshift(<Box
469
+ key="RowSelectHandle"
470
+ className="Spacer-RowSelectHandle px-2 items-center justify-center flex-none w-[40px]"
471
+ >
472
+ <Icon as={ArrowPointer} className={`ArrowPointer w-[20px] h-[20px] text-[#aaa]`} />
473
+ </Box>);
474
+ }
465
475
  if (areRowsDragSource) {
466
476
  headerColumns.unshift(<Box
467
477
  key="spacer"
@@ -16,6 +16,7 @@ import { withDragSource, withDropTarget } from '../Hoc/withDnd.js';
16
16
  import testProps from '../../Functions/testProps.js';
17
17
  import AngleRight from '../Icons/AngleRight.js';
18
18
  import RowDragHandle from './RowDragHandle.js';
19
+ import RowSelectHandle from './RowSelectHandle.js';
19
20
  import _ from 'lodash';
20
21
 
21
22
  // This was broken out from Grid simply so we can memoize it
@@ -27,6 +28,7 @@ function GridRow(props) {
27
28
  fields,
28
29
  rowProps,
29
30
  hideNavColumn,
31
+ showSelectHandle,
30
32
  isSelected,
31
33
  isHovered,
32
34
  bg,
@@ -265,6 +267,8 @@ function GridRow(props) {
265
267
 
266
268
  let rowContents = <>
267
269
  {(isDragSource || isDraggable) && <RowDragHandle />}
270
+ {showSelectHandle && <RowSelectHandle />}
271
+
268
272
  {isPhantom &&
269
273
  <Box
270
274
  className={`
@@ -5,11 +5,10 @@ import {
5
5
  import styles from '../../Styles/StyleSheets.js';
6
6
  import GripVertical from '../Icons/GripVertical.js';
7
7
 
8
- function RowDragHandle(props) {
9
- return <VStack
10
- style={styles.ewResize}
11
- className="HeaderReorderHandle bg-grey-100 w-[3px] items-center justify-center"
12
- >
8
+ function RowDragHandle(props) { return <VStack
9
+ style={styles.ewResize}
10
+ className="RowDragHandle bg-grey-100 w-[3px] items-center justify-center select-none"
11
+ >
13
12
  <Icon
14
13
  as={GripVertical}
15
14
  size="xs"
@@ -0,0 +1,18 @@
1
+ import {
2
+ Icon,
3
+ VStack,
4
+ } from '@project-components/Gluestack';
5
+ import ArrowPointer from '../Icons/ArrowPointer.js';
6
+
7
+ function RowSelectHandle(props) {
8
+ return <VStack
9
+ className="RowSelectHandle w-[40px] px-2 items-center justify-center select-none cursor-grab"
10
+ >
11
+ <Icon
12
+ as={ArrowPointer}
13
+ size="xs"
14
+ className="w-[20px] h-[20px] text-[#ddd]" />
15
+ </VStack>;
16
+ }
17
+
18
+ export default RowSelectHandle;
@@ -0,0 +1,11 @@
1
+ import { createIcon } from "../Gluestack/icon";
2
+ // Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc.
3
+ import Svg, { Path } from "react-native-svg"
4
+
5
+ const SvgComponent = createIcon({
6
+ Root: Svg,
7
+ viewBox: '0 0 320 512',
8
+ path: <Path d="M0 55.2V426c0 12.2 9.9 22 22 22 6.3 0 12.4-2.7 16.6-7.5l82.6-94.5 58.1 116.3c7.9 15.8 27.1 22.2 42.9 14.3s22.2-27.1 14.3-42.9L179.8 320h118.1c12.2 0 22.1-9.9 22.1-22.1 0-6.3-2.7-12.3-7.4-16.5L38.6 37.9c-4.3-3.8-9.7-5.9-15.4-5.9C10.4 32 0 42.4 0 55.2z" />,
9
+ });
10
+
11
+ export default SvgComponent
@@ -23,6 +23,11 @@ import Panel from '../Panel/Panel.js';
23
23
  import Toolbar from '../Toolbar/Toolbar.js';
24
24
  import _ from 'lodash';
25
25
 
26
+ const
27
+ INITIATE = 'INITIATE',
28
+ PROCESSING = 'PROCESSING',
29
+ RESULTS = 'RESULTS';
30
+
26
31
  // NOTE: This component assumes you have an AppSlice, that has
27
32
  // an 'operationsInProgress' state var and a 'setOperationsInProgress' action.
28
33
 
@@ -37,6 +42,7 @@ function AsyncOperation(props) {
37
42
  Repository,
38
43
  formItems = [],
39
44
  formStartingValues = {},
45
+ _form = {},
40
46
  getProgressUpdates = false,
41
47
  parseProgress, // optional fn, accepts 'response' as arg and returns progress string
42
48
  progressStuckThreshold = null, // e.g. 3, if left blank, doesn't check for stuck state
@@ -49,10 +55,25 @@ function AsyncOperation(props) {
49
55
  alert,
50
56
  } = props,
51
57
  dispatch = useDispatch(),
58
+ isValid = useRef(true),
59
+ setIsValid = (valid) => {
60
+ isValid.current = valid;
61
+ },
62
+ getIsValid = () => {
63
+ return isValid.current;
64
+ },
65
+ mode = useRef(INITIATE),
66
+ setMode = (newMode) => {
67
+ mode.current = newMode;
68
+ },
69
+ getMode = () => {
70
+ return mode.current;
71
+ },
52
72
  initiate = async () => {
53
73
 
54
74
  clearProgress();
55
- setFooter(getFooter('processing'));
75
+ setMode(PROCESSING);
76
+ setFooter(getFooter());
56
77
  setIsInProgress(true);
57
78
 
58
79
  const
@@ -85,17 +106,18 @@ function AsyncOperation(props) {
85
106
  }
86
107
  showResults(results);
87
108
  },
88
- getFooter = (which = 'initiate') => {
109
+ getFooter = (which = getMode()) => {
89
110
  switch(which) {
90
- case 'initiate':
111
+ case INITIATE:
91
112
  return <Toolbar>
92
113
  <Button
93
114
  text="Start"
94
115
  rightIcon={ChevronRight}
95
116
  onPress={() => initiate()}
117
+ isDisabled={!getIsValid()}
96
118
  />
97
119
  </Toolbar>;
98
- case 'processing':
120
+ case PROCESSING:
99
121
  return <Toolbar>
100
122
  <Button
101
123
  text="Please wait"
@@ -103,7 +125,7 @@ function AsyncOperation(props) {
103
125
  variant="link"
104
126
  />
105
127
  </Toolbar>;
106
- case 'results':
128
+ case RESULTS:
107
129
  return <Toolbar>
108
130
  <Button
109
131
  text="Reset"
@@ -152,7 +174,8 @@ function AsyncOperation(props) {
152
174
  },
153
175
  showResults = (results) => {
154
176
  setCurrentTab(1);
155
- setFooter(getFooter('results'));
177
+ setMode(RESULTS);
178
+ setFooter(getFooter());
156
179
  setResults(results);
157
180
  getProgress();
158
181
  },
@@ -206,6 +229,7 @@ function AsyncOperation(props) {
206
229
  },
207
230
  resetToInitialState = () => {
208
231
  setCurrentTab(0);
232
+ setMode(INITIATE);
209
233
  setFooter(getFooter());
210
234
  clearProgress();
211
235
  },
@@ -227,6 +251,10 @@ function AsyncOperation(props) {
227
251
  },
228
252
  });
229
253
  },
254
+ onValidityChange = (isValid) => {
255
+ setIsValid(isValid);
256
+ setFooter(getFooter());
257
+ },
230
258
  unchangedProgressCount = getUnchangedProgressCount();
231
259
 
232
260
  useEffect(() => {
@@ -255,6 +283,8 @@ function AsyncOperation(props) {
255
283
  disableFooter={true}
256
284
  items={formItems}
257
285
  startingValues={formStartingValues}
286
+ onValidityChange={onValidityChange}
287
+ {..._form}
258
288
  />,
259
289
  },
260
290
  {
@@ -3,6 +3,7 @@ import {
3
3
  Box,
4
4
  HStack,
5
5
  Icon,
6
+ Pressable,
6
7
  Text,
7
8
  VStack,
8
9
  VStackNative,
@@ -17,6 +18,7 @@ import {
17
18
  REPORT_TYPES__PDF,
18
19
  } from '../../Constants/ReportTypes.js';
19
20
  import Form from '../Form/Form.js';
21
+ import IconButton from '../Buttons/IconButton.js';
20
22
  import withComponent from '../Hoc/withComponent.js';
21
23
  import withAlert from '../Hoc/withAlert.js';
22
24
  import testProps from '../../Functions/testProps.js';
@@ -37,9 +39,19 @@ function Report(props) {
37
39
  disablePdf = false,
38
40
  disableExcel = false,
39
41
  showReportHeaders = true,
42
+ isQuickReport = false,
43
+ quickReportData = {},
40
44
  alert,
41
45
  } = props,
42
46
  buttons = [],
47
+ onPressQuickReport = () => {
48
+ downloadReport({
49
+ reportId,
50
+ reportType: REPORT_TYPES__EXCEL,
51
+ showReportHeaders,
52
+ data: quickReportData,
53
+ });
54
+ },
43
55
  downloadReport = (args) => {
44
56
  getReport(args);
45
57
  alert('Download started');
@@ -59,6 +71,48 @@ function Report(props) {
59
71
  icon = <Icon as={icon} {...propsIcon} />;
60
72
  }
61
73
 
74
+ if (isQuickReport) {
75
+ let className = `
76
+ Report
77
+ max-w-[100px]
78
+ m-2
79
+ `;
80
+ if (props.className) {
81
+ className += ' ' + props.className;
82
+ }
83
+ return <VStackNative
84
+ {...testProps('QuickReport-' + reportId)}
85
+ className={className}
86
+ >
87
+ <Pressable
88
+ onPress={onPressQuickReport}
89
+ className={`
90
+ flex-1
91
+ items-center
92
+ justify-center
93
+ flex-col
94
+ bg-white
95
+ p-3
96
+ rounded-lg
97
+ border
98
+ border-primary-300
99
+ hover:bg-primary-300
100
+ `}
101
+ >
102
+ {icon}
103
+ <Text
104
+ className={`
105
+ text-black
106
+ text-center
107
+ text-[17px]
108
+ leading-tight
109
+ mt-2
110
+ `}
111
+ >{title}</Text>
112
+ </Pressable>
113
+ </VStackNative>;
114
+ }
115
+
62
116
  if (!disableExcel) {
63
117
  buttons.push({
64
118
  ...testProps('excelBtn'),
@@ -9,6 +9,7 @@ import AngleRight from './Icons/AngleRight.js';
9
9
  import AnglesLeft from './Icons/AnglesLeft.js';
10
10
  import AnglesRight from './Icons/AnglesRight.js';
11
11
  import Asterisk from './Icons/Asterisk.js';
12
+ import ArrowPointer from './Icons/ArrowPointer.js';
12
13
  import ArrowUp from './Icons/ArrowUp.js';
13
14
  import Ban from './Icons/Ban.js';
14
15
  import Bars from './Icons/Bars.js';
@@ -204,6 +205,7 @@ import Color from './Form/Field/Color.js';
204
205
  import Combo from './Form/Field/Combo/Combo.js';
205
206
  // import { ComboEditor } from './Form/Field/Combo/Combo.js';
206
207
  import Container from './Container/Container.js';
208
+ import ContainerColumn from './Container/ContainerColumn.js';
207
209
  import DataMgt from './Screens/DataMgt.js';
208
210
  import Date from './Form/Field/Date.js';
209
211
  import DateRange from './Filter/DateRange.js';
@@ -254,6 +256,7 @@ const components = {
254
256
  AnglesLeft,
255
257
  AnglesRight,
256
258
  Asterisk,
259
+ ArrowPointer,
257
260
  ArrowUp,
258
261
  Ban,
259
262
  Bars,
@@ -449,6 +452,7 @@ const components = {
449
452
  Combo,
450
453
  // ComboEditor,
451
454
  Container,
455
+ ContainerColumn,
452
456
  DataMgt,
453
457
  Date,
454
458
  DateRange,