re-run-workflow-and-display-workflow-inside-process-info-card
[arvados-workbench2.git] / src / views / process-panel / process-information-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, WithStyles, withStyles, Card,
8     CardHeader, IconButton, CardContent, Grid, Chip, Typography, Tooltip
9 } from '@material-ui/core';
10 import { ArvadosTheme } from '~/common/custom-theme';
11 import { MoreOptionsIcon, ProcessIcon } from '~/components/icon/icon';
12 import { DetailsAttribute } from '~/components/details-attribute/details-attribute';
13 import { Process } from '~/store/processes/process';
14 import { getProcessStatus, getProcessStatusColor } from '~/store/processes/process';
15 import { formatDate } from '~/common/formatters';
16 import * as classNames from 'classnames';
17
18 type CssRules = 'card' | 'iconHeader' | 'label' | 'value' | 'chip' | 'link' | 'content' | 'title' | 'avatar';
19
20 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
21     card: {
22         height: '100%'
23     },
24     iconHeader: {
25         fontSize: '1.875rem',
26         color: theme.customs.colors.green700,
27     },
28     avatar: {
29         alignSelf: 'flex-start',
30         paddingTop: theme.spacing.unit * 0.5
31     },
32     label: {
33         display: 'flex',
34         justifyContent: 'flex-end',
35         fontSize: '0.875rem',
36         marginRight: theme.spacing.unit * 3,
37         paddingRight: theme.spacing.unit
38     },
39     value: {
40         textTransform: 'none',
41         fontSize: '0.875rem',
42     },
43     link: {
44         fontSize: '0.875rem',
45         color: theme.palette.primary.main,
46         '&:hover': {
47             cursor: 'pointer'
48         }
49     },
50     chip: {
51         height: theme.spacing.unit * 3,
52         width: theme.spacing.unit * 12,
53         color: theme.palette.common.white,
54         fontSize: '0.875rem',
55         borderRadius: theme.spacing.unit * 0.625,
56     },
57     content: {
58         '&:last-child': {
59             paddingBottom: theme.spacing.unit * 2,
60         }
61     },
62     title: {
63         overflow: 'hidden',
64         paddingTop: theme.spacing.unit * 0.5
65     }
66 });
67
68 export interface ProcessInformationCardDataProps {
69     process: Process;
70     onContextMenu: (event: React.MouseEvent<HTMLElement>) => void;
71     openProcessInputDialog: (uuid: string) => void;
72     navigateToOutput: (uuid: string) => void;
73     openWorkflow: (uuid: string) => void;
74 }
75
76 type ProcessInformationCardProps = ProcessInformationCardDataProps & WithStyles<CssRules, true>;
77
78 export const ProcessInformationCard = withStyles(styles, { withTheme: true })(
79     ({ classes, process, onContextMenu, theme, openProcessInputDialog, navigateToOutput, openWorkflow }: ProcessInformationCardProps) => {
80         const { container } = process;
81         const startedAt = container ? formatDate(container.startedAt) : 'N/A';
82         const finishedAt = container ? formatDate(container.finishedAt) : 'N/A';
83         return <Card className={classes.card}>
84             <CardHeader
85                 classes={{
86                     content: classes.title,
87                     avatar: classes.avatar
88                 }}
89                 avatar={<ProcessIcon className={classes.iconHeader} />}
90                 action={
91                     <div>
92                         <Chip label={getProcessStatus(process)}
93                             className={classes.chip}
94                             style={{ backgroundColor: getProcessStatusColor(getProcessStatus(process), theme as ArvadosTheme) }} />
95                         <Tooltip title="More options" disableFocusListener>
96                             <IconButton
97                                 aria-label="More options"
98                                 onClick={event => onContextMenu(event)}>
99                                 <MoreOptionsIcon />
100                             </IconButton>
101                         </Tooltip>
102                     </div>
103                 }
104                 title={
105                     <Tooltip title={process.containerRequest.name} placement="bottom-start">
106                         <Typography noWrap variant='h6' color='inherit'>
107                             {process.containerRequest.name}
108                         </Typography>
109                     </Tooltip>
110                 }
111                 subheader={
112                     <Tooltip title={getDescription(process)} placement="bottom-start">
113                         <Typography noWrap variant='body1' color='inherit'>
114                             {getDescription(process)}
115                         </Typography>
116                     </Tooltip>} />
117             <CardContent className={classes.content}>
118                 <Grid container>
119                     <Grid item xs={6}>
120                         <DetailsAttribute classLabel={classes.label} classValue={classes.value}
121                             label='From'
122                             value={process.container ? formatDate(startedAt) : 'N/A'} />
123                         <DetailsAttribute classLabel={classes.label} classValue={classes.value}
124                             label='To'
125                             value={process.container ? formatDate(finishedAt) : 'N/A'} />
126                         {process.containerRequest.properties.workflowUuid &&
127                             <span onClick={() => openWorkflow(process.containerRequest.properties.workflowUuid)}>
128                                 <DetailsAttribute classLabel={classes.label} classValue={classNames(classes.value, classes.link)} 
129                                 label='Workflow' value={process.containerRequest.properties.workflowName}/>
130                             </span>}
131                     </Grid>
132                     <Grid item xs={6}>
133                         <span onClick={() => navigateToOutput(process.containerRequest.outputUuid!)}>
134                             <DetailsAttribute classLabel={classes.link} label='Outputs' />
135                         </span>
136                         <span onClick={() => openProcessInputDialog(process.containerRequest.uuid)}>
137                             <DetailsAttribute classLabel={classes.link} label='Inputs' />
138                         </span>
139                     </Grid>
140                 </Grid>
141             </CardContent>
142         </Card>;
143     }
144 );
145
146 const getDescription = (process: Process) =>
147     process.containerRequest.description || '(no-description)';