Merge branch '21128-toolbar-context-menu'
[arvados-workbench2.git] / src / store / subprocess-panel / subprocess-panel-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 { updateResources } from 'store/resources/resources-actions';
14 import { ListResults } from 'services/common-service/common-service';
15 import { ProcessResource } from 'models/process';
16 import { FilterBuilder, joinFilters } from 'services/api/filter-builder';
17 import { subprocessPanelActions } from './subprocess-panel-actions';
18 import { DataColumns } from 'components/data-table/data-table';
19 import { ProcessStatusFilter, buildProcessStatusFilters } from '../resource-type-filters/resource-type-filters';
20 import { ContainerRequestResource, containerRequestFieldsNoMounts } from 'models/container-request';
21 import { progressIndicatorActions } from '../progress-indicator/progress-indicator-actions';
22 import { loadMissingProcessesInformation } from '../project-panel/project-panel-middleware-service';
23
24 export class SubprocessMiddlewareService extends DataExplorerMiddlewareService {
25     constructor(private services: ServiceRepository, id: string) {
26         super(id);
27     }
28
29     async requestItems(api: MiddlewareAPI<Dispatch, RootState>, criteriaChanged?: boolean, background?: boolean) {
30         const state = api.getState();
31         const parentContainerRequestUuid = state.processPanel.containerRequestUuid;
32         if (parentContainerRequestUuid === "") { return; }
33         const dataExplorer = getDataExplorer(state.dataExplorer, this.getId());
34
35         try {
36             if (!background) { api.dispatch(progressIndicatorActions.START_WORKING(this.getId())); }
37             const parentContainerRequest = await this.services.containerRequestService.get(parentContainerRequestUuid);
38             if (parentContainerRequest.containerUuid) {
39                 const containerRequests = await this.services.containerRequestService.list(
40                     {
41                         ...getParams(dataExplorer, parentContainerRequest),
42                         select: containerRequestFieldsNoMounts
43                     });
44                 api.dispatch(updateResources(containerRequests.items));
45                 await api.dispatch<any>(loadMissingProcessesInformation(containerRequests.items));
46                 // Populate the actual user view
47                 api.dispatch(setItems(containerRequests));
48             }
49             if (!background) { api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId())); }
50         } catch {
51             if (!background) { api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId())); }
52             api.dispatch(couldNotFetchSubprocesses());
53         }
54     }
55 }
56
57 export const getParams = (
58     dataExplorer: DataExplorer,
59     parentContainerRequest: ContainerRequestResource) => ({
60         ...dataExplorerToListParams(dataExplorer),
61         order: getOrder<ProcessResource>(dataExplorer),
62         filters: getFilters(dataExplorer, parentContainerRequest)
63     });
64
65 export const getFilters = (
66     dataExplorer: DataExplorer,
67     parentContainerRequest: ContainerRequestResource) => {
68     const columns = dataExplorer.columns as DataColumns<string, ProcessResource>;
69     const statusColumnFilters = getDataExplorerColumnFilters(columns, 'Status');
70     const activeStatusFilter = Object.keys(statusColumnFilters).find(
71         filterName => statusColumnFilters[filterName].selected
72     ) || ProcessStatusFilter.ALL;
73
74     // Get all the subprocess' container requests and containers.
75     const fb = new FilterBuilder().addEqual('requesting_container_uuid', parentContainerRequest.containerUuid);
76     const statusFilters = buildProcessStatusFilters(fb, activeStatusFilter).getFilters();
77
78     const nameFilters = dataExplorer.searchValue
79         ? new FilterBuilder()
80             .addILike("name", dataExplorer.searchValue)
81             .getFilters()
82         : '';
83
84     return joinFilters(
85         nameFilters,
86         statusFilters
87     );
88 };
89
90 export const setItems = (listResults: ListResults<ProcessResource>) =>
91     subprocessPanelActions.SET_ITEMS({
92         ...listResultsToDataExplorerItemsMeta(listResults),
93         items: listResults.items.map(resource => resource.uuid),
94     });
95
96 const couldNotFetchSubprocesses = () =>
97     snackbarActions.OPEN_SNACKBAR({
98         message: 'Could not fetch subprocesses.',
99         kind: SnackbarKind.ERROR
100     });