Merge branch '22217-packer-keypair-type'
[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-column';
16 import { serializeSimpleObjectTypeFilters } from '../resource-type-filters/resource-type-filters';
17 import { LinkClass, LinkResource } 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, ListResults } from 'services/common-service/common-service';
22 import { couldNotFetchItemsAvailable } from 'store/data-explorer/data-explorer-action';
23
24 export class PublicFavoritesMiddlewareService extends DataExplorerMiddlewareService {
25     constructor(private services: ServiceRepository, id: string) {
26         super(id);
27     }
28
29     getTypeFilters(dataExplorer: DataExplorer) {
30         const columns = dataExplorer.columns as DataColumns<string, GroupContentsResource>;
31         return serializeSimpleObjectTypeFilters(getDataExplorerColumnFilters(columns, FavoritePanelColumnNames.TYPE));
32     }
33
34     getLinkFilters(dataExplorer: DataExplorer, publicProjectUuid: string): string {
35         return new FilterBuilder()
36             .addEqual('link_class', LinkClass.STAR)
37             .addEqual('owner_uuid', publicProjectUuid)
38             .addIsA("head_uuid", this.getTypeFilters(dataExplorer))
39             .getFilters();
40     }
41
42     getResourceFilters(dataExplorer: DataExplorer, uuids: string[]): string {
43         return new FilterBuilder()
44             .addIn("uuid", uuids)
45             .addILike("name", dataExplorer.searchValue)
46             .addIsA("uuid", this.getTypeFilters(dataExplorer))
47             .getFilters();
48     }
49
50     getLinkParams(dataExplorer: DataExplorer, publicProjectUuid: string): ListArguments {
51         return {
52             ...dataExplorerToListParams(dataExplorer),
53             filters: this.getLinkFilters(dataExplorer, publicProjectUuid),
54             count: "none",
55         };
56     }
57
58     getCountParams(dataExplorer: DataExplorer, publicProjectUuid: string): ListArguments {
59         return {
60             filters: this.getLinkFilters(dataExplorer, publicProjectUuid),
61             limit: 0,
62             count: "exact",
63         };
64     }
65
66     async requestItems(api: MiddlewareAPI<Dispatch, RootState>, criteriaChanged?: boolean, background?: boolean) {
67         const dataExplorer = getDataExplorer(api.getState().dataExplorer, this.getId());
68         if (!dataExplorer) {
69             api.dispatch(favoritesPanelDataExplorerIsNotSet());
70         } else {
71             try {
72                 if (!background) { api.dispatch(progressIndicatorActions.START_WORKING(this.getId())); }
73
74                 const uuidPrefix = api.getState().auth.config.uuidPrefix;
75                 const publicProjectUuid = `${uuidPrefix}-j7d0g-publicfavorites`;
76
77                 // Get items
78                 const responseLinks = await this.services.linkService.list(this.getLinkParams(dataExplorer, publicProjectUuid));
79                 const uuids = responseLinks.items.map(it => it.headUuid);
80
81                 const orderedItems = await this.services.groupsService.contents("", {
82                     filters: this.getResourceFilters(dataExplorer, uuids),
83                     include: ["owner_uuid", "container_uuid"],
84                 });
85
86                 api.dispatch(resourcesActions.SET_RESOURCES(orderedItems.items));
87                 api.dispatch(resourcesActions.SET_RESOURCES(orderedItems.included));
88                 api.dispatch(publicFavoritePanelActions.SET_ITEMS({
89                     ...listResultsToDataExplorerItemsMeta(responseLinks),
90                     items: orderedItems.items.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     async requestCount(api: MiddlewareAPI<Dispatch, RootState>, criteriaChanged?: boolean, background?: boolean) {
108         const state = api.getState();
109         const dataExplorer = getDataExplorer(state.dataExplorer, this.getId());
110         const uuidPrefix = api.getState().auth.config.uuidPrefix;
111         const publicProjectUuid = `${uuidPrefix}-j7d0g-publicfavorites`;
112
113         if (criteriaChanged) {
114             // Get itemsAvailable
115             return this.services.linkService.list(this.getCountParams(dataExplorer, publicProjectUuid))
116                 .then((results: ListResults<LinkResource>) => {
117                     if (results.itemsAvailable !== undefined) {
118                         api.dispatch<any>(publicFavoritePanelActions.SET_ITEMS_AVAILABLE(results.itemsAvailable));
119                     } else {
120                         couldNotFetchItemsAvailable();
121                     }
122                 });
123         }
124     }
125 }
126
127 const favoritesPanelDataExplorerIsNotSet = () =>
128     snackbarActions.OPEN_SNACKBAR({
129         message: 'Favorites panel is not ready.',
130         kind: SnackbarKind.ERROR
131     });
132
133 const couldNotFetchPublicFavorites = () =>
134     snackbarActions.OPEN_SNACKBAR({
135         message: 'Could not fetch public favorites contents.',
136         kind: SnackbarKind.ERROR
137     });