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 ? (
);
+ // For running executions, add an overflow menu with the ability to clone
+ // while we are still running.
+ const moreActionsContent = !isTerminal ? (
+
+ ) : null;
+
return (
<>
@@ -145,6 +164,7 @@ export const ExecutionDetailsAppBarContent: React.FC<{
View Inputs & Outputs
{actionContent}
+ {moreActionsContent}