Implement 'select/unselect all' actions
[arvados.git] / src / store / collection-panel / collection-panel-files / collections-panel-files-reducer.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { CollectionPanelFilesState, CollectionPanelFile } from "./collection-panel-files-state";
6 import { CollectionPanelFilesAction, collectionPanelFilesAction } from "./collection-panel-files-actions";
7 import { stat } from "fs";
8
9 const initialState: CollectionPanelFilesState = [{
10     collapsed: true,
11     id: 'Directory 1',
12     name: 'Directory 1',
13     selected: false,
14     type: 'directory',
15 }, {
16     parentId: 'Directory 1',
17     collapsed: true,
18     id: 'Directory 1.1',
19     name: 'Directory 1.1',
20     selected: false,
21     type: 'directory',
22 }, {
23     parentId: 'Directory 1',
24     collapsed: true,
25     id: 'File 1.1',
26     name: 'File 1.1',
27     selected: false,
28     type: 'file',
29 }, {
30     collapsed: true,
31     id: 'Directory 2',
32     name: 'Directory 2',
33     selected: false,
34     type: 'directory',
35 }, {
36     parentId: 'Directory 2',
37     collapsed: true,
38     id: 'Directory 2.1',
39     name: 'Directory 2.1',
40     selected: false,
41     type: 'directory',
42 }, {
43     parentId: 'Directory 2.1',
44     collapsed: true,
45     id: 'Directory 2.1.1',
46     name: 'Directory 2.1.1',
47     selected: false,
48     type: 'directory',
49 }, {
50     parentId: 'Directory 2.1.1',
51     collapsed: true,
52     id: 'Directory 2.1.1.1',
53     name: 'Directory 2.1.1.1',
54     selected: false,
55     type: 'directory',
56 }];
57
58 export const collectionPanelFilesReducer = (state: CollectionPanelFilesState = initialState, action: CollectionPanelFilesAction) => {
59     return collectionPanelFilesAction.match(action, {
60         SET_COLLECTION_FILES: data => data.files,
61         TOGGLE_COLLECTION_FILE_COLLAPSE: data => toggleCollapsed(state, data.id),
62         TOGGLE_COLLECTION_FILE_SELECTION: data => toggleSelected(state, data.id),
63         SELECT_ALL_COLLECTION_FILES: () => state.map(file => ({...file, selected: true})),
64         UNSELECT_ALL_COLLECTION_FILES: () => state.map(file => ({...file, selected: false})),
65         default: () => state
66     });
67 };
68
69 const toggleCollapsed = (state: CollectionPanelFilesState, id: string) =>
70     state.map(file => file.id === id
71         ? { ...file, collapsed: !file.collapsed }
72         : file);
73
74 const toggleSelected = (state: CollectionPanelFilesState, id: string) =>
75     toggleAncestors(toggleDescendants(state, id), id);
76
77 const toggleDescendants = (state: CollectionPanelFilesState, id: string) => {
78     const ids = getDescendants(state)({ id }).map(file => file.id);
79     if (ids.length > 0) {
80         const selected = !state.find(f => f.id === ids[0])!.selected;
81         return state.map(file => ids.some(id => file.id === id) ? { ...file, selected } : file);
82     }
83     return state;
84 };
85
86 const toggleAncestors = (state: CollectionPanelFilesState, id: string): CollectionPanelFile[] => {
87     const file = state.find(f => f.id === id);
88     if (file) {
89         const selected = state
90             .filter(f => f.parentId === file.parentId)
91             .every(f => f.selected);
92         if (!selected) {
93             const newState = state.map(f => f.id === file.parentId ? { ...f, selected } : f);
94             return toggleAncestors(newState, file.parentId || "");
95         }
96     }
97     return state;
98 };
99
100 const getDescendants = (state: CollectionPanelFilesState) => ({ id }: { id: string }): CollectionPanelFile[] => {
101     const root = state.find(f => f.id === id);
102     if (root) {
103         return [root].concat(...state.filter(f => f.parentId === id).map(getDescendants(state)));
104     } else { return []; }
105 };
106