refs #master Merge branch 'origin/master' into 14007-ts-paths
[arvados-workbench2.git] / src / views-components / tree-picker / tree-picker.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { connect } from "react-redux";
6 import { Tree, TreeProps, TreeItem } from "~/components/tree/tree";
7 import { RootState } from "~/store/store";
8 import { TreePicker as TTreePicker, TreePickerNode, createTreePickerNode } from "~/store/tree-picker/tree-picker";
9 import { getNodeValue, getNodeChildren } from "~/models/tree";
10
11 const memoizedMapStateToProps = () => {
12     let prevState: TTreePicker;
13     let prevTree: Array<TreeItem<any>>;
14
15     return (state: RootState): Pick<TreeProps<any>, 'items'> => {
16         if (prevState !== state.treePicker) {
17             prevState = state.treePicker;
18             prevTree = getNodeChildren('')(state.treePicker)
19                 .map(treePickerToTreeItems(state.treePicker));
20         }
21         return {
22             items: prevTree
23         };
24     };
25 };
26
27 const mapDispatchToProps = (): Pick<TreeProps<any>, 'onContextMenu'> => ({
28     onContextMenu: () => { return; },
29 });
30
31 export const TreePicker = connect(memoizedMapStateToProps(), mapDispatchToProps)(Tree);
32
33 const treePickerToTreeItems = (tree: TTreePicker) =>
34     (id: string): TreeItem<any> => {
35         const node: TreePickerNode = getNodeValue(id)(tree) || createTreePickerNode({ id: '', value: 'InvalidNode' });
36         const items = getNodeChildren(node.id)(tree)
37             .map(treePickerToTreeItems(tree));
38         return {
39             active: node.selected,
40             data: node.value,
41             id: node.id,
42             items: items.length > 0 ? items : undefined,
43             open: !node.collapsed,
44             status: node.status
45         };
46     };
47