Merge branch 'main' into 21224-project-details
[arvados.git] / services / workbench2 / src / store / details-panel / details-panel-action.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { unionize, ofType, UnionOf } from 'common/unionize';
6 import { RootState } from 'store/store';
7 import { Dispatch } from 'redux';
8 import { getResource } from 'store/resources/resources';
9 import { ServiceRepository } from 'services/services';
10 import { resourcesActions } from 'store/resources/resources-actions';
11 import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
12 import { FilterBuilder } from 'services/api/filter-builder';
13 import { OrderBuilder } from 'services/api/order-builder';
14 import { CollectionResource } from 'models/collection';
15 import { extractUuidKind, ResourceKind } from 'models/resource';
16
17 export const SLIDE_TIMEOUT = 500;
18 export const CLOSE_DRAWER = 'CLOSE_DRAWER'
19
20 export const detailsPanelActions = unionize({
21     TOGGLE_DETAILS_PANEL: ofType<{}>(),
22     OPEN_DETAILS_PANEL: ofType<number>(),
23     LOAD_DETAILS_PANEL: ofType<string>(),
24     START_TRANSITION: ofType<{}>(),
25     END_TRANSITION: ofType<{}>(),
26 });
27
28 export type DetailsPanelAction = UnionOf<typeof detailsPanelActions>;
29
30 export const loadDetailsPanel = (uuid: string) =>
31     (dispatch: Dispatch, getState: () => RootState) => {
32         if (getState().detailsPanel.isOpened) {
33             switch(extractUuidKind(uuid)) {
34                 case ResourceKind.COLLECTION:
35                     const c = getResource<CollectionResource>(uuid)(getState().resources);
36                     dispatch<any>(refreshCollectionVersionsList(c!.currentVersionUuid));
37                     break;
38                 default:
39                     break;
40             }
41         }
42         dispatch(detailsPanelActions.LOAD_DETAILS_PANEL(uuid));
43     };
44
45 export const openDetailsPanel = (uuid?: string, tabNr: number = 0) =>
46     (dispatch: Dispatch) => {
47         startDetailsPanelTransition(dispatch)
48         dispatch(detailsPanelActions.OPEN_DETAILS_PANEL(tabNr));
49         if (uuid !== undefined) {
50             dispatch<any>(loadDetailsPanel(uuid));
51         }
52     };
53
54 export const refreshCollectionVersionsList = (uuid: string) =>
55     (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
56         services.collectionService.list({
57             filters: new FilterBuilder()
58                 .addEqual('current_version_uuid', uuid)
59                 .getFilters(),
60             includeOldVersions: true,
61             order: new OrderBuilder<CollectionResource>().addDesc("version").getOrder()
62         }).then(versions => dispatch(resourcesActions.SET_RESOURCES(versions.items))
63         ).catch(e => snackbarActions.OPEN_SNACKBAR({
64             message: `Couldn't retrieve versions: ${e.errors[0]}`,
65             hideDuration: 2000,
66             kind: SnackbarKind.ERROR })
67         );
68     };
69
70 export const toggleDetailsPanel = (uuid: string = '') => (dispatch: Dispatch, getState: () => RootState) => {
71     const { detailsPanel }= getState()
72     const isTargetUuidNew = uuid !== detailsPanel.resourceUuid
73     if(isTargetUuidNew && uuid !== CLOSE_DRAWER && detailsPanel.isOpened){
74         dispatch<any>(loadDetailsPanel(uuid));
75     } else {
76         // because of material-ui issue resizing details panel breaks tabs.
77         // triggering window resize event fixes that.
78         setTimeout(() => {
79             window.dispatchEvent(new Event('resize'));
80         }, SLIDE_TIMEOUT);
81         startDetailsPanelTransition(dispatch)
82         dispatch(detailsPanelActions.TOGGLE_DETAILS_PANEL());
83         if (getState().detailsPanel.isOpened) {
84             dispatch<any>(loadDetailsPanel(isTargetUuidNew ? uuid : detailsPanel.resourceUuid));
85         }
86     }
87     };
88     
89     const startDetailsPanelTransition = (dispatch) => {
90         dispatch(detailsPanelActions.START_TRANSITION())
91     setTimeout(() => {
92         dispatch(detailsPanelActions.END_TRANSITION())
93     }, SLIDE_TIMEOUT);
94 }