1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import React from 'react';
6 import { CustomStyleRulesCallback } from 'common/custom-theme';
7 import { Card, CardHeader, IconButton, CardContent, Tooltip, Typography, Button } from '@mui/material';
8 import { WithStyles } from '@mui/styles';
9 import withStyles from '@mui/styles/withStyles';
10 import { ArvadosTheme } from 'common/custom-theme';
11 import { CloseIcon, MoreVerticalIcon, ProcessIcon, StartIcon, StopIcon } from 'components/icon/icon';
12 import { Process, isProcessRunnable, isProcessResumable, isProcessCancelable } from 'store/processes/process';
13 import { MPVPanelProps } from 'components/multi-panel-view/multi-panel-view';
14 import { ProcessDetailsAttributes } from './process-details-attributes';
15 import { ProcessStatus } from 'views-components/data-explorer/renderers';
16 import classNames from 'classnames';
18 type CssRules = 'card' | 'content' | 'title' | 'header' | 'cancelButton' | 'avatar' | 'iconHeader' | 'actionButton';
20 const styles: CustomStyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
25 paddingTop: theme.spacing(1),
26 paddingBottom: theme.spacing(1),
30 color: theme.customs.colors.greyL,
33 alignSelf: 'flex-start',
34 paddingTop: theme.spacing(0.5)
37 padding: theme.spacing(1),
38 paddingTop: theme.spacing(0.5),
40 paddingBottom: theme.spacing(1),
45 paddingTop: theme.spacing(0.5),
46 color: theme.customs.colors.green700,
49 padding: "0px 5px 0 0",
54 color: theme.palette.common.white,
55 backgroundColor: theme.customs.colors.red900,
57 backgroundColor: theme.customs.colors.red900,
65 export interface ProcessDetailsCardDataProps {
67 cancelProcess: (uuid: string) => void;
68 startProcess: (uuid: string) => void;
69 resumeOnHoldWorkflow: (uuid: string) => void;
70 onContextMenu: (event: React.MouseEvent<HTMLElement>) => void;
73 type ProcessDetailsCardProps = ProcessDetailsCardDataProps & WithStyles<CssRules> & MPVPanelProps;
75 export const ProcessDetailsCard = withStyles(styles)(
76 ({ cancelProcess, startProcess, resumeOnHoldWorkflow, onContextMenu, classes, process, doHidePanel, panelName }: ProcessDetailsCardProps) => {
77 let runAction: ((uuid: string) => void) | undefined = undefined;
78 if (isProcessRunnable(process)) {
79 runAction = startProcess;
80 } else if (isProcessResumable(process)) {
81 runAction = resumeOnHoldWorkflow;
85 <Card className={classes.card}>
87 className={classes.header}
89 content: classes.title,
90 avatar: classes.avatar,
92 avatar={<ProcessIcon className={classes.iconHeader} />}
94 <Tooltip title={process.containerRequest.name} placement="bottom-start">
95 <Typography noWrap variant='h6'>
96 {process.containerRequest.name}
101 <Tooltip title={getDescription(process)} placement="bottom-start">
102 <Typography noWrap variant='body1' color='inherit'>
103 {getDescription(process)}
108 {runAction !== undefined &&
110 data-cy="process-run-button"
114 className={classes.actionButton}
115 onClick={() => runAction && runAction(process.containerRequest.uuid)}>
119 {isProcessCancelable(process) &&
121 data-cy="process-cancel-button"
125 className={classNames(classes.actionButton, classes.cancelButton)}
126 onClick={() => cancelProcess(process.containerRequest.uuid)}>
130 <ProcessStatus uuid={process.containerRequest.uuid} />
131 <Tooltip title="More options" disableFocusListener>
133 aria-label="More options"
134 onClick={event => onContextMenu(event)}
140 <Tooltip title={`Close ${panelName || 'panel'}`} disableFocusListener>
141 <IconButton onClick={doHidePanel} size="large"><CloseIcon /></IconButton>
145 <CardContent className={classes.content}>
146 <ProcessDetailsAttributes request={process.containerRequest} container={process.container} twoCol hideProcessPanelRedundantFields />
153 const getDescription = (process: Process) =>
154 process.containerRequest.description || '(no-description)';