Merge branch '22134-railsapi-envvars'
[arvados.git] / services / workbench2 / src / store / favorite-panel / favorite-panel-middleware-service.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { DataExplorerMiddlewareService, dataExplorerToListParams, listResultsToDataExplorerItemsMeta } from "store/data-explorer/data-explorer-middleware-service";
6 import { FavoritePanelColumnNames } from "views/favorite-panel/favorite-panel";
7 import { RootState } from "../store";
8 import { getUserUuid } from "common/getuser";
9 import { DataColumns } from "components/data-table/data-table";
10 import { ServiceRepository } from "services/services";
11 import { FilterBuilder } from "services/api/filter-builder";
12 import { updateFavorites } from "../favorites/favorites-actions";
13 import { favoritePanelActions } from "./favorite-panel-action";
14 import { Dispatch, MiddlewareAPI } from "redux";
15 import { resourcesActions } from "store/resources/resources-actions";
16 import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
17 import { progressIndicatorActions } from 'store/progress-indicator/progress-indicator-actions';
18 import { DataExplorer, getDataExplorer } from "store/data-explorer/data-explorer-reducer";
19 import { getDataExplorerColumnFilters } from 'store/data-explorer/data-explorer-middleware-service';
20 import { serializeSimpleObjectTypeFilters } from '../resource-type-filters/resource-type-filters';
21 import { ResourceKind } from "models/resource";
22 import { LinkClass, LinkResource } from "models/link";
23 import { GroupContentsResource } from "services/groups-service/groups-service";
24 import { ListArguments, ListResults } from "services/common-service/common-service";
25 import { couldNotFetchItemsAvailable } from "store/data-explorer/data-explorer-action";
26
27 export class FavoritePanelMiddlewareService extends DataExplorerMiddlewareService {
28     constructor(private services: ServiceRepository, id: string) {
29         super(id);
30     }
31
32     getTypeFilters(dataExplorer: DataExplorer) {
33         const columns = dataExplorer.columns as DataColumns<string, GroupContentsResource>;
34         return serializeSimpleObjectTypeFilters(getDataExplorerColumnFilters(columns, FavoritePanelColumnNames.TYPE));
35     }
36
37     getLinkFilters(dataExplorer: DataExplorer, uuid: string): string {
38         return new FilterBuilder()
39             .addEqual("link_class", LinkClass.STAR)
40             .addEqual('tail_uuid', uuid)
41             .addEqual('tail_kind', ResourceKind.USER)
42             .addIsA("head_uuid", this.getTypeFilters(dataExplorer))
43             .getFilters();
44     }
45
46     getResourceFilters(dataExplorer: DataExplorer, uuids: string[]): string {
47         return new FilterBuilder()
48             .addIn("uuid", uuids)
49             .addILike("name", dataExplorer.searchValue)
50             .addIsA("uuid", this.getTypeFilters(dataExplorer))
51             .getFilters();
52     }
53
54     getLinkParams(dataExplorer: DataExplorer, uuid: string): ListArguments {
55         return {
56             ...dataExplorerToListParams(dataExplorer),
57             filters: this.getLinkFilters(dataExplorer, uuid),
58             count: "none",
59         };
60     }
61
62     getCountParams(dataExplorer: DataExplorer, uuid: string): ListArguments {
63         return {
64             filters: this.getLinkFilters(dataExplorer, uuid),
65             limit: 0,
66             count: "exact",
67         };
68     }
69
70     async requestItems(api: MiddlewareAPI<Dispatch, RootState>, criteriaChanged?: boolean, background?: boolean) {
71         const dataExplorer = getDataExplorer(api.getState().dataExplorer, this.getId());
72         const uuid = getUserUuid(api.getState());
73         if (!dataExplorer) {
74             api.dispatch(favoritesPanelDataExplorerIsNotSet());
75         } else if (!uuid || !uuid.length) {
76             userNotAvailable();
77         } else {
78             try {
79                 if (!background) { api.dispatch(progressIndicatorActions.START_WORKING(this.getId())); }
80
81                 // Get items
82                 const responseLinks = await this.services.linkService.list(this.getLinkParams(dataExplorer, uuid));
83                 const uuids = responseLinks.items.map(it => it.headUuid);
84
85                 const orderedItems = await this.services.groupsService.contents("", {
86                     filters: this.getResourceFilters(dataExplorer, uuids),
87                     include: ["owner_uuid", "container_uuid"],
88                 });
89
90                 api.dispatch(resourcesActions.SET_RESOURCES(orderedItems.items));
91                 api.dispatch(resourcesActions.SET_RESOURCES(orderedItems.included));
92                 api.dispatch(favoritePanelActions.SET_ITEMS({
93                     ...listResultsToDataExplorerItemsMeta(responseLinks),
94                     items: orderedItems.items.map((resource: any) => resource.uuid),
95                 }));
96                 api.dispatch<any>(updateFavorites(uuids));
97             } catch (e) {
98                 api.dispatch(favoritePanelActions.SET_ITEMS({
99                     items: [],
100                     itemsAvailable: 0,
101                     page: 0,
102                     rowsPerPage: dataExplorer.rowsPerPage
103                 }));
104                 api.dispatch(couldNotFetchFavoritesContents());
105             } finally {
106                 api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId()));
107             }
108         }
109     }
110
111     async requestCount(api: MiddlewareAPI<Dispatch, RootState>, criteriaChanged?: boolean, background?: boolean) {
112         const state = api.getState();
113         const dataExplorer = getDataExplorer(state.dataExplorer, this.getId());
114         const uuid = getUserUuid(api.getState());
115
116         if (criteriaChanged && uuid && uuid.length) {
117             // Get itemsAvailable
118             return this.services.linkService.list(this.getCountParams(dataExplorer, uuid))
119                 .then((results: ListResults<LinkResource>) => {
120                     if (results.itemsAvailable !== undefined) {
121                         api.dispatch<any>(favoritePanelActions.SET_ITEMS_AVAILABLE(results.itemsAvailable));
122                     } else {
123                         couldNotFetchItemsAvailable();
124                     }
125                 });
126         }
127     }
128 }
129
130 const favoritesPanelDataExplorerIsNotSet = () =>
131     snackbarActions.OPEN_SNACKBAR({
132         message: 'Favorites panel is not ready.',
133         kind: SnackbarKind.ERROR
134     });
135
136 const couldNotFetchFavoritesContents = () =>
137     snackbarActions.OPEN_SNACKBAR({
138         message: 'Could not fetch favorites contents.',
139         kind: SnackbarKind.ERROR
140     });
141
142 const userNotAvailable = () =>
143     snackbarActions.OPEN_SNACKBAR({
144         message: 'User favorites not available.',
145         kind: SnackbarKind.ERROR
146     });