1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import React from 'react';
6 import { WorkflowIcon, StartIcon } from 'components/icon/icon';
8 WorkflowResource, parseWorkflowDefinition, getWorkflowInputs,
9 getWorkflowOutputs, getWorkflow
10 } from 'models/workflow';
11 import { DetailsData } from "./details-data";
12 import { DetailsAttribute } from 'components/details-attribute/details-attribute';
13 import { ResourceWithName } from 'views-components/data-explorer/renderers';
14 import { formatDate } from "common/formatters";
15 import { Grid } from '@mui/material';
16 import { CustomStyleRulesCallback } from 'common/custom-theme';
17 import { Button } from '@mui/material';
18 import { WithStyles } from '@mui/styles';
19 import withStyles from '@mui/styles/withStyles';
20 import { openRunProcess } from "store/workflow-panel/workflow-panel-actions";
21 import { Dispatch } from 'redux';
22 import { connect } from 'react-redux';
23 import { ArvadosTheme } from 'common/custom-theme';
24 import { ProcessIOParameter } from 'views/process-panel/process-io-card';
25 import { formatInputData, formatOutputData } from 'store/process-panel/process-panel-actions';
26 import { AuthState } from 'store/auth/auth-reducer';
27 import { RootState } from 'store/store';
28 import { getPropertyChip } from "views-components/resource-properties-form/property-chip";
30 export interface WorkflowDetailsCardDataProps {
31 workflow?: WorkflowResource;
34 export interface WorkflowDetailsCardActionProps {
35 onClick: (wf: WorkflowResource) => () => void;
38 const mapDispatchToProps = (dispatch: Dispatch) => ({
39 onClick: (wf: WorkflowResource) =>
40 () => wf && dispatch<any>(openRunProcess(wf.uuid, wf.ownerUuid, wf.name)),
43 type CssRules = 'runButton' | 'propertyTag';
45 const styles: CustomStyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
47 backgroundColor: theme.customs.colors.green700,
49 backgroundColor: theme.customs.colors.green800,
53 padding: '2px 10px 2px 5px',
57 marginRight: theme.spacing(0.5),
58 marginBottom: theme.spacing(0.5)
62 interface AuthStateDataProps {
66 export interface RegisteredWorkflowPanelDataProps {
67 item: WorkflowResource;
68 workflowCollection: string;
69 inputParams: ProcessIOParameter[];
70 outputParams: ProcessIOParameter[];
71 gitprops: { [key: string]: string; };
74 export const getRegisteredWorkflowPanelData = (item: WorkflowResource, auth: AuthState): RegisteredWorkflowPanelDataProps => {
75 let inputParams: ProcessIOParameter[] = [];
76 let outputParams: ProcessIOParameter[] = [];
77 let workflowCollection = "";
78 const gitprops: { [key: string]: string; } = {};
81 const wfdef = parseWorkflowDefinition(item);
84 const inputs = getWorkflowInputs(wfdef);
86 inputs.forEach(elm => {
87 if (elm.default !== undefined && elm.default !== null) {
88 elm.value = elm.default;
91 inputParams = formatInputData(inputs, auth);
94 const outputs = getWorkflowOutputs(wfdef);
96 outputParams = formatOutputData(outputs, {}, undefined, auth);
99 const wf = getWorkflow(wfdef);
101 const REGEX = /keep:([0-9a-f]{32}\+\d+)\/.*/;
103 const pdh = wf["steps"][0].run.match(REGEX);
105 workflowCollection = pdh[1];
110 for (const elm in wfdef) {
111 if (elm.startsWith("http://arvados.org/cwl#git")) {
112 gitprops[elm.substr(23)] = wfdef[elm]
117 return { item, workflowCollection, inputParams, outputParams, gitprops };
120 const mapStateToProps = (state: RootState): AuthStateDataProps => {
121 return { auth: state.auth };
124 export const WorkflowDetailsAttributes = connect(mapStateToProps, mapDispatchToProps)(
126 ({ workflow, onClick, auth, classes }: WorkflowDetailsCardDataProps & AuthStateDataProps & WorkflowDetailsCardActionProps & WithStyles<CssRules>) => {
131 const data = getRegisteredWorkflowPanelData(workflow, auth);
132 return <Grid container>
133 <Button onClick={workflow && onClick(workflow)} className={classes.runButton} variant='contained'
134 data-cy='workflow-details-panel-run-btn' color='primary' size='small'>
140 label={"Workflow UUID"}
141 linkToUuid={workflow?.uuid} />
145 label='Owner' linkToUuid={workflow?.ownerUuid}
146 uuidEnhancer={(uuid: string) => <ResourceWithName uuid={uuid} />} />
149 <DetailsAttribute label='Created at' value={formatDate(workflow?.createdAt)} />
152 <DetailsAttribute label='Last modified' value={formatDate(workflow?.modifiedAt)} />
154 <Grid item xs={12} data-cy="workflow-details-attributes-modifiedby-user">
156 label='Last modified by user' linkToUuid={workflow?.modifiedByUserUuid}
157 uuidEnhancer={(uuid: string) => <ResourceWithName uuid={uuid} />} />
159 <Grid item xs={12} md={12}>
160 <DetailsAttribute label='Properties' />
161 {Object.keys(data.gitprops).map(k =>
162 getPropertyChip(k, data.gitprops[k], undefined, classes.propertyTag))}
167 export class WorkflowDetails extends DetailsData<WorkflowResource> {
168 getIcon(className?: string) {
169 return <WorkflowIcon className={className} />;
173 return <WorkflowDetailsAttributes workflow={this.item} />;