Skip to content

Commit

Permalink
Cn 2357 deployment tracker add ability to pause and retrigger executi…
Browse files Browse the repository at this point in the history
…ons (#10)

* add button to pause/resume

* verify still works after date-picker merge

* add retrigger button

* add proxy config for broadside

* added styling for retrigger/pause buttons

---------

Co-authored-by: abe garcia <[email protected]>
Co-authored-by: Victor <[email protected]>
  • Loading branch information
3 people authored Jun 30, 2023
1 parent 834a9d8 commit 72ebb9b
Show file tree
Hide file tree
Showing 17 changed files with 460 additions and 303 deletions.
8 changes: 4 additions & 4 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# #!/usr/bin/env bash
# # CHECK THIS FILE INTO SOURCE CONTROL!
#!/usr/bin/env bash
# CHECK THIS FILE INTO SOURCE CONTROL!

# . "$(dirname "$0")/_/husky.sh"
. "$(dirname "$0")/_/husky.sh"

# [[ -e spin-observatory-plugin-deck/node_modules/.bin/lint-staged ]] && cd spin-observatory-plugin-deck; ./node_modules/.bin/lint-staged -p false
[[ -e spin-observatory-plugin-deck/node_modules/.bin/lint-staged ]] && cd spin-observatory-plugin-deck; ./node_modules/.bin/lint-staged -p false
7 changes: 3 additions & 4 deletions spin-observatory-plugin-deck/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,17 @@
"host": "https://dev.spinnaker.homedepot.com/"
},
"dependencies": {
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
"@date-io/date-fns": "1",
"@material-ui/core": "^4.12.4",
"@material-ui/pickers": "^3.3.10",
"@material-ui/icons": "^4.11.3",
"@material-ui/lab": "^4.0.0-alpha.61",
"@material-ui/pickers": "^3.3.10",
"@rollup/plugin-commonjs": "18.0.0",
"@rollup/plugin-typescript": "8.2.1",
"@rollup/plugin-url": "6.0.0",
"@spinnaker/core": "0.23.0",
"@spinnaker/pluginsdk": "0.3.0",
"@spinnaker/pluginsdk-peerdeps": "0.11.0",
"@spinnaker/pluginsdk-peerdeps": "0.15.0",
"@spinnaker/presentation": "0.2.1",
"@types/react-dom": "18.0.11",
"@uirouter/core": "6.0.4",
Expand All @@ -46,6 +44,7 @@
"react-virtualized-select": "^3.1.3",
"rollup": "2.45.2",
"rxjs": "6.6.7",
"sass": "^1.62.1",
"typescript": "4.9.5"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import React, { useEffect, useState } from 'react';
import type { Application, IPipeline } from '@spinnaker/core';
import { ReactSelectInput, useDataSource } from '@spinnaker/core';

import { DatePicker, IDateRange } from './date-picker/date-picker';
import type { IDateRange } from './date-picker/date-picker';
import { DatePicker } from './date-picker/date-picker';
import { ParameterSelect } from './parameters';
import { MAX_DATE_RANGE, PipelineExecutions } from './pipelines';
import { StatusSelect } from './status';
import { PipelineExecutions, MAX_DATE_RANGE } from './pipelines';

interface IPluginContainerProps {
app: Application;
Expand All @@ -34,7 +35,7 @@ export function PluginContainer({ app }: IPluginContainerProps) {
setSelectedPipeline(pipelineConfig);
};

const handleDateFilterChange = ({ start, end }: { start: number, end: number }) => {
const handleDateFilterChange = ({ start, end }: { start: number; end: number }) => {
setSelectedDateRange({ start, end });
};

Expand Down Expand Up @@ -69,7 +70,7 @@ export function PluginContainer({ app }: IPluginContainerProps) {
<StatusSelect
className="flex-1"
pipeline={selectedPipeline}
selectedStatus={selectedStatus}
selectedStatus={selectedStatus}
setSelectedStatus={setSelectedStatus}
statusCount={statusCount}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Grid from '@material-ui/core/Grid';
import type { ReactNode } from 'react';
import React, { Children } from 'react';

interface IActionButtonsContainerProps {
children: NonNullable<ReactNode>;
}

export const ActionButtonsContainer = ({ children }: IActionButtonsContainerProps) => (
<Grid container direction="row" alignItems="flex-start" spacing={2}>
{Children.toArray(children).map((child) => (
<Grid item>{child}</Grid>
))}
</Grid>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import Button from '@material-ui/core/Button';
import ButtonGroup from '@material-ui/core/ButtonGroup';
import ClickAwayListener from '@material-ui/core/ClickAwayListener';
import Grow from '@material-ui/core/Grow';
import MenuItem from '@material-ui/core/MenuItem';
import MenuList from '@material-ui/core/MenuList';
import Paper from '@material-ui/core/Paper';
import Popper from '@material-ui/core/Popper';
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
import React, { Fragment, useRef, useState } from 'react';
import { gate } from '../../services/';

interface IPauseResumeButtonProps {
executionIds: string[];
refreshExecutions: () => void;
}

const options = [
{ text: 'Pause', action: gate.pauseExecutions },
{ text: 'Resume', action: gate.resumeExecutions },
];

export const PauseResumeButton = ({ executionIds, refreshExecutions }: IPauseResumeButtonProps) => {
const [open, setOpen] = useState(false);
const anchorRef = useRef<HTMLDivElement>(null);
const [selectedIndex, setSelectedIndex] = useState(0);
const [hover, setHover] = useState(false);

const handleButtonClick = () => {
options[selectedIndex].action(executionIds).then(() => refreshExecutions());
};

const handleMenuItemClick = (idx: number) => (_: React.MouseEvent<HTMLLIElement, MouseEvent>) => {
setSelectedIndex(idx);
setOpen(false);
};

const handleToggle = () => {
setOpen((prevOpen) => !prevOpen);
};

const handleClose = (event: React.MouseEvent<Document, MouseEvent>) => {
if (anchorRef.current && anchorRef.current.contains(event.target as HTMLElement)) {
return;
}

setOpen(false);
};

const handleHover = () => setHover((prevHover) => !prevHover);

const disabled = executionIds.length === 0;

const computeBtnColor = () => {
if (disabled) {
return 'var(--color-status-inactive)';
} else if (hover) {
return 'var(--button-primary-hover-bg)';
} else {
return 'var(--color-accent)';
}
};

return (
<Fragment>
<ButtonGroup
onMouseEnter={handleHover}
onMouseLeave={handleHover}
variant="contained"
ref={anchorRef}
disabled={disabled}
>
<Button
style={{
color: 'white',
backgroundColor: computeBtnColor(),
}}
size="small"
onClick={handleToggle}
>
<ArrowDropDownIcon />
</Button>
<Button
style={{
width: '7rem',
color: 'white',
backgroundColor: computeBtnColor(),
}}
onClick={handleButtonClick}
>
{options[selectedIndex].text}
</Button>
</ButtonGroup>
<Popper open={open} anchorEl={anchorRef.current} transition disablePortal>
{({ TransitionProps }) => (
<Grow
{...TransitionProps}
style={{
transformOrigin: 'center top',
}}
>
<Paper>
<ClickAwayListener onClickAway={handleClose}>
<MenuList id="split-button-menu">
{options.map((option, idx) => (
<MenuItem key={option.text} selected={idx === selectedIndex} onClick={handleMenuItemClick(idx)}>
{option.text}
</MenuItem>
))}
</MenuList>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
</Fragment>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Button, ButtonGroup } from '@material-ui/core';
import React, { useState } from 'react';

import type { IExecution } from '@spinnaker/core';

import { broadside } from '../../services/';

interface IRetriggerButtonProps {
executions: IExecution[];
refreshExecutions: () => void;
}

export const RetriggerButton = ({ executions, refreshExecutions }: IRetriggerButtonProps) => {
const [retriggerInProgress, setRetriggerInProgress] = useState(false);
const [hover, setHover] = useState(false);

const handleHover = () => setHover((prevHover) => !prevHover);

const disabled = executions.length === 0 || retriggerInProgress;

const handleRetrigger = () => {
setRetriggerInProgress(true);
broadside
.retriggerExecutions({ executions })
.then((res) => {
/* eslint-disable no-console */
console.log(res.status);
return res.json();
})
/* eslint-disable no-console */
.then((data) => console.log(data))
.catch((e) => console.error('error retriggering: ', e))
.finally(() => {
setRetriggerInProgress(false);
refreshExecutions();
});
};

const computeBtnColor = () => {
if (disabled) {
return 'var(--color-status-inactive)';
} else if (hover) {
return 'var(--button-primary-hover-bg)';
} else {
return 'var(--color-accent)';
}
};

return (
<ButtonGroup onMouseEnter={handleHover} onMouseLeave={handleHover} variant="contained" disabled={disabled}>
<Button
onClick={handleRetrigger}
style={{
width: '7rem',
color: 'white',
backgroundColor: computeBtnColor(),
}}
>
Retrigger
</Button>
</ButtonGroup>
);
};
3 changes: 3 additions & 0 deletions spin-observatory-plugin-deck/src/components/actions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './PauseResumeButton';
export * from './RetriggerButton';
export * from './ActionButtonsContainer';
Loading

0 comments on commit 72ebb9b

Please sign in to comment.