From dfa7e260372e7743efcc42bb5c9f03742e776fa8 Mon Sep 17 00:00:00 2001 From: Randy Schott <1815175+schottra@users.noreply.github.com> Date: Tue, 1 Sep 2020 17:27:06 -0700 Subject: [PATCH] feat: Allow cloning of running executions (#93) * feat: add clone functionality for running executions * fix: updating deprecated method in test --- src/components/Errors/test/DataError.test.tsx | 4 +- .../ExecutionDetailsAppBarContent.tsx | 54 ++++++---- .../Executions/ExecutionDetails/constants.ts | 4 + .../ExecutionDetailsAppBarContent.test.tsx | 98 +++++++++++++++++++ src/components/common/MoreOptionsMenu.tsx | 79 +++++++++++++++ src/components/common/constants.ts | 5 + .../common/test/MoreOptionsMenu.test.tsx | 72 ++++++++++++++ src/test/utils.ts | 2 +- 8 files changed, 298 insertions(+), 20 deletions(-) create mode 100644 src/components/Executions/ExecutionDetails/test/ExecutionDetailsAppBarContent.test.tsx create mode 100644 src/components/common/MoreOptionsMenu.tsx create mode 100644 src/components/common/test/MoreOptionsMenu.test.tsx diff --git a/src/components/Errors/test/DataError.test.tsx b/src/components/Errors/test/DataError.test.tsx index 89f4a6f14..20ef817b1 100644 --- a/src/components/Errors/test/DataError.test.tsx +++ b/src/components/Errors/test/DataError.test.tsx @@ -13,13 +13,13 @@ describe('DataError', () => { const { container } = render( ); - expect(container).toBeEmpty(); + expect(container).toBeEmptyDOMElement(); }); it('renders not found for NotFound errors', () => { const { getByText } = render( ); - expect(getByText('Not found')).not.toBeEmpty(); + expect(getByText('Not found')).not.toBeEmptyDOMElement(); }); }); diff --git a/src/components/Executions/ExecutionDetails/ExecutionDetailsAppBarContent.tsx b/src/components/Executions/ExecutionDetails/ExecutionDetailsAppBarContent.tsx index 696bcb496..4a239b314 100644 --- a/src/components/Executions/ExecutionDetails/ExecutionDetailsAppBarContent.tsx +++ b/src/components/Executions/ExecutionDetails/ExecutionDetailsAppBarContent.tsx @@ -3,10 +3,11 @@ import { makeStyles, Theme } from '@material-ui/core/styles'; import ArrowBack from '@material-ui/icons/ArrowBack'; import * as classnames from 'classnames'; import { navbarGridHeight } from 'common/layout'; +import { MoreOptionsMenu } from 'components/common/MoreOptionsMenu'; import { useCommonStyles } from 'components/common/styles'; import { useLocationState } from 'components/hooks/useLocationState'; import { NavBarContent } from 'components/Navigation/NavBarContent'; -import { interactiveTextDisabledColor, smallFontSize } from 'components/Theme'; +import { interactiveTextDisabledColor } from 'components/Theme'; import { Execution } from 'models'; import * as React from 'react'; import { Link as RouterLink } from 'react-router-dom'; @@ -15,10 +16,14 @@ import { ExecutionInputsOutputsModal } from '../ExecutionInputsOutputsModal'; import { ExecutionStatusBadge } from '../ExecutionStatusBadge'; import { TerminateExecutionButton } from '../TerminateExecution'; import { executionIsTerminal } from '../utils'; +import { executionActionStrings } from './constants'; import { RelaunchExecutionForm } from './RelaunchExecutionForm'; const useStyles = makeStyles((theme: Theme) => { return { + actionButton: { + marginLeft: theme.spacing(2) + }, actions: { alignItems: 'center', display: 'flex', @@ -37,24 +42,25 @@ const useStyles = makeStyles((theme: Theme) => { flex: '1 1 auto', maxWidth: '100%' }, - titleContainer: { - alignItems: 'center', - display: 'flex', - flex: '0 1 auto', - flexDirection: 'column', - maxHeight: theme.spacing(navbarGridHeight), - overflow: 'hidden' - }, inputsOutputsLink: { color: interactiveTextDisabledColor }, - actionButton: { - marginLeft: theme.spacing(2) + moreActions: { + marginLeft: theme.spacing(1), + marginRight: theme.spacing(-2) }, title: { flex: '0 1 auto', marginLeft: theme.spacing(2) }, + titleContainer: { + alignItems: 'center', + display: 'flex', + flex: '0 1 auto', + flexDirection: 'column', + maxHeight: theme.spacing(navbarGridHeight), + overflow: 'hidden' + }, version: { flex: '0 1 auto', overflow: 'hidden' @@ -70,10 +76,8 @@ export const ExecutionDetailsAppBarContent: React.FC<{ const styles = useStyles(); const [showInputsOutputs, setShowInputsOutputs] = React.useState(false); const [showRelaunchForm, setShowRelaunchForm] = React.useState(false); - const { domain, name, project } = execution.id; const { phase, workflowId } = execution.closure; - const { backLink = Routes.WorkflowDetails.makeUrl( workflowId.project, @@ -81,6 +85,10 @@ export const ExecutionDetailsAppBarContent: React.FC<{ workflowId.name ) } = useLocationState(); + const isTerminal = executionIsTerminal(execution); + const onClickShowInputsOutputs = () => setShowInputsOutputs(true); + const onClickRelaunch = () => setShowRelaunchForm(true); + const onCloseRelaunch = () => setShowRelaunchForm(false); let modalContent: JSX.Element | null = null; if (showInputsOutputs) { @@ -92,11 +100,8 @@ export const ExecutionDetailsAppBarContent: React.FC<{ /> ); } - const onClickShowInputsOutputs = () => setShowInputsOutputs(true); - const onClickRelaunch = () => setShowRelaunchForm(true); - const onCloseRelaunch = () => setShowRelaunchForm(false); - const actionContent = executionIsTerminal(execution) ? ( + const actionContent = isTerminal ? (