1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import { CollectionPanelFilesState, CollectionPanelFile, CollectionPanelDirectory, mapCollectionFileToCollectionPanelFile } from "./collection-panel-files-state";
6 import { CollectionPanelFilesAction, collectionPanelFilesAction } from "./collection-panel-files-actions";
7 import { createTree, mapTree, TreeNode, mapNodes, getNode, setNode, getNodeAncestors, getNodeDescendants, mapNodeValue } from "../../../models/tree";
8 import { CollectionFileType } from "../../../models/collection-file";
10 export const collectionPanelFilesReducer = (state: CollectionPanelFilesState = createTree(), action: CollectionPanelFilesAction) => {
11 return collectionPanelFilesAction.match(action, {
12 SET_COLLECTION_FILES: ({ files }) =>
13 mapTree(mapCollectionFileToCollectionPanelFile)(files),
15 TOGGLE_COLLECTION_FILE_COLLAPSE: data =>
16 toggleCollapse(data.id)(state),
18 TOGGLE_COLLECTION_FILE_SELECTION: data => [state]
19 .map(toggleSelected(data.id))
20 .map(toggleAncestors(data.id))
21 .map(toggleDescendants(data.id))[0],
23 SELECT_ALL_COLLECTION_FILES: () =>
24 mapTree(mapNodeValue(v => ({ ...v, selected: true })))(state),
26 UNSELECT_ALL_COLLECTION_FILES: () =>
27 mapTree(mapNodeValue(v => ({ ...v, selected: false })))(state),
33 const toggleCollapse = (id: string) => (tree: CollectionPanelFilesState) =>
36 (mapNodeValue((v: CollectionPanelDirectory | CollectionPanelFile) =>
37 v.type === CollectionFileType.DIRECTORY
38 ? { ...v, collapsed: !v.collapsed }
42 const toggleSelected = (id: string) => (tree: CollectionPanelFilesState) =>
45 (mapNodeValue((v: CollectionPanelDirectory | CollectionPanelFile) => ({ ...v, selected: !v.selected })))
49 const toggleDescendants = (id: string) => (tree: CollectionPanelFilesState) => {
50 const node = getNode(id)(tree);
51 if (node && node.value.type === CollectionFileType.DIRECTORY) {
52 return mapNodes(getNodeDescendants(id)(tree))(mapNodeValue(v => ({ ...v, selected: node.value.selected })))(tree);
57 const toggleAncestors = (id: string) => (tree: CollectionPanelFilesState) => {
58 const ancestors = getNodeAncestors(id)(tree)
59 .map(id => getNode(id)(tree))
61 return ancestors.reduce((newTree, parent) => parent !== undefined ? toggleParentNode(parent)(newTree) : newTree, tree);
64 const toggleParentNode = (node: TreeNode<CollectionPanelDirectory | CollectionPanelFile>) => (tree: CollectionPanelFilesState) => {
65 const parentNode = getNode(node.id)(tree);
67 const selected = parentNode.children
68 .map(id => getNode(id)(tree))
69 .every(node => node !== undefined && node.value.selected);
70 return setNode(mapNodeValue(v => ({ ...v, selected }))(parentNode))(tree);
72 return setNode(node)(tree);