From 7c6d47d766b7b37463281387d8badbfe18522d09 Mon Sep 17 00:00:00 2001 From: Stephen Smith Date: Tue, 12 Apr 2022 14:04:47 -0400 Subject: [PATCH] 16068: Merge process info card and process details card. Arvados-DCO-1.1-Signed-off-by: Stephen Smith --- .../details-panel/process-details.tsx | 2 +- .../process-details-attributes.tsx | 163 +++++++++++------ .../process-panel/process-details-card.tsx | 80 +++++++-- .../process-information-card.tsx | 169 ------------------ .../process-panel/process-panel-root.tsx | 17 +- src/views/process-panel/process-panel.tsx | 6 - 6 files changed, 185 insertions(+), 252 deletions(-) delete mode 100644 src/views/process-panel/process-information-card.tsx diff --git a/src/views-components/details-panel/process-details.tsx b/src/views-components/details-panel/process-details.tsx index d9c991f5..bb0e8a40 100644 --- a/src/views-components/details-panel/process-details.tsx +++ b/src/views-components/details-panel/process-details.tsx @@ -15,6 +15,6 @@ export class ProcessDetails extends DetailsData { } getDetails() { - return ; + return ; } } diff --git a/src/views/process-panel/process-details-attributes.tsx b/src/views/process-panel/process-details-attributes.tsx index 4f26a71f..6ddeab7a 100644 --- a/src/views/process-panel/process-details-attributes.tsx +++ b/src/views/process-panel/process-details-attributes.tsx @@ -3,63 +3,122 @@ // SPDX-License-Identifier: AGPL-3.0 import React from "react"; -import { Grid } from "@material-ui/core"; +import { Grid, StyleRulesCallback, withStyles } from "@material-ui/core"; +import { Dispatch } from 'redux'; import { formatDate } from "common/formatters"; import { resourceLabel } from "common/labels"; import { DetailsAttribute } from "components/details-attribute/details-attribute"; -import { ProcessResource } from "models/process"; import { ResourceKind } from "models/resource"; import { ResourceOwnerWithName } from "views-components/data-explorer/renderers"; +import { getProcess } from "store/processes/process"; +import { RootState } from "store/store"; +import { connect } from "react-redux"; +import { ProcessResource } from "models/process"; +import { ContainerResource } from "models/container"; +import { openProcessInputDialog } from "store/processes/process-input-actions"; +import { navigateToOutput, openWorkflow } from "store/process-panel/process-panel-actions"; +import { ArvadosTheme } from "common/custom-theme"; + +type CssRules = 'link'; -type CssRules = 'label' | 'value'; +const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ + link: { + fontSize: '0.875rem', + color: theme.palette.primary.main, + '&:hover': { + cursor: 'pointer' + } + }, +}); -export const ProcessDetailsAttributes = (props: { item: ProcessResource, twoCol?: boolean, classes?: Record }) => { - const item = props.item; - const classes = props.classes || { label: '', value: '', button: '' }; - const mdSize = props.twoCol ? 6 : 12; - return - - - - - } /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; +const mapStateToProps = (state: RootState, props: { request: ProcessResource }) => { + return { + container: getProcess(props.request.uuid)(state.resources)?.container, + }; }; + +interface ProcessDetailsAttributesActionProps { + openProcessInputDialog: (uuid: string) => void; + navigateToOutput: (uuid: string) => void; + openWorkflow: (uuid: string) => void; +} + +const mapDispatchToProps = (dispatch: Dispatch): ProcessDetailsAttributesActionProps => ({ + openProcessInputDialog: (uuid) => dispatch(openProcessInputDialog(uuid)), + navigateToOutput: (uuid) => dispatch(navigateToOutput(uuid)), + openWorkflow: (uuid) => dispatch(openWorkflow(uuid)), +}); + +export const ProcessDetailsAttributes = withStyles(styles, { withTheme: true })( + connect(mapStateToProps, mapDispatchToProps)( + (props: { request: ProcessResource, container?: ContainerResource, twoCol?: boolean, classes?: Record } & ProcessDetailsAttributesActionProps) => { + const containerRequest = props.request; + const container = props.container; + const classes = props.classes || { label: '', value: '', button: '', link: '' }; + const mdSize = props.twoCol ? 6 : 12; + return + + + + + } /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + props.navigateToOutput(containerRequest.outputUuid!)}> + + + props.openProcessInputDialog(containerRequest.uuid)}> + + + + {containerRequest.properties.workflowUuid && + + props.openWorkflow(containerRequest.properties.workflowUuid)}> + + + } + + + + + + + + + + ; + } + ) +); diff --git a/src/views/process-panel/process-details-card.tsx b/src/views/process-panel/process-details-card.tsx index d3349c3a..5cca904a 100644 --- a/src/views/process-panel/process-details-card.tsx +++ b/src/views/process-panel/process-details-card.tsx @@ -12,14 +12,17 @@ import { IconButton, CardContent, Tooltip, + Typography, + Chip, } from '@material-ui/core'; import { ArvadosTheme } from 'common/custom-theme'; -import { CloseIcon } from 'components/icon/icon'; -import { Process } from 'store/processes/process'; +import { CloseIcon, MoreOptionsIcon, ProcessIcon } from 'components/icon/icon'; +import { Process, getProcessStatus, getProcessStatusColor } from 'store/processes/process'; import { MPVPanelProps } from 'components/multi-panel-view/multi-panel-view'; import { ProcessDetailsAttributes } from './process-details-attributes'; +import { ContainerState } from 'models/container'; -type CssRules = 'card' | 'content' | 'title' | 'header'; +type CssRules = 'card' | 'content' | 'title' | 'header' | 'cancelButton' | 'chip' | 'avatar' | 'iconHeader'; const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ card: { @@ -29,6 +32,14 @@ const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ paddingTop: theme.spacing.unit, paddingBottom: theme.spacing.unit, }, + iconHeader: { + fontSize: '1.875rem', + color: theme.customs.colors.green700, + }, + avatar: { + alignSelf: 'flex-start', + paddingTop: theme.spacing.unit * 0.5 + }, content: { '&:last-child': { paddingBottom: theme.spacing.unit * 2, @@ -38,31 +49,80 @@ const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ overflow: 'hidden', paddingTop: theme.spacing.unit * 0.5 }, + cancelButton: { + paddingRight: theme.spacing.unit * 2, + fontSize: '14px', + color: theme.customs.colors.red900, + "&:hover": { + cursor: 'pointer' + } + }, + chip: { + height: theme.spacing.unit * 3, + width: theme.spacing.unit * 12, + color: theme.palette.common.white, + fontSize: '0.875rem', + borderRadius: theme.spacing.unit * 0.625, + }, }); export interface ProcessDetailsCardDataProps { process: Process; + cancelProcess: (uuid: string) => void; + onContextMenu: (event: React.MouseEvent) => void; } -type ProcessDetailsCardProps = ProcessDetailsCardDataProps & WithStyles & MPVPanelProps; +type ProcessDetailsCardProps = ProcessDetailsCardDataProps & WithStyles & MPVPanelProps; -export const ProcessDetailsCard = withStyles(styles)( - ({ classes, process, doHidePanel, panelName }: ProcessDetailsCardProps) => { +export const ProcessDetailsCard = withStyles(styles, {withTheme: true})( + ({ theme, cancelProcess, onContextMenu, classes, process, doHidePanel, panelName }: ProcessDetailsCardProps) => { return } + title={ + + + {process.containerRequest.name} + + + } + subheader={ + + + {getDescription(process)} + + } + action={ +
+ {process.container && process.container.state === ContainerState.RUNNING && + cancelProcess(process.containerRequest.uuid)}>Cancel} + + + onContextMenu(event)}> + + + + { doHidePanel && - } /> + } +
+ } /> - +
; } ); +const getDescription = (process: Process) => + process.containerRequest.description || '(no-description)'; diff --git a/src/views/process-panel/process-information-card.tsx b/src/views/process-panel/process-information-card.tsx deleted file mode 100644 index fc34a31c..00000000 --- a/src/views/process-panel/process-information-card.tsx +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (C) The Arvados Authors. All rights reserved. -// -// SPDX-License-Identifier: AGPL-3.0 - -import React from 'react'; -import { - StyleRulesCallback, WithStyles, withStyles, Card, - CardHeader, IconButton, CardContent, Grid, Chip, Typography, Tooltip -} from '@material-ui/core'; -import { ArvadosTheme } from 'common/custom-theme'; -import { CloseIcon, MoreOptionsIcon, ProcessIcon } from 'components/icon/icon'; -import { DetailsAttribute } from 'components/details-attribute/details-attribute'; -import { Process } from 'store/processes/process'; -import { getProcessStatus, getProcessStatusColor } from 'store/processes/process'; -import { formatDate } from 'common/formatters'; -import classNames from 'classnames'; -import { ContainerState } from 'models/container'; -import { MPVPanelProps } from 'components/multi-panel-view/multi-panel-view'; - -type CssRules = 'card' | 'iconHeader' | 'label' | 'value' | 'chip' | 'link' | 'content' | 'title' | 'avatar' | 'cancelButton' | 'header'; - -const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ - card: { - height: '100%' - }, - header: { - paddingTop: theme.spacing.unit, - paddingBottom: theme.spacing.unit, - }, - iconHeader: { - fontSize: '1.875rem', - color: theme.customs.colors.green700, - }, - avatar: { - alignSelf: 'flex-start', - paddingTop: theme.spacing.unit * 0.5 - }, - label: { - display: 'flex', - justifyContent: 'flex-end', - fontSize: '0.875rem', - marginRight: theme.spacing.unit * 3, - paddingRight: theme.spacing.unit - }, - value: { - textTransform: 'none', - fontSize: '0.875rem', - }, - link: { - fontSize: '0.875rem', - color: theme.palette.primary.main, - '&:hover': { - cursor: 'pointer' - } - }, - chip: { - height: theme.spacing.unit * 3, - width: theme.spacing.unit * 12, - color: theme.palette.common.white, - fontSize: '0.875rem', - borderRadius: theme.spacing.unit * 0.625, - }, - content: { - '&:last-child': { - paddingBottom: theme.spacing.unit * 2, - } - }, - title: { - overflow: 'hidden', - paddingTop: theme.spacing.unit * 0.5 - }, - cancelButton: { - paddingRight: theme.spacing.unit * 2, - fontSize: '14px', - color: theme.customs.colors.red900, - "&:hover": { - cursor: 'pointer' - } - } -}); - -export interface ProcessInformationCardDataProps { - process: Process; - onContextMenu: (event: React.MouseEvent) => void; - openProcessInputDialog: (uuid: string) => void; - navigateToOutput: (uuid: string) => void; - openWorkflow: (uuid: string) => void; - cancelProcess: (uuid: string) => void; -} - -type ProcessInformationCardProps = ProcessInformationCardDataProps & WithStyles & MPVPanelProps; - -export const ProcessInformationCard = withStyles(styles, { withTheme: true })( - ({ classes, process, onContextMenu, theme, openProcessInputDialog, navigateToOutput, openWorkflow, cancelProcess, doHidePanel, panelName }: ProcessInformationCardProps) => { - const { container } = process; - const startedAt = container ? formatDate(container.startedAt) : 'N/A'; - const finishedAt = container ? formatDate(container.finishedAt) : 'N/A'; - return - } - action={ -
- {process.container && process.container.state === ContainerState.RUNNING && - cancelProcess(process.containerRequest.uuid)}>Cancel} - - - onContextMenu(event)}> - - - - { doHidePanel && - - - } -
- } - title={ - - - {process.containerRequest.name} - - - } - subheader={ - - - {getDescription(process)} - - } /> - - - - - - {process.containerRequest.properties.workflowUuid && - openWorkflow(process.containerRequest.properties.workflowUuid)}> - - } - - - navigateToOutput(process.containerRequest.outputUuid!)}> - - - openProcessInputDialog(process.containerRequest.uuid)}> - - - - - -
; - } -); - -const getDescription = (process: Process) => - process.containerRequest.description || '(no-description)'; diff --git a/src/views/process-panel/process-panel-root.tsx b/src/views/process-panel/process-panel-root.tsx index 156789a2..4f95d0d8 100644 --- a/src/views/process-panel/process-panel-root.tsx +++ b/src/views/process-panel/process-panel-root.tsx @@ -4,7 +4,6 @@ import React from 'react'; import { Grid, StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core'; -import { ProcessInformationCard } from './process-information-card'; import { DefaultView } from 'components/default-view/default-view'; import { ProcessIcon } from 'components/icon/icon'; import { Process } from 'store/processes/process'; @@ -35,9 +34,6 @@ export interface ProcessPanelRootDataProps { export interface ProcessPanelRootActionProps { onContextMenu: (event: React.MouseEvent, process: Process) => void; onToggle: (status: string) => void; - openProcessInputDialog: (uuid: string) => void; - navigateToOutput: (uuid: string) => void; - navigateToWorkflow: (uuid: string) => void; cancelProcess: (uuid: string) => void; onLogFilterChange: (filter: FilterOption) => void; navigateToLog: (uuid: string) => void; @@ -47,8 +43,7 @@ export interface ProcessPanelRootActionProps { export type ProcessPanelRootProps = ProcessPanelRootDataProps & ProcessPanelRootActionProps & WithStyles; const panelsData: MPVPanelState[] = [ - {name: "Info"}, - {name: "Details", visible: false}, + {name: "Details"}, {name: "Logs", visible: true}, {name: "Subprocesses"}, ]; @@ -57,19 +52,13 @@ export const ProcessPanelRoot = withStyles(styles)( ({ process, processLogsPanel, ...props }: ProcessPanelRootProps) => process ? - - + props.onContextMenu(event, process)} - openProcessInputDialog={props.openProcessInputDialog} - navigateToOutput={props.navigateToOutput} - openWorkflow={props.navigateToWorkflow} cancelProcess={props.cancelProcess} /> - - - onToggle: status => { dispatch(toggleProcessPanelFilter(status)); }, - openProcessInputDialog: (uuid) => dispatch(openProcessInputDialog(uuid)), - navigateToOutput: (uuid) => dispatch(navigateToOutput(uuid)), - navigateToWorkflow: (uuid) => dispatch(openWorkflow(uuid)), cancelProcess: (uuid) => dispatch(cancelRunningWorkflow(uuid)), onLogFilterChange: (filter) => dispatch(setProcessLogsPanelFilter(filter.value)), navigateToLog: (uuid) => dispatch(navigateToLogCollection(uuid)), -- 2.30.2