@onehat/ui 0.2.70 → 0.2.71
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 +1 -1
- package/src/Components/Grid/Grid.js +24 -2
- package/src/Components/Hoc/withEditor.js +2 -1
- package/src/Components/Hoc/withPresetButtons.js +4 -3
- package/src/Components/Hoc/withSideEditor.js +4 -0
- package/src/Components/Hoc/withWindowedEditor.js +4 -0
- package/src/Components/Panel/InlineGridEditorPanel.js +39 -0
- package/src/Components/Panel/SideGridEditorPanel.js +39 -0
- package/src/Components/Panel/SideTreeEditorPanel.js +39 -0
- package/src/Components/Panel/WindowedGridEditorPanel.js +39 -0
- package/src/Components/Panel/WindowedTreeEditorPanel.js +39 -0
- package/src/Components/Tree/Tree.js +125 -83
package/package.json
CHANGED
|
@@ -851,6 +851,27 @@ export function Grid(props) {
|
|
|
851
851
|
|
|
852
852
|
}
|
|
853
853
|
|
|
854
|
+
export const Grid = withAlert(
|
|
855
|
+
withEvents(
|
|
856
|
+
withData(
|
|
857
|
+
withMultiSelection(
|
|
858
|
+
withSelection(
|
|
859
|
+
// withSideEditor(
|
|
860
|
+
withFilters(
|
|
861
|
+
withPresetButtons(
|
|
862
|
+
withContextMenu(
|
|
863
|
+
Grid
|
|
864
|
+
),
|
|
865
|
+
true // isGrid
|
|
866
|
+
)
|
|
867
|
+
)
|
|
868
|
+
// )
|
|
869
|
+
)
|
|
870
|
+
)
|
|
871
|
+
)
|
|
872
|
+
)
|
|
873
|
+
);
|
|
874
|
+
|
|
854
875
|
export const SideGridEditor = withAlert(
|
|
855
876
|
withEvents(
|
|
856
877
|
withData(
|
|
@@ -861,7 +882,8 @@ export const SideGridEditor = withAlert(
|
|
|
861
882
|
withPresetButtons(
|
|
862
883
|
withContextMenu(
|
|
863
884
|
Grid
|
|
864
|
-
)
|
|
885
|
+
),
|
|
886
|
+
true // isGrid
|
|
865
887
|
)
|
|
866
888
|
)
|
|
867
889
|
)
|
|
@@ -913,4 +935,4 @@ export const InlineGridEditor = withAlert(
|
|
|
913
935
|
)
|
|
914
936
|
);
|
|
915
937
|
|
|
916
|
-
export default
|
|
938
|
+
export default Grid;
|
|
@@ -11,7 +11,7 @@ export default function withEditor(WrappedComponent) {
|
|
|
11
11
|
|
|
12
12
|
let [editorMode, setEditorMode] = useState(EDITOR_MODE__VIEW); // Can change below, so use 'let'
|
|
13
13
|
const {
|
|
14
|
-
useEditor =
|
|
14
|
+
useEditor = true,
|
|
15
15
|
userCanEdit = true,
|
|
16
16
|
userCanView = true,
|
|
17
17
|
disableAdd = false,
|
|
@@ -213,6 +213,7 @@ export default function withEditor(WrappedComponent) {
|
|
|
213
213
|
onEditorCancel={onEditorCancel}
|
|
214
214
|
onEditorDelete={(!userCanEdit || disableDelete || (editorMode === EDITOR_MODE__ADD && (selection[0]?.isPhantom || currentRecord?.isPhantom))) ? null : onEditorDelete}
|
|
215
215
|
onEditorClose={onEditorClose}
|
|
216
|
+
isEditor={true}
|
|
216
217
|
useEditor={useEditor}
|
|
217
218
|
userCanEdit={userCanEdit}
|
|
218
219
|
userCanView={userCanView}
|
|
@@ -33,10 +33,11 @@ export default function withPresetButtons(WrappedComponent, isGrid = false) {
|
|
|
33
33
|
} = props,
|
|
34
34
|
{
|
|
35
35
|
// for local use
|
|
36
|
+
isEditor = false,
|
|
36
37
|
useEditor = true,
|
|
37
|
-
disableAdd =
|
|
38
|
-
disableEdit =
|
|
39
|
-
disableDelete =
|
|
38
|
+
disableAdd = !isEditor,
|
|
39
|
+
disableEdit = !isEditor,
|
|
40
|
+
disableDelete = !isEditor,
|
|
40
41
|
disableView = !isGrid,
|
|
41
42
|
disableCopy = !isGrid,
|
|
42
43
|
disableDuplicate = !isGrid,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useEffect, useState, } from 'react';
|
|
2
|
+
import Panel from './Panel.js';
|
|
3
|
+
import { InlineGridEditor, } from '../Grid/Grid.js';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
|
|
6
|
+
export function GridPanel(props) {
|
|
7
|
+
const {
|
|
8
|
+
disableTitleChange = false,
|
|
9
|
+
selectorSelected,
|
|
10
|
+
} = props,
|
|
11
|
+
originalTitle = props.title,
|
|
12
|
+
[isReady, setIsReady] = useState(disableTitleChange),
|
|
13
|
+
[title, setTitle] = useState(originalTitle);
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (!disableTitleChange && originalTitle) {
|
|
17
|
+
let newTitle = originalTitle;
|
|
18
|
+
if (selectorSelected?.[0]?.displayValue) {
|
|
19
|
+
newTitle = originalTitle + ' for ' + selectorSelected[0].displayValue;
|
|
20
|
+
}
|
|
21
|
+
if (newTitle !== title) {
|
|
22
|
+
setTitle(newTitle);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (!isReady) {
|
|
26
|
+
setIsReady(true);
|
|
27
|
+
}
|
|
28
|
+
}, [selectorSelected, disableTitleChange, originalTitle]);
|
|
29
|
+
|
|
30
|
+
if (!isReady) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return <Panel {...props} title={title}>
|
|
35
|
+
<InlineGridEditor {...props} />
|
|
36
|
+
</Panel>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default GridPanel;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useEffect, useState, } from 'react';
|
|
2
|
+
import Panel from './Panel.js';
|
|
3
|
+
import { SideGridEditor, } from '../Grid/Grid.js';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
|
|
6
|
+
export function GridPanel(props) {
|
|
7
|
+
const {
|
|
8
|
+
disableTitleChange = false,
|
|
9
|
+
selectorSelected,
|
|
10
|
+
} = props,
|
|
11
|
+
originalTitle = props.title,
|
|
12
|
+
[isReady, setIsReady] = useState(disableTitleChange),
|
|
13
|
+
[title, setTitle] = useState(originalTitle);
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (!disableTitleChange && originalTitle) {
|
|
17
|
+
let newTitle = originalTitle;
|
|
18
|
+
if (selectorSelected?.[0]?.displayValue) {
|
|
19
|
+
newTitle = originalTitle + ' for ' + selectorSelected[0].displayValue;
|
|
20
|
+
}
|
|
21
|
+
if (newTitle !== title) {
|
|
22
|
+
setTitle(newTitle);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (!isReady) {
|
|
26
|
+
setIsReady(true);
|
|
27
|
+
}
|
|
28
|
+
}, [selectorSelected, disableTitleChange, originalTitle]);
|
|
29
|
+
|
|
30
|
+
if (!isReady) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return <Panel {...props} title={title}>
|
|
35
|
+
<SideGridEditor {...props} />
|
|
36
|
+
</Panel>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default GridPanel;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useEffect, useState, } from 'react';
|
|
2
|
+
import Panel from './Panel.js';
|
|
3
|
+
import { SideTreeEditor, } from '../Tree/Tree.js';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
|
|
6
|
+
export function TreePanel(props) {
|
|
7
|
+
const {
|
|
8
|
+
disableTitleChange = false,
|
|
9
|
+
selectorSelected,
|
|
10
|
+
} = props,
|
|
11
|
+
originalTitle = props.title,
|
|
12
|
+
[isReady, setIsReady] = useState(disableTitleChange),
|
|
13
|
+
[title, setTitle] = useState(originalTitle);
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (!disableTitleChange && originalTitle) {
|
|
17
|
+
let newTitle = originalTitle;
|
|
18
|
+
if (selectorSelected?.[0]?.displayValue) {
|
|
19
|
+
newTitle = originalTitle + ' for ' + selectorSelected[0].displayValue;
|
|
20
|
+
}
|
|
21
|
+
if (newTitle !== title) {
|
|
22
|
+
setTitle(newTitle);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (!isReady) {
|
|
26
|
+
setIsReady(true);
|
|
27
|
+
}
|
|
28
|
+
}, [selectorSelected, disableTitleChange, originalTitle]);
|
|
29
|
+
|
|
30
|
+
if (!isReady) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return <Panel {...props} title={title}>
|
|
35
|
+
<SideTreeEditor {...props} />
|
|
36
|
+
</Panel>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default TreePanel;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useEffect, useState, } from 'react';
|
|
2
|
+
import Panel from './Panel.js';
|
|
3
|
+
import { WindowedGridEditor, } from '../Grid/Grid.js';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
|
|
6
|
+
export function GridPanel(props) {
|
|
7
|
+
const {
|
|
8
|
+
disableTitleChange = false,
|
|
9
|
+
selectorSelected,
|
|
10
|
+
} = props,
|
|
11
|
+
originalTitle = props.title,
|
|
12
|
+
[isReady, setIsReady] = useState(disableTitleChange),
|
|
13
|
+
[title, setTitle] = useState(originalTitle);
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (!disableTitleChange && originalTitle) {
|
|
17
|
+
let newTitle = originalTitle;
|
|
18
|
+
if (selectorSelected?.[0]?.displayValue) {
|
|
19
|
+
newTitle = originalTitle + ' for ' + selectorSelected[0].displayValue;
|
|
20
|
+
}
|
|
21
|
+
if (newTitle !== title) {
|
|
22
|
+
setTitle(newTitle);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (!isReady) {
|
|
26
|
+
setIsReady(true);
|
|
27
|
+
}
|
|
28
|
+
}, [selectorSelected, disableTitleChange, originalTitle]);
|
|
29
|
+
|
|
30
|
+
if (!isReady) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return <Panel {...props} title={title}>
|
|
35
|
+
<WindowedGridEditor {...props} />
|
|
36
|
+
</Panel>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default GridPanel;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useEffect, useState, } from 'react';
|
|
2
|
+
import Panel from './Panel.js';
|
|
3
|
+
import { WindowedTreeEditor, } from '../Tree/Tree.js';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
|
|
6
|
+
export function TreePanel(props) {
|
|
7
|
+
const {
|
|
8
|
+
disableTitleChange = false,
|
|
9
|
+
selectorSelected,
|
|
10
|
+
} = props,
|
|
11
|
+
originalTitle = props.title,
|
|
12
|
+
[isReady, setIsReady] = useState(disableTitleChange),
|
|
13
|
+
[title, setTitle] = useState(originalTitle);
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (!disableTitleChange && originalTitle) {
|
|
17
|
+
let newTitle = originalTitle;
|
|
18
|
+
if (selectorSelected?.[0]?.displayValue) {
|
|
19
|
+
newTitle = originalTitle + ' for ' + selectorSelected[0].displayValue;
|
|
20
|
+
}
|
|
21
|
+
if (newTitle !== title) {
|
|
22
|
+
setTitle(newTitle);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (!isReady) {
|
|
26
|
+
setIsReady(true);
|
|
27
|
+
}
|
|
28
|
+
}, [selectorSelected, disableTitleChange, originalTitle]);
|
|
29
|
+
|
|
30
|
+
if (!isReady) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return <Panel {...props} title={title}>
|
|
35
|
+
<WindowedTreeEditor {...props} />
|
|
36
|
+
</Panel>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default TreePanel;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useState, useEffect, useRef, useMemo, } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Column,
|
|
4
4
|
FlatList,
|
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
DROP_POSITION_BEFORE,
|
|
20
20
|
DROP_POSITION_AFTER,
|
|
21
21
|
} from '../../Constants/Tree.js';
|
|
22
|
-
import sleep from '@onehat/ui/src/Functions/sleep.js';
|
|
23
22
|
import * as colourMixer from '@k-renwick/colour-mixer'
|
|
24
23
|
import UiGlobals from '../../UiGlobals.js';
|
|
25
24
|
import useForceUpdate from '../../Hooks/useForceUpdate.js';
|
|
@@ -69,7 +68,10 @@ export function Tree(props) {
|
|
|
69
68
|
areRootsVisible = true,
|
|
70
69
|
extraParams = {}, // Additional params to send with each request ( e.g. { order: 'Categories.name ASC' })
|
|
71
70
|
getNodeText = (item) => { // extracts model/data and decides what the row text should be
|
|
72
|
-
|
|
71
|
+
if (Repository) {
|
|
72
|
+
return item.displayValue;
|
|
73
|
+
}
|
|
74
|
+
return item[displayIx];
|
|
73
75
|
},
|
|
74
76
|
getNodeIcon = (item, isExpanded) => { // decides what icon to show for this node
|
|
75
77
|
// TODO: Allow for dynamic props on the icon (e.g. special color for some icons)
|
|
@@ -98,6 +100,8 @@ export function Tree(props) {
|
|
|
98
100
|
bottomToolbar = null,
|
|
99
101
|
topToolbar = null,
|
|
100
102
|
additionalToolbarButtons = [],
|
|
103
|
+
reload = null, // Whenever this value changes after initial render, the tree will reload from scratch
|
|
104
|
+
parentIdIx,
|
|
101
105
|
|
|
102
106
|
// withEditor
|
|
103
107
|
onAdd,
|
|
@@ -141,6 +145,7 @@ export function Tree(props) {
|
|
|
141
145
|
[isReorderMode, setIsReorderMode] = useState(false),
|
|
142
146
|
[isSearchModalShown, setIsSearchModalShown] = useState(false),
|
|
143
147
|
[treeNodeData, setTreeNodeData] = useState({}),
|
|
148
|
+
[searchResults, setSearchResults] = useState([]),
|
|
144
149
|
[searchFormData, setSearchFormData] = useState([]),
|
|
145
150
|
[dragNodeSlot, setDragNodeSlot] = useState(null),
|
|
146
151
|
[dragNodeIx, setDragNodeIx] = useState(),
|
|
@@ -477,6 +482,69 @@ export function Tree(props) {
|
|
|
477
482
|
|
|
478
483
|
return !_.isEmpty(intersection);
|
|
479
484
|
},
|
|
485
|
+
buildAndSetTreeNodeData = async () => {
|
|
486
|
+
let rootNodes;
|
|
487
|
+
if (Repository) {
|
|
488
|
+
if (!Repository.areRootNodesLoaded) {
|
|
489
|
+
rootNodes = await Repository.getRootNodes(1);
|
|
490
|
+
}
|
|
491
|
+
} else {
|
|
492
|
+
rootNodes = assembleDataTreeNodes();
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
const treeNodeData = buildTreeNodeData(rootNodes);
|
|
496
|
+
setTreeNodeData(treeNodeData);
|
|
497
|
+
},
|
|
498
|
+
assembleDataTreeNodes = () => {
|
|
499
|
+
// Populates the TreeNodes with .parent and .children references
|
|
500
|
+
// NOTE: This is only for 'data', not for Repositories!
|
|
501
|
+
// 'data' is essentially an Adjacency List, not a ClosureTable.
|
|
502
|
+
|
|
503
|
+
const clonedData = _.clone(data);
|
|
504
|
+
|
|
505
|
+
// Reset all parent/child relationships
|
|
506
|
+
_.each(clonedData, (treeNode) => {
|
|
507
|
+
treeNode.isRoot = !treeNode[parentIdIx];
|
|
508
|
+
treeNode.parent = null;
|
|
509
|
+
treeNode.children = [];
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
// Rebuild all parent/child relationships
|
|
513
|
+
_.each(clonedData, (treeNode) => {
|
|
514
|
+
const parent = _.find(clonedData, (tn) => {
|
|
515
|
+
return tn[idIx] === treeNode[parentIdIx];
|
|
516
|
+
});
|
|
517
|
+
if (parent) {
|
|
518
|
+
treeNode.parent = parent;
|
|
519
|
+
parent.children.push(treeNode);
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
// populate calculated fields
|
|
524
|
+
const treeNodes = [];
|
|
525
|
+
_.each(clonedData, (treeNode) => {
|
|
526
|
+
treeNode.hasChildren = !_.isEmpty(treeNode.children);
|
|
527
|
+
|
|
528
|
+
let parent = treeNode.parent,
|
|
529
|
+
i = 0;
|
|
530
|
+
while(parent) {
|
|
531
|
+
i++;
|
|
532
|
+
parent = parent.parent;
|
|
533
|
+
}
|
|
534
|
+
treeNode.depth = i;
|
|
535
|
+
treeNode.hash = treeNode[idIx];
|
|
536
|
+
|
|
537
|
+
if (treeNode.isRoot) {
|
|
538
|
+
treeNodes.push(treeNode);
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
return treeNodes;
|
|
543
|
+
},
|
|
544
|
+
reloadTree = () => {
|
|
545
|
+
Repository.areRootNodesLoaded = false;
|
|
546
|
+
return buildAndSetTreeNodeData();
|
|
547
|
+
};
|
|
480
548
|
|
|
481
549
|
// Button handlers
|
|
482
550
|
onToggle = (datum) => {
|
|
@@ -539,7 +607,6 @@ export function Tree(props) {
|
|
|
539
607
|
});
|
|
540
608
|
},
|
|
541
609
|
onSearchTree = async (value) => {
|
|
542
|
-
|
|
543
610
|
let found = [];
|
|
544
611
|
if (Repository?.isRemote) {
|
|
545
612
|
// Search tree on server
|
|
@@ -550,16 +617,17 @@ export function Tree(props) {
|
|
|
550
617
|
}
|
|
551
618
|
|
|
552
619
|
const isMultipleHits = found.length > 1;
|
|
553
|
-
let path = '';
|
|
554
|
-
let searchFormData = [];
|
|
555
|
-
|
|
556
620
|
if (!isMultipleHits) {
|
|
557
|
-
|
|
558
|
-
expandPath(path);
|
|
621
|
+
expandPath(found[0].path);
|
|
559
622
|
return;
|
|
560
623
|
}
|
|
561
624
|
|
|
625
|
+
const searchFormData = [];
|
|
626
|
+
_.each(found, (item) => {
|
|
627
|
+
searchFormData.push([item.id, getNodeText(item)]);
|
|
628
|
+
});
|
|
562
629
|
setSearchFormData(searchFormData);
|
|
630
|
+
setSearchResults(found);
|
|
563
631
|
setIsSearchModalShown(true);
|
|
564
632
|
},
|
|
565
633
|
findTreeNodesByText = (text) => {
|
|
@@ -588,33 +656,6 @@ export function Tree(props) {
|
|
|
588
656
|
}
|
|
589
657
|
return data[node_id]; // TODO: This is probably not right!
|
|
590
658
|
},
|
|
591
|
-
getPathByTreeNode = (treeNode) => {
|
|
592
|
-
|
|
593
|
-
///////// THIS DOESN'T WORK YET /////////
|
|
594
|
-
|
|
595
|
-
function searchChildren(children, currentPath = []) {
|
|
596
|
-
let found = [];
|
|
597
|
-
_.each(children, (child) => {
|
|
598
|
-
const
|
|
599
|
-
item = child.item,
|
|
600
|
-
id = idField ? item[idField] : item.id;
|
|
601
|
-
if (child.text.match(regex)) {
|
|
602
|
-
found.push(child);
|
|
603
|
-
return false;
|
|
604
|
-
}
|
|
605
|
-
if (child.children) {
|
|
606
|
-
const childrenFound = searchChildren(child.children, [...currentPath, id]);
|
|
607
|
-
if (!_.isEmpty(childrenFound)) {
|
|
608
|
-
return false;
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
});
|
|
612
|
-
return found;
|
|
613
|
-
}
|
|
614
|
-
const nodes = searchChildren(treeNodeData);
|
|
615
|
-
return nodes.join('/');
|
|
616
|
-
|
|
617
|
-
},
|
|
618
659
|
expandPath = async (path) => {
|
|
619
660
|
// Helper for onSearchTree
|
|
620
661
|
|
|
@@ -628,6 +669,7 @@ export function Tree(props) {
|
|
|
628
669
|
id,
|
|
629
670
|
currentLevelData = newTreeNodeData,
|
|
630
671
|
currentDatum,
|
|
672
|
+
parentDatum,
|
|
631
673
|
currentNode;
|
|
632
674
|
|
|
633
675
|
while(path.length) {
|
|
@@ -641,9 +683,11 @@ export function Tree(props) {
|
|
|
641
683
|
|
|
642
684
|
if (!currentDatum) {
|
|
643
685
|
// datum is not currently loaded, so load it
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
686
|
+
await loadChildren(parentDatum, 1);
|
|
687
|
+
currentLevelData = parentDatum.children;
|
|
688
|
+
currentDatum = _.find(currentLevelData, (treeNodeDatum) => {
|
|
689
|
+
return treeNodeDatum.item.id === id;
|
|
690
|
+
});
|
|
647
691
|
}
|
|
648
692
|
|
|
649
693
|
currentNode = currentDatum.item;
|
|
@@ -653,6 +697,7 @@ export function Tree(props) {
|
|
|
653
697
|
|
|
654
698
|
path = pathParts.slice(1).join('/'); // put the rest of it back together
|
|
655
699
|
currentLevelData = currentDatum.children;
|
|
700
|
+
parentDatum = currentDatum;
|
|
656
701
|
}
|
|
657
702
|
|
|
658
703
|
setSelection([currentNode]);
|
|
@@ -923,29 +968,15 @@ export function Tree(props) {
|
|
|
923
968
|
}
|
|
924
969
|
setDragNodeSlot(null);
|
|
925
970
|
};
|
|
926
|
-
|
|
927
|
-
useEffect(() => {
|
|
928
|
-
|
|
929
|
-
async function buildAndSetTreeNodeData() {
|
|
930
|
-
|
|
931
|
-
let rootNodes;
|
|
932
|
-
if (Repository) {
|
|
933
|
-
if (!Repository.areRootNodesLoaded) {
|
|
934
|
-
rootNodes = await Repository.getRootNodes(1);
|
|
935
|
-
}
|
|
936
|
-
} else {
|
|
937
|
-
// TODO: Make this work for data array
|
|
938
971
|
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
setTreeNodeData(treeNodeData);
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
function reloadTreeData() {
|
|
946
|
-
Repository.areRootNodesLoaded = false;
|
|
947
|
-
return buildAndSetTreeNodeData();
|
|
972
|
+
useEffect(() => {
|
|
973
|
+
if (!isReady) {
|
|
974
|
+
return () => {};
|
|
948
975
|
}
|
|
976
|
+
reloadTree();
|
|
977
|
+
}, [reload]);
|
|
978
|
+
|
|
979
|
+
useEffect(() => {
|
|
949
980
|
|
|
950
981
|
if (!isReady) {
|
|
951
982
|
if (Repository) {
|
|
@@ -970,16 +1001,16 @@ export function Tree(props) {
|
|
|
970
1001
|
Repository.on('load', setFalse);
|
|
971
1002
|
Repository.ons(['changePage', 'changePageSize',], deselectAll);
|
|
972
1003
|
Repository.ons(['changeData', 'change'], buildAndSetTreeNodeData);
|
|
973
|
-
Repository.on('changeFilters',
|
|
974
|
-
Repository.on('changeSorters',
|
|
1004
|
+
Repository.on('changeFilters', reloadTree);
|
|
1005
|
+
Repository.on('changeSorters', reloadTree);
|
|
975
1006
|
|
|
976
1007
|
return () => {
|
|
977
1008
|
Repository.off('beforeLoad', setTrue);
|
|
978
1009
|
Repository.off('load', setFalse);
|
|
979
1010
|
Repository.offs(['changePage', 'changePageSize',], deselectAll);
|
|
980
1011
|
Repository.offs(['changeData', 'change'], buildAndSetTreeNodeData);
|
|
981
|
-
Repository.off('changeFilters',
|
|
982
|
-
Repository.off('changeSorters',
|
|
1012
|
+
Repository.off('changeFilters', reloadTree);
|
|
1013
|
+
Repository.off('changeSorters', reloadTree);
|
|
983
1014
|
};
|
|
984
1015
|
}, []);
|
|
985
1016
|
|
|
@@ -1037,11 +1068,11 @@ export function Tree(props) {
|
|
|
1037
1068
|
{treeFooterComponent}
|
|
1038
1069
|
</Column>
|
|
1039
1070
|
|
|
1040
|
-
|
|
1071
|
+
<Modal
|
|
1041
1072
|
isOpen={isSearchModalShown}
|
|
1042
1073
|
onClose={() => setIsSearchModalShown(false)}
|
|
1043
1074
|
>
|
|
1044
|
-
<Column bg="#fff" w={
|
|
1075
|
+
<Column bg="#fff" w={300}>
|
|
1045
1076
|
<FormPanel
|
|
1046
1077
|
title="Choose Tree Node"
|
|
1047
1078
|
instructions="Multiple tree nodes matched your search. Please select which one to show."
|
|
@@ -1066,32 +1097,43 @@ export function Tree(props) {
|
|
|
1066
1097
|
setIsSearchModalShown(false);
|
|
1067
1098
|
}}
|
|
1068
1099
|
onSave={(data, e) => {
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
} else {
|
|
1078
|
-
// Show the path based on local data
|
|
1079
|
-
const
|
|
1080
|
-
treeNode = getTreeNodeByNodeId(node_id),
|
|
1081
|
-
path = getPathByTreeNode(treeNode);
|
|
1082
|
-
expandPath(path);
|
|
1083
|
-
}
|
|
1100
|
+
const
|
|
1101
|
+
treeNode = _.find(searchResults, (item) => {
|
|
1102
|
+
return item.id === data.node_id;
|
|
1103
|
+
}),
|
|
1104
|
+
path = treeNode.path;
|
|
1105
|
+
expandPath(path);
|
|
1084
1106
|
|
|
1085
1107
|
// Close the modal
|
|
1086
1108
|
setIsSearchModalShown(false);
|
|
1087
1109
|
}}
|
|
1088
1110
|
/>
|
|
1089
1111
|
</Column>
|
|
1090
|
-
</Modal>
|
|
1112
|
+
</Modal>
|
|
1091
1113
|
</>;
|
|
1092
1114
|
|
|
1093
1115
|
}
|
|
1094
1116
|
|
|
1117
|
+
export const Tree = withAlert(
|
|
1118
|
+
withEvents(
|
|
1119
|
+
withData(
|
|
1120
|
+
// withMultiSelection(
|
|
1121
|
+
withSelection(
|
|
1122
|
+
// withSideEditor(
|
|
1123
|
+
withFilters(
|
|
1124
|
+
// withPresetButtons(
|
|
1125
|
+
withContextMenu(
|
|
1126
|
+
Tree
|
|
1127
|
+
)
|
|
1128
|
+
// )
|
|
1129
|
+
)
|
|
1130
|
+
// )
|
|
1131
|
+
)
|
|
1132
|
+
// )
|
|
1133
|
+
)
|
|
1134
|
+
)
|
|
1135
|
+
);
|
|
1136
|
+
|
|
1095
1137
|
export const SideTreeEditor = withAlert(
|
|
1096
1138
|
withEvents(
|
|
1097
1139
|
withData(
|
|
@@ -1132,4 +1174,4 @@ export const WindowedTreeEditor = withAlert(
|
|
|
1132
1174
|
)
|
|
1133
1175
|
);
|
|
1134
1176
|
|
|
1135
|
-
export default
|
|
1177
|
+
export default Tree;
|