@onehat/ui 0.2.67 → 0.2.69
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.
|
|
3
|
+
"version": "0.2.69",
|
|
4
4
|
"description": "Base UI for OneHat apps",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"license": "UNLICENSED",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@onehat/data": "^1.18.
|
|
28
|
+
"@onehat/data": "^1.18.7",
|
|
29
29
|
"@hookform/resolvers": "^3.1.1",
|
|
30
30
|
"@k-renwick/colour-mixer": "^1.2.1",
|
|
31
31
|
"js-cookie": "^3.0.5",
|
|
@@ -881,7 +881,8 @@ export const WindowedGridEditor = withAlert(
|
|
|
881
881
|
withPresetButtons(
|
|
882
882
|
withContextMenu(
|
|
883
883
|
Grid
|
|
884
|
-
)
|
|
884
|
+
),
|
|
885
|
+
true // isGrid
|
|
885
886
|
)
|
|
886
887
|
)
|
|
887
888
|
)
|
|
@@ -901,7 +902,8 @@ export const InlineGridEditor = withAlert(
|
|
|
901
902
|
withContextMenu(
|
|
902
903
|
withFilters(
|
|
903
904
|
Grid
|
|
904
|
-
)
|
|
905
|
+
),
|
|
906
|
+
true // isGrid
|
|
905
907
|
)
|
|
906
908
|
)
|
|
907
909
|
)
|
|
@@ -22,7 +22,7 @@ const presetButtons = [
|
|
|
22
22
|
// 'print',
|
|
23
23
|
];
|
|
24
24
|
|
|
25
|
-
export default function withPresetButtons(WrappedComponent) {
|
|
25
|
+
export default function withPresetButtons(WrappedComponent, isGrid = false) {
|
|
26
26
|
return (props) => {
|
|
27
27
|
const {
|
|
28
28
|
// extract and pass
|
|
@@ -37,10 +37,10 @@ export default function withPresetButtons(WrappedComponent) {
|
|
|
37
37
|
disableAdd = false,
|
|
38
38
|
disableEdit = false,
|
|
39
39
|
disableDelete = false,
|
|
40
|
-
disableView =
|
|
41
|
-
disableCopy =
|
|
42
|
-
disableDuplicate =
|
|
43
|
-
disablePrint =
|
|
40
|
+
disableView = !isGrid,
|
|
41
|
+
disableCopy = !isGrid,
|
|
42
|
+
disableDuplicate = !isGrid,
|
|
43
|
+
disablePrint = !isGrid,
|
|
44
44
|
|
|
45
45
|
// withEditor
|
|
46
46
|
userCanEdit = true,
|
|
@@ -60,14 +60,14 @@ import _ from 'lodash';
|
|
|
60
60
|
//////////////////////
|
|
61
61
|
|
|
62
62
|
// I'm thinking if a repository senses that it's a tree, then at initial load
|
|
63
|
-
// it should get the root
|
|
63
|
+
// it should get the root nodes +1 level of children.
|
|
64
64
|
//
|
|
65
65
|
// How would it then subsequently get the proper children?
|
|
66
66
|
// i.e. When a node gets its children, how will it do this
|
|
67
67
|
// while maintaining the nodes that already exist there?
|
|
68
68
|
// We don't want it to *replace* all exisitng nodes!
|
|
69
69
|
//
|
|
70
|
-
// And if the repository does a reload, should it just get
|
|
70
|
+
// And if the repository does a reload, should it just get roots+1 again?
|
|
71
71
|
// Changing filters would potentially change the tree structure.
|
|
72
72
|
// Changing sorting would only change the ordering, not what is expanded/collapsed or visible/invisible.
|
|
73
73
|
|
|
@@ -78,9 +78,6 @@ import _ from 'lodash';
|
|
|
78
78
|
// How does this interface with Repository?
|
|
79
79
|
// Maybe if Repository is not AjaxRepository, everything needs to be present at once!
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
// isRootVisible
|
|
83
|
-
|
|
84
81
|
//////////////////////
|
|
85
82
|
//////////////////////
|
|
86
83
|
|
|
@@ -91,7 +88,7 @@ import _ from 'lodash';
|
|
|
91
88
|
|
|
92
89
|
export function Tree(props) {
|
|
93
90
|
const {
|
|
94
|
-
|
|
91
|
+
areRootsVisible = true,
|
|
95
92
|
getAdditionalParams = () => { // URL params needed to get nodes from server (e.g, { venue_id: 1, getEquipment: true, getRentalEquipment: false, }), in addition to filters.
|
|
96
93
|
return {};
|
|
97
94
|
},
|
|
@@ -111,7 +108,7 @@ export function Tree(props) {
|
|
|
111
108
|
}
|
|
112
109
|
return icon;
|
|
113
110
|
},
|
|
114
|
-
|
|
111
|
+
getNodeProps = (item) => {
|
|
115
112
|
return {};
|
|
116
113
|
},
|
|
117
114
|
noneFoundText,
|
|
@@ -170,6 +167,7 @@ export function Tree(props) {
|
|
|
170
167
|
[searchFormData, setSearchFormData] = useState([]),
|
|
171
168
|
[dragNodeSlot, setDragNodeSlot] = useState(null),
|
|
172
169
|
[dragNodeIx, setDragNodeIx] = useState(),
|
|
170
|
+
[treeSearchValue, setTreeSearchValue] = useState(''),
|
|
173
171
|
onNodeClick = (item, e) => {
|
|
174
172
|
const
|
|
175
173
|
{
|
|
@@ -243,13 +241,12 @@ export function Tree(props) {
|
|
|
243
241
|
getHeaderToolbarItems = () => {
|
|
244
242
|
const
|
|
245
243
|
buttons = [
|
|
246
|
-
|
|
247
244
|
{
|
|
248
245
|
key: 'searchBtn',
|
|
249
246
|
text: 'Search tree',
|
|
250
247
|
handler: onSearchTree,
|
|
251
248
|
icon: MagnifyingGlass,
|
|
252
|
-
isDisabled:
|
|
249
|
+
isDisabled: !treeSearchValue.length,
|
|
253
250
|
},
|
|
254
251
|
{
|
|
255
252
|
key: 'collapseBtn',
|
|
@@ -262,7 +259,7 @@ export function Tree(props) {
|
|
|
262
259
|
if (canNodesReorder) {
|
|
263
260
|
buttons.push({
|
|
264
261
|
key: 'reorderBtn',
|
|
265
|
-
text: '
|
|
262
|
+
text: 'Enter reorder mode',
|
|
266
263
|
handler: () => setIsReorderMode(!isReorderMode),
|
|
267
264
|
icon: isReorderMode ? NoReorderRows : ReorderRows,
|
|
268
265
|
isDisabled: false,
|
|
@@ -274,7 +271,8 @@ export function Tree(props) {
|
|
|
274
271
|
key="searchTree"
|
|
275
272
|
flex={1}
|
|
276
273
|
placeholder="Search all tree nodes"
|
|
277
|
-
|
|
274
|
+
onChangeText={(val) => setTreeSearchValue(val)}
|
|
275
|
+
value={treeSearchValue}
|
|
278
276
|
autoSubmit={false}
|
|
279
277
|
/>);
|
|
280
278
|
|
|
@@ -292,11 +290,12 @@ export function Tree(props) {
|
|
|
292
290
|
mx: 1,
|
|
293
291
|
px: 3,
|
|
294
292
|
},
|
|
295
|
-
|
|
293
|
+
_icon = {
|
|
296
294
|
alignSelf: 'center',
|
|
297
295
|
size: styles.TREE_TOOLBAR_ITEMS_ICON_SIZE,
|
|
298
296
|
h: 20,
|
|
299
297
|
w: 20,
|
|
298
|
+
color: isDisabled ? styles.TREE_TOOLBAR_ITEMS_DISABLED_COLOR : styles.TREE_TOOLBAR_ITEMS_COLOR,
|
|
300
299
|
};
|
|
301
300
|
let {
|
|
302
301
|
key,
|
|
@@ -305,16 +304,11 @@ export function Tree(props) {
|
|
|
305
304
|
icon = null,
|
|
306
305
|
isDisabled = false,
|
|
307
306
|
} = config;
|
|
308
|
-
if (icon) {
|
|
309
|
-
const thisIconProps = {
|
|
310
|
-
color: isDisabled ? styles.TREE_TOOLBAR_ITEMS_DISABLED_COLOR : styles.TREE_TOOLBAR_ITEMS_COLOR,
|
|
311
|
-
};
|
|
312
|
-
icon = React.cloneElement(icon, {...iconProps, ...thisIconProps});
|
|
313
|
-
}
|
|
314
307
|
return <IconButton
|
|
315
308
|
key={key || ix}
|
|
316
309
|
onPress={handler}
|
|
317
310
|
icon={icon}
|
|
311
|
+
_icon={_icon}
|
|
318
312
|
isDisabled={isDisabled}
|
|
319
313
|
tooltip={text}
|
|
320
314
|
{...iconButtonProps}
|
|
@@ -326,15 +320,14 @@ export function Tree(props) {
|
|
|
326
320
|
// renderTreeNode uses this to render the nodes.
|
|
327
321
|
const
|
|
328
322
|
isRoot = treeNode.isRoot,
|
|
329
|
-
isLeaf = !treeNode.hasChildren,
|
|
330
323
|
datum = {
|
|
331
324
|
item: treeNode,
|
|
332
325
|
text: getNodeText(treeNode),
|
|
333
|
-
iconCollapsed:
|
|
334
|
-
iconExpanded:
|
|
335
|
-
iconLeaf:
|
|
326
|
+
iconCollapsed: getNodeIcon(treeNode, false),
|
|
327
|
+
iconExpanded: getNodeIcon(treeNode, true),
|
|
328
|
+
iconLeaf: getNodeIcon(treeNode),
|
|
336
329
|
isExpanded: isRoot, // all non-root treeNodes are not expanded by default
|
|
337
|
-
isVisible: isRoot ?
|
|
330
|
+
isVisible: isRoot ? areRootsVisible : true,
|
|
338
331
|
children: buildTreeNodeData(treeNode.children), // recursively get data for children
|
|
339
332
|
};
|
|
340
333
|
|
|
@@ -348,7 +341,9 @@ export function Tree(props) {
|
|
|
348
341
|
return data;
|
|
349
342
|
},
|
|
350
343
|
renderTreeNode = (datum) => {
|
|
351
|
-
const
|
|
344
|
+
const
|
|
345
|
+
item = datum.item,
|
|
346
|
+
depth = item.depth;
|
|
352
347
|
if (item.isDestroyed) {
|
|
353
348
|
return null;
|
|
354
349
|
}
|
|
@@ -402,7 +397,7 @@ export function Tree(props) {
|
|
|
402
397
|
}
|
|
403
398
|
}}
|
|
404
399
|
flexDirection="row"
|
|
405
|
-
|
|
400
|
+
ml={((areRootsVisible ? depth : depth -1) * 20) + 'px'}
|
|
406
401
|
>
|
|
407
402
|
{({
|
|
408
403
|
isHovered,
|
|
@@ -462,7 +457,7 @@ export function Tree(props) {
|
|
|
462
457
|
return nodes;
|
|
463
458
|
},
|
|
464
459
|
renderAllTreeNodes = () => {
|
|
465
|
-
|
|
460
|
+
let nodes = [];
|
|
466
461
|
_.each(treeNodeData, (datum) => {
|
|
467
462
|
const node = renderTreeNode(datum);
|
|
468
463
|
if (_.isEmpty(node)) {
|
|
@@ -471,6 +466,10 @@ export function Tree(props) {
|
|
|
471
466
|
|
|
472
467
|
nodes.push(node);
|
|
473
468
|
|
|
469
|
+
if (!datum.isExpanded) {
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
|
|
474
473
|
if (_.isEmpty(datum.children)) {
|
|
475
474
|
return;
|
|
476
475
|
}
|
|
@@ -480,7 +479,7 @@ export function Tree(props) {
|
|
|
480
479
|
return;
|
|
481
480
|
}
|
|
482
481
|
|
|
483
|
-
nodes.concat(children);
|
|
482
|
+
nodes = nodes.concat(children);
|
|
484
483
|
});
|
|
485
484
|
return nodes;
|
|
486
485
|
},
|
|
@@ -490,7 +489,7 @@ export function Tree(props) {
|
|
|
490
489
|
datum.isExpanded = !datum.isExpanded;
|
|
491
490
|
forceUpdate();
|
|
492
491
|
|
|
493
|
-
if (datum.item?.repository.isRemote && datum.item.hasChildren && !datum.item.isChildrenLoaded) {
|
|
492
|
+
if (datum.isExpanded && datum.item?.repository.isRemote && datum.item.hasChildren && !datum.item.isChildrenLoaded) {
|
|
494
493
|
loadChildren(datum, 1);
|
|
495
494
|
}
|
|
496
495
|
},
|
|
@@ -514,16 +513,16 @@ export function Tree(props) {
|
|
|
514
513
|
const newTreeNodeData = _.clone(treeNodeData);
|
|
515
514
|
|
|
516
515
|
// Recursive method to collapse all children
|
|
517
|
-
function
|
|
518
|
-
_.each(
|
|
519
|
-
|
|
520
|
-
if (!_.isEmpty(
|
|
521
|
-
|
|
516
|
+
function collapseNodes(nodes) {
|
|
517
|
+
_.each(nodes, (node) => {
|
|
518
|
+
node.isExpanded = false;
|
|
519
|
+
if (!_.isEmpty(node.children)) {
|
|
520
|
+
collapseNodes(node.children);
|
|
522
521
|
}
|
|
523
522
|
});
|
|
524
523
|
}
|
|
525
524
|
|
|
526
|
-
|
|
525
|
+
collapseNodes(newTreeNodeData);
|
|
527
526
|
|
|
528
527
|
if (setNewTreeNodeData) {
|
|
529
528
|
setTreeNodeData(newTreeNodeData);
|
|
@@ -935,7 +934,9 @@ export function Tree(props) {
|
|
|
935
934
|
|
|
936
935
|
let rootNodes;
|
|
937
936
|
if (Repository) {
|
|
938
|
-
|
|
937
|
+
if (!Repository.areRootNodesLoaded) {
|
|
938
|
+
rootNodes = await Repository.getRootNodes(true, 1, getAdditionalParams);
|
|
939
|
+
}
|
|
939
940
|
} else {
|
|
940
941
|
// TODO: Make this work for data array
|
|
941
942
|
|
|
@@ -1004,14 +1005,12 @@ export function Tree(props) {
|
|
|
1004
1005
|
}, [selectorId, selectorSelected]);
|
|
1005
1006
|
|
|
1006
1007
|
const
|
|
1007
|
-
headerToolbarItemComponents = useMemo(() => getHeaderToolbarItems(), []),
|
|
1008
|
-
footerToolbarItemComponents = useMemo(() => getFooterToolbarItems(), [additionalToolbarButtons, isReorderMode]);
|
|
1008
|
+
headerToolbarItemComponents = useMemo(() => getHeaderToolbarItems(), [treeSearchValue, treeNodeData]),
|
|
1009
|
+
footerToolbarItemComponents = useMemo(() => getFooterToolbarItems(), [additionalToolbarButtons, isReorderMode, treeNodeData]);
|
|
1009
1010
|
|
|
1010
1011
|
if (!isReady) {
|
|
1011
1012
|
return null;
|
|
1012
1013
|
}
|
|
1013
|
-
|
|
1014
|
-
// Actual TreeNodes
|
|
1015
1014
|
const treeNodes = renderAllTreeNodes();
|
|
1016
1015
|
|
|
1017
1016
|
// headers & footers
|
|
@@ -1031,21 +1030,21 @@ export function Tree(props) {
|
|
|
1031
1030
|
w="100%"
|
|
1032
1031
|
>
|
|
1033
1032
|
{topToolbar}
|
|
1034
|
-
{headerToolbarItemComponents}
|
|
1033
|
+
{headerToolbarItemComponents?.length && <Row>{headerToolbarItemComponents}</Row>}
|
|
1035
1034
|
|
|
1036
|
-
<Column w="100%" flex={1} borderTopWidth={isLoading ? 2 : 1} borderTopColor={isLoading ? '#f00' : 'trueGray.300'} onClick={() => {
|
|
1035
|
+
<Column w="100%" flex={1} p={2} borderTopWidth={isLoading ? 2 : 1} borderTopColor={isLoading ? '#f00' : 'trueGray.300'} onClick={() => {
|
|
1037
1036
|
if (!isReorderMode) {
|
|
1038
1037
|
deselectAll();
|
|
1039
1038
|
}
|
|
1040
1039
|
}}>
|
|
1041
|
-
{!treeNodes
|
|
1040
|
+
{!treeNodes?.length ? <NoRecordsFound text={noneFoundText} onRefresh={onRefresh} /> :
|
|
1042
1041
|
treeNodes}
|
|
1043
1042
|
</Column>
|
|
1044
1043
|
|
|
1045
1044
|
{treeFooterComponent}
|
|
1046
1045
|
</Column>
|
|
1047
1046
|
|
|
1048
|
-
<Modal
|
|
1047
|
+
{/* <Modal
|
|
1049
1048
|
isOpen={isSearchModalShown}
|
|
1050
1049
|
onClose={() => setIsSearchModalShown(false)}
|
|
1051
1050
|
>
|
|
@@ -1095,7 +1094,7 @@ export function Tree(props) {
|
|
|
1095
1094
|
}}
|
|
1096
1095
|
/>
|
|
1097
1096
|
</Column>
|
|
1098
|
-
</Modal>
|
|
1097
|
+
</Modal> */}
|
|
1099
1098
|
</>;
|
|
1100
1099
|
|
|
1101
1100
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useState, useMemo, } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Box,
|
|
4
|
+
Icon,
|
|
4
5
|
Row,
|
|
5
6
|
Text,
|
|
6
7
|
} from 'native-base';
|
|
@@ -20,20 +21,21 @@ export default function TreeNode(props) {
|
|
|
20
21
|
bg,
|
|
21
22
|
datum,
|
|
22
23
|
onToggle,
|
|
24
|
+
...propsToPass
|
|
23
25
|
} = props,
|
|
24
26
|
styles = UiGlobals.styles,
|
|
25
27
|
item = datum.item,
|
|
26
28
|
isPhantom = item.isPhantom,
|
|
27
29
|
isExpanded = datum.isExpanded,
|
|
28
|
-
hasChildren =
|
|
29
|
-
depth =
|
|
30
|
+
hasChildren = item.hasChildren,
|
|
31
|
+
depth = item.depth,
|
|
30
32
|
text = datum.text,
|
|
31
33
|
iconCollapsed = datum.iconCollapsed,
|
|
32
34
|
iconExpanded = datum.iconExpanded,
|
|
33
35
|
iconLeaf = datum.iconLeaf,
|
|
34
36
|
hash = item?.hash || item;
|
|
35
37
|
|
|
36
|
-
const icon = hasChildren ? (isExpanded ?
|
|
38
|
+
const icon = hasChildren ? (isExpanded ? iconExpanded : iconCollapsed) : iconLeaf;
|
|
37
39
|
|
|
38
40
|
return useMemo(() => {
|
|
39
41
|
|
|
@@ -47,13 +49,9 @@ export default function TreeNode(props) {
|
|
|
47
49
|
>
|
|
48
50
|
{isPhantom && <Box position="absolute" bg="#f00" h={2} w={2} t={0} l={0} />}
|
|
49
51
|
|
|
50
|
-
<IconButton
|
|
51
|
-
icon={icon}
|
|
52
|
-
onPress={onToggle}
|
|
53
|
-
/>
|
|
52
|
+
{hasChildren ? <IconButton icon={icon} onPress={() => onToggle(datum)} /> : <Icon as={icon} />}
|
|
54
53
|
|
|
55
54
|
<Text
|
|
56
|
-
key={key}
|
|
57
55
|
overflow="hidden"
|
|
58
56
|
textOverflow="ellipsis"
|
|
59
57
|
alignSelf="center"
|