Merge branch 'master'
[arvados-workbench2.git] / src / store / tree-picker / tree-picker-reducer.ts
index d195a98a6836b3f861768b703494e4c7ec5a783b..8eaada6fc3e092e477c042db44c36ade006df9f5 100644 (file)
@@ -2,29 +2,40 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { createTree, setNodeValueWith, TreeNode, setNode, mapTree, mapTreeValues } from "../../models/tree";
+import { createTree, setNodeValueWith, TreeNode, setNode, mapTreeValues, Tree } from "~/models/tree";
 import { TreePicker, TreePickerNode } from "./tree-picker";
 import { treePickerActions, TreePickerAction } from "./tree-picker-actions";
-import { TreeItemStatus } from "../../components/tree/tree";
+import { TreeItemStatus } from "~/components/tree/tree";
+import { compose } from "redux";
 
-
-export const treePickerReducer = (state: TreePicker = createTree(), action: TreePickerAction) =>
+export const treePickerReducer = (state: TreePicker = {}, action: TreePickerAction) =>
     treePickerActions.match(action, {
-        LOAD_TREE_PICKER_NODE: ({ id }) =>
-            setNodeValueWith(setPending)(id)(state),
-        LOAD_TREE_PICKER_NODE_SUCCESS: ({ id, nodes }) => {
-            const [newState] = [state]
-                .map(receiveNodes(nodes)(id))
-                .map(setNodeValueWith(setLoaded)(id));
-            return newState;
-        },
-        TOGGLE_TREE_PICKER_NODE_COLLAPSE: ({ id }) =>
-            setNodeValueWith(toggleCollapse)(id)(state),
-        TOGGLE_TREE_PICKER_NODE_SELECT: ({ id }) =>
-            mapTreeValues(toggleSelect(id))(state),
+        LOAD_TREE_PICKER_NODE: ({ nodeId, pickerId }) =>
+            updateOrCreatePicker(state, pickerId, setNodeValueWith(setPending)(nodeId)),
+        LOAD_TREE_PICKER_NODE_SUCCESS: ({ nodeId, nodes, pickerId }) =>
+            updateOrCreatePicker(state, pickerId, compose(receiveNodes(nodes)(nodeId), setNodeValueWith(setLoaded)(nodeId))),
+        TOGGLE_TREE_PICKER_NODE_COLLAPSE: ({ nodeId, pickerId }) =>
+            updateOrCreatePicker(state, pickerId, setNodeValueWith(toggleCollapse)(nodeId)),
+        TOGGLE_TREE_PICKER_NODE_SELECT: ({ nodeId, pickerId }) =>
+            updateOrCreatePicker(state, pickerId, mapTreeValues(toggleSelect(nodeId))),
+        RESET_TREE_PICKER: ({ pickerId }) =>
+            updateOrCreatePicker(state, pickerId, createTree),
+        EXPAND_TREE_PICKER_NODES: ({ pickerId, nodeIds }) =>
+            updateOrCreatePicker(state, pickerId, mapTreeValues(expand(nodeIds))),
         default: () => state
     });
 
+const updateOrCreatePicker = (state: TreePicker, pickerId: string, func: (value: Tree<TreePickerNode>) => Tree<TreePickerNode>) => {
+    const picker = state[pickerId] || createTree();
+    const updatedPicker = func(picker);
+    return { ...state, [pickerId]: updatedPicker };
+};
+
+const expand = (ids: string[]) => (node: TreePickerNode): TreePickerNode =>
+    ids.some(id => id === node.nodeId)
+        ? { ...node, collapsed: false }
+        : node;
+
 const setPending = (value: TreePickerNode): TreePickerNode =>
     ({ ...value, status: TreeItemStatus.PENDING });
 
@@ -34,12 +45,12 @@ const setLoaded = (value: TreePickerNode): TreePickerNode =>
 const toggleCollapse = (value: TreePickerNode): TreePickerNode =>
     ({ ...value, collapsed: !value.collapsed });
 
-const toggleSelect = (id: string) => (value: TreePickerNode): TreePickerNode =>
-    value.id === id
+const toggleSelect = (nodeId: string) => (value: TreePickerNode): TreePickerNode =>
+    value.nodeId === nodeId
         ? ({ ...value, selected: !value.selected })
         : ({ ...value, selected: false });
 
-const receiveNodes = (nodes: Array<TreePickerNode>) => (parent: string) => (state: TreePicker) =>
+const receiveNodes = (nodes: Array<TreePickerNode>) => (parent: string) => (state: Tree<TreePickerNode>) =>
     nodes.reduce((tree, node) =>
         setNode(
             createTreeNode(parent)(node)
@@ -47,7 +58,7 @@ const receiveNodes = (nodes: Array<TreePickerNode>) => (parent: string) => (stat
 
 const createTreeNode = (parent: string) => (node: TreePickerNode): TreeNode<TreePickerNode> => ({
     children: [],
-    id: node.id,
+    id: node.nodeId,
     parent,
     value: node
-});
\ No newline at end of file
+});