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:
Amit Kumar Das 2021-06-09 12:48:48 +05:30 committed by GitHub
parent ed36c9c16a
commit 89f29a2a74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 137 additions and 144 deletions

View File

@ -1,5 +1,5 @@
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 React, {
forwardRef,
@ -215,32 +215,38 @@ const ChooseWorkflowAgent = forwardRef((_, ref) => {
/>
{/* Cluster Data */}
<div className={classes.agentWrapperDiv} data-cy="AgentsRadioGroup">
{filteredCluster.map((cluster) => (
<LitmusCard
key={cluster.cluster_id}
glow={currentlySelectedAgent === cluster.cluster_id}
width="100%"
height="4rem"
className={classes.litmusCard}
borderColor={
currentlySelectedAgent === cluster.cluster_id
? palette.primary.main
: palette.border.main
}
>
<RadioButton
data-cy="AgentRadioButtons"
value={cluster.cluster_id}
className={classes.agentRadioButton}
onChange={(e) => handleChange(e)}
<RadioGroup
name="Agent Selection"
value={currentlySelectedAgent}
onChange={(e) => handleChange(e)}
>
<div className={classes.agentWrapperDiv} data-cy="AgentsRadioGroup">
{filteredCluster.map((cluster) => (
<LitmusCard
key={cluster.cluster_id}
glow={currentlySelectedAgent === cluster.cluster_id}
width="40%"
height="4rem"
className={classes.litmusCard}
borderColor={
currentlySelectedAgent === cluster.cluster_id
? palette.primary.main
: palette.border.main
}
>
{cluster.cluster_name} <br />
{cluster.cluster_id}
</RadioButton>
</LitmusCard>
))}
</div>
<RadioButton
value={cluster.cluster_id}
className={classes.agentRadioButton}
>
<div>
<Typography>{cluster.cluster_name}</Typography>
<Typography>{cluster.cluster_id}</Typography>
</div>
</RadioButton>
</LitmusCard>
))}
</div>
</RadioGroup>
</div>
</div>
);

View File

@ -43,12 +43,13 @@ const useStyles = makeStyles((theme: Theme) => ({
// Agent Div
agentWrapperDiv: {
marginTop: theme.spacing(5),
display: 'grid',
gridTemplateColumns: '1fr 1fr',
gridGap: '1.5rem',
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
},
litmusCard: {
background: theme.palette.cards.background,
margin: theme.spacing(2, 2, 2, 0),
},
agentRadioButton: {
marginTop: theme.spacing(1),

View File

@ -247,7 +247,7 @@ const AddProbe: React.FC<AddProbeProps> = ({
<div className={classes.detailContainer}>
<div className={classes.formField}>
<InputLabel className={classes.formLabel} htmlFor="timeout">
{t('createWorkflow.tuneWorkflow.addProbe.labels.timeout')}(ms)
{t('createWorkflow.tuneWorkflow.addProbe.labels.timeout')}(sec)
</InputLabel>
<InputField
variant="primary"
@ -279,7 +279,7 @@ const AddProbe: React.FC<AddProbeProps> = ({
<div className={classes.detailContainer}>
<div className={classes.formField}>
<InputLabel className={classes.formLabel} htmlFor="interval">
{t('createWorkflow.tuneWorkflow.addProbe.labels.interval')}(ms)
{t('createWorkflow.tuneWorkflow.addProbe.labels.interval')}(sec)
</InputLabel>
<InputField
variant="primary"
@ -294,7 +294,7 @@ const AddProbe: React.FC<AddProbeProps> = ({
</div>
<div className={classes.formField}>
<InputLabel className={classes.formLabel} htmlFor="polling">
{t('createWorkflow.tuneWorkflow.addProbe.labels.polling')}(ms)
{t('createWorkflow.tuneWorkflow.addProbe.labels.polling')}(sec)
</InputLabel>
<InputField
variant="primary"
@ -310,7 +310,7 @@ const AddProbe: React.FC<AddProbeProps> = ({
<div className={classes.formField}>
<InputLabel className={classes.formLabel} htmlFor="initial-delay">
{t('createWorkflow.tuneWorkflow.addProbe.labels.initialDelay')}
(ms)
(sec)
</InputLabel>
<InputField
variant="primary"

View File

@ -5,17 +5,10 @@ import StepLabel from '@material-ui/core/StepLabel';
import StepContent from '@material-ui/core/StepContent';
import Typography from '@material-ui/core/Typography';
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 SteadyState from '../TuneWorkflowSteps/SteadyState';
import TargetApplication from '../TuneWorkflowSteps/TargetApplication';
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 {
experimentIndex: number;
@ -57,7 +50,6 @@ const ConfigurationStepper: React.FC<ConfigurationStepperProps> = ({
closeStepper,
isCustom,
}) => {
const { t } = useTranslation();
const classes = useStyles();
// State variable to handle Stepper Steps
@ -73,76 +65,6 @@ const ConfigurationStepper: React.FC<ConfigurationStepperProps> = ({
const gotoStep = (page: number) => {
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 (
<div className={classes.root}>
@ -151,26 +73,6 @@ const ConfigurationStepper: React.FC<ConfigurationStepperProps> = ({
&#x2715;
</ButtonOutlined>
</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">
{steps.map((label, index) => (
<Step key={label}>

View File

@ -1,5 +1,5 @@
/* 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 Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
@ -224,6 +224,75 @@ const WorkflowTable = forwardRef(
});
}, [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() {
if (experiments.length === 0) {
return false; // Should show alert
@ -264,26 +333,29 @@ const WorkflowTable = forwardRef(
<TableCell align="left">
{t('createWorkflow.chooseWorkflow.table.head5')}
</TableCell>
<TableCell />
</TableRow>
</TableHead>
<TableBody>
{experiments.length > 0 ? (
experiments.map((experiment: ChaosCRDTable, index) => (
<TableRow
key={experiment.Name}
onClick={() => {
setDisplayStepper(true);
setEngineIndex(experiment.StepIndex);
workflow.setWorkflowManifest({
engineYAML: experiment.ChaosEngine,
});
}}
className={classes.selection}
>
<TableRow key={experiment.Name}>
<TableCell component="th" scope="row">
{index + 1}
</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">
{experiment.Namespace}
</TableCell>
@ -291,6 +363,18 @@ const WorkflowTable = forwardRef(
{experiment.Application}
</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>
))
) : (