merge master
[arvados-workbench2.git] / src / store / tree-picker / tree-picker-reducer.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { createTree, setNodeValueWith, TreeNode, setNode, mapTreeValues, Tree } from "~/models/tree";
6 import { TreePicker, TreePickerNode } from "./tree-picker";
7 import { treePickerActions, TreePickerAction } from "./tree-picker-actions";
8 import { TreeItemStatus } from "~/components/tree/tree";
9
10 export const treePickerReducer = (state: TreePicker = {}, action: TreePickerAction) =>
11     treePickerActions.match(action, {
12         LOAD_TREE_PICKER_NODE: ({ id, pickerId }) => {
13             const picker = state[pickerId] || createTree();
14             const updatedPicker = setNodeValueWith(setPending)(id)(picker);
15             return { ...state, [pickerId]: updatedPicker };
16         },
17         LOAD_TREE_PICKER_NODE_SUCCESS: ({ id, nodes, pickerId }) => {
18             const picker = state[pickerId] || createTree();
19             const [updatedPicker] = [picker]
20                 .map(receiveNodes(nodes)(id))
21                 .map(setNodeValueWith(setLoaded)(id));
22             return { ...state, [pickerId]: updatedPicker };
23         },
24         TOGGLE_TREE_PICKER_NODE_COLLAPSE: ({ id, pickerId }) => {
25             const picker = state[pickerId] || createTree();
26             const updatedPicker = setNodeValueWith(toggleCollapse)(id)(picker);
27             return { ...state, [pickerId]: updatedPicker };
28         },
29         TOGGLE_TREE_PICKER_NODE_SELECT: ({ id, pickerId }) => {
30             const picker = state[pickerId] || createTree();
31             const updatedPicker = mapTreeValues(toggleSelect(id))(picker);
32             return { ...state, [pickerId]: updatedPicker };
33         },
34         default: () => state
35     });
36
37 const setPending = (value: TreePickerNode): TreePickerNode =>
38     ({ ...value, status: TreeItemStatus.PENDING });
39
40 const setLoaded = (value: TreePickerNode): TreePickerNode =>
41     ({ ...value, status: TreeItemStatus.LOADED });
42
43 const toggleCollapse = (value: TreePickerNode): TreePickerNode =>
44     ({ ...value, collapsed: !value.collapsed });
45
46 const toggleSelect = (id: string) => (value: TreePickerNode): TreePickerNode =>
47     value.id === id
48         ? ({ ...value, selected: !value.selected })
49         : ({ ...value, selected: false });
50
51 const receiveNodes = (nodes: Array<TreePickerNode>) => (parent: string) => (state: Tree<TreePickerNode>) =>
52     nodes.reduce((tree, node) => 
53         setNode(
54             createTreeNode(parent)(node)
55         )(tree), state);
56
57 const createTreeNode = (parent: string) => (node: TreePickerNode): TreeNode<TreePickerNode> => ({
58     children: [],
59     id: node.id,
60     parent,
61     value: node
62 });