From 5c6e7a1fcb3e951c09e4a794f92a80a35f4db2ee Mon Sep 17 00:00:00 2001 From: Michal Klobukowski Date: Tue, 4 Sep 2018 11:54:48 +0200 Subject: [PATCH] Update process statuses, update process status rendering in tables, disable process status table filters Feature #13776 Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski --- src/components/data-table/data-column.ts | 2 +- .../favorite-panel-middleware-service.ts | 64 +++++++-------- src/store/processes/process.ts | 80 +++++++++++++------ .../project-panel-middleware-service.ts | 20 ++++- .../data-explorer/renderers.tsx | 31 ++++--- src/views/favorite-panel/favorite-panel.tsx | 22 +---- src/views/project-panel/project-panel.tsx | 22 +---- 7 files changed, 128 insertions(+), 113 deletions(-) diff --git a/src/components/data-table/data-column.ts b/src/components/data-table/data-column.ts index 90e87a88..8dbdf0cc 100644 --- a/src/components/data-table/data-column.ts +++ b/src/components/data-table/data-column.ts @@ -10,7 +10,7 @@ export interface DataColumn React.ReactElement; renderHeader?: () => React.ReactElement; diff --git a/src/store/favorite-panel/favorite-panel-middleware-service.ts b/src/store/favorite-panel/favorite-panel-middleware-service.ts index f808b97e..c385309f 100644 --- a/src/store/favorite-panel/favorite-panel-middleware-service.ts +++ b/src/store/favorite-panel/favorite-panel-middleware-service.ts @@ -18,17 +18,18 @@ import { GroupContentsResource, GroupContentsResourcePrefix } from "~/services/g import { resourcesActions } from "~/store/resources/resources-actions"; import { snackbarActions } from '~/store/snackbar/snackbar-actions'; import { getDataExplorer } from "~/store/data-explorer/data-explorer-reducer"; +import { loadMissingProcessesInformation } from "~/store/project-panel/project-panel-middleware-service"; export class FavoritePanelMiddlewareService extends DataExplorerMiddlewareService { constructor(private services: ServiceRepository, id: string) { super(id); } - requestItems(api: MiddlewareAPI) { + async requestItems(api: MiddlewareAPI) { const dataExplorer = getDataExplorer(api.getState().dataExplorer, this.getId()); if (!dataExplorer) { api.dispatch(favoritesPanelDataExplorerIsNotSet()); - } else { + } else { const columns = dataExplorer.columns as DataColumns; const sortColumn = dataExplorer.columns.find(c => c.sortDirection !== SortDirection.NONE); @@ -48,36 +49,35 @@ export class FavoritePanelMiddlewareService extends DataExplorerMiddlewareServic .addOrder(direction, "name", GroupContentsResourcePrefix.PROCESS) .addOrder(direction, "name", GroupContentsResourcePrefix.PROJECT); } - - this.services.favoriteService - .list(this.services.authService.getUuid()!, { - limit: dataExplorer.rowsPerPage, - offset: dataExplorer.page * dataExplorer.rowsPerPage, - linkOrder: linkOrder.getOrder(), - contentOrder: contentOrder.getOrder(), - filters: new FilterBuilder() - .addIsA("headUuid", typeFilters.map(filter => filter.type)) - .addILike("name", dataExplorer.searchValue) - .getFilters() - }) - .then(response => { - api.dispatch(resourcesActions.SET_RESOURCES(response.items)); - api.dispatch(favoritePanelActions.SET_ITEMS({ - items: response.items.map(resource => resource.uuid), - itemsAvailable: response.itemsAvailable, - page: Math.floor(response.offset / response.limit), - rowsPerPage: response.limit - })); - api.dispatch(updateFavorites(response.items.map(item => item.uuid))); - }) - .catch(() => { - api.dispatch(favoritePanelActions.SET_ITEMS({ - items: [], - itemsAvailable: 0, - page: 0, - rowsPerPage: dataExplorer.rowsPerPage - })); - }); + try { + const response = await this.services.favoriteService + .list(this.services.authService.getUuid()!, { + limit: dataExplorer.rowsPerPage, + offset: dataExplorer.page * dataExplorer.rowsPerPage, + linkOrder: linkOrder.getOrder(), + contentOrder: contentOrder.getOrder(), + filters: new FilterBuilder() + .addIsA("headUuid", typeFilters.map(filter => filter.type)) + .addILike("name", dataExplorer.searchValue) + .getFilters() + }); + api.dispatch(resourcesActions.SET_RESOURCES(response.items)); + await api.dispatch(loadMissingProcessesInformation(response.items)); + api.dispatch(favoritePanelActions.SET_ITEMS({ + items: response.items.map(resource => resource.uuid), + itemsAvailable: response.itemsAvailable, + page: Math.floor(response.offset / response.limit), + rowsPerPage: response.limit + })); + api.dispatch(updateFavorites(response.items.map(item => item.uuid))); + } catch (e) { + api.dispatch(favoritePanelActions.SET_ITEMS({ + items: [], + itemsAvailable: 0, + page: 0, + rowsPerPage: dataExplorer.rowsPerPage + })); + } } } } diff --git a/src/store/processes/process.ts b/src/store/processes/process.ts index 467fc8a9..c9e62f94 100644 --- a/src/store/processes/process.ts +++ b/src/store/processes/process.ts @@ -2,13 +2,12 @@ // // SPDX-License-Identifier: AGPL-3.0 -import { ContainerRequestResource } from '../../models/container-request'; -import { ContainerResource } from '../../models/container'; +import { ContainerRequestResource, ContainerRequestState } from '../../models/container-request'; +import { ContainerResource, ContainerState } from '../../models/container'; import { ResourcesState, getResource } from '~/store/resources/resources'; import { filterResources } from '../resources/resources'; -import { ResourceKind, Resource } from '~/models/resource'; +import { ResourceKind, Resource, extractUuidKind } from '~/models/resource'; import { getTimeDiff } from '~/common/formatters'; -import { SubprocessesStatus } from '~/views/process-panel/process-subprocesses-card'; import { ArvadosTheme } from '~/common/custom-theme'; export interface Process { @@ -16,16 +15,29 @@ export interface Process { container?: ContainerResource; } +export enum ProcessStatus { + CANCELLED = 'Cancelled', + COMPLETED = 'Completed', + DRAFT = 'Draft', + FAILED = 'Failed', + LOCKED = 'Locked', + QUEUED = 'Queued', + RUNNING = 'Running', + UNKNOWN = 'Unknown', +} + export const getProcess = (uuid: string) => (resources: ResourcesState): Process | undefined => { - const containerRequest = getResource(uuid)(resources); - if (containerRequest) { - if (containerRequest.containerUuid) { - const container = getResource(containerRequest.containerUuid)(resources); - if (container) { - return { containerRequest, container }; + if (extractUuidKind(uuid) === ResourceKind.CONTAINER_REQUEST) { + const containerRequest = getResource(uuid)(resources); + if (containerRequest) { + if (containerRequest.containerUuid) { + const container = getResource(containerRequest.containerUuid)(resources); + if (container) { + return { containerRequest, container }; + } } + return { containerRequest }; } - return { containerRequest }; } return; }; @@ -51,27 +63,47 @@ export const getProcessRuntime = ({ container }: Process) => export const getProcessStatusColor = (status: string, { customs }: ArvadosTheme) => { switch (status) { - case SubprocessesStatus.COMPLETED: + case ProcessStatus.RUNNING: + return customs.colors.blue500; + case ProcessStatus.COMPLETED: return customs.colors.green700; - case SubprocessesStatus.CANCELED: - return customs.colors.red900; - case SubprocessesStatus.QUEUED: - return customs.colors.grey500; - case SubprocessesStatus.FAILED: + case ProcessStatus.CANCELLED: + case ProcessStatus.FAILED: return customs.colors.red900; - case SubprocessesStatus.ACTIVE: - return customs.colors.blue500; default: return customs.colors.grey500; } }; -export const getProcessStatus = (process: Process) => - process.container - ? process.container.state - : process.containerRequest.state; +export const getProcessStatus = ({ containerRequest, container }: Process): ProcessStatus => { + switch (true) { + case containerRequest.state === ContainerRequestState.UNCOMMITTED: + return ProcessStatus.DRAFT; + + case containerRequest.priority === 0: + case container && container.state === ContainerState.CANCELLED: + return ProcessStatus.CANCELLED; + + case container && container.state === ContainerState.QUEUED: + return ProcessStatus.QUEUED; + + case container && container.state === ContainerState.LOCKED: + return ProcessStatus.LOCKED; + + case container && container.state === ContainerState.RUNNING: + return ProcessStatus.RUNNING; + + case container && container.state === ContainerState.COMPLETE && container.exitCode === 0: + return ProcessStatus.COMPLETED; + + case container && container.state === ContainerState.COMPLETE && container.exitCode !== 0: + return ProcessStatus.FAILED; + + default: + return ProcessStatus.UNKNOWN; + } +}; const isSubprocess = (containerUuid: string) => (resource: Resource) => resource.kind === ResourceKind.CONTAINER_REQUEST && (resource as ContainerRequestResource).requestingContainerUuid === containerUuid; - diff --git a/src/store/project-panel/project-panel-middleware-service.ts b/src/store/project-panel/project-panel-middleware-service.ts index aade4172..4b4ec269 100644 --- a/src/store/project-panel/project-panel-middleware-service.ts +++ b/src/store/project-panel/project-panel-middleware-service.ts @@ -20,6 +20,8 @@ import { getProperty } from "~/store/properties/properties"; import { snackbarActions } from '../snackbar/snackbar-actions'; import { DataExplorer, getDataExplorer } from '../data-explorer/data-explorer-reducer'; import { ListResults } from '~/services/common-service/common-resource-service'; +import { loadContainers } from '../processes/processes-actions'; +import { ResourceKind } from '~/models/resource'; export class ProjectPanelMiddlewareService extends DataExplorerMiddlewareService { constructor(private services: ServiceRepository, id: string) { @@ -39,6 +41,7 @@ export class ProjectPanelMiddlewareService extends DataExplorerMiddlewareService const response = await this.services.groupsService.contents(projectUuid, getParams(dataExplorer)); api.dispatch(updateFavorites(response.items.map(item => item.uuid))); api.dispatch(updateResources(response.items)); + await api.dispatch(loadMissingProcessesInformation(response.items)); api.dispatch(setItems(response)); } catch (e) { api.dispatch(couldNotFetchProjectContents()); @@ -47,6 +50,22 @@ export class ProjectPanelMiddlewareService extends DataExplorerMiddlewareService } } +export const loadMissingProcessesInformation = (resources: GroupContentsResource[]) => + async (dispatch: Dispatch) => { + const containerUuids = resources.reduce((uuids, resource) => { + return resource.kind === ResourceKind.CONTAINER_REQUEST + ? resource.containerUuid + ? [...uuids, resource.containerUuid] + : uuids + : uuids; + }, []); + if (containerUuids.length > 0) { + await dispatch(loadContainers( + new FilterBuilder().addIn('uuid', containerUuids).getFilters() + )); + } + }; + const setItems = (listResults: ListResults) => projectPanelActions.SET_ITEMS({ ...listResultsToDataExplorerItemsMeta(listResults), @@ -65,7 +84,6 @@ const getFilters = (dataExplorer: DataExplorer) => { const statusFilters = getDataExplorerColumnFilters(columns, ProjectPanelColumnNames.STATUS); return new FilterBuilder() .addIsA("uuid", typeFilters.map(f => f.type)) - .addIn("state", statusFilters.map(f => f.type), GroupContentsResourcePrefix.PROCESS) .addILike("name", dataExplorer.searchValue, GroupContentsResourcePrefix.COLLECTION) .addILike("name", dataExplorer.searchValue, GroupContentsResourcePrefix.PROCESS) .addILike("name", dataExplorer.searchValue, GroupContentsResourcePrefix.PROJECT) diff --git a/src/views-components/data-explorer/renderers.tsx b/src/views-components/data-explorer/renderers.tsx index c96813df..72644f93 100644 --- a/src/views-components/data-explorer/renderers.tsx +++ b/src/views-components/data-explorer/renderers.tsx @@ -3,7 +3,7 @@ // SPDX-License-Identifier: AGPL-3.0 import * as React from 'react'; -import { Grid, Typography } from '@material-ui/core'; +import { Grid, Typography, withStyles } from '@material-ui/core'; import { FavoriteStar } from '../favorite-star/favorite-star'; import { ResourceKind, TrashableResource } from '~/models/resource'; import { ProjectIcon, CollectionIcon, ProcessIcon, DefaultIcon } from '~/components/icon/icon'; @@ -13,8 +13,9 @@ import { connect } from 'react-redux'; import { RootState } from '~/store/store'; import { getResource } from '~/store/resources/resources'; import { GroupContentsResource } from '~/services/groups-service/groups-service'; -import { ProcessResource } from '~/models/process'; - +import { getProcess, Process, getProcessStatus, getProcessStatusColor } from '~/store/processes/process'; +import { ArvadosTheme } from '~/common/custom-theme'; +import { compose } from 'redux'; export const renderName = (item: { name: string; uuid: string, kind: string }) => @@ -107,13 +108,17 @@ export const ResourceType = connect( return { type: resource ? resource.kind : '' }; })((props: { type: string }) => renderType(props.type)); -export const renderStatus = (item: { status?: string }) => - - {item.status || "-"} - ; - -export const ProcessStatus = connect( - (state: RootState, props: { uuid: string }) => { - const resource = getResource(props.uuid)(state.resources); - return { status: resource ? resource.state : '-' }; - })((props: { status: string }) => renderType(props.status)); +export const ProcessStatus = compose( + connect((state: RootState, props: { uuid: string }) => { + return { process: getProcess(props.uuid)(state.resources) }; + }), + withStyles({}, { withTheme: true })) + ((props: { process?: Process, theme: ArvadosTheme }) => { + const status = props.process ? getProcessStatus(props.process) : "-"; + return + {status} + ; + }); diff --git a/src/views/favorite-panel/favorite-panel.tsx b/src/views/favorite-panel/favorite-panel.tsx index 2cb30198..803d8002 100644 --- a/src/views/favorite-panel/favorite-panel.tsx +++ b/src/views/favorite-panel/favorite-panel.tsx @@ -68,24 +68,7 @@ export const favoritePanelColumns: DataColumns = [ name: "Status", selected: true, configurable: true, - sortDirection: SortDirection.NONE, - filters: [ - { - name: ContainerRequestState.COMMITTED, - selected: true, - type: ContainerRequestState.COMMITTED - }, - { - name: ContainerRequestState.FINAL, - selected: true, - type: ContainerRequestState.FINAL - }, - { - name: ContainerRequestState.UNCOMMITTED, - selected: true, - type: ContainerRequestState.UNCOMMITTED - } - ], + filters: [], render: uuid => , width: "75px" }, @@ -93,7 +76,6 @@ export const favoritePanelColumns: DataColumns = [ name: FavoritePanelColumnNames.TYPE, selected: true, configurable: true, - sortDirection: SortDirection.NONE, filters: [ { name: resourceLabel(ResourceKind.COLLECTION), @@ -118,7 +100,6 @@ export const favoritePanelColumns: DataColumns = [ name: FavoritePanelColumnNames.OWNER, selected: true, configurable: true, - sortDirection: SortDirection.NONE, filters: [], render: uuid => , width: "200px" @@ -127,7 +108,6 @@ export const favoritePanelColumns: DataColumns = [ name: FavoritePanelColumnNames.FILE_SIZE, selected: true, configurable: true, - sortDirection: SortDirection.NONE, filters: [], render: uuid => , width: "50px" diff --git a/src/views/project-panel/project-panel.tsx b/src/views/project-panel/project-panel.tsx index 1cb72a96..b75b37aa 100644 --- a/src/views/project-panel/project-panel.tsx +++ b/src/views/project-panel/project-panel.tsx @@ -72,24 +72,7 @@ export const projectPanelColumns: DataColumns = [ name: "Status", selected: true, configurable: true, - sortDirection: SortDirection.NONE, - filters: [ - { - name: ContainerRequestState.COMMITTED, - selected: true, - type: ContainerRequestState.COMMITTED - }, - { - name: ContainerRequestState.FINAL, - selected: true, - type: ContainerRequestState.FINAL - }, - { - name: ContainerRequestState.UNCOMMITTED, - selected: true, - type: ContainerRequestState.UNCOMMITTED - } - ], + filters: [], render: uuid => , width: "75px" }, @@ -97,7 +80,6 @@ export const projectPanelColumns: DataColumns = [ name: ProjectPanelColumnNames.TYPE, selected: true, configurable: true, - sortDirection: SortDirection.NONE, filters: [ { name: resourceLabel(ResourceKind.COLLECTION), @@ -122,7 +104,6 @@ export const projectPanelColumns: DataColumns = [ name: ProjectPanelColumnNames.OWNER, selected: true, configurable: true, - sortDirection: SortDirection.NONE, filters: [], render: uuid => , width: "200px" @@ -131,7 +112,6 @@ export const projectPanelColumns: DataColumns = [ name: ProjectPanelColumnNames.FILE_SIZE, selected: true, configurable: true, - sortDirection: SortDirection.NONE, filters: [], render: uuid => , width: "50px" -- 2.30.2