1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import { connect } from "react-redux";
6 import { Tree, TreeProps, TreeItem, TreeItemStatus } from "~/components/tree/tree";
7 import { RootState } from "~/store/store";
8 import { getNodeValue, getNodeChildrenIds, Tree as Ttree, createTree, getNode, TreeNodeStatus } from '~/models/tree';
9 import { Dispatch } from "redux";
10 import { initTreeNode } from '../../models/tree';
12 export interface TreePickerProps {
14 onContextMenu: (event: React.MouseEvent<HTMLElement>, nodeId: string, pickerId: string) => void;
15 toggleItemOpen: (nodeId: string, status: TreeItemStatus, pickerId: string) => void;
16 toggleItemActive: (nodeId: string, status: TreeItemStatus, pickerId: string) => void;
17 toggleItemSelection: (nodeId: string, pickerId: string) => void;
20 const memoizedMapStateToProps = () => {
21 let prevTree: Ttree<any>;
22 let mappedProps: Pick<TreeProps<any>, 'items'>;
23 return (state: RootState, props: TreePickerProps): Pick<TreeProps<any>, 'items'> => {
24 const tree = state.treePicker[props.pickerId] || createTree();
25 if (tree !== prevTree) {
28 items: getNodeChildrenIds('')(tree)
29 .map(treePickerToTreeItems(tree))
36 const mapDispatchToProps = (dispatch: Dispatch, props: TreePickerProps): Pick<TreeProps<any>, 'onContextMenu' | 'toggleItemOpen' | 'toggleItemActive' | 'toggleItemSelection'> => ({
37 onContextMenu: (event, item) => props.onContextMenu(event, item.id, props.pickerId),
38 toggleItemActive: (id, status) => props.toggleItemActive(id, status, props.pickerId),
39 toggleItemOpen: (id, status) => props.toggleItemOpen(id, status, props.pickerId),
40 toggleItemSelection: (_, item) => props.toggleItemSelection(item.id, props.pickerId),
43 export const TreePicker = connect(memoizedMapStateToProps(), mapDispatchToProps)(Tree);
45 const treePickerToTreeItems = (tree: Ttree<any>) =>
46 (id: string): TreeItem<any> => {
47 const node = getNode(id)(tree) || initTreeNode({ id: '', value: 'InvalidNode' });
48 const items = getNodeChildrenIds(node.id)(tree)
49 .map(treePickerToTreeItems(tree));
54 items: items.length > 0 ? items : undefined,
56 selected: node.selected,
57 status: treeNodeStatusToTreeItem(node.status),
61 export const treeNodeStatusToTreeItem = (status: TreeNodeStatus) => {
63 case TreeNodeStatus.INITIAL:
64 return TreeItemStatus.INITIAL;
65 case TreeNodeStatus.PENDING:
66 return TreeItemStatus.PENDING;
67 case TreeNodeStatus.LOADED:
68 return TreeItemStatus.LOADED;