1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
6 createTree, TreeNode, setNode, Tree, TreeNodeStatus, setNodeStatus,
7 expandNode, deactivateNode, selectNodes, deselectNodes,
8 activateNode, getNode, toggleNodeCollapse, toggleNodeSelection, appendSubtree
10 import { TreePicker } from "./tree-picker";
11 import { treePickerActions, treePickerSearchActions, TreePickerAction, TreePickerSearchAction, LoadProjectParams } from "./tree-picker-actions";
12 import { compose } from "redux";
13 import { pipe } from 'lodash/fp';
15 export const treePickerReducer = (state: TreePicker = {}, action: TreePickerAction) =>
16 treePickerActions.match(action, {
17 LOAD_TREE_PICKER_NODE: ({ id, pickerId }) =>
18 updateOrCreatePicker(state, pickerId, setNodeStatus(id)(TreeNodeStatus.PENDING)),
20 LOAD_TREE_PICKER_NODE_SUCCESS: ({ id, nodes, pickerId }) =>
21 updateOrCreatePicker(state, pickerId, compose(receiveNodes(nodes)(id), setNodeStatus(id)(TreeNodeStatus.LOADED))),
23 APPEND_TREE_PICKER_NODE_SUBTREE: ({ id, subtree, pickerId }) =>
24 updateOrCreatePicker(state, pickerId, compose(appendSubtree(id, subtree), setNodeStatus(id)(TreeNodeStatus.LOADED))),
26 TOGGLE_TREE_PICKER_NODE_COLLAPSE: ({ id, pickerId }) =>
27 updateOrCreatePicker(state, pickerId, toggleNodeCollapse(id)),
29 EXPAND_TREE_PICKER_NODE: ({ id, pickerId }) =>
30 updateOrCreatePicker(state, pickerId, expandNode(id)),
32 ACTIVATE_TREE_PICKER_NODE: ({ id, pickerId, relatedTreePickers = [] }) =>
34 () => relatedTreePickers.reduce(
35 (state, relatedPickerId) => updateOrCreatePicker(state, relatedPickerId, deactivateNode),
38 state => updateOrCreatePicker(state, pickerId, activateNode(id))
41 DEACTIVATE_TREE_PICKER_NODE: ({ pickerId }) =>
42 updateOrCreatePicker(state, pickerId, deactivateNode),
44 TOGGLE_TREE_PICKER_NODE_SELECTION: ({ id, pickerId }) =>
45 updateOrCreatePicker(state, pickerId, toggleNodeSelection(id)),
47 SELECT_TREE_PICKER_NODE: ({ id, pickerId }) =>
48 updateOrCreatePicker(state, pickerId, selectNodes(id)),
50 DESELECT_TREE_PICKER_NODE: ({ id, pickerId }) =>
51 updateOrCreatePicker(state, pickerId, deselectNodes(id)),
53 RESET_TREE_PICKER: ({ pickerId }) =>
54 updateOrCreatePicker(state, pickerId, createTree),
56 EXPAND_TREE_PICKER_NODES: ({ pickerId, ids }) =>
57 updateOrCreatePicker(state, pickerId, expandNode(...ids)),
62 const updateOrCreatePicker = <V>(state: TreePicker, pickerId: string, func: (value: Tree<V>) => Tree<V>) => {
63 const picker = state[pickerId] || createTree();
64 const updatedPicker = func(picker);
65 return { ...state, [pickerId]: updatedPicker };
68 const receiveNodes = <V>(nodes: Array<TreeNode<V>>) => (parent: string) => (state: Tree<V>) => {
69 const parentNode = getNode(parent)(state);
72 newState = setNode({ ...parentNode, children: [] })(state);
74 return nodes.reduce((tree, node) => {
75 const preexistingNode = getNode(node.id)(state);
76 if (preexistingNode) {
77 node = { ...preexistingNode, value: node.value };
79 return setNode({ ...node, parent })(tree);
83 interface TreePickerSearch {
84 projectSearchValues: { [pickerId: string]: string };
85 collectionFilterValues: { [pickerId: string]: string };
86 loadProjectParams: { [pickerId: string]: LoadProjectParams };
89 export const treePickerSearchReducer = (state: TreePickerSearch = { projectSearchValues: {}, collectionFilterValues: {}, loadProjectParams: {} }, action: TreePickerSearchAction) =>
90 treePickerSearchActions.match(action, {
91 SET_TREE_PICKER_PROJECT_SEARCH: ({ pickerId, projectSearchValue }) => ({
92 ...state, projectSearchValues: { ...state.projectSearchValues, [pickerId]: projectSearchValue }
95 SET_TREE_PICKER_COLLECTION_FILTER: ({ pickerId, collectionFilterValue }) => ({
96 ...state, collectionFilterValues: { ...state.collectionFilterValues, [pickerId]: collectionFilterValue }
99 SET_TREE_PICKER_LOAD_PARAMS: ({ pickerId, params }) => ({
100 ...state, loadProjectParams: { ...state.loadProjectParams, [pickerId]: params }