chore(litmus-portal): Added validation in probes modal and minor fix (#2842)

* Added validation in probes modal and minor fix
* Minor change in directory structure and fixed template graph not rendering issue
* Minor regex change for validating ssh links

Signed-off-by: Amit Kumar Das <amit@chaosnative.com>
This commit is contained in:
Amit Kumar Das 2021-05-31 09:34:15 +05:30 committed by GitHub
parent cd72a7a40a
commit c638304960
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 357 additions and 298 deletions

View File

@ -855,6 +855,7 @@ createWorkflow:
addProbe: addProbe:
heading: Add heading: Add
headingStrong: Probe headingStrong: Probe
validate: Probe name already exists
labels: labels:
probeName: Probe Name probeName: Probe Name
probeType: Probe Type probeType: Probe Type

View File

@ -84,6 +84,7 @@ export interface ListManifestTemplateArray {
project_name: string; project_name: string;
template_description: string; template_description: string;
template_name: string; template_name: string;
isCustomWorkflow: boolean;
} }
export interface ListManifestTemplate { export interface ListManifestTemplate {

View File

@ -41,6 +41,18 @@ export const validateWorkflowName = (value: string) => {
return false; return false;
}; };
export const validateProbeName = (allProbe: any, probeName: string) => {
if (allProbe.length) {
const filteredProbes = allProbe.filter(
(probe: any) => probe.name.toLowerCase() === probeName
);
if (filteredProbes.length) {
return true;
}
}
return false;
};
export const validatePassword = (value: string) => { export const validatePassword = (value: string) => {
const passValid = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,20}$/; const passValid = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,20}$/;
if (value.length > 0) { if (value.length > 0) {
@ -77,7 +89,7 @@ export const isValidWebUrl = (value: string) => {
const regExLocal = /^http:\/\/localhost:([0-9]){1,4}$/g; const regExLocal = /^http:\/\/localhost:([0-9]){1,4}$/g;
const regExIpv4 = /^http:\/\/(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]):([0-9]){1,4}$/g; const regExIpv4 = /^http:\/\/(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]):([0-9]){1,4}$/g;
const regExIpv6 = /^http:\/\/((([0-9a-fA-F]){1,4})\\:){7}([0-9a-fA-F]){1,4}:([0-9]){1,4}$/g; const regExIpv6 = /^http:\/\/((([0-9a-fA-F]){1,4})\\:){7}([0-9a-fA-F]){1,4}:([0-9]){1,4}$/g;
const sshRegEx = /^([A-Za-z0-9]+@|http(|s)\:\/\/)([A-Za-z0-9.]+(:\d+)?)(?::|\/)([\d\/\w.-]+?)(\.git)?$/i; const sshRegEx = /^([A-Za-z0-9]+@|http(|s)\:\/\/)([-a-zA-Z0-9@:%._\+~#=]+(:\d+)?)(?::|\/)([\d\/\w.-]+?)(\.git)?$/i;
if ( if (
value.match(regEx) || value.match(regEx) ||
value.match(regExLocal) || value.match(regExLocal) ||

View File

@ -19,7 +19,9 @@ import {
ListManifestTemplateArray, ListManifestTemplateArray,
} from '../../../models/graphql/workflowListData'; } from '../../../models/graphql/workflowListData';
import { getProjectID } from '../../../utils/getSearchParams'; import { getProjectID } from '../../../utils/getSearchParams';
import * as WorkflowActions from '../../../redux/actions/workflow';
import useStyles from './styles'; import useStyles from './styles';
import useActions from '../../../redux/actions';
interface ChooseWorkflowRadio { interface ChooseWorkflowRadio {
selected: string; selected: string;
@ -33,7 +35,7 @@ const ChooseWorkflowFromExisting = () => {
// Local States // Local States
const [search, setSearch] = useState<string | null>(null); const [search, setSearch] = useState<string | null>(null);
const [selected, setSelected] = useState<string>(''); const [selected, setSelected] = useState<string>('');
const workflowAction = useActions(WorkflowActions);
const { data: templateData } = useQuery<ListManifestTemplate>( const { data: templateData } = useQuery<ListManifestTemplate>(
LIST_MANIFEST_TEMPLATE, LIST_MANIFEST_TEMPLATE,
{ {
@ -74,7 +76,9 @@ const ChooseWorkflowFromExisting = () => {
const templateData = filteredExistingWorkflows.filter((workflow) => { const templateData = filteredExistingWorkflows.filter((workflow) => {
return workflow.template_id === event.target.value; return workflow.template_id === event.target.value;
})[0]; })[0];
workflowAction.setWorkflowManifest({
isCustomWorkflow: templateData.isCustomWorkflow,
});
localforage.setItem('selectedScheduleOption', selection); localforage.setItem('selectedScheduleOption', selection);
localforage.setItem('workflow', { localforage.setItem('workflow', {
name: templateData.template_name.toLowerCase(), name: templateData.template_name.toLowerCase(),

View File

@ -37,7 +37,7 @@ const ProbeDetails: React.FC<ProbeDetailsProps> = ({
| { name?: string | undefined; value: unknown } | { name?: string | undefined; value: unknown }
> >
) => { ) => {
if (e.target.name === 'url' || e.target.name === 'responseTimeout') { if (e.target.name === 'url') {
setProbeData({ setProbeData({
...probeData, ...probeData,
'httpProbe/inputs': { 'httpProbe/inputs': {
@ -46,6 +46,15 @@ const ProbeDetails: React.FC<ProbeDetailsProps> = ({
}, },
}); });
} }
if (e.target.name === 'responseTimeout') {
setProbeData({
...probeData,
'httpProbe/inputs': {
...probeData['httpProbe/inputs'],
[e.target.name]: parseInt(e.target.value as string, 10),
},
});
}
if (e.target.name === 'insecureSkipVerify') { if (e.target.name === 'insecureSkipVerify') {
setProbeData({ setProbeData({
...probeData, ...probeData,
@ -185,7 +194,7 @@ const ProbeDetails: React.FC<ProbeDetailsProps> = ({
width="50%" width="50%"
id="responseTimeout" id="responseTimeout"
name="responseTimeout" name="responseTimeout"
type="text" type="number"
value={probeData['httpProbe/inputs']?.responseTimeout} value={probeData['httpProbe/inputs']?.responseTimeout}
onChange={handleHttp} onChange={handleHttp}
/> />

View File

@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
import React from 'react'; import React from 'react';
import useStyles from './styles'; import useStyles from './styles';
import ProbeDetails from './ProbeDetails'; import ProbeDetails from './ProbeDetails';
import { validateProbeName } from '../../../../utils/validate';
interface AddProbeProps { interface AddProbeProps {
probesValue: any; probesValue: any;
@ -153,12 +154,21 @@ const AddProbe: React.FC<AddProbeProps> = ({
{t('createWorkflow.tuneWorkflow.addProbe.labels.probeName')} {t('createWorkflow.tuneWorkflow.addProbe.labels.probeName')}
</InputLabel> </InputLabel>
<InputField <InputField
variant="primary"
id="name" id="name"
name="name" name="name"
type="text" type="text"
required required
value={probeData.name} value={probeData.name}
helperText={
validateProbeName(allProbes, probeData.name)
? t('createWorkflow.tuneWorkflow.addProbe.validate')
: ''
}
variant={
validateProbeName(allProbes, probeData.name)
? 'error'
: 'primary'
}
onChange={(e) => onChange={(e) =>
setProbeData({ ...probeData, name: e.target.value }) setProbeData({ ...probeData, name: e.target.value })
} }
@ -328,7 +338,13 @@ const AddProbe: React.FC<AddProbeProps> = ({
> >
{t('createWorkflow.tuneWorkflow.addProbe.button.cancel')} {t('createWorkflow.tuneWorkflow.addProbe.button.cancel')}
</ButtonOutlined> </ButtonOutlined>
<ButtonFilled type="submit"> <ButtonFilled
type="submit"
disabled={
validateProbeName(allProbes, probeData.name) ||
probeData.name.trim().length === 0
}
>
{t('createWorkflow.tuneWorkflow.addProbe.button.addProbe')} {t('createWorkflow.tuneWorkflow.addProbe.button.addProbe')}
</ButtonFilled> </ButtonFilled>
</div> </div>

View File

@ -30,6 +30,7 @@ import useStyles from './styles';
interface WorkflowTableProps { interface WorkflowTableProps {
isCustom: boolean | undefined; isCustom: boolean | undefined;
namespace: string;
} }
interface ChaosCRDTable { interface ChaosCRDTable {
@ -41,311 +42,322 @@ interface ChaosCRDTable {
ChaosEngine: string; ChaosEngine: string;
} }
const WorkflowTable = forwardRef(({ isCustom }: WorkflowTableProps, ref) => { const WorkflowTable = forwardRef(
const classes = useStyles(); ({ isCustom, namespace }: WorkflowTableProps, ref) => {
const { t } = useTranslation(); const classes = useStyles();
const { t } = useTranslation();
const theme = useTheme(); const theme = useTheme();
const workflow = useActions(WorkflowActions); const workflow = useActions(WorkflowActions);
const [experiments, setExperiments] = useState<ChaosCRDTable[]>([]); const [experiments, setExperiments] = useState<ChaosCRDTable[]>([]);
const [revertChaos, setRevertChaos] = useState<boolean>(true); const [revertChaos, setRevertChaos] = useState<boolean>(true);
const [displayStepper, setDisplayStepper] = useState<boolean>(false); const [displayStepper, setDisplayStepper] = useState<boolean>(false);
const [engineIndex, setEngineIndex] = useState<number>(0); const [engineIndex, setEngineIndex] = useState<number>(0);
const [selected, setSelected] = useState<string>(''); const [selected, setSelected] = useState<string>('');
const manifest = useSelector( const manifest = useSelector(
(state: RootState) => state.workflowManifest.manifest (state: RootState) => state.workflowManifest.manifest
); );
const imageRegistryData = useSelector( const imageRegistryData = useSelector(
(state: RootState) => state.selectedImageRegistry (state: RootState) => state.selectedImageRegistry
); );
const addWeights = (manifest: string) => { const addWeights = (manifest: string) => {
const arr: experimentMap[] = []; const arr: experimentMap[] = [];
const hashMap = new Map(); const hashMap = new Map();
const tests = parsed(manifest); const tests = parsed(manifest);
tests.forEach((test) => { tests.forEach((test) => {
let value = 10; let value = 10;
if (hashMap.has(test)) { if (hashMap.has(test)) {
value = hashMap.get(test); value = hashMap.get(test);
} }
arr.push({ experimentName: test, weight: value }); arr.push({ experimentName: test, weight: value });
}); });
localforage.setItem('weights', arr); localforage.setItem('weights', arr);
};
const parsing = (yamlText: string) => {
const parsedYaml = YAML.parse(yamlText);
const expData: ChaosCRDTable[] = [];
addWeights(manifest);
const extractInfo = (template: any, index: number) => {
if (template.inputs && template.inputs.artifacts) {
template.inputs.artifacts.forEach((artifact: any) => {
const chaosEngine = YAML.parse(artifact.raw.data);
if (chaosEngine.kind === 'ChaosEngine') {
expData.push({
StepIndex: index,
Name: chaosEngine.metadata.generateName,
Namespace: chaosEngine.spec.appinfo?.appns ?? '',
Application: chaosEngine.spec.appinfo?.applabel ?? '',
Probes: chaosEngine.spec.experiments[0].spec.probe?.length ?? 0,
ChaosEngine: artifact.raw.data,
});
}
});
}
}; };
if (parsedYaml.kind === 'Workflow') { const parsing = (yamlText: string) => {
parsedYaml.spec.templates.forEach((template: any, index: number) => { const parsedYaml = YAML.parse(yamlText);
extractInfo(template, index); const expData: ChaosCRDTable[] = [];
}); addWeights(manifest);
} else if (parsedYaml.kind === 'CronWorkflow') {
parsedYaml.spec.workflowSpec.templates.forEach( const extractInfo = (template: any, index: number) => {
(template: any, index: number) => { if (template.inputs && template.inputs.artifacts) {
extractInfo(template, index); template.inputs.artifacts.forEach((artifact: any) => {
const chaosEngine = YAML.parse(artifact.raw.data);
if (chaosEngine.kind === 'ChaosEngine') {
expData.push({
StepIndex: index,
Name: chaosEngine.metadata.generateName,
Namespace:
chaosEngine.spec.appinfo?.appns ===
'{{workflow.parameters.adminModeNamespace}}'
? namespace
: chaosEngine.spec.appinfo?.appns ?? '',
Application: chaosEngine.spec.appinfo?.applabel ?? '',
Probes: chaosEngine.spec.experiments[0].spec.probe?.length ?? 0,
ChaosEngine: artifact.raw.data,
});
}
});
} }
};
if (parsedYaml.kind === 'Workflow') {
parsedYaml.spec.templates.forEach((template: any, index: number) => {
extractInfo(template, index);
});
} else if (parsedYaml.kind === 'CronWorkflow') {
parsedYaml.spec.workflowSpec.templates.forEach(
(template: any, index: number) => {
extractInfo(template, index);
}
);
}
setExperiments(expData);
};
// Revert Chaos
const toggleRevertChaos = (manifest: string) => {
const parsedYAML = YAML.parse(manifest);
let deleteEngines: string = '';
// Else if Revert Chaos is set to true and it is not already set in the manifest
// For Workflows
if (revertChaos && parsedYAML.kind === 'Workflow') {
parsedYAML.spec.templates[0].steps.push([
{
name: 'revert-chaos',
template: 'revert-chaos',
},
]);
parsed(manifest).forEach((_, i) => {
deleteEngines += `${
YAML.parse(
parsedYAML.spec.templates[2 + i].inputs.artifacts[0].raw.data
).metadata.labels['instance_id']
}, `;
});
parsedYAML.spec.templates[parsedYAML.spec.templates.length] = {
name: 'revert-chaos',
container: {
image: 'litmuschaos/k8s:latest',
command: ['sh', '-c'],
args: [
`kubectl delete chaosengine -l 'instance_id in (${deleteEngines})' -n {{workflow.parameters.adminModeNamespace}} `,
],
},
};
}
// Else if Revert Chaos is set to True and it is not already set in the manifest
// For Cron Workflow
else if (revertChaos && parsedYAML.kind === 'CronWorkflow') {
parsedYAML.spec.workflowSpec.templates[0].steps.push([
{
name: 'revert-chaos',
template: 'revert-chaos',
},
]);
parsed(manifest).forEach((_, i) => {
deleteEngines = `${
deleteEngines +
YAML.parse(
parsedYAML.spec.workflowSpec.templates[2 + i].inputs.artifacts[0]
.raw.data
).metadata.name
} `;
});
deleteEngines += '-n {{workflow.parameters.adminModeNamespace}}';
parsedYAML.spec.workflowSpec.templates[
parsedYAML.spec.workflowSpec.templates.length
] = {
name: 'revert-chaos',
container: {
image: 'litmuschaos/k8s:latest',
command: ['sh', '-c'],
args: [deleteEngines],
},
};
}
const updatedManifest = updateManifestImage(
parsedYAML,
imageRegistryData
); );
} workflow.setWorkflowManifest({
setExperiments(expData); manifest: updatedManifest,
};
// Revert Chaos
const toggleRevertChaos = (manifest: string) => {
const parsedYAML = YAML.parse(manifest);
let deleteEngines: string = '';
// Else if Revert Chaos is set to true and it is not already set in the manifest
// For Workflows
if (revertChaos && parsedYAML.kind === 'Workflow') {
parsedYAML.spec.templates[0].steps.push([
{
name: 'revert-chaos',
template: 'revert-chaos',
},
]);
parsed(manifest).forEach((_, i) => {
deleteEngines += `${
YAML.parse(
parsedYAML.spec.templates[2 + i].inputs.artifacts[0].raw.data
).metadata.labels['instance_id']
}, `;
}); });
};
parsedYAML.spec.templates[parsedYAML.spec.templates.length] = { const closeConfigurationStepper = () => {
name: 'revert-chaos', workflow.setWorkflowManifest({
container: { engineYAML: '',
image: 'litmuschaos/k8s:latest',
command: ['sh', '-c'],
args: [
`kubectl delete chaosengine -l 'instance_id in (${deleteEngines})' -n {{workflow.parameters.adminModeNamespace}} `,
],
},
};
}
// Else if Revert Chaos is set to True and it is not already set in the manifest
// For Cron Workflow
else if (revertChaos && parsedYAML.kind === 'CronWorkflow') {
parsedYAML.spec.workflowSpec.templates[0].steps.push([
{
name: 'revert-chaos',
template: 'revert-chaos',
},
]);
parsed(manifest).forEach((_, i) => {
deleteEngines = `${
deleteEngines +
YAML.parse(
parsedYAML.spec.workflowSpec.templates[2 + i].inputs.artifacts[0]
.raw.data
).metadata.name
} `;
}); });
setDisplayStepper(false);
};
deleteEngines += '-n {{workflow.parameters.adminModeNamespace}}'; const handleChange = (
event: React.MouseEvent<HTMLElement>,
newValue: boolean
) => {
setRevertChaos(newValue);
};
parsedYAML.spec.workflowSpec.templates[ useEffect(() => {
parsedYAML.spec.workflowSpec.templates.length if (manifest.length) {
] = { parsing(manifest);
name: 'revert-chaos', }
container: { localforage.getItem('selectedScheduleOption').then((value) => {
image: 'litmuschaos/k8s:latest', if (value) {
command: ['sh', '-c'], setSelected((value as ChooseWorkflowRadio).selected);
args: [deleteEngines], } else setSelected('');
}, });
}; }, [manifest]);
function onNext() {
if (experiments.length === 0) {
return false; // Should show alert
}
if (!isCustom) {
return true;
}
if (selected === 'C') {
toggleRevertChaos(manifest);
}
return true; // Should not show any alert
} }
const updatedManifest = updateManifestImage(parsedYAML, imageRegistryData); useImperativeHandle(ref, () => ({
workflow.setWorkflowManifest({ onNext,
manifest: updatedManifest, }));
});
};
const closeConfigurationStepper = () => { return (
workflow.setWorkflowManifest({ <div>
engineYAML: '', {!displayStepper ? (
}); <>
setDisplayStepper(false); <TableContainer className={classes.table} component={Paper}>
}; <Table aria-label="simple table">
<TableHead>
const handleChange = (
event: React.MouseEvent<HTMLElement>,
newValue: boolean
) => {
setRevertChaos(newValue);
};
useEffect(() => {
if (manifest.length) {
parsing(manifest);
}
localforage.getItem('selectedScheduleOption').then((value) => {
if (value) {
setSelected((value as ChooseWorkflowRadio).selected);
} else setSelected('');
});
}, [manifest]);
function onNext() {
if (experiments.length === 0) {
return false; // Should show alert
}
if (!isCustom) {
return true;
}
if (selected === 'C') {
toggleRevertChaos(manifest);
}
return true; // Should not show any alert
}
useImperativeHandle(ref, () => ({
onNext,
}));
return (
<div>
{!displayStepper ? (
<>
<TableContainer className={classes.table} component={Paper}>
<Table aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>
{t('createWorkflow.chooseWorkflow.table.head1')}
</TableCell>
<TableCell align="left">
{t('createWorkflow.chooseWorkflow.table.head2')}
</TableCell>
<TableCell align="left">
{t('createWorkflow.chooseWorkflow.table.head3')}
</TableCell>
<TableCell align="left">
{t('createWorkflow.chooseWorkflow.table.head4')}
</TableCell>
<TableCell align="left">
{t('createWorkflow.chooseWorkflow.table.head5')}
</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}
>
<TableCell component="th" scope="row">
{index + 1}
</TableCell>
<TableCell align="left">{experiment.Name}</TableCell>
<TableCell align="left">{experiment.Namespace}</TableCell>
<TableCell align="left">
{experiment.Application}
</TableCell>
<TableCell align="left">{experiment.Probes}</TableCell>
</TableRow>
))
) : (
<TableRow> <TableRow>
<TableCell colSpan={5}> <TableCell>
<Typography align="center"> {t('createWorkflow.chooseWorkflow.table.head1')}
{t('createWorkflow.chooseWorkflow.pleaseAddExp')} </TableCell>
</Typography> <TableCell align="left">
{t('createWorkflow.chooseWorkflow.table.head2')}
</TableCell>
<TableCell align="left">
{t('createWorkflow.chooseWorkflow.table.head3')}
</TableCell>
<TableCell align="left">
{t('createWorkflow.chooseWorkflow.table.head4')}
</TableCell>
<TableCell align="left">
{t('createWorkflow.chooseWorkflow.table.head5')}
</TableCell> </TableCell>
</TableRow> </TableRow>
)} </TableHead>
</TableBody> <TableBody>
</Table> {experiments.length > 0 ? (
</TableContainer> experiments.map((experiment: ChaosCRDTable, index) => (
{selected === 'C' && ( <TableRow
<TableContainer className={classes.revertChaos} component={Paper}> key={experiment.Name}
<Row className={classes.wrapper}> onClick={() => {
<div className={classes.key}> setDisplayStepper(true);
<Typography> setEngineIndex(experiment.StepIndex);
{t('createWorkflow.chooseWorkflow.revertSchedule')} workflow.setWorkflowManifest({
</Typography> engineYAML: experiment.ChaosEngine,
</div> });
<div> }}
<ToggleButtonGroup className={classes.selection}
value={revertChaos} >
exclusive <TableCell component="th" scope="row">
onChange={handleChange} {index + 1}
aria-label="text alignment" </TableCell>
> <TableCell align="left">{experiment.Name}</TableCell>
<ToggleButton <TableCell align="left">
value {experiment.Namespace}
style={{ </TableCell>
backgroundColor: revertChaos <TableCell align="left">
? theme.palette.success.main {experiment.Application}
: theme.palette.disabledBackground, </TableCell>
color: revertChaos <TableCell align="left">{experiment.Probes}</TableCell>
? theme.palette.common.white </TableRow>
: theme.palette.text.disabled, ))
}} ) : (
aria-label="centered" <TableRow>
> <TableCell colSpan={5}>
{t('createWorkflow.chooseWorkflow.trueValue')} <Typography align="center">
</ToggleButton> {t('createWorkflow.chooseWorkflow.pleaseAddExp')}
<ToggleButton </Typography>
value={false} </TableCell>
style={{ </TableRow>
backgroundColor: !revertChaos )}
? theme.palette.error.main </TableBody>
: theme.palette.disabledBackground, </Table>
color: !revertChaos
? theme.palette.common.white
: theme.palette.text.disabled,
}}
aria-label="centered"
>
{t('createWorkflow.chooseWorkflow.falseValue')}
</ToggleButton>
</ToggleButtonGroup>
</div>
</Row>
</TableContainer> </TableContainer>
)} {selected === 'C' && (
</> <TableContainer className={classes.revertChaos} component={Paper}>
) : ( <Row className={classes.wrapper}>
<ConfigurationStepper <div className={classes.key}>
experimentIndex={engineIndex} <Typography>
closeStepper={closeConfigurationStepper} {t('createWorkflow.chooseWorkflow.revertSchedule')}
isCustom={isCustom} </Typography>
/> </div>
)} <div>
</div> <ToggleButtonGroup
); value={revertChaos}
}); exclusive
onChange={handleChange}
aria-label="text alignment"
>
<ToggleButton
value
style={{
backgroundColor: revertChaos
? theme.palette.success.main
: theme.palette.disabledBackground,
color: revertChaos
? theme.palette.common.white
: theme.palette.text.disabled,
}}
aria-label="centered"
>
{t('createWorkflow.chooseWorkflow.trueValue')}
</ToggleButton>
<ToggleButton
value={false}
style={{
backgroundColor: !revertChaos
? theme.palette.error.main
: theme.palette.disabledBackground,
color: !revertChaos
? theme.palette.common.white
: theme.palette.text.disabled,
}}
aria-label="centered"
>
{t('createWorkflow.chooseWorkflow.falseValue')}
</ToggleButton>
</ToggleButtonGroup>
</div>
</Row>
</TableContainer>
)}
</>
) : (
<ConfigurationStepper
experimentIndex={engineIndex}
closeStepper={closeConfigurationStepper}
isCustom={isCustom}
/>
)}
</div>
);
}
);
export default WorkflowTable; export default WorkflowTable;

View File

@ -788,7 +788,11 @@ const TuneWorkflow = forwardRef((_, ref) => {
</Width> </Width>
{/* Workflow Table */} {/* Workflow Table */}
<Width width="70%"> <Width width="70%">
<WorkflowTable ref={childRef} isCustom={isCustomWorkflow} /> <WorkflowTable
ref={childRef}
isCustom={isCustomWorkflow}
namespace={namespace}
/>
</Width> </Width>
</Row> </Row>
</div> </div>

View File

@ -3,7 +3,7 @@ import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import DeveloperGuide from '../../../components/DeveloperGuide'; import DeveloperGuide from '../../../components/DeveloperGuide';
import ExperimentHeader from '../../../components/ExperimentHeader'; import ExperimentHeader from '../ExperimentHeader';
import ExperimentInfo from '../../../components/ExperimentInfo'; import ExperimentInfo from '../../../components/ExperimentInfo';
import InstallChaos from '../../../components/InstallChaos'; import InstallChaos from '../../../components/InstallChaos';
import Loader from '../../../components/Loader'; import Loader from '../../../components/Loader';