left-side-panel-with-tests
[arvados-workbench2.git] / src / store / project / project-reducer.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import * as _ from "lodash";
6
7 import { Project } from "../../models/project";
8 import actions, { ProjectAction } from "./project-action";
9 import { TreeItem, TreeItemStatus } from "../../components/tree/tree";
10
11 export type ProjectState = Array<TreeItem<Project>>;
12
13 function findTreeItem<T>(tree: Array<TreeItem<T>>, itemId: string): TreeItem<T> | undefined {
14     let item;
15     for (const t of tree) {
16         item = t.id === itemId
17             ? t
18             : findTreeItem(t.items ? t.items : [], itemId);
19         if (item) {
20             break;
21         }
22     }
23     return item;
24 }
25
26 function resetTreeActivity<T>(tree: Array<TreeItem<T>>) {
27     for (const t of tree) {
28         t.active = false;
29         resetTreeActivity(t.items ? t.items : []);
30     }
31 }
32
33 function updateProjectTree(tree: Array<TreeItem<Project>>, projects: Project[], parentItemId?: string): Array<TreeItem<Project>> {
34     let treeItem;
35     if (parentItemId) {
36         treeItem = findTreeItem(tree, parentItemId);
37         if (treeItem) {
38             treeItem.status = TreeItemStatus.Loaded;
39         }
40     }
41     const items = projects.map((p, idx) => ({
42         id: p.uuid,
43         open: false,
44         active: false,
45         status: TreeItemStatus.Initial,
46         data: p,
47         items: []
48     } as TreeItem<Project>));
49
50     if (treeItem) {
51         treeItem.items = items;
52         return tree;
53     }
54
55     return items;
56 }
57
58 const projectsReducer = (state: ProjectState = [], action: ProjectAction) => {
59     return actions.match(action, {
60         CREATE_PROJECT: project => [...state, project],
61         REMOVE_PROJECT: () => state,
62         PROJECTS_REQUEST: itemId => {
63             const tree = _.cloneDeep(state);
64             const item = findTreeItem(tree, itemId);
65             if (item) {
66                 item.status = TreeItemStatus.Pending;
67             }
68             return tree;
69         },
70         PROJECTS_SUCCESS: ({ projects, parentItemId }) => {
71             return updateProjectTree(state, projects, parentItemId);
72         },
73         TOGGLE_PROJECT_TREE_ITEM_OPEN: itemId => {
74             const tree = _.cloneDeep(state);
75             const item = findTreeItem(tree, itemId);
76             if (item) {
77                 item.toggled = true;
78                 item.open = !item.open;
79             }
80             return tree;
81         },
82         TOGGLE_PROJECT_TREE_ITEM_ACTIVE: itemId => {
83             const tree = _.cloneDeep(state);
84             resetTreeActivity(tree);
85             const item = findTreeItem(tree, itemId);
86             if (item) {
87                 item.active = true;
88             }
89             return tree;
90         },
91         RESET_PROJECT_TREE_ACTIVITY: () => {
92             const tree = _.cloneDeep(state);
93             resetTreeActivity(tree);
94             return tree;
95         },
96         default: () => state
97     });
98 };
99
100 export default projectsReducer;