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:
heading: Add
headingStrong: Probe
validate: Probe name already exists
labels:
probeName: Probe Name
probeType: Probe Type

View File

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

View File

@ -41,6 +41,18 @@ export const validateWorkflowName = (value: string) => {
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) => {
const passValid = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,20}$/;
if (value.length > 0) {
@ -77,7 +89,7 @@ export const isValidWebUrl = (value: string) => {
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 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 (
value.match(regEx) ||
value.match(regExLocal) ||

View File

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

View File

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

View File

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

View File

@ -30,6 +30,7 @@ import useStyles from './styles';
interface WorkflowTableProps {
isCustom: boolean | undefined;
namespace: string;
}
interface ChaosCRDTable {
@ -41,7 +42,8 @@ interface ChaosCRDTable {
ChaosEngine: string;
}
const WorkflowTable = forwardRef(({ isCustom }: WorkflowTableProps, ref) => {
const WorkflowTable = forwardRef(
({ isCustom, namespace }: WorkflowTableProps, ref) => {
const classes = useStyles();
const { t } = useTranslation();
@ -85,7 +87,11 @@ const WorkflowTable = forwardRef(({ isCustom }: WorkflowTableProps, ref) => {
expData.push({
StepIndex: index,
Name: chaosEngine.metadata.generateName,
Namespace: chaosEngine.spec.appinfo?.appns ?? '',
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,
@ -178,7 +184,10 @@ const WorkflowTable = forwardRef(({ isCustom }: WorkflowTableProps, ref) => {
};
}
const updatedManifest = updateManifestImage(parsedYAML, imageRegistryData);
const updatedManifest = updateManifestImage(
parsedYAML,
imageRegistryData
);
workflow.setWorkflowManifest({
manifest: updatedManifest,
});
@ -269,7 +278,9 @@ const WorkflowTable = forwardRef(({ isCustom }: WorkflowTableProps, ref) => {
{index + 1}
</TableCell>
<TableCell align="left">{experiment.Name}</TableCell>
<TableCell align="left">{experiment.Namespace}</TableCell>
<TableCell align="left">
{experiment.Namespace}
</TableCell>
<TableCell align="left">
{experiment.Application}
</TableCell>
@ -346,6 +357,7 @@ const WorkflowTable = forwardRef(({ isCustom }: WorkflowTableProps, ref) => {
)}
</div>
);
});
}
);
export default WorkflowTable;

View File

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

View File

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