1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import * as _ from "lodash";
7 import { projectActions, ProjectAction } from "./project-action";
8 import { TreeItem, TreeItemStatus } from "~/components/tree/tree";
9 import { ProjectResource } from "~/models/project";
11 export type ProjectState = {
12 items: Array<TreeItem<ProjectResource>>,
13 currentItemId: string,
14 updater: ProjectUpdater
17 interface ProjectUpdater {
22 export function findTreeItem<T>(tree: Array<TreeItem<T>>, itemId: string): TreeItem<T> | undefined {
24 for (const t of tree) {
25 item = t.id === itemId
27 : findTreeItem(t.items ? t.items : [], itemId);
35 export function getActiveTreeItem<T>(tree: Array<TreeItem<T>>): TreeItem<T> | undefined {
37 for (const t of tree) {
40 : getActiveTreeItem(t.items ? t.items : []);
48 export function getTreePath<T>(tree: Array<TreeItem<T>>, itemId: string): Array<TreeItem<T>> {
49 for (const item of tree) {
50 if (item.id === itemId) {
53 const branch = getTreePath(item.items || [], itemId);
54 if (branch.length > 0) {
55 return [item, ...branch];
62 function resetTreeActivity<T>(tree: Array<TreeItem<T>>) {
63 for (const t of tree) {
65 resetTreeActivity(t.items ? t.items : []);
69 function updateProjectTree(tree: Array<TreeItem<ProjectResource>>, projects: ProjectResource[], parentItemId?: string): Array<TreeItem<ProjectResource>> {
72 treeItem = findTreeItem(tree, parentItemId);
74 treeItem.status = TreeItemStatus.LOADED;
77 const items = projects.map(p => ({
81 status: TreeItemStatus.INITIAL,
84 } as TreeItem<ProjectResource>));
87 treeItem.items = items;
94 const updateProject = (state: ProjectState, updater?: Partial<ProjectUpdater>) => ({
102 const initialState: ProjectState = {
112 export const projectsReducer = (state: ProjectState = initialState, action: ProjectAction) => {
113 return projectActions.match(action, {
114 OPEN_PROJECT_UPDATER: ({ uuid }) => updateProject(state, { uuid, opened: true }),
115 CLOSE_PROJECT_UPDATER: () => updateProject(state, { opened: false, uuid: "" }),
116 UPDATE_PROJECT_SUCCESS: () => updateProject(state, { opened: false, uuid: "" }),
117 REMOVE_PROJECT: () => state,
118 PROJECTS_REQUEST: itemId => {
119 const items = _.cloneDeep(state.items);
120 const item = findTreeItem(items, itemId);
122 item.status = TreeItemStatus.PENDING;
125 return { ...state, items };
127 PROJECTS_SUCCESS: ({ projects, parentItemId }) => {
128 const items = _.cloneDeep(state.items);
131 items: updateProjectTree(items, projects, parentItemId)
134 TOGGLE_PROJECT_TREE_ITEM_OPEN: itemId => {
135 const items = _.cloneDeep(state.items);
136 const item = findTreeItem(items, itemId);
138 item.open = !item.open;
143 currentItemId: itemId
146 TOGGLE_PROJECT_TREE_ITEM_ACTIVE: itemId => {
147 const items = _.cloneDeep(state.items);
148 resetTreeActivity(items);
149 const item = findTreeItem(items, itemId);
156 currentItemId: itemId
159 RESET_PROJECT_TREE_ACTIVITY: () => {
160 const items = _.cloneDeep(state.items);
161 resetTreeActivity(items);