17074: Cleanup and refactor public favorites middleware
[arvados.git] / services / workbench2 / src / store / public-favorites-panel / public-favorites-middleware-service.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { ServiceRepository } from 'services/services';
6 import { MiddlewareAPI, Dispatch } from 'redux';
7 import { DataExplorerMiddlewareService, dataExplorerToListParams, getDataExplorerColumnFilters, listResultsToDataExplorerItemsMeta } from 'store/data-explorer/data-explorer-middleware-service';
8 import { RootState } from 'store/store';
9 import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
10 import { DataExplorer, getDataExplorer } from 'store/data-explorer/data-explorer-reducer';
11 import { resourcesActions } from 'store/resources/resources-actions';
12 import { FilterBuilder } from 'services/api/filter-builder';
13 import { FavoritePanelColumnNames } from 'views/favorite-panel/favorite-panel';
14 import { publicFavoritePanelActions } from 'store/public-favorites-panel/public-favorites-action';
15 import { DataColumns } from 'components/data-table/data-table';
16 import { serializeSimpleObjectTypeFilters } from '../resource-type-filters/resource-type-filters';
17 import { LinkClass } from 'models/link';
18 import { progressIndicatorActions } from 'store/progress-indicator/progress-indicator-actions';
19 import { updatePublicFavorites } from 'store/public-favorites/public-favorites-actions';
20 import { GroupContentsResource } from 'services/groups-service/groups-service';
21 import { ListArguments } from 'services/common-service/common-service';
22
23 export class PublicFavoritesMiddlewareService extends DataExplorerMiddlewareService {
24     constructor(private services: ServiceRepository, id: string) {
25         super(id);
26     }
27
28     getTypeFilters(dataExplorer: DataExplorer) {
29         const columns = dataExplorer.columns as DataColumns<string, GroupContentsResource>;
30         return serializeSimpleObjectTypeFilters(getDataExplorerColumnFilters(columns, FavoritePanelColumnNames.TYPE));
31     }
32
33     getLinkFilters(dataExplorer: DataExplorer, publicProjectUuid: string): string {
34         return new FilterBuilder()
35             .addEqual('link_class', LinkClass.STAR)
36             .addEqual('owner_uuid', publicProjectUuid)
37             .addIsA("head_uuid", this.getTypeFilters(dataExplorer))
38             .getFilters();
39     }
40
41     getResourceFilters(dataExplorer: DataExplorer, uuids: string[]): string {
42         return new FilterBuilder()
43             .addIn("uuid", uuids)
44             .addILike("name", dataExplorer.searchValue)
45             .addIsA("uuid", this.getTypeFilters(dataExplorer))
46             .getFilters();
47     }
48
49     getLinkParams(dataExplorer: DataExplorer, publicProjectUuid: string): ListArguments {
50         return {
51             ...dataExplorerToListParams(dataExplorer),
52             filters: this.getLinkFilters(dataExplorer, publicProjectUuid),
53             count: "none",
54         };
55     }
56
57     async requestItems(api: MiddlewareAPI<Dispatch, RootState>, criteriaChanged?: boolean, background?: boolean) {
58         const dataExplorer = getDataExplorer(api.getState().dataExplorer, this.getId());
59         if (!dataExplorer) {
60             api.dispatch(favoritesPanelDataExplorerIsNotSet());
61         } else {
62             try {
63                 api.dispatch(progressIndicatorActions.START_WORKING(this.getId()));
64                 const uuidPrefix = api.getState().auth.config.uuidPrefix;
65                 const publicProjectUuid = `${uuidPrefix}-j7d0g-publicfavorites`;
66
67                 // Get items
68                 const responseLinks = await this.services.linkService.list(this.getLinkParams(dataExplorer, publicProjectUuid));
69                 const uuids = responseLinks.items.map(it => it.headUuid);
70
71                 const groupItems = await this.services.groupsService.list({
72                     filters: this.getResourceFilters(dataExplorer, uuids),
73                 });
74                 const collectionItems = await this.services.collectionService.list({
75                     filters: this.getResourceFilters(dataExplorer, uuids),
76                 });
77                 const processItems = await this.services.containerRequestService.list({
78                     filters: this.getResourceFilters(dataExplorer, uuids),
79                 });
80
81                 const orderedItems = [
82                     ...groupItems.items,
83                     ...collectionItems.items,
84                     ...processItems.items
85                 ];
86
87                 api.dispatch(resourcesActions.SET_RESOURCES(orderedItems));
88                 api.dispatch(publicFavoritePanelActions.SET_ITEMS({
89                     ...listResultsToDataExplorerItemsMeta(responseLinks),
90                     items: orderedItems.map((resource: any) => resource.uuid),
91                 }));
92                 api.dispatch<any>(updatePublicFavorites(uuids));
93             } catch (e) {
94                 api.dispatch(publicFavoritePanelActions.SET_ITEMS({
95                     items: [],
96                     itemsAvailable: 0,
97                     page: 0,
98                     rowsPerPage: dataExplorer.rowsPerPage
99                 }));
100                 api.dispatch(couldNotFetchPublicFavorites());
101             } finally {
102                 api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId()));
103             }
104         }
105     }
106 }
107
108 const favoritesPanelDataExplorerIsNotSet = () =>
109     snackbarActions.OPEN_SNACKBAR({
110         message: 'Favorites panel is not ready.',
111         kind: SnackbarKind.ERROR
112     });
113
114 const couldNotFetchPublicFavorites = () =>
115     snackbarActions.OPEN_SNACKBAR({
116         message: 'Could not fetch public favorites contents.',
117         kind: SnackbarKind.ERROR
118     });