Merge branch 'master' into 14277-search-view-editing-saved-queries
[arvados-workbench2.git] / src / views / workflow-panel / workflow-description-card.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import * as React from 'react';
6 import {
7     StyleRulesCallback,
8     WithStyles,
9     withStyles,
10     CardContent,
11     Tab,
12     Tabs,
13     Table,
14     TableHead,
15     TableCell,
16     TableBody,
17     TableRow,
18     Divider
19 } from '@material-ui/core';
20 import { ArvadosTheme } from '~/common/custom-theme';
21 import { WorkflowIcon } from '~/components/icon/icon';
22 import { DataTableDefaultView } from '~/components/data-table-default-view/data-table-default-view';
23 import { WorkflowResource, parseWorkflowDefinition, getWorkflowInputs, getInputLabel, stringifyInputType } from '~/models/workflow';
24 import { WorkflowGraph } from "~/views/workflow-panel/workflow-graph";
25
26 export type CssRules = 'root' | 'tab' | 'inputTab';
27
28 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
29     root: {
30         height: '100%'
31     },
32     tab: {
33         minWidth: '33%'
34     },
35     inputTab: {
36         height: 'calc(100% - 48px - 16px * 2)',
37         overflowX: 'auto',
38         overflowY: 'hidden',
39         '&:last-child': {
40             paddingBottom: theme.spacing.unit / 2,
41         }
42     }
43 });
44
45 interface WorkflowDetailsCardDataProps {
46     workflow?: WorkflowResource;
47 }
48
49 type WorkflowDetailsCardProps = WorkflowDetailsCardDataProps & WithStyles<CssRules>;
50
51 export const WorkflowDetailsCard = withStyles(styles)(
52     class extends React.Component<WorkflowDetailsCardProps> {
53         state = {
54             value: 0,
55         };
56
57         handleChange = (event: React.MouseEvent<HTMLElement>, value: number) => {
58             this.setState({ value });
59         }
60
61         render() {
62             const { classes, workflow } = this.props;
63             const { value } = this.state;
64             return <div className={classes.root}>
65                 <Tabs value={value} onChange={this.handleChange} centered={true}>
66                     <Tab className={classes.tab} label="Description" />
67                     <Tab className={classes.tab} label="Inputs" />
68                     <Tab className={classes.tab} label="Graph" />
69                 </Tabs>
70                 {value === 0 && <CardContent>
71                     {workflow ? <div>
72                         {workflow.description}
73                     </div> : (
74                             <DataTableDefaultView
75                                 icon={WorkflowIcon}
76                                 messages={['Please select a workflow to see its description.']} />
77                         )}
78                 </CardContent>}
79                 {value === 1 && <CardContent className={classes.inputTab}>
80                     {workflow
81                         ? this.renderInputsTable()
82                         : <DataTableDefaultView
83                             icon={WorkflowIcon}
84                             messages={['Please select a workflow to see its inputs.']} />
85                     }
86                 </CardContent>}
87                 {value === 2 && <CardContent className={classes.inputTab}>
88                     {workflow
89                         ? <WorkflowGraph workflow={workflow}/>
90                         : <DataTableDefaultView
91                             icon={WorkflowIcon}
92                             messages={['Please select a workflow to see its visualisation.']} />
93                     }
94                 </CardContent>}
95             </div>;
96         }
97
98         get inputs() {
99             if (this.props.workflow) {
100                 const definition = parseWorkflowDefinition(this.props.workflow);
101                 if (definition) {
102                     return getWorkflowInputs(definition);
103                 }
104             }
105             return;
106         }
107
108         renderInputsTable() {
109             return <Table>
110                 <TableHead>
111                     <TableRow>
112                         <TableCell>Label</TableCell>
113                         <TableCell>Type</TableCell>
114                         <TableCell>Description</TableCell>
115                     </TableRow>
116                 </TableHead>
117                 <TableBody>
118                     {this.inputs && this.inputs.map(input =>
119                         <TableRow key={input.id}>
120                             <TableCell>{getInputLabel(input)}</TableCell>
121                             <TableCell>{stringifyInputType(input)}</TableCell>
122                             <TableCell>{input.doc}</TableCell>
123                         </TableRow>)}
124                 </TableBody>
125             </Table>;
126         }
127     });