X-Git-Url: https://git.arvados.org/arvados-workbench2.git/blobdiff_plain/62abdd5fbf51cde6c61350082a7924b3ebaf8526..bdcaea37455b72c345c7305e6a7bc4ba63d5c1b7:/src/views/process-panel/process-panel-root.tsx diff --git a/src/views/process-panel/process-panel-root.tsx b/src/views/process-panel/process-panel-root.tsx index 3447dc2a..d4c8d937 100644 --- a/src/views/process-panel/process-panel-root.tsx +++ b/src/views/process-panel/process-panel-root.tsx @@ -2,31 +2,34 @@ // // SPDX-License-Identifier: AGPL-3.0 -import React, { useState } from 'react'; -import { Grid, StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core'; -import { DefaultView } from 'components/default-view/default-view'; -import { ProcessIcon } from 'components/icon/icon'; -import { Process } from 'store/processes/process'; -import { SubprocessPanel } from 'views/subprocess-panel/subprocess-panel'; -import { SubprocessFilterDataProps } from 'components/subprocess-filter/subprocess-filter'; -import { MPVContainer, MPVPanelContent, MPVPanelState } from 'components/multi-panel-view/multi-panel-view'; -import { ArvadosTheme } from 'common/custom-theme'; -import { ProcessDetailsCard } from './process-details-card'; -import { getInputDisplayValue, ProcessIOCard, ProcessIOParameter } from './process-io-card'; - -import { getProcessPanelLogs, ProcessLogsPanel } from 'store/process-logs-panel/process-logs-panel'; -import { ProcessLogsCard } from './process-log-card'; -import { FilterOption } from 'views/process-panel/process-log-form'; -import { getInputs } from 'store/processes/processes-actions'; -import { CommandInputParameter, getInputId } from 'models/workflow'; -import { CommandOutputParameter } from 'cwlts/mappings/v1.0/CommandOutputParameter'; -import { AuthState } from 'store/auth/auth-reducer'; - -type CssRules = 'root'; +import React from "react"; +import { Grid, StyleRulesCallback, WithStyles, withStyles } from "@material-ui/core"; +import { DefaultView } from "components/default-view/default-view"; +import { ProcessIcon } from "components/icon/icon"; +import { Process } from "store/processes/process"; +import { SubprocessPanel } from "views/subprocess-panel/subprocess-panel"; +import { SubprocessFilterDataProps } from "components/subprocess-filter/subprocess-filter"; +import { MPVContainer, MPVPanelContent, MPVPanelState } from "components/multi-panel-view/multi-panel-view"; +import { ArvadosTheme } from "common/custom-theme"; +import { ProcessDetailsCard } from "./process-details-card"; +import { ProcessIOCard, ProcessIOCardType, ProcessIOParameter } from "./process-io-card"; +import { ProcessResourceCard } from "./process-resource-card"; +import { getProcessPanelLogs, ProcessLogsPanel } from "store/process-logs-panel/process-logs-panel"; +import { ProcessLogsCard } from "./process-log-card"; +import { FilterOption } from "views/process-panel/process-log-form"; +import { getInputCollectionMounts } from "store/processes/processes-actions"; +import { WorkflowInputsData } from "models/workflow"; +import { CommandOutputParameter } from "cwlts/mappings/v1.0/CommandOutputParameter"; +import { AuthState } from "store/auth/auth-reducer"; +import { ProcessCmdCard } from "./process-cmd-card"; +import { ContainerRequestResource } from "models/container-request"; +import { OutputDetails, NodeInstanceType } from "store/process-panel/process-panel"; + +type CssRules = "root"; const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ root: { - width: '100%', + width: "100%", }, }); @@ -36,151 +39,184 @@ export interface ProcessPanelRootDataProps { filters: Array; processLogsPanel: ProcessLogsPanel; auth: AuthState; + inputRaw: WorkflowInputsData | null; + inputParams: ProcessIOParameter[] | null; + outputRaw: OutputDetails | null; + outputDefinitions: CommandOutputParameter[]; + outputParams: ProcessIOParameter[] | null; + nodeInfo: NodeInstanceType | null; } export interface ProcessPanelRootActionProps { onContextMenu: (event: React.MouseEvent, process: Process) => void; onToggle: (status: string) => void; cancelProcess: (uuid: string) => void; + startProcess: (uuid: string) => void; + resumeOnHoldWorkflow: (uuid: string) => void; onLogFilterChange: (filter: FilterOption) => void; navigateToLog: (uuid: string) => void; - onLogCopyToClipboard: (uuid: string) => void; - fetchOutputs: (uuid: string, fetchOutputs) => void; + onCopyToClipboard: (uuid: string) => void; + loadInputs: (containerRequest: ContainerRequestResource) => void; + loadOutputs: (containerRequest: ContainerRequestResource) => void; + loadNodeJson: (containerRequest: ContainerRequestResource) => void; + loadOutputDefinitions: (containerRequest: ContainerRequestResource) => void; + updateOutputParams: () => void; } export type ProcessPanelRootProps = ProcessPanelRootDataProps & ProcessPanelRootActionProps & WithStyles; -type OutputDetails = { - rawOutputs?: any; - pdh?: string; -} - const panelsData: MPVPanelState[] = [ - {name: "Details"}, - {name: "Logs", visible: true}, - {name: "Inputs"}, - {name: "Outputs"}, - {name: "Subprocesses"}, + { name: "Details" }, + { name: "Command" }, + { name: "Logs", visible: true }, + { name: "Inputs" }, + { name: "Outputs" }, + { name: "Resources" }, + { name: "Subprocesses" }, ]; export const ProcessPanelRoot = withStyles(styles)( - ({ process, auth, processLogsPanel, fetchOutputs, ...props }: ProcessPanelRootProps) => { - - const [outputDetails, setOutputs] = useState({}); - const [rawInputs, setInputs] = useState([]); - - - const [processedOutputs, setProcessedOutputs] = useState([]); - const [processedInputs, setProcessedInputs] = useState([]); - - const outputUuid = process?.containerRequest.outputUuid; - const requestUuid = process?.containerRequest.uuid; - - React.useEffect(() => { - if (outputUuid) { - fetchOutputs(outputUuid, setOutputs); - } - }, [outputUuid, fetchOutputs]); - - React.useEffect(() => { - if (outputDetails.rawOutputs) { - setProcessedOutputs(formatOutputData(outputDetails.rawOutputs, outputDetails.pdh, auth)); - } else { - setProcessedOutputs([]); - } - }, [outputDetails, auth]); - - React.useEffect(() => { - if (process) { - const rawInputs = getInputs(process.containerRequest); - setInputs(rawInputs); - setProcessedInputs(formatInputData(rawInputs, auth)); - } - }, [requestUuid, auth, process]); - - return process - ? - - props.onContextMenu(event, process)} - cancelProcess={props.cancelProcess} + ({ + process, + auth, + processLogsPanel, + inputRaw, + inputParams, + outputRaw, + outputDefinitions, + outputParams, + nodeInfo, + loadInputs, + loadOutputs, + loadNodeJson, + loadOutputDefinitions, + updateOutputParams, + ...props + }: ProcessPanelRootProps) => { + const outputUuid = process?.containerRequest.outputUuid; + const containerRequest = process?.containerRequest; + const inputMounts = getInputCollectionMounts(process?.containerRequest); + + React.useEffect(() => { + if (containerRequest) { + // Load inputs from mounts or props + loadInputs(containerRequest); + // Fetch raw output (loads from props or keep) + loadOutputs(containerRequest); + // Loads output definitions from mounts into store + loadOutputDefinitions(containerRequest); + // load the assigned instance type from node.json in + // the log collection + loadNodeJson(containerRequest); + } + }, [containerRequest, loadInputs, loadOutputs, loadOutputDefinitions, loadNodeJson]); + + // Trigger processing output params when raw or definitions change + React.useEffect(() => { + updateOutputParams(); + }, [outputRaw, outputDefinitions, updateOutputParams]); + + return process ? ( + + + props.onContextMenu(event, process)} + cancelProcess={props.cancelProcess} + startProcess={props.startProcess} + resumeOnHoldWorkflow={props.resumeOnHoldWorkflow} + /> + + + + + + ({ label: filter, value: filter }))} + onLogFilterChange={props.onLogFilterChange} + navigateToLog={props.navigateToLog} + /> + + + + + + + + + + + + + + + ) : ( + + - - - ({ label: filter, value: filter }) - )} - onLogFilterChange={props.onLogFilterChange} - navigateToLog={props.navigateToLog} - /> - - - - - - - - - - - - : - - ; + + ); } ); - -const formatInputData = (inputs: CommandInputParameter[], auth: AuthState): ProcessIOParameter[] => { - return inputs.map(input => { - return { - id: getInputId(input), - doc: input.label || "", - value: getInputDisplayValue(auth, input) - }; - }); -}; - -const formatOutputData = (rawData: any, pdh: string | undefined, auth: AuthState): ProcessIOParameter[] => { - if (!rawData) { return []; } - return Object.keys(rawData).map((id): ProcessIOParameter => { - const multiple = rawData[id].length > 0; - const outputArray = multiple ? rawData[id] : [rawData[id]]; - return { - id, - doc: outputArray.map((outputParam: CommandOutputParameter) => (outputParam.doc)) - // Doc can be string or string[], concat conveniently works with both - .reduce((acc: string[], input: string | string[]) => (acc.concat(input)), []) - // Remove undefined and empty doc strings - .filter(str => str) - .join(", "), - value: outputArray.map(outputParam => getInputDisplayValue(auth, { - type: outputParam.class, - value: outputParam, - ...outputParam - }, pdh, outputParam.secondaryFiles)) - .reduce((acc: ProcessIOParameter[], params: ProcessIOParameter[]) => (acc.concat(params)), []) - }; - }); -};