From 68dee98de77221374456e635881f7e268f2745ea Mon Sep 17 00:00:00 2001 From: Peter Amstutz Date: Fri, 27 Oct 2023 16:05:18 -0400 Subject: [PATCH] 21158: Refactor Process list middleware to a common base class Arvados-DCO-1.1-Signed-off-by: Peter Amstutz --- .../all-processes-panel-middleware-service.ts | 86 +++-------------- .../data-explorer/data-explorer-action.ts | 2 + .../processes/processes-middleware-service.ts | 95 +++++++++++++++++++ .../subprocess-panel-middleware-service.ts | 87 ++++------------- 4 files changed, 125 insertions(+), 145 deletions(-) create mode 100644 src/store/processes/processes-middleware-service.ts diff --git a/src/store/all-processes-panel/all-processes-panel-middleware-service.ts b/src/store/all-processes-panel/all-processes-panel-middleware-service.ts index 955d9689af..e6d0192dad 100644 --- a/src/store/all-processes-panel/all-processes-panel-middleware-service.ts +++ b/src/store/all-processes-panel/all-processes-panel-middleware-service.ts @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: AGPL-3.0 -import { DataExplorerMiddlewareService, dataExplorerToListParams, getDataExplorerColumnFilters, getOrder } from "store/data-explorer/data-explorer-middleware-service"; +import { dataExplorerToListParams, getDataExplorerColumnFilters, getOrder } from "store/data-explorer/data-explorer-middleware-service"; import { RootState } from "../store"; import { ServiceRepository } from "services/services"; import { FilterBuilder, joinFilters } from "services/api/filter-builder"; @@ -20,82 +20,20 @@ import { serializeOnlyProcessTypeFilters } from "../resource-type-filters/resource-type-filters"; import { AllProcessesPanelColumnNames } from "views/all-processes-panel/all-processes-panel"; -import { containerRequestFieldsNoMounts, ContainerRequestResource } from "models/container-request"; +import { ProcessesMiddlewareService } from "store/processes/processes-middleware-service"; +import { ContainerRequestResource } from 'models/container-request'; -export class AllProcessesPanelMiddlewareService extends DataExplorerMiddlewareService { - constructor(private services: ServiceRepository, id: string) { - super(id); +export class AllProcessesPanelMiddlewareService extends ProcessesMiddlewareService { + constructor(services: ServiceRepository, id: string) { + super(services, allProcessesPanelActions, id); } - async requestItems(api: MiddlewareAPI, criteriaChanged?: boolean, background?: boolean) { - const dataExplorer = getDataExplorer(api.getState().dataExplorer, this.getId()); - if (!dataExplorer) { - api.dispatch(allProcessesPanelDataExplorerIsNotSet()); - } else { - try { - if (!background) { api.dispatch(progressIndicatorActions.START_WORKING(this.getId())); } - const processItems = await this.services.containerRequestService.list( - { - ...getParams(dataExplorer), - // Omit mounts when viewing all process panel - select: containerRequestFieldsNoMounts, - }); + getFilters(api: MiddlewareAPI, dataExplorer: DataExplorer): string | null { + const sup = super.getFilters(api, dataExplorer); + if (sup === null) { return null; } + const columns = dataExplorer.columns as DataColumns; - if (!background) { api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId())); } - api.dispatch(resourcesActions.SET_RESOURCES(processItems.items)); - await api.dispatch(loadMissingProcessesInformation(processItems.items)); - api.dispatch(allProcessesPanelActions.SET_ITEMS({ - items: processItems.items.map((resource: any) => resource.uuid), - itemsAvailable: processItems.itemsAvailable, - page: Math.floor(processItems.offset / processItems.limit), - rowsPerPage: processItems.limit - })); - } catch { - if (!background) { api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId())); } - api.dispatch(allProcessesPanelActions.SET_ITEMS({ - items: [], - itemsAvailable: 0, - page: 0, - rowsPerPage: dataExplorer.rowsPerPage - })); - api.dispatch(couldNotFetchAllProcessesListing()); - } - } + const typeFilters = serializeOnlyProcessTypeFilters(getDataExplorerColumnFilters(columns, AllProcessesPanelColumnNames.TYPE)); + return joinFilters(sup, typeFilters); } } - -const getParams = (dataExplorer: DataExplorer) => ({ - ...dataExplorerToListParams(dataExplorer), - order: getOrder(dataExplorer), - filters: getFilters(dataExplorer) -}); - -const getFilters = (dataExplorer: DataExplorer) => { - const columns = dataExplorer.columns as DataColumns; - const statusColumnFilters = getDataExplorerColumnFilters(columns, 'Status'); - const activeStatusFilter = Object.keys(statusColumnFilters).find( - filterName => statusColumnFilters[filterName].selected - ) || ProcessStatusFilter.ALL; - - const nameFilter = new FilterBuilder().addILike("name", dataExplorer.searchValue).getFilters(); - const statusFilter = buildProcessStatusFilters(new FilterBuilder(), activeStatusFilter).getFilters(); - const typeFilters = serializeOnlyProcessTypeFilters(getDataExplorerColumnFilters(columns, AllProcessesPanelColumnNames.TYPE)); - - return joinFilters( - nameFilter, - statusFilter, - typeFilters - ); -}; - -const allProcessesPanelDataExplorerIsNotSet = () => - snackbarActions.OPEN_SNACKBAR({ - message: 'All Processes panel is not ready.', - kind: SnackbarKind.ERROR - }); - -const couldNotFetchAllProcessesListing = () => - snackbarActions.OPEN_SNACKBAR({ - message: 'Could not fetch All Processes listing.', - kind: SnackbarKind.ERROR - }); diff --git a/src/store/data-explorer/data-explorer-action.ts b/src/store/data-explorer/data-explorer-action.ts index ea050e609f..98df6f0c4a 100644 --- a/src/store/data-explorer/data-explorer-action.ts +++ b/src/store/data-explorer/data-explorer-action.ts @@ -52,3 +52,5 @@ export const bindDataExplorerActions = (id: string) => ({ RESET_EXPLORER_SEARCH_VALUE: () => dataExplorerActions.RESET_EXPLORER_SEARCH_VALUE({ id }), SET_REQUEST_STATE: (payload: { requestState: DataTableRequestState }) => dataExplorerActions.SET_REQUEST_STATE({ ...payload, id }), }); + +export type BoundDataExplorerActions = ReturnType; diff --git a/src/store/processes/processes-middleware-service.ts b/src/store/processes/processes-middleware-service.ts new file mode 100644 index 0000000000..d252527276 --- /dev/null +++ b/src/store/processes/processes-middleware-service.ts @@ -0,0 +1,95 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import { ServiceRepository } from 'services/services'; +import { MiddlewareAPI, Dispatch } from 'redux'; +import { + DataExplorerMiddlewareService, dataExplorerToListParams, listResultsToDataExplorerItemsMeta, getDataExplorerColumnFilters, getOrder +} from 'store/data-explorer/data-explorer-middleware-service'; +import { RootState } from 'store/store'; +import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions'; +import { DataExplorer, getDataExplorer } from 'store/data-explorer/data-explorer-reducer'; +import { BoundDataExplorerActions } from 'store/data-explorer/data-explorer-action'; +import { updateResources } from 'store/resources/resources-actions'; +import { ListArguments, ListResults } from 'services/common-service/common-service'; +import { ProcessResource } from 'models/process'; +import { FilterBuilder, joinFilters } from 'services/api/filter-builder'; +import { DataColumns } from 'components/data-table/data-table'; +import { ProcessStatusFilter, buildProcessStatusFilters } from '../resource-type-filters/resource-type-filters'; +import { ContainerRequestResource, containerRequestFieldsNoMounts } from 'models/container-request'; +import { progressIndicatorActions } from '../progress-indicator/progress-indicator-actions'; +import { loadMissingProcessesInformation } from '../project-panel/project-panel-middleware-service'; + +export class ProcessesMiddlewareService extends DataExplorerMiddlewareService { + constructor(private services: ServiceRepository, private actions: BoundDataExplorerActions, id: string) { + super(id); + } + + getFilters(api: MiddlewareAPI, dataExplorer: DataExplorer): string | null { + const columns = dataExplorer.columns as DataColumns; + const statusColumnFilters = getDataExplorerColumnFilters(columns, 'Status'); + const activeStatusFilter = Object.keys(statusColumnFilters).find( + filterName => statusColumnFilters[filterName].selected + ) || ProcessStatusFilter.ALL; + + const nameFilter = new FilterBuilder().addILike("name", dataExplorer.searchValue).getFilters(); + const statusFilter = buildProcessStatusFilters(new FilterBuilder(), activeStatusFilter).getFilters(); + + return joinFilters( + nameFilter, + statusFilter, + ); + } + + getParams(api: MiddlewareAPI, dataExplorer: DataExplorer): ListArguments | null { + const filters = this.getFilters(api, dataExplorer) + if (filters === null) { + return null; + } + return { + ...dataExplorerToListParams(dataExplorer), + order: getOrder(dataExplorer), + filters + }; + } + + async requestItems(api: MiddlewareAPI, criteriaChanged?: boolean, background?: boolean) { + const state = api.getState(); + const dataExplorer = getDataExplorer(state.dataExplorer, this.getId()); + + try { + if (!background) { api.dispatch(progressIndicatorActions.START_WORKING(this.getId())); } + + const params = this.getParams(api, dataExplorer); + + if (params !== null) { + const containerRequests = await this.services.containerRequestService.list( + { + ...this.getParams(api, dataExplorer), + select: containerRequestFieldsNoMounts + }); + api.dispatch(updateResources(containerRequests.items)); + await api.dispatch(loadMissingProcessesInformation(containerRequests.items)); + api.dispatch(this.actions.SET_ITEMS({ + ...listResultsToDataExplorerItemsMeta(containerRequests), + items: containerRequests.items.map(resource => resource.uuid), + })); + } else { + api.dispatch(this.actions.SET_ITEMS({ + itemsAvailable: 0, + page: 0, + rowsPerPage: dataExplorer.rowsPerPage, + items: [], + })); + } + if (!background) { api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId())); } + } catch { + api.dispatch(snackbarActions.OPEN_SNACKBAR({ + message: 'Could not fetch process list.', + kind: SnackbarKind.ERROR + })); + if (!background) { api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId())); } + } + } +} diff --git a/src/store/subprocess-panel/subprocess-panel-middleware-service.ts b/src/store/subprocess-panel/subprocess-panel-middleware-service.ts index 5124c8346a..1ae9c41e41 100644 --- a/src/store/subprocess-panel/subprocess-panel-middleware-service.ts +++ b/src/store/subprocess-panel/subprocess-panel-middleware-service.ts @@ -5,7 +5,7 @@ import { ServiceRepository } from 'services/services'; import { MiddlewareAPI, Dispatch } from 'redux'; import { - DataExplorerMiddlewareService, dataExplorerToListParams, listResultsToDataExplorerItemsMeta, getDataExplorerColumnFilters, getOrder + dataExplorerToListParams, listResultsToDataExplorerItemsMeta, getDataExplorerColumnFilters, getOrder } from 'store/data-explorer/data-explorer-middleware-service'; import { RootState } from 'store/store'; import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions'; @@ -20,81 +20,26 @@ import { ProcessStatusFilter, buildProcessStatusFilters } from '../resource-type import { ContainerRequestResource, containerRequestFieldsNoMounts } from 'models/container-request'; import { progressIndicatorActions } from '../progress-indicator/progress-indicator-actions'; import { loadMissingProcessesInformation } from '../project-panel/project-panel-middleware-service'; +import { ProcessesMiddlewareService } from "store/processes/processes-middleware-service"; +import { getProcess } from "store/processes/process"; -export class SubprocessMiddlewareService extends DataExplorerMiddlewareService { - constructor(private services: ServiceRepository, id: string) { - super(id); +export class SubprocessMiddlewareService extends ProcessesMiddlewareService { + constructor(services: ServiceRepository, id: string) { + super(services, subprocessPanelActions, id); } - async requestItems(api: MiddlewareAPI, criteriaChanged?: boolean, background?: boolean) { + getFilters(api: MiddlewareAPI, dataExplorer: DataExplorer): string | null { const state = api.getState(); const parentContainerRequestUuid = state.processPanel.containerRequestUuid; - if (parentContainerRequestUuid === "") { return; } - const dataExplorer = getDataExplorer(state.dataExplorer, this.getId()); + if (!parentContainerRequestUuid) { return null; } - try { - if (!background) { api.dispatch(progressIndicatorActions.START_WORKING(this.getId())); } - const parentContainerRequest = await this.services.containerRequestService.get(parentContainerRequestUuid); - if (parentContainerRequest.containerUuid) { - const containerRequests = await this.services.containerRequestService.list( - { - ...getParams(dataExplorer, parentContainerRequest), - select: containerRequestFieldsNoMounts - }); - api.dispatch(updateResources(containerRequests.items)); - await api.dispatch(loadMissingProcessesInformation(containerRequests.items)); - // Populate the actual user view - api.dispatch(setItems(containerRequests)); - } - if (!background) { api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId())); } - } catch { - if (!background) { api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId())); } - api.dispatch(couldNotFetchSubprocesses()); - } - } -} - -export const getParams = ( - dataExplorer: DataExplorer, - parentContainerRequest: ContainerRequestResource) => ({ - ...dataExplorerToListParams(dataExplorer), - order: getOrder(dataExplorer), - filters: getFilters(dataExplorer, parentContainerRequest) - }); - -export const getFilters = ( - dataExplorer: DataExplorer, - parentContainerRequest: ContainerRequestResource) => { - const columns = dataExplorer.columns as DataColumns; - const statusColumnFilters = getDataExplorerColumnFilters(columns, 'Status'); - const activeStatusFilter = Object.keys(statusColumnFilters).find( - filterName => statusColumnFilters[filterName].selected - ) || ProcessStatusFilter.ALL; - - // Get all the subprocess' container requests and containers. - const fb = new FilterBuilder().addEqual('requesting_container_uuid', parentContainerRequest.containerUuid); - const statusFilters = buildProcessStatusFilters(fb, activeStatusFilter).getFilters(); + const process = getProcess(parentContainerRequestUuid)(state.resources); + if (!process?.container) { return null; } - const nameFilters = dataExplorer.searchValue - ? new FilterBuilder() - .addILike("name", dataExplorer.searchValue) - .getFilters() - : ''; + const requesting_container = new FilterBuilder().addEqual('requesting_container_uuid', process.container.uuid).getFilters(); + const sup = super.getFilters(api, dataExplorer); + if (sup === null) { return null; } - return joinFilters( - nameFilters, - statusFilters - ); -}; - -export const setItems = (listResults: ListResults) => - subprocessPanelActions.SET_ITEMS({ - ...listResultsToDataExplorerItemsMeta(listResults), - items: listResults.items.map(resource => resource.uuid), - }); - -const couldNotFetchSubprocesses = () => - snackbarActions.OPEN_SNACKBAR({ - message: 'Could not fetch subprocesses.', - kind: SnackbarKind.ERROR - }); + return joinFilters(sup, requesting_container); + } +} -- 2.30.2