diff --git a/litmus-portal/frontend/src/components/LitmusStepper/index.tsx b/litmus-portal/frontend/src/components/LitmusStepper/index.tsx index 89ca86c34..2e8f428b5 100644 --- a/litmus-portal/frontend/src/components/LitmusStepper/index.tsx +++ b/litmus-portal/frontend/src/components/LitmusStepper/index.tsx @@ -1,4 +1,11 @@ -import { Paper, Step, StepLabel, Stepper, Typography } from '@material-ui/core'; +import { + Paper, + Step, + StepLabel, + Stepper, + Tooltip, + Typography, +} from '@material-ui/core'; import clsx from 'clsx'; import { ButtonFilled, ButtonOutlined } from 'litmus-ui'; import React from 'react'; @@ -77,11 +84,23 @@ const LitmusStepper: React.FC = ({ {/* Stepper Actions */}
- {activeStep > 0 && ( + {activeStep === 2 ? ( + +
+ + {t('workflowStepper.back')} + +
+
+ ) : activeStep > 0 ? ( {t('workflowStepper.back')} - )} + ) : null} {moreStepperActions}
{activeStep !== steps.length - 1 ? ( diff --git a/litmus-portal/frontend/src/components/WorkflowStepper/index.tsx b/litmus-portal/frontend/src/components/WorkflowStepper/index.tsx index 1eb68d40a..e04567e36 100644 --- a/litmus-portal/frontend/src/components/WorkflowStepper/index.tsx +++ b/litmus-portal/frontend/src/components/WorkflowStepper/index.tsx @@ -1,3 +1,4 @@ +import { Tooltip } from '@material-ui/core'; import Snackbar from '@material-ui/core/Snackbar'; import Typography from '@material-ui/core/Typography'; import MuiAlert, { AlertProps } from '@material-ui/lab/Alert'; @@ -145,6 +146,26 @@ const WorkflowStepper = () => { Finish ) + ) : activeStep === 2 ? ( +
+ +
+ handleBack()} + > + Back + +
+
+ handleNext()}> + Next + +
) : ( // Apply headerButtonWrapper style for top button's div
diff --git a/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/ChooseWorkflowFromExisting.tsx b/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/ChooseWorkflowFromExisting.tsx index ac0709aea..f13b55be5 100644 --- a/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/ChooseWorkflowFromExisting.tsx +++ b/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/ChooseWorkflowFromExisting.tsx @@ -8,7 +8,7 @@ import { } from '@material-ui/core'; import { LitmusCard, RadioButton, Search } from 'litmus-ui'; import localforage from 'localforage'; -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { DELETE_WORKFLOW_TEMPLATE, @@ -18,17 +18,23 @@ import { ListManifestTemplate, 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'; +import * as WorkflowActions from '../../../redux/actions/workflow'; +import { getProjectID } from '../../../utils/getSearchParams'; +import useStyles from './styles'; interface ChooseWorkflowRadio { selected: string; id: string; } -const ChooseWorkflowFromExisting = () => { +interface ChooseWorkflowFromExistingProps { + selectedExp: (expID: string) => void; +} + +const ChooseWorkflowFromExisting: React.FC = ({ + selectedExp, +}) => { const { t } = useTranslation(); const classes = useStyles(); const { palette } = useTheme(); @@ -73,6 +79,7 @@ const ChooseWorkflowFromExisting = () => { selected: 'B', id: event.target.value, }; + selectedExp(selection.id); const templateData = filteredExistingWorkflows.filter((workflow) => { return workflow.template_id === event.target.value; })[0]; @@ -83,17 +90,6 @@ const ChooseWorkflowFromExisting = () => { localforage.setItem('hasSetWorkflowData', false); }; - // Selects Option B -> Sub Experiment Options which was already selected by the user - useEffect(() => { - localforage - .getItem('selectedScheduleOption') - .then((value) => - value !== null - ? setSelected((value as ChooseWorkflowRadio).id) - : setSelected('') - ); - }, []); - return ( {/* Wrapping content inside the Accordion to take full width */} diff --git a/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/choosePreDefinedExperiments.tsx b/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/choosePreDefinedExperiments.tsx index ffa7373c0..c6e0f1ed3 100644 --- a/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/choosePreDefinedExperiments.tsx +++ b/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/choosePreDefinedExperiments.tsx @@ -25,234 +25,229 @@ interface ChooseWorkflowRadio { id: string; } -const ChoosePreDefinedExperiments = () => { - const { t } = useTranslation(); - const classes = useStyles(); - const { palette } = useTheme(); +interface ChoosePreDefinedExperimentsProps { + selectedExp: (expID: string) => void; +} - // Local States - const [search, setSearch] = useState(null); - const [selected, setSelected] = useState(''); +const ChoosePreDefinedExperiments: React.FC = + ({ selectedExp }) => { + const { t } = useTranslation(); + const classes = useStyles(); + const { palette } = useTheme(); - const selectedProjectID = getProjectID(); - const [selectedHub, setSelectedHub] = useState(''); - const [availableHubs, setAvailableHubs] = useState([]); - const [workflowList, setWorkflowlist] = useState([]); + // Local States + const [search, setSearch] = useState(null); + const [selected, setSelected] = useState(''); - // Get all MyHubs with status - const { data, loading } = useQuery(GET_HUB_STATUS, { - variables: { data: selectedProjectID }, - fetchPolicy: 'cache-and-network', - }); + const selectedProjectID = getProjectID(); + const [selectedHub, setSelectedHub] = useState(''); + const [availableHubs, setAvailableHubs] = useState([]); + const [workflowList, setWorkflowlist] = useState([]); - /** - * Query to get the list of Pre-defined workflows - */ - const [getPredefinedWorkflow] = useLazyQuery(GET_PREDEFINED_WORKFLOW_LIST, { - fetchPolicy: 'network-only', - onCompleted: (data) => { - if (data.GetPredefinedWorkflowList !== undefined) { - setWorkflowlist(data.GetPredefinedWorkflowList); - } - }, - onError: () => { - setWorkflowlist([]); - }, - }); + // Get all MyHubs with status + const { data, loading } = useQuery(GET_HUB_STATUS, { + variables: { data: selectedProjectID }, + fetchPolicy: 'cache-and-network', + }); - /** - * Function to handle changes in Radio Buttons - */ - const handleChange = (event: React.ChangeEvent) => { - setSelected(event.target.value); - const selection: ChooseWorkflowRadio = { - selected: 'A', - id: event.target.value, - }; - localforage.setItem('selectedScheduleOption', selection); - localforage.setItem('hasSetWorkflowData', false); - }; - - const filteredPreDefinedWorkflows = workflowList.filter((w: string) => { - if (search === null) return w; - if (w.toLowerCase().includes(search.toLowerCase())) return w; - return null; - }); - - /** - * Function to handle change in MyHub dropdown - */ - const handleMyHubChange = ( - event: React.ChangeEvent<{ - name?: string | undefined; - value: unknown; - }> - ) => { - setSelectedHub(event.target.value as string); - getPredefinedWorkflow({ - variables: { - hubname: event.target.value as string, - projectid: selectedProjectID, + /** + * Query to get the list of Pre-defined workflows + */ + const [getPredefinedWorkflow] = useLazyQuery(GET_PREDEFINED_WORKFLOW_LIST, { + fetchPolicy: 'network-only', + onCompleted: (data) => { + if (data.GetPredefinedWorkflowList !== undefined) { + setWorkflowlist(data.GetPredefinedWorkflowList); + } + }, + onError: () => { + setWorkflowlist([]); }, }); - localforage.setItem('selectedHub', event.target.value as string); + + /** + * Function to handle changes in Radio Buttons + */ + const handleChange = (event: React.ChangeEvent) => { + setSelected(event.target.value); + const selection: ChooseWorkflowRadio = { + selected: 'A', + id: event.target.value, + }; + selectedExp(selection.id); + localforage.setItem('selectedScheduleOption', selection); + localforage.setItem('hasSetWorkflowData', false); + }; + + const filteredPreDefinedWorkflows = workflowList.filter((w: string) => { + if (search === null) return w; + if (w.toLowerCase().includes(search.toLowerCase())) return w; + return null; + }); + + /** + * Function to handle change in MyHub dropdown + */ + const handleMyHubChange = ( + event: React.ChangeEvent<{ + name?: string | undefined; + value: unknown; + }> + ) => { + setSelectedHub(event.target.value as string); + getPredefinedWorkflow({ + variables: { + hubname: event.target.value as string, + projectid: selectedProjectID, + }, + }); + localforage.setItem('selectedHub', event.target.value as string); + }; + + /** + * UseEffect to check if Chaos Hub exists and if exists + * fetch the pre-defined workflows + */ + useEffect(() => { + if (data?.getHubStatus !== undefined) { + if (data.getHubStatus.length) { + setAvailableHubs([...data.getHubStatus]); + } + data.getHubStatus.forEach((hubData) => { + if (hubData.HubName.toLowerCase() === 'chaos hub') { + setSelectedHub('Chaos Hub'); + localforage.setItem('selectedHub', 'Chaos Hub'); + getPredefinedWorkflow({ + variables: { + hubname: 'Chaos Hub', + projectid: selectedProjectID, + }, + }); + } + }); + } + }, [loading]); + + return ( + + {/* Wrapping content inside the Accordion to take full width */} +
+
+
+ + + {t('createWorkflow.chooseWorkflow.selectMyHub')} + + + +
+
+ setSearch(event.target.value)} + /> +
+
+ + {/* Leaving some space between the search and pre-defined workflow cards */} +
+ + {/* List of Pre-defined workflows */} +
+ {selectedHub === '' ? ( +
+ + {t('createWorkflow.chooseWorkflow.noMyHub')} + + + {t('createWorkflow.chooseWorkflow.selectHub')} + +
+ ) : workflowList.length === 0 ? ( +
+ + + {t('createWorkflow.chooseWorkflow.noPredefined')} + + + + {t('createWorkflow.chooseWorkflow.addPredefined')} + +
+ ) : ( + + {filteredPreDefinedWorkflows?.length > 0 ? ( + filteredPreDefinedWorkflows?.map((wfData) => ( + + + {/* Wrap the entire body with 100% width to divide into 40-60 */} +
+ {/* Left Div => Icon + Name of Workflow */} +
+ Experiment Icon + + {wfData} + +
+
+
+
+ )) + ) : ( +
+ + + {t('createWorkflow.chooseWorkflow.noPredefined')} + + + + {t('createWorkflow.chooseWorkflow.searchTerm')} + +
+ )} +
+ )} +
+ {/* Bottom Blur */} +
+
+ + ); }; - // Selects Option A -> Sub Experiment Options which was already selected by the user - useEffect(() => { - localforage - .getItem('selectedScheduleOption') - .then((value) => - value !== null - ? setSelected((value as ChooseWorkflowRadio).id) - : setSelected('') - ); - }, []); - - /** - * UseEffect to check if Chaos Hub exists and if exists - * fetch the pre-defined workflows - */ - useEffect(() => { - if (data?.getHubStatus !== undefined) { - if (data.getHubStatus.length) { - setAvailableHubs([...data.getHubStatus]); - } - data.getHubStatus.forEach((hubData) => { - if (hubData.HubName.toLowerCase() === 'chaos hub') { - setSelectedHub('Chaos Hub'); - localforage.setItem('selectedHub', 'Chaos Hub'); - getPredefinedWorkflow({ - variables: { - hubname: 'Chaos Hub', - projectid: selectedProjectID, - }, - }); - } - }); - } - }, [loading]); - - return ( - - {/* Wrapping content inside the Accordion to take full width */} -
-
-
- - - {t('createWorkflow.chooseWorkflow.selectMyHub')} - - - -
-
- setSearch(event.target.value)} - /> -
-
- - {/* Leaving some space between the search and pre-defined workflow cards */} -
- - {/* List of Pre-defined workflows */} -
- {selectedHub === '' ? ( -
- - {t('createWorkflow.chooseWorkflow.noMyHub')} - - - {t('createWorkflow.chooseWorkflow.selectHub')} - -
- ) : workflowList.length === 0 ? ( -
- - - {t('createWorkflow.chooseWorkflow.noPredefined')} - - - - {t('createWorkflow.chooseWorkflow.addPredefined')} - -
- ) : ( - - {filteredPreDefinedWorkflows?.length > 0 ? ( - filteredPreDefinedWorkflows?.map((wfData) => ( - - - {/* Wrap the entire body with 100% width to divide into 40-60 */} -
- {/* Left Div => Icon + Name of Workflow */} -
- Experiment Icon - - {wfData} - -
-
-
-
- )) - ) : ( -
- - - {t('createWorkflow.chooseWorkflow.noPredefined')} - - - - {t('createWorkflow.chooseWorkflow.searchTerm')} - -
- )} -
- )} -
- {/* Bottom Blur */} -
-
- - ); -}; - export default ChoosePreDefinedExperiments; diff --git a/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/index.tsx b/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/index.tsx index c2ca5e242..b12901fef 100644 --- a/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/index.tsx +++ b/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/index.tsx @@ -14,7 +14,6 @@ import React, { } from 'react'; import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; -import { ChooseWorkflowRadio } from '../../../models/localforage/radioButton'; import useActions from '../../../redux/actions'; import * as AlertActions from '../../../redux/actions/alert'; import * as WorkflowActions from '../../../redux/actions/workflow'; @@ -30,6 +29,7 @@ const ChooseWorkflow = forwardRef((_, ref) => { const { t } = useTranslation(); const alert = useActions(AlertActions); const [selected, setSelected] = useState(''); + const [id, setSelectedID] = useState(undefined); const workflowDetails = useSelector( (state: RootState) => state.workflowManifest.manifest ); @@ -50,11 +50,21 @@ const ChooseWorkflow = forwardRef((_, ref) => { } }; + useEffect(() => { + workflowAction.setWorkflowManifest({ manifest: '' }); + }, []); + function onNext() { if (selected === '') { alert.changeAlertState(true); // No Workflow Type has been selected and user clicked on Next return false; } + if (selected === 'A' || selected === 'B') { + if (id === undefined) { + alert.changeAlertState(true); + return false; + } + } if (selected === 'D' && workflowDetails === '') { alert.changeAlertState(true); return false; @@ -63,20 +73,9 @@ const ChooseWorkflow = forwardRef((_, ref) => { return true; } - useEffect(() => { - localforage.getItem('selectedScheduleOption').then((value) => { - if (value) { - setSelected((value as ChooseWorkflowRadio).selected); - } else setSelected(''); - }); - workflowAction.setWorkflowManifest({ - manifest: '', - }); - /** - * Removes the workflow details if already present - */ - localforage.removeItem('workflow'); - }, []); + const pickedExperiment = (subExpNumber: string) => { + setSelectedID(subExpNumber); + }; useImperativeHandle(ref, () => ({ onNext, @@ -120,7 +119,7 @@ const ChooseWorkflow = forwardRef((_, ref) => { - + { - + { * Index DB Fetching for extracting selected Button and Workflow Details */ const getSelectedWorkflowDetails = () => { - localforage.getItem('workflow').then((workflow) => + localforage.getItem('workflow').then((workflow) => { setWorkflow({ name: (workflow as WorkflowDetailsProps).name, crd: (workflow as WorkflowDetailsProps).CRDLink, description: (workflow as WorkflowDetailsProps).description, - }) - ); + }); + }); localforage.getItem('selectedScheduleOption').then((value) => { /** * Setting default data when MyHub is selected @@ -331,7 +331,7 @@ const TuneWorkflow = forwardRef((_, ref) => { useEffect(() => { getSelectedWorkflowDetails(); - }, []); + }, [manifest]); /** * Graphql Query for fetching Engine YAML diff --git a/litmus-portal/frontend/src/views/CreateWorkflow/VerifyCommit/index.tsx b/litmus-portal/frontend/src/views/CreateWorkflow/VerifyCommit/index.tsx index 1fa816aad..ce9e54586 100644 --- a/litmus-portal/frontend/src/views/CreateWorkflow/VerifyCommit/index.tsx +++ b/litmus-portal/frontend/src/views/CreateWorkflow/VerifyCommit/index.tsx @@ -241,11 +241,7 @@ const VerifyCommit = forwardRef( isLoading(loading); const handleMutation = () => { - if ( - workflow.name.length !== 0 && - workflow.description.length !== 0 && - weights.length !== 0 - ) { + if (workflow.name.length !== 0 && weights.length !== 0) { const weightData: WeightMap[] = []; weights.forEach((data) => { diff --git a/litmus-portal/frontend/src/views/CreateWorkflow/WorkflowSettings/index.tsx b/litmus-portal/frontend/src/views/CreateWorkflow/WorkflowSettings/index.tsx index 064ceb3d1..f46f16510 100644 --- a/litmus-portal/frontend/src/views/CreateWorkflow/WorkflowSettings/index.tsx +++ b/litmus-portal/frontend/src/views/CreateWorkflow/WorkflowSettings/index.tsx @@ -130,6 +130,7 @@ const WorkflowSettings = forwardRef((_, ref) => { }, }); }); + workflowAction.setWorkflowManifest({ manifest: '' }); } if ((value as ChooseWorkflowRadio).selected === 'B') { getSavedTemplateDetails({