Merge branch '22235-toolbar-access-fixes'
[arvados.git] / services / workbench2 / src / store / processes / processes-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 {
8     DataExplorerMiddlewareService, dataExplorerToListParams, listResultsToDataExplorerItemsMeta, getDataExplorerColumnFilters, getOrder
9 } from 'store/data-explorer/data-explorer-middleware-service';
10 import { RootState } from 'store/store';
11 import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
12 import { DataExplorer, getDataExplorer } from 'store/data-explorer/data-explorer-reducer';
13 import { BoundDataExplorerActions, couldNotFetchItemsAvailable } from 'store/data-explorer/data-explorer-action';
14 import { updateResources } from 'store/resources/resources-actions';
15 import { ListArguments, ListResults } from 'services/common-service/common-service';
16 import { ContentsArguments } from 'services/groups-service/groups-service';
17 import { ProcessResource } from 'models/process';
18 import { FilterBuilder } from 'services/api/filter-builder';
19 import { DataColumns } from 'components/data-table/data-column';
20 import { ProcessStatusFilter, buildProcessStatusFilters } from '../resource-type-filters/resource-type-filters';
21 import { ContainerRequestResource, containerRequestFieldsNoMounts } from 'models/container-request';
22 import { progressIndicatorActions } from '../progress-indicator/progress-indicator-actions';
23 import { containerFieldsNoMounts } from 'store/processes/processes-actions';
24
25     export class ProcessesMiddlewareService extends DataExplorerMiddlewareService {
26         constructor(private services: ServiceRepository, private actions: BoundDataExplorerActions, id: string) {
27         super(id);
28     }
29
30     getFilters(api: MiddlewareAPI<Dispatch, RootState>, dataExplorer: DataExplorer): string | null {
31         const columns = dataExplorer.columns as DataColumns<string, ContainerRequestResource>;
32         const statusColumnFilters = getDataExplorerColumnFilters(columns, 'Status');
33         const activeStatusFilter = Object.keys(statusColumnFilters).find(
34             filterName => statusColumnFilters[filterName].selected
35         ) || ProcessStatusFilter.ALL;
36
37
38         let filters = new FilterBuilder().addIsA('uuid', 'arvados#containerRequest');
39         if (dataExplorer.searchValue && dataExplorer.searchValue !== "") {
40             filters = filters.addILike("name", dataExplorer.searchValue);
41         }
42
43         return buildProcessStatusFilters(filters, activeStatusFilter).getFilters();
44     }
45
46
47     getParams(api: MiddlewareAPI<Dispatch, RootState>, dataExplorer: DataExplorer): ContentsArguments | null {
48         const filters = this.getFilters(api, dataExplorer)
49         if (filters === null) {
50             return null;
51         }
52         return {
53             ...dataExplorerToListParams(dataExplorer),
54             filters,
55             order: getOrder<ProcessResource>(dataExplorer),
56             select: containerRequestFieldsNoMounts,
57             count: 'none',
58             include: ["owner_uuid", "container_uuid"]
59         };
60     }
61
62     getCountParams(api: MiddlewareAPI<Dispatch, RootState>, dataExplorer: DataExplorer): ListArguments | null {
63         const filters = this.getFilters(api, dataExplorer);
64         if (filters === null) {
65             return null;
66         }
67         return {
68             filters,
69             limit: 0,
70             count: 'exact',
71         };
72     }
73
74     async requestItems(api: MiddlewareAPI<Dispatch, RootState>, criteriaChanged?: boolean, background?: boolean) {
75         const state = api.getState();
76         const dataExplorer = getDataExplorer(state.dataExplorer, this.getId());
77
78         try {
79             if (!background) { api.dispatch(progressIndicatorActions.START_WORKING(this.getId())); }
80             const params = this.getParams(api, dataExplorer);
81
82             // Get items
83             if (params !== null) {
84                 const containerRequests = await this.services.groupsService.contents('',
85                     {
86                         ...this.getParams(api, dataExplorer),
87                         select: [...containerRequestFieldsNoMounts, "can_write", "can_manage"].concat(containerFieldsNoMounts)
88                 });
89                 api.dispatch(updateResources(containerRequests.items));
90                 if (containerRequests.included) {
91                     api.dispatch(updateResources(containerRequests.included));
92                 }
93
94                 api.dispatch(this.actions.SET_ITEMS({
95                     ...listResultsToDataExplorerItemsMeta(containerRequests),
96                     items: containerRequests.items.map(resource => resource.uuid),
97                 }));
98             } else {
99                 api.dispatch(this.actions.SET_ITEMS({
100                     itemsAvailable: 0,
101                     page: 0,
102                     rowsPerPage: dataExplorer.rowsPerPage,
103                     items: [],
104                 }));
105             }
106         } catch {
107             api.dispatch(snackbarActions.OPEN_SNACKBAR({
108                 message: 'Could not fetch process list.',
109                 kind: SnackbarKind.ERROR
110             }));
111         } finally {
112             if (!background) { api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId())); }
113         }
114     }
115
116     async requestCount(api: MiddlewareAPI<Dispatch, RootState>, criteriaChanged?: boolean, background?: boolean) {
117         const state = api.getState();
118         const dataExplorer = getDataExplorer(state.dataExplorer, this.getId());
119         const countParams = this.getCountParams(api, dataExplorer);
120
121         if (criteriaChanged && countParams !== null) {
122             // Get itemsAvailable
123             return this.services.groupsService.contents('', countParams)
124                        .then((results: ListResults<ContainerRequestResource>) => {
125                     if (results.itemsAvailable !== undefined) {
126                         api.dispatch<any>(this.actions.SET_ITEMS_AVAILABLE(results.itemsAvailable));
127                     } else {
128                         couldNotFetchItemsAvailable();
129                     }
130                 });
131         }
132     }
133 }