X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/d940d88f991c14785110855ba0ee79ea5f401276..5e87aa73a04e8c88812df1366b490333a2526c12:/services/workbench2/src/components/subprocess-progress-bar/subprocess-progress-bar.tsx diff --git a/services/workbench2/src/components/subprocess-progress-bar/subprocess-progress-bar.tsx b/services/workbench2/src/components/subprocess-progress-bar/subprocess-progress-bar.tsx index b21d879185..78df83f6ca 100644 --- a/services/workbench2/src/components/subprocess-progress-bar/subprocess-progress-bar.tsx +++ b/services/workbench2/src/components/subprocess-progress-bar/subprocess-progress-bar.tsx @@ -6,20 +6,22 @@ import React, { useEffect, useState } from "react"; import { StyleRulesCallback, Tooltip, WithStyles, withStyles } from "@material-ui/core"; import { CProgressStacked, CProgress } from '@coreui/react'; import { useAsyncInterval } from "common/use-async-interval"; -import { Process, isProcessRunning } from "store/processes/process"; +import { Process } from "store/processes/process"; import { connect } from "react-redux"; import { Dispatch } from "redux"; -import { fetchSubprocessProgress } from "store/subprocess-panel/subprocess-panel-actions"; -import { ProcessStatusFilter } from "store/resource-type-filters/resource-type-filters"; +import { fetchProcessProgressBarStatus } from "store/subprocess-panel/subprocess-panel-actions"; +import { ProcessStatusFilter, serializeOnlyProcessTypeFilters } from "store/resource-type-filters/resource-type-filters"; +import { ProjectResource } from "models/project"; +import { getDataExplorer } from "store/data-explorer/data-explorer-reducer"; +import { RootState } from "store/store"; +import { ProcessResource } from "models/process"; +import { getDataExplorerColumnFilters } from "store/data-explorer/data-explorer-middleware-service"; +import { ProjectPanelRunColumnNames } from "views/project-panel/project-panel-run"; +import { DataColumns } from "components/data-table/data-table"; -type CssRules = 'progressWrapper' | 'progressStacked' ; +type CssRules = 'progressStacked'; const styles: StyleRulesCallback = (theme) => ({ - progressWrapper: { - margin: "28px 0 0", - flexGrow: 1, - flexBasis: "100px", - }, progressStacked: { border: "1px solid gray", height: "10px", @@ -32,74 +34,116 @@ const styles: StyleRulesCallback = (theme) => ({ }); export interface ProgressBarDataProps { - process: Process; + parentResource: Process | ProjectResource | undefined; + dataExplorerId?: string; + typeFilter?: string; } export interface ProgressBarActionProps { - fetchSubprocessProgress: (requestingContainerUuid: string) => Promise; + fetchProcessProgressBarStatus: (parentResource: Process | ProjectResource, typeFilter?: string) => Promise; } type ProgressBarProps = ProgressBarDataProps & ProgressBarActionProps & WithStyles; -export type ProgressBarData = { +export type ProgressBarCounts = { [ProcessStatusFilter.COMPLETED]: number; [ProcessStatusFilter.RUNNING]: number; [ProcessStatusFilter.FAILED]: number; [ProcessStatusFilter.QUEUED]: number; }; +export type ProgressBarStatus = { + counts: ProgressBarCounts; + isRunning: boolean; +}; + +const mapStateToProps = (state: RootState, props: ProgressBarDataProps) => { + let typeFilter: string | undefined = undefined; + + if (props.dataExplorerId) { + const dataExplorerState = getDataExplorer(state.dataExplorer, props.dataExplorerId); + const columns = dataExplorerState.columns as DataColumns; + typeFilter = serializeOnlyProcessTypeFilters(getDataExplorerColumnFilters(columns, ProjectPanelRunColumnNames.TYPE)); + } + + return { typeFilter }; +}; + const mapDispatchToProps = (dispatch: Dispatch): ProgressBarActionProps => ({ - fetchSubprocessProgress: (requestingContainerUuid: string) => { - return dispatch(fetchSubprocessProgress(requestingContainerUuid)); + fetchProcessProgressBarStatus: (parentResource: Process | ProjectResource, typeFilter?: string) => { + return dispatch(fetchProcessProgressBarStatus(parentResource, typeFilter)); }, }); -export const SubprocessProgressBar = connect(null, mapDispatchToProps)(withStyles(styles)( - ({process, classes, fetchSubprocessProgress}: ProgressBarProps) => { +export const SubprocessProgressBar = connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)( + ({ parentResource, typeFilter, classes, fetchProcessProgressBarStatus }: ProgressBarProps) => { - const [progressData, setProgressData] = useState(undefined); - const requestingContainerUuid = process.containerRequest.containerUuid; - const isRunning = isProcessRunning(process); + const [progressCounts, setProgressData] = useState(undefined); + const [isRunning, setIsRunning] = useState(false); - useAsyncInterval(async () => ( - requestingContainerUuid && setProgressData(await fetchSubprocessProgress(requestingContainerUuid)) - ), isRunning ? 5000 : null); + useAsyncInterval(async () => { + if (parentResource) { + fetchProcessProgressBarStatus(parentResource, typeFilter) + .then(result => { + if (result) { + setProgressData(result.counts); + setIsRunning(result.isRunning); + } + }); + } + }, isRunning ? 5000 : null); useEffect(() => { - if (!isRunning && requestingContainerUuid) { - fetchSubprocessProgress(requestingContainerUuid) - .then(result => setProgressData(result)); + if (!isRunning && parentResource) { + fetchProcessProgressBarStatus(parentResource, typeFilter) + .then(result => { + if (result) { + setProgressData(result.counts); + setIsRunning(result.isRunning); + } + }); + } + }, [fetchProcessProgressBarStatus, isRunning, parentResource, typeFilter]); + + let tooltip = ""; + if (progressCounts) { + let total = 0; + [ProcessStatusFilter.COMPLETED, + ProcessStatusFilter.RUNNING, + ProcessStatusFilter.FAILED, + ProcessStatusFilter.QUEUED].forEach(psf => { + if (progressCounts[psf] > 0) { + if (tooltip.length > 0) { tooltip += ", "; } + tooltip += `${progressCounts[psf]} ${psf}`; + total += progressCounts[psf]; + } + }); + if (total > 0) { + if (tooltip.length > 0) { tooltip += ", "; } + tooltip += `${total} Total`; } - }, [fetchSubprocessProgress, isRunning, requestingContainerUuid]); + } - return progressData !== undefined && getStatusTotal(progressData) > 0 ?
+ return progressCounts !== undefined && getStatusTotal(progressCounts) > 0 ? - - - - - - - - - - - - + + + + -
: <>; + : <>; } )); -const getStatusTotal = (progressData: ProgressBarData) => - (Object.keys(progressData).reduce((accumulator, key) => (accumulator += progressData[key]), 0)); +const getStatusTotal = (progressCounts: ProgressBarCounts) => + (Object.keys(progressCounts).reduce((accumulator, key) => (accumulator += progressCounts[key]), 0)); /** * Gets the integer percent value for process status */ -const getStatusPercent = (progressData: ProgressBarData, status: keyof ProgressBarData) => - (progressData[status] / getStatusTotal(progressData) * 100); +const getStatusPercent = (progressCounts: ProgressBarCounts, status: keyof ProgressBarCounts) => + (progressCounts[status] / getStatusTotal(progressCounts) * 100);