18559: User breadcrumbs fallback to uuid
[arvados-workbench2.git] / src / store / breadcrumbs / breadcrumbs-actions.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { Dispatch } from 'redux';
6 import { RootState } from 'store/store';
7 import { getUserUuid } from "common/getuser";
8 import { Breadcrumb } from 'components/breadcrumbs/breadcrumbs';
9 import { getResource } from 'store/resources/resources';
10 import { TreePicker } from '../tree-picker/tree-picker';
11 import { getSidePanelTreeBranch, getSidePanelTreeNodeAncestorsIds } from '../side-panel-tree/side-panel-tree-actions';
12 import { propertiesActions } from '../properties/properties-actions';
13 import { getProcess } from 'store/processes/process';
14 import { ServiceRepository } from 'services/services';
15 import { SidePanelTreeCategory, activateSidePanelTreeItem } from 'store/side-panel-tree/side-panel-tree-actions';
16 import { updateResources } from '../resources/resources-actions';
17 import { ResourceKind } from 'models/resource';
18 import { GroupResource } from 'models/group';
19 import { extractUuidKind } from 'models/resource';
20 import { UserResource } from 'models/user';
21
22 export const BREADCRUMBS = 'breadcrumbs';
23
24 export interface ResourceBreadcrumb extends Breadcrumb {
25     uuid: string;
26 }
27
28 export const setBreadcrumbs = (breadcrumbs: any, currentItem?: any) => {
29     if (currentItem) {
30         const addLastItem = { label: currentItem.name, uuid: currentItem.uuid };
31         breadcrumbs.push(addLastItem);
32     }
33     return propertiesActions.SET_PROPERTY({ key: BREADCRUMBS, value: breadcrumbs });
34 };
35
36
37 const getSidePanelTreeBreadcrumbs = (uuid: string) => (treePicker: TreePicker): ResourceBreadcrumb[] => {
38     const nodes = getSidePanelTreeBranch(uuid)(treePicker);
39     return nodes.map(node =>
40         typeof node.value === 'string'
41             ? { label: node.value, uuid: node.id }
42             : { label: node.value.name, uuid: node.value.uuid });
43 };
44
45 export const setSidePanelBreadcrumbs = (uuid: string) =>
46     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
47         const { treePicker, collectionPanel: { item } } = getState();
48         const breadcrumbs = getSidePanelTreeBreadcrumbs(uuid)(treePicker);
49         const path = getState().router.location!.pathname;
50         const currentUuid = path.split('/')[2];
51         const uuidKind = extractUuidKind(currentUuid);
52
53         if (uuidKind === ResourceKind.COLLECTION) {
54             const collectionItem = item ? item : await services.collectionService.get(currentUuid);
55             dispatch(setBreadcrumbs(breadcrumbs, collectionItem));
56         } else if (uuidKind === ResourceKind.PROCESS) {
57             const processItem = await services.containerRequestService.get(currentUuid);
58             dispatch(setBreadcrumbs(breadcrumbs, processItem));
59         }
60         dispatch(setBreadcrumbs(breadcrumbs));
61     };
62
63 export const setSharedWithMeBreadcrumbs = (uuid: string) =>
64     setCategoryBreadcrumbs(uuid, SidePanelTreeCategory.SHARED_WITH_ME);
65
66 export const setTrashBreadcrumbs = (uuid: string) =>
67     setCategoryBreadcrumbs(uuid, SidePanelTreeCategory.TRASH);
68
69 export const setCategoryBreadcrumbs = (uuid: string, category: string) =>
70     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
71         const ancestors = await services.ancestorsService.ancestors(uuid, '');
72         dispatch(updateResources(ancestors));
73         const initialBreadcrumbs: ResourceBreadcrumb[] = [
74             { label: category, uuid: category }
75         ];
76         const { collectionPanel: { item } } = getState();
77         const path = getState().router.location!.pathname;
78         const currentUuid = path.split('/')[2];
79         const uuidKind = extractUuidKind(currentUuid);
80         const breadcrumbs = ancestors.reduce((breadcrumbs, ancestor) =>
81             ancestor.kind === ResourceKind.GROUP
82                 ? [...breadcrumbs, { label: ancestor.name, uuid: ancestor.uuid }]
83                 : breadcrumbs,
84             initialBreadcrumbs);
85         if (uuidKind === ResourceKind.COLLECTION) {
86             const collectionItem = item ? item : await services.collectionService.get(currentUuid);
87             dispatch(setBreadcrumbs(breadcrumbs, collectionItem));
88         } else if (uuidKind === ResourceKind.PROCESS) {
89             const processItem = await services.containerRequestService.get(currentUuid);
90             dispatch(setBreadcrumbs(breadcrumbs, processItem));
91         }
92         dispatch(setBreadcrumbs(breadcrumbs));
93     };
94
95 export const setProjectBreadcrumbs = (uuid: string) =>
96     (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
97         const ancestors = getSidePanelTreeNodeAncestorsIds(uuid)(getState().treePicker);
98         const rootUuid = getUserUuid(getState());
99         if (uuid === rootUuid || ancestors.find(uuid => uuid === rootUuid)) {
100             dispatch(setSidePanelBreadcrumbs(uuid));
101         } else {
102             dispatch(setSharedWithMeBreadcrumbs(uuid));
103             dispatch(activateSidePanelTreeItem(SidePanelTreeCategory.SHARED_WITH_ME));
104         }
105     };
106
107 export const setProcessBreadcrumbs = (processUuid: string) =>
108     (dispatch: Dispatch, getState: () => RootState) => {
109         const { resources } = getState();
110         const process = getProcess(processUuid)(resources);
111         if (process) {
112             dispatch<any>(setProjectBreadcrumbs(process.containerRequest.ownerUuid));
113         }
114     };
115
116 export const setGroupsBreadcrumbs = () =>
117     setBreadcrumbs([{ label: SidePanelTreeCategory.GROUPS }]);
118
119 export const setGroupDetailsBreadcrumbs = (groupUuid: string) =>
120     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
121
122         const group = getResource<GroupResource>(groupUuid)(getState().resources);
123
124         const breadcrumbs: ResourceBreadcrumb[] = [
125             { label: SidePanelTreeCategory.GROUPS, uuid: SidePanelTreeCategory.GROUPS },
126             { label: group ? group.name : (await services.groupsService.get(groupUuid)).name, uuid: groupUuid },
127         ];
128
129         dispatch(setBreadcrumbs(breadcrumbs));
130
131     };
132
133 export const USERS_PANEL_LABEL = 'Users';
134
135 export const setUsersBreadcrumbs = () =>
136     setBreadcrumbs([{ label: USERS_PANEL_LABEL, uuid: USERS_PANEL_LABEL }]);
137
138 export const setUserProfileBreadcrumbs = (userUuid: string) =>
139     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
140         try {
141             const user = getResource<UserResource>(userUuid)(getState().resources)
142                         || await services.userService.get(userUuid, false);
143             const breadcrumbs: ResourceBreadcrumb[] = [
144                 { label: USERS_PANEL_LABEL, uuid: USERS_PANEL_LABEL },
145                 { label: user ? user.username : userUuid, uuid: userUuid },
146             ];
147             dispatch(setBreadcrumbs(breadcrumbs));
148         } catch (e) {
149             const breadcrumbs: ResourceBreadcrumb[] = [
150                 { label: USERS_PANEL_LABEL, uuid: USERS_PANEL_LABEL },
151                 { label: userUuid, uuid: userUuid },
152             ];
153             dispatch(setBreadcrumbs(breadcrumbs));
154         }
155     };
156
157 export const MY_ACCOUNT_PANEL_LABEL = 'My Account';
158
159 export const setMyAccountBreadcrumbs = () =>
160     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
161         dispatch(setBreadcrumbs([
162             { label: MY_ACCOUNT_PANEL_LABEL, uuid: MY_ACCOUNT_PANEL_LABEL },
163         ]));
164     };