Skip to content

Commit

Permalink
Feature: Fullview Flyte Deck modal (#764)
Browse files Browse the repository at this point in the history
* chore: full viewport modal

Signed-off-by: Frank Flitton <[email protected]>

* chore: close modal on escape

Signed-off-by: Frank Flitton <[email protected]>

* chore: key events as hook

Signed-off-by: Frank Flitton <[email protected]>

* chore: add close on esc key to other modals

Signed-off-by: Frank Flitton <[email protected]>

---------

Signed-off-by: Frank Flitton <[email protected]>
  • Loading branch information
FrankFlitton authored May 19, 2023
1 parent 333940f commit c69f010
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getProjectDomain } from 'models/Project/utils';
import * as React from 'react';
import { Link } from 'react-router-dom';
import { LaunchForm } from 'components/Launch/LaunchForm/LaunchForm';
import { useEscapeKey } from 'components/hooks/useKeyListener';
import { backUrlGenerator, backToDetailUrlGenerator } from './generators';
import { entityStrings } from './constants';
import t, { patternKey } from './strings';
Expand Down Expand Up @@ -64,7 +65,12 @@ export const EntityDetailsHeader: React.FC<EntityDetailsHeaderProps> = ({
const commonStyles = useCommonStyles();

const [showLaunchForm, setShowLaunchForm] = React.useState(false);
const onCancelLaunch = () => setShowLaunchForm(false);
const onCancelLaunch = (_?: KeyboardEvent) => {
setShowLaunchForm(false);
};

// Close modal on escape key press
useEscapeKey(onCancelLaunch);

const domain = getProjectDomain(project, id.domain);
const headerText = `${domain.name} / ${id.name}`;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { Button, Dialog, IconButton } from '@material-ui/core';
import { Button, Dialog, Grid, IconButton } from '@material-ui/core';
import { ResourceIdentifier, Identifier } from 'models/Common/types';
import { makeStyles, Theme } from '@material-ui/core/styles';
import { getTask } from 'models/Task/api';
Expand All @@ -15,6 +15,8 @@ import { NodeExecutionPhase } from 'models/Execution/enums';
import { extractCompiledNodes } from 'components/hooks/utils';
import Close from '@material-ui/icons/Close';
import classnames from 'classnames';
import { Fullscreen, FullscreenExit } from '@material-ui/icons';
import { useEscapeKey } from 'components/hooks/useKeyListener';
import { NodeExecutionDetails } from '../types';
import t from './strings';
import { ExecutionNodeDeck } from './ExecutionNodeDeck';
Expand All @@ -38,10 +40,18 @@ const useStyles = makeStyles((theme: Theme) => {
maxHeight: `calc(100% - ${theme.spacing(12)}px)`,
height: theme.spacing(90),
width: theme.spacing(110),
transition: 'all 0.3s ease',
},
dialogTitle: {
display: 'flex',
alignItems: 'center',
fullscreenDialog: {
maxWidth: '100vw',
width: '100vw',
maxHeight: '100svh',
height: '100svh',
margin: 0,
transition: 'all 0.3s ease',
borderRadius: 0,
},
dialogHeader: {
padding: theme.spacing(2),
paddingBottom: theme.spacing(0),
fontFamily: 'Open sans',
Expand All @@ -56,8 +66,7 @@ const useStyles = makeStyles((theme: Theme) => {
paddingBottom: theme.spacing(2),
},
close: {
position: 'absolute',
right: theme.spacing(2),
paddingRight: theme.spacing(2),
},
};
});
Expand Down Expand Up @@ -128,6 +137,14 @@ export const ExecutionDetailsActions = ({
const [showDeck, setShowDeck] = React.useState(false);
const onCloseDeck = () => setShowDeck(false);

// Close deck modal on escape key press
useEscapeKey(onCloseDeck);

const [fullScreen, setSetFullScreen] = React.useState(false);
const toggleFullScreen = () => {
setSetFullScreen(!fullScreen);
};

const rerunOnClick = (e: React.MouseEvent<HTMLElement>) => {
e.stopPropagation();
setShowLaunchForm(true);
Expand Down Expand Up @@ -181,20 +198,32 @@ export const ExecutionDetailsActions = ({
)}
{execution?.value?.closure?.deckUri && (
<Dialog
PaperProps={{ className: styles.dialog }}
PaperProps={{
className: fullScreen ? styles.fullscreenDialog : styles.dialog,
}}
maxWidth={false}
open={showDeck}
>
<div className={styles.dialogTitle}>
<h2 className={styles.deckTitle}>{t('flyteDeck')}</h2>
<IconButton
aria-label="close"
onClick={onCloseDeck}
className={styles.close}
>
<Close />
</IconButton>
</div>
<Grid
container
justifyContent="space-between"
alignContent="center"
className={styles.dialogHeader}
>
<Grid item>
<IconButton aria-label="Expand" onClick={toggleFullScreen}>
{fullScreen ? <FullscreenExit /> : <Fullscreen />}
</IconButton>
</Grid>
<Grid item>
<h2 className={styles.deckTitle}>{t('flyteDeck')}</h2>
</Grid>
<Grid item>
<IconButton aria-label="close" onClick={onCloseDeck}>
<Close />
</IconButton>
</Grid>
</Grid>
<ExecutionNodeDeck nodeExecutionId={nodeExecutionId} />
</Dialog>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { history } from 'routes/history';
import { Routes } from 'routes/routes';
import { WorkflowExecutionPhase } from 'models/Execution/enums';
import { SubNavBarContent } from 'components/Navigation/SubNavBarContent';
import { useEscapeKey } from 'components/hooks/useKeyListener';
import { ExecutionInputsOutputsModal } from '../ExecutionInputsOutputsModal';
import { ExecutionStatusBadge } from '../ExecutionStatusBadge';
import { TerminateExecutionButton } from '../TerminateExecution/TerminateExecutionButton';
Expand Down Expand Up @@ -90,7 +91,11 @@ export const ExecutionDetailsAppBarContentInner: React.FC<{}> = () => {
const isTerminal = executionIsTerminal(execution);
const onClickShowInputsOutputs = () => setShowInputsOutputs(true);
const onClickRelaunch = () => setShowRelaunchForm(true);
const onCloseRelaunch = () => setShowRelaunchForm(false);
const onCloseRelaunch = (_?: any) => setShowRelaunchForm(false);

// Close modal on escape key press
useEscapeKey(onCloseRelaunch);

const fromExecutionNav = new URLSearchParams(history.location.search).get(
'fromExecutionNav',
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { LiteralMapViewer } from 'components/Literals/LiteralMapViewer';
import { emptyLiteralMapBlob } from 'models/Common/constants';
import { Execution } from 'models/Execution/types';
import * as React from 'react';
import { useEscapeKey } from 'components/hooks/useKeyListener';
import { useWorkflowExecutionData } from './useWorkflowExecution';

const useStyles = makeStyles((theme: Theme) => ({
Expand Down Expand Up @@ -126,6 +127,7 @@ export const ExecutionInputsOutputsModal: React.FC<
ExecutionInputsOutputsModalProps
> = ({ execution, onClose }) => {
const styles = useStyles();
useEscapeKey(onClose);
return (
<Dialog
PaperProps={{ className: styles.dialog }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from 'components/Launch/LaunchForm/types';
import { CompiledNode } from 'models/Node/types';
import { NodeExecutionIdentifier } from 'models/Execution/types';
import { useEscapeKey } from 'components/hooks/useKeyListener';
import { ResumeForm } from './ResumeForm';

interface LaunchFormDialogProps {
Expand Down Expand Up @@ -38,7 +39,10 @@ export const LaunchFormDialog = ({
compiledNode,
nodeExecutionId,
}: LaunchFormDialogProps): JSX.Element => {
const onCancelLaunch = () => setShowLaunchForm(false);
const onCancelLaunch = (_?: any) => setShowLaunchForm(false);

// Close modal on escape key press
useEscapeKey(onCancelLaunch);

// prevent child onclick event in the dialog triggers parent onclick event
const dialogOnClick = (e: React.MouseEvent<HTMLElement>) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DialogTitle, IconButton, Typography } from '@material-ui/core';
import { makeStyles, Theme } from '@material-ui/core/styles';
import Close from '@material-ui/icons/Close';
import { useEscapeKey } from 'components/hooks/useKeyListener';
import * as React from 'react';

const useStyles = makeStyles((theme: Theme) => ({
Expand All @@ -27,6 +28,10 @@ export const ClosableDialogTitle: React.FC<ClosableDialogTitleProps> = ({
onClose,
}) => {
const styles = useStyles();

// Close modal on escape key press
useEscapeKey(onClose);

return (
<DialogTitle disableTypography={true} className={styles.root}>
<Typography variant="h6">{children}</Typography>
Expand Down
23 changes: 23 additions & 0 deletions packages/console/src/components/hooks/test/useKeyListener.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import { fireEvent, getByText, render } from '@testing-library/react';
import { useEscapeKey } from '../useKeyListener';

it('calls the callback on pressing the ESC key', () => {
const callbackSpy = jest.fn();
const callback = (_?: KeyboardEvent) => {
callbackSpy();
};

const TestComponent = () => {
useEscapeKey(callback);
return <div>test</div>;
};

render(<TestComponent />);

fireEvent.keyDown(getByText(global.document.body, 'test'), {
key: 'Escape',
});

expect(callbackSpy).toHaveBeenCalled();
});
29 changes: 29 additions & 0 deletions packages/console/src/components/hooks/useKeyListener.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useEffect } from 'react';

/**
* Safely register and unregister a key listener on the document.
* @param onKeyPress
* @param keycode
*/
export const useKeyListener = (
onKeyPress: (e: KeyboardEvent) => void,
keycode = 'Escape',
) => {
useEffect(() => {
const eventCallback = e => {
if (e.key === keycode) {
onKeyPress(e);
}
};
document.addEventListener('keydown', eventCallback);
return () => document.removeEventListener('keydown', eventCallback);
}, []);
};

/**
* Register a key listener for the Escape key.
* @param onKeyPress
*/
export const useEscapeKey = (onKeyPress: (e: KeyboardEvent) => void) => {
useKeyListener(onKeyPress, 'Escape');
};

0 comments on commit c69f010

Please sign in to comment.