type(ux): Added delete option in experiment table, fixed agent select radio buttons and minor ux changes (#2862)
* Added delete option in exp table, fixed select agent radio buttons and minor ux change * Minor Radio Group Fix * Minor CSS change Signed-off-by: Amit Kumar Das <amit@chaosnative.com>
This commit is contained in:
parent
ed36c9c16a
commit
89f29a2a74
|
@ -1,5 +1,5 @@
|
||||||
import { useLazyQuery, useQuery } from '@apollo/client';
|
import { useLazyQuery, useQuery } from '@apollo/client';
|
||||||
import { Typography, useTheme } from '@material-ui/core';
|
import { RadioGroup, Typography, useTheme } from '@material-ui/core';
|
||||||
import { LitmusCard, RadioButton, Search } from 'litmus-ui';
|
import { LitmusCard, RadioButton, Search } from 'litmus-ui';
|
||||||
import React, {
|
import React, {
|
||||||
forwardRef,
|
forwardRef,
|
||||||
|
@ -215,32 +215,38 @@ const ChooseWorkflowAgent = forwardRef((_, ref) => {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Cluster Data */}
|
{/* Cluster Data */}
|
||||||
<div className={classes.agentWrapperDiv} data-cy="AgentsRadioGroup">
|
<RadioGroup
|
||||||
{filteredCluster.map((cluster) => (
|
name="Agent Selection"
|
||||||
<LitmusCard
|
value={currentlySelectedAgent}
|
||||||
key={cluster.cluster_id}
|
onChange={(e) => handleChange(e)}
|
||||||
glow={currentlySelectedAgent === cluster.cluster_id}
|
>
|
||||||
width="100%"
|
<div className={classes.agentWrapperDiv} data-cy="AgentsRadioGroup">
|
||||||
height="4rem"
|
{filteredCluster.map((cluster) => (
|
||||||
className={classes.litmusCard}
|
<LitmusCard
|
||||||
borderColor={
|
key={cluster.cluster_id}
|
||||||
currentlySelectedAgent === cluster.cluster_id
|
glow={currentlySelectedAgent === cluster.cluster_id}
|
||||||
? palette.primary.main
|
width="40%"
|
||||||
: palette.border.main
|
height="4rem"
|
||||||
}
|
className={classes.litmusCard}
|
||||||
>
|
borderColor={
|
||||||
<RadioButton
|
currentlySelectedAgent === cluster.cluster_id
|
||||||
data-cy="AgentRadioButtons"
|
? palette.primary.main
|
||||||
value={cluster.cluster_id}
|
: palette.border.main
|
||||||
className={classes.agentRadioButton}
|
}
|
||||||
onChange={(e) => handleChange(e)}
|
|
||||||
>
|
>
|
||||||
{cluster.cluster_name} <br />
|
<RadioButton
|
||||||
{cluster.cluster_id}
|
value={cluster.cluster_id}
|
||||||
</RadioButton>
|
className={classes.agentRadioButton}
|
||||||
</LitmusCard>
|
>
|
||||||
))}
|
<div>
|
||||||
</div>
|
<Typography>{cluster.cluster_name}</Typography>
|
||||||
|
<Typography>{cluster.cluster_id}</Typography>
|
||||||
|
</div>
|
||||||
|
</RadioButton>
|
||||||
|
</LitmusCard>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</RadioGroup>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -43,12 +43,13 @@ const useStyles = makeStyles((theme: Theme) => ({
|
||||||
// Agent Div
|
// Agent Div
|
||||||
agentWrapperDiv: {
|
agentWrapperDiv: {
|
||||||
marginTop: theme.spacing(5),
|
marginTop: theme.spacing(5),
|
||||||
display: 'grid',
|
display: 'flex',
|
||||||
gridTemplateColumns: '1fr 1fr',
|
flexDirection: 'row',
|
||||||
gridGap: '1.5rem',
|
flexWrap: 'wrap',
|
||||||
},
|
},
|
||||||
litmusCard: {
|
litmusCard: {
|
||||||
background: theme.palette.cards.background,
|
background: theme.palette.cards.background,
|
||||||
|
margin: theme.spacing(2, 2, 2, 0),
|
||||||
},
|
},
|
||||||
agentRadioButton: {
|
agentRadioButton: {
|
||||||
marginTop: theme.spacing(1),
|
marginTop: theme.spacing(1),
|
||||||
|
|
|
@ -247,7 +247,7 @@ const AddProbe: React.FC<AddProbeProps> = ({
|
||||||
<div className={classes.detailContainer}>
|
<div className={classes.detailContainer}>
|
||||||
<div className={classes.formField}>
|
<div className={classes.formField}>
|
||||||
<InputLabel className={classes.formLabel} htmlFor="timeout">
|
<InputLabel className={classes.formLabel} htmlFor="timeout">
|
||||||
{t('createWorkflow.tuneWorkflow.addProbe.labels.timeout')}(ms)
|
{t('createWorkflow.tuneWorkflow.addProbe.labels.timeout')}(sec)
|
||||||
</InputLabel>
|
</InputLabel>
|
||||||
<InputField
|
<InputField
|
||||||
variant="primary"
|
variant="primary"
|
||||||
|
@ -279,7 +279,7 @@ const AddProbe: React.FC<AddProbeProps> = ({
|
||||||
<div className={classes.detailContainer}>
|
<div className={classes.detailContainer}>
|
||||||
<div className={classes.formField}>
|
<div className={classes.formField}>
|
||||||
<InputLabel className={classes.formLabel} htmlFor="interval">
|
<InputLabel className={classes.formLabel} htmlFor="interval">
|
||||||
{t('createWorkflow.tuneWorkflow.addProbe.labels.interval')}(ms)
|
{t('createWorkflow.tuneWorkflow.addProbe.labels.interval')}(sec)
|
||||||
</InputLabel>
|
</InputLabel>
|
||||||
<InputField
|
<InputField
|
||||||
variant="primary"
|
variant="primary"
|
||||||
|
@ -294,7 +294,7 @@ const AddProbe: React.FC<AddProbeProps> = ({
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.formField}>
|
<div className={classes.formField}>
|
||||||
<InputLabel className={classes.formLabel} htmlFor="polling">
|
<InputLabel className={classes.formLabel} htmlFor="polling">
|
||||||
{t('createWorkflow.tuneWorkflow.addProbe.labels.polling')}(ms)
|
{t('createWorkflow.tuneWorkflow.addProbe.labels.polling')}(sec)
|
||||||
</InputLabel>
|
</InputLabel>
|
||||||
<InputField
|
<InputField
|
||||||
variant="primary"
|
variant="primary"
|
||||||
|
@ -310,7 +310,7 @@ const AddProbe: React.FC<AddProbeProps> = ({
|
||||||
<div className={classes.formField}>
|
<div className={classes.formField}>
|
||||||
<InputLabel className={classes.formLabel} htmlFor="initial-delay">
|
<InputLabel className={classes.formLabel} htmlFor="initial-delay">
|
||||||
{t('createWorkflow.tuneWorkflow.addProbe.labels.initialDelay')}
|
{t('createWorkflow.tuneWorkflow.addProbe.labels.initialDelay')}
|
||||||
(ms)
|
(sec)
|
||||||
</InputLabel>
|
</InputLabel>
|
||||||
<InputField
|
<InputField
|
||||||
variant="primary"
|
variant="primary"
|
||||||
|
|
|
@ -5,17 +5,10 @@ import StepLabel from '@material-ui/core/StepLabel';
|
||||||
import StepContent from '@material-ui/core/StepContent';
|
import StepContent from '@material-ui/core/StepContent';
|
||||||
import Typography from '@material-ui/core/Typography';
|
import Typography from '@material-ui/core/Typography';
|
||||||
import { ButtonOutlined } from 'litmus-ui';
|
import { ButtonOutlined } from 'litmus-ui';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import YAML from 'yaml';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import General from '../TuneWorkflowSteps/General';
|
import General from '../TuneWorkflowSteps/General';
|
||||||
import SteadyState from '../TuneWorkflowSteps/SteadyState';
|
import SteadyState from '../TuneWorkflowSteps/SteadyState';
|
||||||
import TargetApplication from '../TuneWorkflowSteps/TargetApplication';
|
import TargetApplication from '../TuneWorkflowSteps/TargetApplication';
|
||||||
import useStyles from './styles';
|
import useStyles from './styles';
|
||||||
import * as WorkflowActions from '../../../../redux/actions/workflow';
|
|
||||||
import { WorkflowManifest } from '../../../../models/redux/workflow';
|
|
||||||
import { RootState } from '../../../../redux/reducers';
|
|
||||||
import useActions from '../../../../redux/actions';
|
|
||||||
|
|
||||||
interface ConfigurationStepperProps {
|
interface ConfigurationStepperProps {
|
||||||
experimentIndex: number;
|
experimentIndex: number;
|
||||||
|
@ -57,7 +50,6 @@ const ConfigurationStepper: React.FC<ConfigurationStepperProps> = ({
|
||||||
closeStepper,
|
closeStepper,
|
||||||
isCustom,
|
isCustom,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
// State variable to handle Stepper Steps
|
// State variable to handle Stepper Steps
|
||||||
|
@ -73,76 +65,6 @@ const ConfigurationStepper: React.FC<ConfigurationStepperProps> = ({
|
||||||
const gotoStep = (page: number) => {
|
const gotoStep = (page: number) => {
|
||||||
setActiveStep(page);
|
setActiveStep(page);
|
||||||
};
|
};
|
||||||
const workflow = useActions(WorkflowActions);
|
|
||||||
const manifest: WorkflowManifest = useSelector(
|
|
||||||
(state: RootState) => state.workflowManifest
|
|
||||||
);
|
|
||||||
|
|
||||||
const deleteExperiment = () => {
|
|
||||||
/**
|
|
||||||
* Workflow manifest saved in redux state
|
|
||||||
*/
|
|
||||||
const wfManifest = YAML.parse(manifest.manifest);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get template name according to the experiment index
|
|
||||||
*/
|
|
||||||
const templateName = wfManifest.spec.templates[experimentIndex].name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the workflow name according to the experiment index
|
|
||||||
*/
|
|
||||||
const wfName = YAML.parse(manifest.engineYAML).metadata.generateName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* if the template is a revert-chaos template
|
|
||||||
* the engine name is removed from the
|
|
||||||
* revert-chaos template args
|
|
||||||
*/
|
|
||||||
if (
|
|
||||||
wfManifest.spec.templates[
|
|
||||||
wfManifest.spec.templates.length - 1
|
|
||||||
].name.includes('revert-')
|
|
||||||
) {
|
|
||||||
const argument = wfManifest.spec.templates[
|
|
||||||
wfManifest.spec.templates.length - 1
|
|
||||||
].container.args[0].replace(wfName, '');
|
|
||||||
wfManifest.spec.templates[
|
|
||||||
wfManifest.spec.templates.length - 1
|
|
||||||
].container.args[0] = argument;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the experiment name from steps
|
|
||||||
*/
|
|
||||||
wfManifest.spec.templates[0].steps.forEach(
|
|
||||||
(data: any, stepIndex: number) => {
|
|
||||||
data.forEach((step: any, index: number) => {
|
|
||||||
if (step.name === templateName) {
|
|
||||||
data.splice(index, 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (data.length === 0) {
|
|
||||||
wfManifest.spec.templates[0].steps.splice(stepIndex, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the chaos engine from the overall manifest
|
|
||||||
* according to the experiment index
|
|
||||||
*/
|
|
||||||
wfManifest.spec.templates.splice(experimentIndex, 1);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the updated manifest to redux state
|
|
||||||
*/
|
|
||||||
workflow.setWorkflowManifest({
|
|
||||||
manifest: YAML.stringify(wfManifest),
|
|
||||||
engineYAML: '',
|
|
||||||
});
|
|
||||||
closeStepper();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
|
@ -151,26 +73,6 @@ const ConfigurationStepper: React.FC<ConfigurationStepperProps> = ({
|
||||||
✕
|
✕
|
||||||
</ButtonOutlined>
|
</ButtonOutlined>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.deleteExpDiv}>
|
|
||||||
<Typography className={classes.editExpText}>
|
|
||||||
{t('createWorkflow.tuneWorkflow.verticalStepper.editExp')}
|
|
||||||
</Typography>
|
|
||||||
<ButtonOutlined
|
|
||||||
onClick={() => {
|
|
||||||
deleteExperiment();
|
|
||||||
}}
|
|
||||||
className={classes.deleteBtn}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src="./icons/delete-exp.svg"
|
|
||||||
alt="delete"
|
|
||||||
className={classes.deleteIcon}
|
|
||||||
/>
|
|
||||||
<Typography color="error" className={classes.deleteExpText}>
|
|
||||||
{t('createWorkflow.tuneWorkflow.verticalStepper.deleteExp')}
|
|
||||||
</Typography>
|
|
||||||
</ButtonOutlined>
|
|
||||||
</div>
|
|
||||||
<Stepper activeStep={activeStep} orientation="vertical">
|
<Stepper activeStep={activeStep} orientation="vertical">
|
||||||
{steps.map((label, index) => (
|
{steps.map((label, index) => (
|
||||||
<Step key={label}>
|
<Step key={label}>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* eslint-disable no-const-assign */
|
/* eslint-disable no-const-assign */
|
||||||
import { Typography, useTheme } from '@material-ui/core';
|
import { IconButton, Typography, useTheme } from '@material-ui/core';
|
||||||
import Paper from '@material-ui/core/Paper';
|
import Paper from '@material-ui/core/Paper';
|
||||||
import Table from '@material-ui/core/Table';
|
import Table from '@material-ui/core/Table';
|
||||||
import TableBody from '@material-ui/core/TableBody';
|
import TableBody from '@material-ui/core/TableBody';
|
||||||
|
@ -224,6 +224,75 @@ const WorkflowTable = forwardRef(
|
||||||
});
|
});
|
||||||
}, [manifest]);
|
}, [manifest]);
|
||||||
|
|
||||||
|
const deleteExperiment = (experimentIndex: number) => {
|
||||||
|
/**
|
||||||
|
* Workflow manifest saved in redux state
|
||||||
|
*/
|
||||||
|
const wfManifest = YAML.parse(manifest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get template name according to the experiment index
|
||||||
|
*/
|
||||||
|
const templateName = wfManifest.spec.templates[experimentIndex].name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get instance_id of Chaos Engines
|
||||||
|
*/
|
||||||
|
const selectedEngine =
|
||||||
|
wfManifest.spec.templates[experimentIndex].inputs.artifacts[0];
|
||||||
|
const { instance_id } = YAML.parse(
|
||||||
|
selectedEngine.raw.data
|
||||||
|
).metadata.labels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if the template is a revert-chaos template
|
||||||
|
* the engine name is removed from the
|
||||||
|
* revert-chaos template args
|
||||||
|
*/
|
||||||
|
if (
|
||||||
|
wfManifest.spec.templates[
|
||||||
|
wfManifest.spec.templates.length - 1
|
||||||
|
].name.includes('revert-')
|
||||||
|
) {
|
||||||
|
const argument = wfManifest.spec.templates[
|
||||||
|
wfManifest.spec.templates.length - 1
|
||||||
|
].container.args[0].replace(`${instance_id}, `, '');
|
||||||
|
wfManifest.spec.templates[
|
||||||
|
wfManifest.spec.templates.length - 1
|
||||||
|
].container.args[0] = argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the experiment name from steps
|
||||||
|
*/
|
||||||
|
wfManifest.spec.templates[0].steps.forEach(
|
||||||
|
(data: any, stepIndex: number) => {
|
||||||
|
data.forEach((step: any, index: number) => {
|
||||||
|
if (step.name === templateName) {
|
||||||
|
data.splice(index, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (data.length === 0) {
|
||||||
|
wfManifest.spec.templates[0].steps.splice(stepIndex, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the chaos engine from the overall manifest
|
||||||
|
* according to the experiment index
|
||||||
|
*/
|
||||||
|
wfManifest.spec.templates.splice(experimentIndex, 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the updated manifest to redux state
|
||||||
|
*/
|
||||||
|
workflow.setWorkflowManifest({
|
||||||
|
manifest: YAML.stringify(wfManifest),
|
||||||
|
engineYAML: '',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
function onNext() {
|
function onNext() {
|
||||||
if (experiments.length === 0) {
|
if (experiments.length === 0) {
|
||||||
return false; // Should show alert
|
return false; // Should show alert
|
||||||
|
@ -264,26 +333,29 @@ const WorkflowTable = forwardRef(
|
||||||
<TableCell align="left">
|
<TableCell align="left">
|
||||||
{t('createWorkflow.chooseWorkflow.table.head5')}
|
{t('createWorkflow.chooseWorkflow.table.head5')}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
<TableCell />
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{experiments.length > 0 ? (
|
{experiments.length > 0 ? (
|
||||||
experiments.map((experiment: ChaosCRDTable, index) => (
|
experiments.map((experiment: ChaosCRDTable, index) => (
|
||||||
<TableRow
|
<TableRow key={experiment.Name}>
|
||||||
key={experiment.Name}
|
|
||||||
onClick={() => {
|
|
||||||
setDisplayStepper(true);
|
|
||||||
setEngineIndex(experiment.StepIndex);
|
|
||||||
workflow.setWorkflowManifest({
|
|
||||||
engineYAML: experiment.ChaosEngine,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
className={classes.selection}
|
|
||||||
>
|
|
||||||
<TableCell component="th" scope="row">
|
<TableCell component="th" scope="row">
|
||||||
{index + 1}
|
{index + 1}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align="left">{experiment.Name}</TableCell>
|
<TableCell
|
||||||
|
className={classes.selection}
|
||||||
|
align="left"
|
||||||
|
onClick={() => {
|
||||||
|
setDisplayStepper(true);
|
||||||
|
setEngineIndex(experiment.StepIndex);
|
||||||
|
workflow.setWorkflowManifest({
|
||||||
|
engineYAML: experiment.ChaosEngine,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{experiment.Name}
|
||||||
|
</TableCell>
|
||||||
<TableCell align="left">
|
<TableCell align="left">
|
||||||
{experiment.Namespace}
|
{experiment.Namespace}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
@ -291,6 +363,18 @@ const WorkflowTable = forwardRef(
|
||||||
{experiment.Application}
|
{experiment.Application}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align="left">{experiment.Probes}</TableCell>
|
<TableCell align="left">{experiment.Probes}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<IconButton
|
||||||
|
onClick={() =>
|
||||||
|
deleteExperiment(experiment.StepIndex)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="./icons/bin-red.svg"
|
||||||
|
alt="delete experiment"
|
||||||
|
/>
|
||||||
|
</IconButton>
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
|
|
Loading…
Reference in New Issue