chore(scheduling): Added Edit Schedule Functionality + Fixed a CronWorkflow Bug 🐛 (#2657)
* Added Edit Schedule Functionality + Fixed a CronWorkflow Bug 🐛
* Reverting Sidebar text color
* Resolved comments/suggestions
* Adding missing translation
Signed-off-by: Sayan Mondal <sayan@chaosnative.com>
			
			
This commit is contained in:
		
							parent
							
								
									43d0e02810
								
							
						
					
					
						commit
						1a8e67e61d
					
				|  | @ -154,6 +154,15 @@ schedule: | ||||||
|   workflowBtn: Go to Workflow |   workflowBtn: Go to Workflow | ||||||
|   backBtn: Go Back |   backBtn: Go Back | ||||||
| 
 | 
 | ||||||
|  | editSchedule: | ||||||
|  |   title: Edit Schedule | ||||||
|  |   verify: Verify | ||||||
|  |   cancel: Cancel | ||||||
|  |   save: Save Changes | ||||||
|  |   edit: Edit | ||||||
|  |   theSchedule: The Schedule | ||||||
|  |   successfullyCreated: is successfully created | ||||||
|  | 
 | ||||||
| community: | community: | ||||||
|   title: 'Community' |   title: 'Community' | ||||||
|   heading: 'Litmus Insights' |   heading: 'Litmus Insights' | ||||||
|  | @ -794,6 +803,8 @@ createWorkflow: | ||||||
|     errYaml: Error in CRD Yaml. |     errYaml: Error in CRD Yaml. | ||||||
|     codeIsFine: Your code is fine. |     codeIsFine: Your code is fine. | ||||||
|     youCanMoveOn: You can move on ! |     youCanMoveOn: You can move on ! | ||||||
|  |     test: test | ||||||
|  |     YAML: YAML | ||||||
|     button: |     button: | ||||||
|       edit: Edit |       edit: Edit | ||||||
|       viewYaml: View YAML |       viewYaml: View YAML | ||||||
|  |  | ||||||
|  | @ -1,13 +1,8 @@ | ||||||
| import { Card, CardActionArea, Typography } from '@material-ui/core'; | import { Card, CardActionArea, Typography } from '@material-ui/core'; | ||||||
| import React from 'react'; | import React from 'react'; | ||||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||||
| import useActions from '../../redux/actions'; |  | ||||||
| import * as TemplateSelectionActions from '../../redux/actions/template'; |  | ||||||
| import * as WorkflowActions from '../../redux/actions/workflow'; |  | ||||||
| import { history } from '../../redux/configureStore'; |  | ||||||
| import { ReactComponent as Arrow } from '../../svg/arrow.svg'; | import { ReactComponent as Arrow } from '../../svg/arrow.svg'; | ||||||
| import { ReactComponent as ArrowDisabled } from '../../svg/arrow_disabled.svg'; | import { ReactComponent as ArrowDisabled } from '../../svg/arrow_disabled.svg'; | ||||||
| import { getProjectID, getProjectRole } from '../../utils/getSearchParams'; |  | ||||||
| import useStyles from './styles'; | import useStyles from './styles'; | ||||||
| 
 | 
 | ||||||
| interface CreateWorkflowCardProps { | interface CreateWorkflowCardProps { | ||||||
|  | @ -19,28 +14,9 @@ const CreateWorkflowCard: React.FC<CreateWorkflowCardProps> = ({ | ||||||
| }) => { | }) => { | ||||||
|   const { t } = useTranslation(); |   const { t } = useTranslation(); | ||||||
|   const classes = useStyles({ isDisabled }); |   const classes = useStyles({ isDisabled }); | ||||||
|   const template = useActions(TemplateSelectionActions); |  | ||||||
|   const projectID = getProjectID(); |  | ||||||
|   const userRole = getProjectRole(); |  | ||||||
|   const workflowAction = useActions(WorkflowActions); |  | ||||||
|   const handleCreateWorkflow = () => { |  | ||||||
|     workflowAction.setWorkflowDetails({ |  | ||||||
|       isCustomWorkflow: false, |  | ||||||
|       customWorkflows: [], |  | ||||||
|     }); |  | ||||||
|     template.selectTemplate({ selectedTemplateID: 0, isDisable: true }); |  | ||||||
|     history.push({ |  | ||||||
|       pathname: '/create-workflow', |  | ||||||
|       search: `?projectID=${projectID}&projectRole=${userRole}`, |  | ||||||
|     }); |  | ||||||
|   }; |  | ||||||
| 
 | 
 | ||||||
|   return ( |   return ( | ||||||
|     <Card |     <Card className={classes.createCard} data-cy="createWorkflow"> | ||||||
|       onClick={isDisabled ? () => {} : handleCreateWorkflow} |  | ||||||
|       className={classes.createCard} |  | ||||||
|       data-cy="createWorkflow" |  | ||||||
|     > |  | ||||||
|       <CardActionArea className={classes.createCardAction}> |       <CardActionArea className={classes.createCardAction}> | ||||||
|         <Typography className={classes.createCardHeading}> |         <Typography className={classes.createCardHeading}> | ||||||
|           {t('home.workflow.heading')} |           {t('home.workflow.heading')} | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| import { QuickActionCard } from 'litmus-ui'; | import { QuickActionCard } from 'litmus-ui'; | ||||||
| import React from 'react'; | import React from 'react'; | ||||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||||
|  | import { constants } from '../../constants'; | ||||||
| import { Role } from '../../models/graphql/user'; | import { Role } from '../../models/graphql/user'; | ||||||
| import useActions from '../../redux/actions'; | import useActions from '../../redux/actions'; | ||||||
| import * as TabActions from '../../redux/actions/tabs'; | import * as TabActions from '../../redux/actions/tabs'; | ||||||
|  | @ -97,7 +98,7 @@ const LocalQuickActionCard: React.FC<LocalQuickActionCardProps> = ({ | ||||||
|       ? { |       ? { | ||||||
|           src: '/icons/survey.svg', |           src: '/icons/survey.svg', | ||||||
|           alt: 'survey', |           alt: 'survey', | ||||||
|           onClick: () => window.open('https://forms.gle/qMuVphRyEWCFqjD56'), |           onClick: () => window.open(constants.FeedbackForm), | ||||||
|           text: t('quickActionCard.quickSurvey'), |           text: t('quickActionCard.quickSurvey'), | ||||||
|         } |         } | ||||||
|       : emptyData, |       : emptyData, | ||||||
|  |  | ||||||
|  | @ -7,9 +7,8 @@ const useStyles = makeStyles((theme: Theme) => ({ | ||||||
|   }, |   }, | ||||||
|   drawerPaper: { |   drawerPaper: { | ||||||
|     width: '100%', |     width: '100%', | ||||||
|     backgroundColor: theme.palette.background.default, |     backgroundColor: theme.palette.sidebarMenu, | ||||||
|     position: 'relative', |     position: 'relative', | ||||||
|     color: 'inherit', |  | ||||||
|   }, |   }, | ||||||
|   litmusDiv: { |   litmusDiv: { | ||||||
|     display: 'flex', |     display: 'flex', | ||||||
|  |  | ||||||
|  | @ -0,0 +1,13 @@ | ||||||
|  | export const constants = { | ||||||
|  |   // Litmus HomePage [Component Used in -> LocalQuickActionCard]
 | ||||||
|  |   FeedbackForm: 'https://forms.gle/KQp5qj8MUneMSxLp9', | ||||||
|  | 
 | ||||||
|  |   /** | ||||||
|  |    * Schedule & Edit Schedule [Component Used in -> views/ScheduleWorkflow, | ||||||
|  |    * pages/EditSchedule/Schedule] | ||||||
|  |    * */ | ||||||
|  |   recurringEveryHour: 'everyHr', | ||||||
|  |   recurringEveryDay: 'everyDay', | ||||||
|  |   recurringEveryWeek: 'everyWeek', | ||||||
|  |   recurringEveryMonth: 'everyMonth', | ||||||
|  | }; | ||||||
|  | @ -25,6 +25,8 @@ const HomePage = lazy(() => import('../../pages/HomePage')); | ||||||
| const Community = lazy(() => import('../../pages/Community')); | const Community = lazy(() => import('../../pages/Community')); | ||||||
| const Settings = lazy(() => import('../../pages/Settings')); | const Settings = lazy(() => import('../../pages/Settings')); | ||||||
| const Targets = lazy(() => import('../../pages/Targets')); | const Targets = lazy(() => import('../../pages/Targets')); | ||||||
|  | const EditSchedule = lazy(() => import('../../pages/EditSchedule')); | ||||||
|  | const SetNewSchedule = lazy(() => import('../../pages/EditSchedule/Schedule')); | ||||||
| const ConnectTargets = lazy(() => import('../../pages/ConnectTarget')); | const ConnectTargets = lazy(() => import('../../pages/ConnectTarget')); | ||||||
| const AnalyticsPage = lazy(() => import('../../pages/AnalyticsPage')); | const AnalyticsPage = lazy(() => import('../../pages/AnalyticsPage')); | ||||||
| const AnalyticsDashboard = lazy( | const AnalyticsDashboard = lazy( | ||||||
|  | @ -194,11 +196,16 @@ const Routes: React.FC = () => { | ||||||
|             path="/workflows/:workflowRunId" |             path="/workflows/:workflowRunId" | ||||||
|             component={WorkflowDetails} |             component={WorkflowDetails} | ||||||
|           /> |           /> | ||||||
|           {/* <Route |           <Route | ||||||
|             exact |             exact | ||||||
|             path="/workflows/schedule/:scheduleProjectID/:workflowName" // Check
 |             path="/workflows/schedule/:scheduleProjectID/:workflowName" | ||||||
|             component={SchedulePage} |             component={EditSchedule} | ||||||
|           /> */} |           /> | ||||||
|  |           <Route | ||||||
|  |             exact | ||||||
|  |             path="/workflows/schedule/:scheduleProjectID/:workflowName/set" | ||||||
|  |             component={SetNewSchedule} | ||||||
|  |           /> | ||||||
|           <Route |           <Route | ||||||
|             exact |             exact | ||||||
|             path="/workflows/template/:templateName" |             path="/workflows/template/:templateName" | ||||||
|  |  | ||||||
|  | @ -28,9 +28,6 @@ export interface customWorkflow { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface WorkflowData { | export interface WorkflowData { | ||||||
|   id: string; |  | ||||||
|   isRecurring: boolean; |  | ||||||
|   isDisabled: boolean; |  | ||||||
|   chaosEngineChanged: boolean; |   chaosEngineChanged: boolean; | ||||||
|   namespace: string; |   namespace: string; | ||||||
|   workflow_id?: string; |   workflow_id?: string; | ||||||
|  |  | ||||||
|  | @ -0,0 +1,767 @@ | ||||||
|  | import { | ||||||
|  |   Divider, | ||||||
|  |   FormControl, | ||||||
|  |   FormControlLabel, | ||||||
|  |   Radio, | ||||||
|  |   RadioGroup, | ||||||
|  |   Select, | ||||||
|  |   Typography, | ||||||
|  | } from '@material-ui/core'; | ||||||
|  | import { ButtonFilled, ButtonOutlined } from 'litmus-ui'; | ||||||
|  | import localforage from 'localforage'; | ||||||
|  | import React, { useEffect, useState } from 'react'; | ||||||
|  | import { useTranslation } from 'react-i18next'; | ||||||
|  | import { useSelector } from 'react-redux'; | ||||||
|  | import YAML from 'yaml'; | ||||||
|  | import BackButton from '../../components/Button/BackButton'; | ||||||
|  | import CustomDate from '../../components/DateTime/CustomDate/index'; | ||||||
|  | import CustomTime from '../../components/DateTime/CustomTime/index'; | ||||||
|  | import { constants } from '../../constants'; | ||||||
|  | import Scaffold from '../../containers/layouts/Scaffold'; | ||||||
|  | import { WorkflowData } from '../../models/redux/workflow'; | ||||||
|  | import useActions from '../../redux/actions'; | ||||||
|  | import * as TemplateSelectionActions from '../../redux/actions/template'; | ||||||
|  | import * as WorkflowActions from '../../redux/actions/workflow'; | ||||||
|  | import { history } from '../../redux/configureStore'; | ||||||
|  | import { RootState } from '../../redux/reducers'; | ||||||
|  | import { getProjectID, getProjectRole } from '../../utils/getSearchParams'; | ||||||
|  | import { cronWorkflow, workflowOnce } from '../../utils/workflowTemplate'; | ||||||
|  | import { fetchWorkflowNameFromManifest } from '../../utils/yamlUtils'; | ||||||
|  | import SetTime from '../../views/CreateWorkflow/ScheduleWorkflow/SetTime'; | ||||||
|  | import useStyles from '../../views/CreateWorkflow/ScheduleWorkflow/styles'; | ||||||
|  | 
 | ||||||
|  | interface ScheduleSyntax { | ||||||
|  |   minute: string | undefined; | ||||||
|  |   hour: string | undefined; | ||||||
|  |   day_month: string | undefined; | ||||||
|  |   month: string | undefined; | ||||||
|  |   day_week: string; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const ScheduleWorkflow = () => { | ||||||
|  |   // Initial Cron State
 | ||||||
|  |   const [cronValue, setCronValue] = useState<ScheduleSyntax>({ | ||||||
|  |     minute: '*', | ||||||
|  |     hour: '*', | ||||||
|  |     day_month: '*', | ||||||
|  |     month: '*', | ||||||
|  |     day_week: '*', | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   const manifest = useSelector( | ||||||
|  |     (state: RootState) => state.workflowManifest.manifest | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   // Redux States for Schedule
 | ||||||
|  |   const workflowData: WorkflowData = useSelector( | ||||||
|  |     (state: RootState) => state.workflowData | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   const { cronSyntax, scheduleType } = workflowData; | ||||||
|  | 
 | ||||||
|  |   const workflowAction = useActions(WorkflowActions); | ||||||
|  |   const template = useActions(TemplateSelectionActions); | ||||||
|  |   // Controls Radio Buttons
 | ||||||
|  |   const [value, setValue] = React.useState( | ||||||
|  |     workflowData.scheduleType.scheduleOnce | ||||||
|  |   ); | ||||||
|  |   const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { | ||||||
|  |     setValue(event.target.value); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   // Controls inner radio buttons of Recurring Schedule
 | ||||||
|  |   const [valueDef, setValueDef] = React.useState( | ||||||
|  |     workflowData.scheduleType.recurringSchedule | ||||||
|  |   ); | ||||||
|  |   const handleChangeInstance = (event: React.ChangeEvent<HTMLInputElement>) => { | ||||||
|  |     setValueDef(event.target.value); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const scheduleOnce = workflowOnce; | ||||||
|  |   const scheduleMore = cronWorkflow; | ||||||
|  | 
 | ||||||
|  |   function EditYaml() { | ||||||
|  |     const oldParsedYaml = YAML.parse(manifest); | ||||||
|  |     let NewYaml: string; | ||||||
|  |     if ( | ||||||
|  |       oldParsedYaml.kind === 'Workflow' && | ||||||
|  |       scheduleType.scheduleOnce !== 'now' | ||||||
|  |     ) { | ||||||
|  |       const oldParsedYaml = YAML.parse(manifest); | ||||||
|  |       const newParsedYaml = YAML.parse(scheduleMore); | ||||||
|  |       delete newParsedYaml.spec.workflowSpec; | ||||||
|  |       newParsedYaml.spec.schedule = cronSyntax; | ||||||
|  |       delete newParsedYaml.metadata.generateName; | ||||||
|  |       newParsedYaml.metadata.name = fetchWorkflowNameFromManifest(manifest); | ||||||
|  |       newParsedYaml.metadata.labels = { | ||||||
|  |         workflow_id: workflowData.workflow_id, | ||||||
|  |       }; | ||||||
|  |       newParsedYaml.spec.workflowSpec = oldParsedYaml.spec; | ||||||
|  |       const tz = { | ||||||
|  |         timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC', | ||||||
|  |       }; | ||||||
|  |       Object.entries(tz).forEach(([key, value]) => { | ||||||
|  |         newParsedYaml.spec[key] = value; | ||||||
|  |       }); | ||||||
|  |       NewYaml = YAML.stringify(newParsedYaml); | ||||||
|  |       workflowAction.setWorkflowManifest({ | ||||||
|  |         manifest: NewYaml, | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     if ( | ||||||
|  |       oldParsedYaml.kind === 'CronWorkflow' && | ||||||
|  |       scheduleType.scheduleOnce === 'now' | ||||||
|  |     ) { | ||||||
|  |       const oldParsedYaml = YAML.parse(manifest); | ||||||
|  |       const newParsedYaml = YAML.parse(scheduleOnce); | ||||||
|  |       delete newParsedYaml.spec; | ||||||
|  |       delete newParsedYaml.metadata.generateName; | ||||||
|  |       newParsedYaml.metadata.name = fetchWorkflowNameFromManifest(manifest); | ||||||
|  |       newParsedYaml.spec = oldParsedYaml.spec.workflowSpec; | ||||||
|  |       newParsedYaml.metadata.labels = { | ||||||
|  |         workflow_id: workflowData.workflow_id, | ||||||
|  |       }; | ||||||
|  |       NewYaml = YAML.stringify(newParsedYaml); | ||||||
|  |       workflowAction.setWorkflowManifest({ | ||||||
|  |         manifest: NewYaml, | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     if ( | ||||||
|  |       oldParsedYaml.kind === 'CronWorkflow' && | ||||||
|  |       scheduleType.scheduleOnce !== 'now' | ||||||
|  |       //   && !isDisabled
 | ||||||
|  |     ) { | ||||||
|  |       const newParsedYaml = YAML.parse(manifest); | ||||||
|  |       newParsedYaml.spec.schedule = cronSyntax; | ||||||
|  |       //   newParsedYaml.spec.suspend = false;
 | ||||||
|  |       delete newParsedYaml.metadata.generateName; | ||||||
|  |       newParsedYaml.metadata.name = fetchWorkflowNameFromManifest(manifest); | ||||||
|  |       newParsedYaml.metadata.labels = { workflow_id: workflowData.workflow_id }; | ||||||
|  |       const tz = { | ||||||
|  |         timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC', | ||||||
|  |       }; | ||||||
|  |       Object.entries(tz).forEach(([key, value]) => { | ||||||
|  |         newParsedYaml.spec[key] = value; | ||||||
|  |       }); | ||||||
|  |       NewYaml = YAML.stringify(newParsedYaml); | ||||||
|  |       workflowAction.setWorkflowManifest({ | ||||||
|  |         manifest: NewYaml, | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     // if (oldParsedYaml.kind === 'CronWorkflow' && isDisabled === true) {
 | ||||||
|  |     //   const newParsedYaml = YAML.parse(yaml);
 | ||||||
|  |     //   newParsedYaml.spec.suspend = true;
 | ||||||
|  |     //   const tz = {
 | ||||||
|  |     //     timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC',
 | ||||||
|  |     //   };
 | ||||||
|  |     //   Object.entries(tz).forEach(([key, value]) => {
 | ||||||
|  |     //     newParsedYaml.spec[key] = value;
 | ||||||
|  |     //   });
 | ||||||
|  |     //   NewYaml = YAML.stringify(newParsedYaml);
 | ||||||
|  |     //   workflowAction.setWorkflowDetails({
 | ||||||
|  |     //     link: NewLink,
 | ||||||
|  |     //     yaml: NewYaml,
 | ||||||
|  |     //   });
 | ||||||
|  |     // }
 | ||||||
|  |     localforage.setItem('editSchedule', true); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // UseEffect to update the cron syntax with changes
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     const cronSyntax = `${cronValue.minute} ${cronValue.hour} ${cronValue.day_month} ${cronValue.month} ${cronValue.day_week}`; | ||||||
|  |     if (value === 'now') | ||||||
|  |       workflowAction.setWorkflowDetails({ | ||||||
|  |         cronSyntax: '', | ||||||
|  |       }); | ||||||
|  |     else | ||||||
|  |       workflowAction.setWorkflowDetails({ | ||||||
|  |         cronSyntax, | ||||||
|  |       }); | ||||||
|  |   }, [cronValue]); | ||||||
|  | 
 | ||||||
|  |   const classes = useStyles(); | ||||||
|  |   const { t } = useTranslation(); | ||||||
|  | 
 | ||||||
|  |   // Sets individual minutes
 | ||||||
|  |   const [minute, setMinute] = React.useState( | ||||||
|  |     workflowData.scheduleInput.hour_interval | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   // Sets Weekdays
 | ||||||
|  |   const [days, setDays] = React.useState(workflowData.scheduleInput.weekday); | ||||||
|  | 
 | ||||||
|  |   // Sets Day in number
 | ||||||
|  |   const [dates, setDates] = React.useState(workflowData.scheduleInput.day); | ||||||
|  | 
 | ||||||
|  |   // Sets Time
 | ||||||
|  |   const [selectedTime, setSelectedTime] = React.useState<Date | null>( | ||||||
|  |     new Date(workflowData.scheduleInput.time) | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   // Sets Date
 | ||||||
|  |   const [selectedDate, setSelectedDate] = React.useState<Date | null>( | ||||||
|  |     new Date(workflowData.scheduleInput.date) | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   // Function to validate the date and time for "Specific Time" radio button
 | ||||||
|  |   const validateTime = (time: Date | null, date: Date | null) => { | ||||||
|  |     if ( | ||||||
|  |       value === 'specificTime' && | ||||||
|  |       (time?.setSeconds(0) as number) <= new Date().setSeconds(0) && | ||||||
|  |       (date?.getTime() as number) <= new Date().getTime() | ||||||
|  |     ) { | ||||||
|  |       const newTime = new Date(); | ||||||
|  |       newTime.setMinutes(newTime.getMinutes() + 5); | ||||||
|  |       setSelectedTime(newTime); | ||||||
|  |       workflowAction.setWorkflowDetails({ | ||||||
|  |         scheduleInput: { | ||||||
|  |           ...workflowData.scheduleInput, | ||||||
|  |           date, | ||||||
|  |           time: newTime, | ||||||
|  |         }, | ||||||
|  |       }); | ||||||
|  |       setCronValue({ | ||||||
|  |         ...cronValue, | ||||||
|  |         minute: newTime.getMinutes().toString(), | ||||||
|  |         hour: newTime.getHours().toString(), | ||||||
|  |         day_month: date?.getDate().toString(), | ||||||
|  |         month: (date && date.getMonth() + 1)?.toString(), | ||||||
|  |       }); | ||||||
|  |     } else { | ||||||
|  |       workflowAction.setWorkflowDetails({ | ||||||
|  |         scheduleInput: { | ||||||
|  |           ...workflowData.scheduleInput, | ||||||
|  |           date, | ||||||
|  |           time, | ||||||
|  |         }, | ||||||
|  |       }); | ||||||
|  |       setCronValue({ | ||||||
|  |         ...cronValue, | ||||||
|  |         minute: time?.getMinutes().toString(), | ||||||
|  |         hour: time?.getHours().toString(), | ||||||
|  |         day_month: date?.getDate().toString(), | ||||||
|  |         month: (date && date.getMonth() + 1)?.toString(), | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const handleTimeChange = (time: Date | null) => { | ||||||
|  |     setSelectedTime(time); | ||||||
|  |     validateTime(time, selectedDate); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const handleDateChange = (date: Date | null) => { | ||||||
|  |     setSelectedDate(date); | ||||||
|  |     validateTime(selectedTime, date); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   // Function for recurring date change
 | ||||||
|  |   const reccuringDateChange = (date: Date | null) => { | ||||||
|  |     setSelectedTime(date); | ||||||
|  |     setCronValue({ | ||||||
|  |       ...cronValue, | ||||||
|  |       minute: date?.getMinutes().toString(), | ||||||
|  |       hour: date?.getHours().toString(), | ||||||
|  |     }); | ||||||
|  |     workflowAction.setWorkflowDetails({ | ||||||
|  |       scheduleInput: { | ||||||
|  |         ...workflowData.scheduleInput, | ||||||
|  |         time: date, | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   // Stores dates in an array
 | ||||||
|  |   const names: number[] = [1]; | ||||||
|  |   for (let i = 1; i <= 30; i += 1) { | ||||||
|  |     names[i] = i + 1; | ||||||
|  |   } | ||||||
|  |   const mins: number[] = [0]; | ||||||
|  |   for (let i = 0; i <= 59; i += 1) { | ||||||
|  |     mins[i] = i; | ||||||
|  |   } | ||||||
|  |   // Day names
 | ||||||
|  |   const weekdays: string[] = [ | ||||||
|  |     'Monday', | ||||||
|  |     'Tuesday', | ||||||
|  |     'Wednesday', | ||||||
|  |     'Thursday', | ||||||
|  |     'Friday', | ||||||
|  |     'Saturday', | ||||||
|  |     'Sunday', | ||||||
|  |   ]; | ||||||
|  | 
 | ||||||
|  |   // UseEffect to update the values of CronSyntax on radio button change
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     if (value === 'now') { | ||||||
|  |       setValueDef(''); | ||||||
|  |       setCronValue({ | ||||||
|  |         minute: '', | ||||||
|  |         hour: '', | ||||||
|  |         day_month: '', | ||||||
|  |         month: '', | ||||||
|  |         day_week: '', | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     if (value === 'specificTime') { | ||||||
|  |       setValueDef(''); | ||||||
|  |       setCronValue({ | ||||||
|  |         minute: selectedTime?.getMinutes().toString(), | ||||||
|  |         hour: selectedTime?.getHours().toString(), | ||||||
|  |         day_month: selectedDate?.getDate().toString(), | ||||||
|  |         month: (selectedDate && selectedDate.getMonth() + 1)?.toString(), | ||||||
|  |         day_week: '*', | ||||||
|  |       }); | ||||||
|  |       if (workflowData.scheduleInput.time <= new Date()) { | ||||||
|  |         const newTime = new Date(); | ||||||
|  |         newTime.setMinutes(newTime.getMinutes() + 5); | ||||||
|  |         setSelectedTime(newTime); | ||||||
|  |         setCronValue({ | ||||||
|  |           minute: newTime.getMinutes().toString(), | ||||||
|  |           hour: newTime.getHours().toString(), | ||||||
|  |           day_month: selectedDate?.getDate().toString(), | ||||||
|  |           month: (selectedDate && selectedDate.getMonth() + 1)?.toString(), | ||||||
|  |           day_week: '*', | ||||||
|  |         }); | ||||||
|  |         workflowAction.setWorkflowDetails({ | ||||||
|  |           scheduleInput: { | ||||||
|  |             ...workflowData.scheduleInput, | ||||||
|  |             time: newTime, | ||||||
|  |           }, | ||||||
|  |         }); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     if (valueDef === constants.recurringEveryHour) { | ||||||
|  |       setCronValue({ | ||||||
|  |         minute: minute.toString(), | ||||||
|  |         hour: '0-23', | ||||||
|  |         day_month: '*', | ||||||
|  |         month: '*', | ||||||
|  |         day_week: '*', | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     if (valueDef === constants.recurringEveryDay) { | ||||||
|  |       setCronValue({ | ||||||
|  |         minute: selectedTime?.getMinutes().toString(), | ||||||
|  |         hour: selectedTime?.getHours().toString(), | ||||||
|  |         day_month: '*', | ||||||
|  |         month: '*', | ||||||
|  |         day_week: '0-6', | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     if (valueDef === constants.recurringEveryWeek) { | ||||||
|  |       setCronValue({ | ||||||
|  |         minute: selectedTime?.getMinutes().toString(), | ||||||
|  |         hour: selectedTime?.getHours().toString(), | ||||||
|  |         day_month: '*', | ||||||
|  |         month: '*', | ||||||
|  |         day_week: days.slice(0, 3), | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     if (valueDef === constants.recurringEveryMonth) { | ||||||
|  |       setCronValue({ | ||||||
|  |         minute: selectedTime?.getMinutes().toString(), | ||||||
|  |         hour: selectedTime?.getHours().toString(), | ||||||
|  |         day_month: dates.toString(), | ||||||
|  |         month: '*', | ||||||
|  |         day_week: '*', | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     if (value === 'recurringSchedule' && valueDef === '') { | ||||||
|  |       template.selectTemplate({ isDisable: true }); | ||||||
|  |     } else { | ||||||
|  |       template.selectTemplate({ isDisable: false }); | ||||||
|  |     } | ||||||
|  |     workflowAction.setWorkflowDetails({ | ||||||
|  |       scheduleType: { | ||||||
|  |         scheduleOnce: value, | ||||||
|  |         recurringSchedule: valueDef, | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  |   }, [valueDef, value]); | ||||||
|  | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     EditYaml(); | ||||||
|  |   }, [cronValue]); | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <Scaffold> | ||||||
|  |       <BackButton /> | ||||||
|  |       <Typography className={classes.title}> | ||||||
|  |         {t('editSchedule.title')} | ||||||
|  |       </Typography> | ||||||
|  |       <div className={classes.root}> | ||||||
|  |         <div className={classes.innerContainer}> | ||||||
|  |           <br /> | ||||||
|  |           {/* Upper segment */} | ||||||
|  |           <div className={classes.scSegments}> | ||||||
|  |             <div> | ||||||
|  |               <Typography className={classes.headerText}> | ||||||
|  |                 <strong>{t('createWorkflow.scheduleWorkflow.header')}</strong> | ||||||
|  |               </Typography> | ||||||
|  | 
 | ||||||
|  |               <div className={classes.schBody}> | ||||||
|  |                 <Typography align="left" className={classes.description}> | ||||||
|  |                   {t('createWorkflow.scheduleWorkflow.info')} | ||||||
|  |                 </Typography> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |             <img | ||||||
|  |               src="/icons/calendarWorkflowIcon.svg" | ||||||
|  |               alt="calendar" | ||||||
|  |               className={classes.calIcon} | ||||||
|  |             /> | ||||||
|  |           </div> | ||||||
|  |           <Divider /> | ||||||
|  | 
 | ||||||
|  |           {/* Lower segment */} | ||||||
|  |           <div className={classes.scFormControl}> | ||||||
|  |             <FormControl component="fieldset" className={classes.formControl}> | ||||||
|  |               <RadioGroup | ||||||
|  |                 data-cy="ScheduleOptions" | ||||||
|  |                 aria-label="schedule" | ||||||
|  |                 name="schedule" | ||||||
|  |                 value={value} | ||||||
|  |                 onChange={handleChange} | ||||||
|  |               > | ||||||
|  |                 {/* options to choose schedule */} | ||||||
|  |                 <FormControlLabel | ||||||
|  |                   value="now" | ||||||
|  |                   control={ | ||||||
|  |                     <Radio | ||||||
|  |                       classes={{ | ||||||
|  |                         root: classes.radio, | ||||||
|  |                         checked: classes.checked, | ||||||
|  |                       }} | ||||||
|  |                     /> | ||||||
|  |                   } | ||||||
|  |                   label={ | ||||||
|  |                     <Typography className={classes.radioText}> | ||||||
|  |                       {t('createWorkflow.scheduleWorkflow.radio.now')} | ||||||
|  |                     </Typography> | ||||||
|  |                   } | ||||||
|  |                 /> | ||||||
|  |                 {value === 'specificTime' && ( | ||||||
|  |                   <div className={classes.schLater}> | ||||||
|  |                     <Typography className={classes.captionText}> | ||||||
|  |                       {t('createWorkflow.scheduleWorkflow.radio.future')} | ||||||
|  |                     </Typography> | ||||||
|  |                     <div className={classes.innerSpecific}> | ||||||
|  |                       <CustomDate | ||||||
|  |                         selectedDate={selectedDate} | ||||||
|  |                         handleDateChange={(event) => { | ||||||
|  |                           handleDateChange(event); | ||||||
|  |                         }} | ||||||
|  |                         disabled={false} | ||||||
|  |                       /> | ||||||
|  |                       <CustomTime | ||||||
|  |                         handleDateChange={(event) => { | ||||||
|  |                           handleTimeChange(event); | ||||||
|  |                         }} | ||||||
|  |                         value={selectedTime} | ||||||
|  |                         ampm | ||||||
|  |                         disabled={false} | ||||||
|  |                       /> | ||||||
|  |                     </div> | ||||||
|  |                   </div> | ||||||
|  |                 )} | ||||||
|  |                 <FormControlLabel | ||||||
|  |                   value="recurringSchedule" | ||||||
|  |                   control={ | ||||||
|  |                     <Radio | ||||||
|  |                       classes={{ | ||||||
|  |                         root: classes.radio, | ||||||
|  |                         checked: classes.checked, | ||||||
|  |                       }} | ||||||
|  |                     /> | ||||||
|  |                   } | ||||||
|  |                   label={ | ||||||
|  |                     <Typography className={classes.radioText}> | ||||||
|  |                       {t('createWorkflow.scheduleWorkflow.radio.recurr')} | ||||||
|  |                     </Typography> | ||||||
|  |                   } | ||||||
|  |                 /> | ||||||
|  |                 {value === 'recurringSchedule' && ( | ||||||
|  |                   <div className={classes.schLater}> | ||||||
|  |                     <Typography className={classes.captionText}> | ||||||
|  |                       {t('createWorkflow.scheduleWorkflow.radio.rightRecurr')} | ||||||
|  |                     </Typography> | ||||||
|  | 
 | ||||||
|  |                     {/* options to select time of recurring schedule */} | ||||||
|  |                     <div className={classes.innerRecurring}> | ||||||
|  |                       <FormControl component="fieldset"> | ||||||
|  |                         <RadioGroup | ||||||
|  |                           aria-label="instanceDef" | ||||||
|  |                           name="instanceDef" | ||||||
|  |                           value={valueDef} | ||||||
|  |                           onChange={(event) => { | ||||||
|  |                             handleChangeInstance(event); | ||||||
|  |                           }} | ||||||
|  |                         > | ||||||
|  |                           <FormControlLabel | ||||||
|  |                             value={constants.recurringEveryHour} | ||||||
|  |                             control={ | ||||||
|  |                               <Radio | ||||||
|  |                                 classes={{ | ||||||
|  |                                   root: classes.radio, | ||||||
|  |                                   checked: classes.checked, | ||||||
|  |                                 }} | ||||||
|  |                               /> | ||||||
|  |                             } | ||||||
|  |                             label={t( | ||||||
|  |                               'createWorkflow.scheduleWorkflow.every.hr' | ||||||
|  |                             )} | ||||||
|  |                           /> | ||||||
|  |                           {valueDef === constants.recurringEveryHour && ( | ||||||
|  |                             <div> | ||||||
|  |                               <div className={classes.scRandom}> | ||||||
|  |                                 <Typography className={classes.scRandsub1}> | ||||||
|  |                                   {t('createWorkflow.scheduleWorkflow.at')} | ||||||
|  |                                 </Typography> | ||||||
|  |                                 <SetTime | ||||||
|  |                                   data={mins} | ||||||
|  |                                   handleChange={(event) => { | ||||||
|  |                                     setMinute(event.target.value as number); | ||||||
|  |                                     setCronValue({ | ||||||
|  |                                       ...cronValue, | ||||||
|  |                                       minute: (event.target | ||||||
|  |                                         .value as number).toString(), | ||||||
|  |                                       hour: '0-23', | ||||||
|  |                                     }); | ||||||
|  |                                     workflowAction.setWorkflowDetails({ | ||||||
|  |                                       scheduleInput: { | ||||||
|  |                                         ...workflowData.scheduleInput, | ||||||
|  |                                         hour_interval: event.target | ||||||
|  |                                           .value as number, | ||||||
|  |                                       }, | ||||||
|  |                                     }); | ||||||
|  |                                   }} | ||||||
|  |                                   value={minute} | ||||||
|  |                                 /> | ||||||
|  |                                 {minute === 0 || minute === 1 ? ( | ||||||
|  |                                   <Typography> | ||||||
|  |                                     {t('createWorkflow.scheduleWorkflow.min')} | ||||||
|  |                                   </Typography> | ||||||
|  |                                 ) : ( | ||||||
|  |                                   <Typography> | ||||||
|  |                                     {t('createWorkflow.scheduleWorkflow.mins')} | ||||||
|  |                                   </Typography> | ||||||
|  |                                 )} | ||||||
|  |                               </div> | ||||||
|  |                             </div> | ||||||
|  |                           )} | ||||||
|  |                           <FormControlLabel | ||||||
|  |                             value={constants.recurringEveryDay} | ||||||
|  |                             control={ | ||||||
|  |                               <Radio | ||||||
|  |                                 classes={{ | ||||||
|  |                                   root: classes.radio, | ||||||
|  |                                   checked: classes.checked, | ||||||
|  |                                 }} | ||||||
|  |                               /> | ||||||
|  |                             } | ||||||
|  |                             label={t( | ||||||
|  |                               'createWorkflow.scheduleWorkflow.every.day' | ||||||
|  |                             )} | ||||||
|  |                           /> | ||||||
|  |                           {valueDef === constants.recurringEveryDay && ( | ||||||
|  |                             <div> | ||||||
|  |                               <div className={classes.scRandom}> | ||||||
|  |                                 <Typography className={classes.scRandsub1}> | ||||||
|  |                                   {t('createWorkflow.scheduleWorkflow.at')} | ||||||
|  |                                 </Typography> | ||||||
|  |                                 <CustomTime | ||||||
|  |                                   handleDateChange={(date: Date | null) => { | ||||||
|  |                                     setSelectedTime(date); | ||||||
|  |                                     setCronValue({ | ||||||
|  |                                       ...cronValue, | ||||||
|  |                                       minute: date?.getMinutes().toString(), | ||||||
|  |                                       hour: date?.getHours().toString(), | ||||||
|  |                                       day_week: '0-6', | ||||||
|  |                                     }); | ||||||
|  |                                     workflowAction.setWorkflowDetails({ | ||||||
|  |                                       scheduleInput: { | ||||||
|  |                                         ...workflowData.scheduleInput, | ||||||
|  |                                         time: date, | ||||||
|  |                                       }, | ||||||
|  |                                     }); | ||||||
|  |                                   }} | ||||||
|  |                                   value={selectedTime} | ||||||
|  |                                   ampm | ||||||
|  |                                   disabled={false} | ||||||
|  |                                 /> | ||||||
|  |                               </div> | ||||||
|  |                             </div> | ||||||
|  |                           )} | ||||||
|  |                           <FormControlLabel | ||||||
|  |                             value={constants.recurringEveryWeek} | ||||||
|  |                             control={ | ||||||
|  |                               <Radio | ||||||
|  |                                 classes={{ | ||||||
|  |                                   root: classes.radio, | ||||||
|  |                                   checked: classes.checked, | ||||||
|  |                                 }} | ||||||
|  |                               /> | ||||||
|  |                             } | ||||||
|  |                             label={t( | ||||||
|  |                               'createWorkflow.scheduleWorkflow.every.week' | ||||||
|  |                             )} | ||||||
|  |                           /> | ||||||
|  |                           {valueDef === constants.recurringEveryWeek && ( | ||||||
|  |                             <div> | ||||||
|  |                               <div className={classes.scRandom}> | ||||||
|  |                                 <Typography className={classes.scRandsub1}> | ||||||
|  |                                   {t('createWorkflow.scheduleWorkflow.on')} | ||||||
|  |                                 </Typography> | ||||||
|  |                                 <FormControl className={classes.formControlDT}> | ||||||
|  |                                   <Select | ||||||
|  |                                     className={classes.select} | ||||||
|  |                                     disableUnderline | ||||||
|  |                                     value={days} | ||||||
|  |                                     onChange={(e) => { | ||||||
|  |                                       setCronValue({ | ||||||
|  |                                         ...cronValue, | ||||||
|  |                                         month: '*', | ||||||
|  |                                         day_week: ((e.target | ||||||
|  |                                           .value as unknown) as string).slice( | ||||||
|  |                                           0, | ||||||
|  |                                           3 | ||||||
|  |                                         ), | ||||||
|  |                                       }); | ||||||
|  |                                       setDays( | ||||||
|  |                                         (e.target.value as unknown) as string | ||||||
|  |                                       ); | ||||||
|  |                                       workflowAction.setWorkflowDetails({ | ||||||
|  |                                         scheduleInput: { | ||||||
|  |                                           ...workflowData.scheduleInput, | ||||||
|  |                                           weekday: (e.target | ||||||
|  |                                             .value as unknown) as string, | ||||||
|  |                                         }, | ||||||
|  |                                       }); | ||||||
|  |                                     }} | ||||||
|  |                                     label="days" | ||||||
|  |                                     inputProps={{ | ||||||
|  |                                       name: 'days', | ||||||
|  |                                       style: { | ||||||
|  |                                         fontSize: '0.75rem', | ||||||
|  |                                         height: '0.43rem', | ||||||
|  |                                       }, | ||||||
|  |                                     }} | ||||||
|  |                                   > | ||||||
|  |                                     {weekdays.map((day) => ( | ||||||
|  |                                       <option | ||||||
|  |                                         key={day} | ||||||
|  |                                         className={classes.opt} | ||||||
|  |                                         value={day} | ||||||
|  |                                       > | ||||||
|  |                                         {day} | ||||||
|  |                                       </option> | ||||||
|  |                                     ))} | ||||||
|  |                                   </Select> | ||||||
|  |                                 </FormControl> | ||||||
|  |                                 <Typography className={classes.scRandsub1}> | ||||||
|  |                                   {t('createWorkflow.scheduleWorkflow.at')} | ||||||
|  |                                 </Typography> | ||||||
|  |                                 <CustomTime | ||||||
|  |                                   handleDateChange={(date: Date | null) => { | ||||||
|  |                                     reccuringDateChange(date); | ||||||
|  |                                   }} | ||||||
|  |                                   value={selectedTime} | ||||||
|  |                                   ampm | ||||||
|  |                                   disabled={false} | ||||||
|  |                                 /> | ||||||
|  |                               </div> | ||||||
|  |                             </div> | ||||||
|  |                           )} | ||||||
|  |                           <FormControlLabel | ||||||
|  |                             value={constants.recurringEveryMonth} | ||||||
|  |                             control={ | ||||||
|  |                               <Radio | ||||||
|  |                                 classes={{ | ||||||
|  |                                   root: classes.radio, | ||||||
|  |                                   checked: classes.checked, | ||||||
|  |                                 }} | ||||||
|  |                               /> | ||||||
|  |                             } | ||||||
|  |                             label={t( | ||||||
|  |                               'createWorkflow.scheduleWorkflow.every.month' | ||||||
|  |                             )} | ||||||
|  |                           /> | ||||||
|  |                           {valueDef === constants.recurringEveryMonth && ( | ||||||
|  |                             <div> | ||||||
|  |                               <div className={classes.scRandom}> | ||||||
|  |                                 <Typography className={classes.scRandsub1}> | ||||||
|  |                                   {t('createWorkflow.scheduleWorkflow.on')} | ||||||
|  |                                 </Typography> | ||||||
|  |                                 <SetTime | ||||||
|  |                                   data={names} | ||||||
|  |                                   handleChange={(event) => { | ||||||
|  |                                     setCronValue({ | ||||||
|  |                                       ...cronValue, | ||||||
|  |                                       day_month: (event.target | ||||||
|  |                                         .value as number).toString(), | ||||||
|  |                                     }); | ||||||
|  |                                     setDates(event.target.value as number); | ||||||
|  |                                     workflowAction.setWorkflowDetails({ | ||||||
|  |                                       scheduleInput: { | ||||||
|  |                                         ...workflowData.scheduleInput, | ||||||
|  |                                         day: event.target.value as number, | ||||||
|  |                                       }, | ||||||
|  |                                     }); | ||||||
|  |                                   }} | ||||||
|  |                                   value={dates} | ||||||
|  |                                 /> | ||||||
|  |                                 <Typography className={classes.scRandsub1}> | ||||||
|  |                                   {t('createWorkflow.scheduleWorkflow.at')} | ||||||
|  |                                 </Typography> | ||||||
|  |                                 <CustomTime | ||||||
|  |                                   handleDateChange={(date: Date | null) => { | ||||||
|  |                                     reccuringDateChange(date); | ||||||
|  |                                   }} | ||||||
|  |                                   value={selectedTime} | ||||||
|  |                                   ampm | ||||||
|  |                                   disabled={false} | ||||||
|  |                                 /> | ||||||
|  |                               </div> | ||||||
|  |                             </div> | ||||||
|  |                           )} | ||||||
|  |                         </RadioGroup> | ||||||
|  |                       </FormControl> | ||||||
|  |                     </div> | ||||||
|  |                   </div> | ||||||
|  |                 )} | ||||||
|  |               </RadioGroup> | ||||||
|  |             </FormControl> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |       {/* Cancel and Save Button */} | ||||||
|  |       <div className={classes.buttonDiv} aria-label="buttons"> | ||||||
|  |         <ButtonOutlined | ||||||
|  |           onClick={() => { | ||||||
|  |             history.push({ | ||||||
|  |               pathname: `/workflows/`, | ||||||
|  |               search: `?projectID=${getProjectID()}&projectRole=${getProjectRole()}`, | ||||||
|  |             }); | ||||||
|  |           }} | ||||||
|  |         > | ||||||
|  |           Cancel | ||||||
|  |         </ButtonOutlined> | ||||||
|  |         <ButtonFilled | ||||||
|  |           onClick={() => | ||||||
|  |             history.push({ | ||||||
|  |               pathname: `/workflows/schedule/${getProjectID()}/${fetchWorkflowNameFromManifest( | ||||||
|  |                 manifest | ||||||
|  |               )}`,
 | ||||||
|  |               search: `?projectID=${getProjectID()}&projectRole=${getProjectRole()}`, | ||||||
|  |             }) | ||||||
|  |           } | ||||||
|  |         > | ||||||
|  |           {t('editSchedule.verify')} | ||||||
|  |         </ButtonFilled> | ||||||
|  |       </div> | ||||||
|  |     </Scaffold> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export default ScheduleWorkflow; | ||||||
|  | @ -0,0 +1,504 @@ | ||||||
|  | import { useMutation, useQuery } from '@apollo/client'; | ||||||
|  | import Typography from '@material-ui/core/Typography'; | ||||||
|  | import EditIcon from '@material-ui/icons/Edit'; | ||||||
|  | import cronstrue from 'cronstrue'; | ||||||
|  | import { ButtonFilled, ButtonOutlined, Modal } from 'litmus-ui'; | ||||||
|  | import localforage from 'localforage'; | ||||||
|  | import React, { useEffect, useState } from 'react'; | ||||||
|  | import { useTranslation } from 'react-i18next'; | ||||||
|  | import { useSelector } from 'react-redux'; | ||||||
|  | import { useParams } from 'react-router-dom'; | ||||||
|  | import YAML from 'yaml'; | ||||||
|  | import AdjustedWeights from '../../components/AdjustedWeights'; | ||||||
|  | import BackButton from '../../components/Button/BackButton'; | ||||||
|  | import Loader from '../../components/Loader'; | ||||||
|  | import YamlEditor from '../../components/YamlEditor/Editor'; | ||||||
|  | import { parseYamlValidations } from '../../components/YamlEditor/Validations'; | ||||||
|  | import Scaffold from '../../containers/layouts/Scaffold'; | ||||||
|  | import { UPDATE_SCHEDULE } from '../../graphql/mutations'; | ||||||
|  | import { SCHEDULE_DETAILS } from '../../graphql/queries'; | ||||||
|  | import { | ||||||
|  |   CreateWorkFlowInput, | ||||||
|  |   UpdateWorkflowResponse, | ||||||
|  |   WeightMap, | ||||||
|  | } from '../../models/graphql/createWorkflowData'; | ||||||
|  | import { ScheduleDataVars, Schedules } from '../../models/graphql/scheduleData'; | ||||||
|  | import { experimentMap, WorkflowData } from '../../models/redux/workflow'; | ||||||
|  | import useActions from '../../redux/actions'; | ||||||
|  | import * as TabActions from '../../redux/actions/tabs'; | ||||||
|  | import * as TemplateSelectionActions from '../../redux/actions/template'; | ||||||
|  | import * as WorkflowActions from '../../redux/actions/workflow'; | ||||||
|  | import { history } from '../../redux/configureStore'; | ||||||
|  | import { RootState } from '../../redux/reducers'; | ||||||
|  | import { getProjectID, getProjectRole } from '../../utils/getSearchParams'; | ||||||
|  | import { fetchWorkflowNameFromManifest } from '../../utils/yamlUtils'; | ||||||
|  | import useStyles from './styles'; | ||||||
|  | 
 | ||||||
|  | interface URLParams { | ||||||
|  |   workflowName: string; | ||||||
|  |   scheduleProjectID: string; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | interface Weights { | ||||||
|  |   experimentName: string; | ||||||
|  |   weight: number; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | interface WorkflowProps { | ||||||
|  |   name: string; | ||||||
|  |   description: string; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const EditSchedule: React.FC = () => { | ||||||
|  |   const classes = useStyles(); | ||||||
|  |   const { t } = useTranslation(); | ||||||
|  | 
 | ||||||
|  |   const [workflow, setWorkflow] = useState<WorkflowProps>({ | ||||||
|  |     name: '', | ||||||
|  |     description: '', | ||||||
|  |   }); | ||||||
|  |   const [weights, setWeights] = useState<experimentMap[]>([ | ||||||
|  |     { | ||||||
|  |       experimentName: '', | ||||||
|  |       weight: 0, | ||||||
|  |     }, | ||||||
|  |   ]); | ||||||
|  | 
 | ||||||
|  |   const [open, setOpen] = React.useState(false); | ||||||
|  |   const [finishModalOpen, setFinishModalOpen] = useState(false); | ||||||
|  |   const [errorModal, setErrorModal] = useState(false); | ||||||
|  | 
 | ||||||
|  |   const template = useActions(TemplateSelectionActions); | ||||||
|  |   const workflowData: WorkflowData = useSelector( | ||||||
|  |     (state: RootState) => state.workflowData | ||||||
|  |   ); | ||||||
|  |   const workflowAction = useActions(WorkflowActions); | ||||||
|  |   // Get Parameters from URL
 | ||||||
|  |   const paramData: URLParams = useParams(); | ||||||
|  |   const projectID = getProjectID(); | ||||||
|  |   const userRole = getProjectRole(); | ||||||
|  | 
 | ||||||
|  |   // Apollo query to get the scheduled data
 | ||||||
|  |   const { data, loading } = useQuery<Schedules, ScheduleDataVars>( | ||||||
|  |     SCHEDULE_DETAILS, | ||||||
|  |     { | ||||||
|  |       variables: { projectID: paramData.scheduleProjectID }, | ||||||
|  |       fetchPolicy: 'cache-and-network', | ||||||
|  |     } | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   const manifest = useSelector( | ||||||
|  |     (state: RootState) => state.workflowManifest.manifest | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   const wfDetails = | ||||||
|  |     data && | ||||||
|  |     data.getScheduledWorkflows.filter( | ||||||
|  |       (wf) => wf.workflow_name === paramData.workflowName | ||||||
|  |     )[0]; | ||||||
|  |   const doc = new YAML.Document(); | ||||||
|  |   const w: Weights[] = []; | ||||||
|  |   const { cronSyntax, clusterid, clustername } = workflowData; | ||||||
|  | 
 | ||||||
|  |   const [createChaosWorkFlow, { error: workflowError }] = useMutation< | ||||||
|  |     UpdateWorkflowResponse, | ||||||
|  |     CreateWorkFlowInput | ||||||
|  |   >(UPDATE_SCHEDULE, { | ||||||
|  |     onCompleted: () => { | ||||||
|  |       setFinishModalOpen(true); | ||||||
|  |     }, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   const handleMutation = () => { | ||||||
|  |     if ( | ||||||
|  |       workflow.name.length !== 0 && | ||||||
|  |       workflow.description.length !== 0 && | ||||||
|  |       weights.length !== 0 | ||||||
|  |     ) { | ||||||
|  |       const weightData: WeightMap[] = []; | ||||||
|  | 
 | ||||||
|  |       weights.forEach((data) => { | ||||||
|  |         weightData.push({ | ||||||
|  |           experiment_name: data.experimentName, | ||||||
|  |           weightage: data.weight, | ||||||
|  |         }); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       /* JSON.stringify takes 3 parameters [object to be converted, | ||||||
|  |       a function to alter the conversion, spaces to be shown in final result for indentation ] */ | ||||||
|  |       const yml = YAML.parse(manifest); | ||||||
|  |       const yamlJson = JSON.stringify(yml, null, 2); // Converted to Stringified JSON
 | ||||||
|  | 
 | ||||||
|  |       const chaosWorkFlowInputs = { | ||||||
|  |         workflow_id: wfDetails?.workflow_id, | ||||||
|  |         workflow_manifest: yamlJson, | ||||||
|  |         cronSyntax, | ||||||
|  |         workflow_name: fetchWorkflowNameFromManifest(manifest), | ||||||
|  |         workflow_description: workflow.description, | ||||||
|  |         isCustomWorkflow: false, | ||||||
|  |         weightages: weightData, | ||||||
|  |         project_id: projectID, | ||||||
|  |         cluster_id: clusterid, | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       createChaosWorkFlow({ | ||||||
|  |         variables: { ChaosWorkFlowInput: chaosWorkFlowInputs }, | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     localforage.getItem('editSchedule').then((isCronEdited) => { | ||||||
|  |       if (wfDetails !== undefined) { | ||||||
|  |         for (let i = 0; i < wfDetails?.weightages.length; i++) { | ||||||
|  |           w.push({ | ||||||
|  |             experimentName: wfDetails?.weightages[i].experiment_name, | ||||||
|  |             weight: wfDetails?.weightages[i].weightage, | ||||||
|  |           }); | ||||||
|  |         } | ||||||
|  |         doc.contents = JSON.parse(wfDetails?.workflow_manifest); | ||||||
|  |         workflowAction.setWorkflowManifest({ | ||||||
|  |           manifest: isCronEdited === null ? doc.toString() : manifest, | ||||||
|  |         }); | ||||||
|  |         setWorkflow({ | ||||||
|  |           name: wfDetails?.workflow_name, | ||||||
|  |           description: wfDetails?.workflow_description, | ||||||
|  |         }); | ||||||
|  |         localforage.setItem('weights', w); | ||||||
|  |         workflowAction.setWorkflowDetails({ | ||||||
|  |           workflow_id: wfDetails?.workflow_id, | ||||||
|  |           clusterid: wfDetails?.cluster_id, | ||||||
|  |           cronSyntax: | ||||||
|  |             isCronEdited === null ? wfDetails?.cronSyntax : cronSyntax, | ||||||
|  |           scheduleType: { | ||||||
|  |             scheduleOnce: | ||||||
|  |               wfDetails?.cronSyntax === '' ? 'now' : 'recurringSchedule', | ||||||
|  |             recurringSchedule: '', | ||||||
|  |           }, | ||||||
|  |           scheduleInput: { | ||||||
|  |             hour_interval: 0, | ||||||
|  |             day: 1, | ||||||
|  |             weekday: 'Monday', | ||||||
|  |             time: new Date(), | ||||||
|  |             date: new Date(), | ||||||
|  |           }, | ||||||
|  |         }); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     template.selectTemplate({ selectTemplateID: 0, isDisable: false }); | ||||||
|  |     setWeights(w); | ||||||
|  |   }, [data]); | ||||||
|  | 
 | ||||||
|  |   const tabs = useActions(TabActions); | ||||||
|  | 
 | ||||||
|  |   const [yamlStatus, setYamlStatus] = React.useState( | ||||||
|  |     `${t('createWorkflow.verifyCommit.codeIsFine')}` | ||||||
|  |   ); | ||||||
|  |   const [modified, setModified] = React.useState(false); | ||||||
|  | 
 | ||||||
|  |   const handleEditOpen = () => { | ||||||
|  |     setModified(false); | ||||||
|  |     setOpen(true); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const handleEditClose = () => { | ||||||
|  |     setModified(true); | ||||||
|  |     setOpen(false); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const handleNext = () => { | ||||||
|  |     handleMutation(); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     const editorValidations = parseYamlValidations(manifest, classes); | ||||||
|  |     const stateObject = { | ||||||
|  |       markers: editorValidations.markers, | ||||||
|  |       annotations: editorValidations.annotations, | ||||||
|  |     }; | ||||||
|  |     if (stateObject.annotations.length > 0) { | ||||||
|  |       setYamlStatus(`${t('createWorkflow.verifyCommit.errYaml')}`); | ||||||
|  |     } else { | ||||||
|  |       setYamlStatus(`${t('createWorkflow.verifyCommit.codeIsFine')}`); | ||||||
|  |     } | ||||||
|  |   }, [modified]); | ||||||
|  | 
 | ||||||
|  |   const handleFinishModal = () => { | ||||||
|  |     history.push({ | ||||||
|  |       pathname: `/workflows`, | ||||||
|  |       search: `?projectID=${projectID}&projectRole=${userRole}`, | ||||||
|  |     }); | ||||||
|  |     setFinishModalOpen(false); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const handleErrorModalClose = () => { | ||||||
|  |     setErrorModal(false); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <Scaffold> | ||||||
|  |       {loading ? ( | ||||||
|  |         <Loader /> | ||||||
|  |       ) : ( | ||||||
|  |         <> | ||||||
|  |           <BackButton /> | ||||||
|  |           <Typography className={classes.title}> | ||||||
|  |             {t('editSchedule.title')} | ||||||
|  |           </Typography> | ||||||
|  |           <div className={classes.root}> | ||||||
|  |             <div className={classes.innerContainer}> | ||||||
|  |               <Typography className={classes.sumText}> | ||||||
|  |                 {t('createWorkflow.verifyCommit.summary.header')} | ||||||
|  |               </Typography> | ||||||
|  | 
 | ||||||
|  |               <div className={classes.outerSum}> | ||||||
|  |                 <div className={classes.summaryDiv}> | ||||||
|  |                   <div className={classes.innerSumDiv}> | ||||||
|  |                     <Typography className={classes.col1}> | ||||||
|  |                       {t('createWorkflow.verifyCommit.summary.workflowName')}: | ||||||
|  |                     </Typography> | ||||||
|  |                   </div> | ||||||
|  |                   <div className={classes.col2} data-cy="WorkflowName"> | ||||||
|  |                     <Typography> | ||||||
|  |                       {fetchWorkflowNameFromManifest(manifest)} | ||||||
|  |                     </Typography> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  | 
 | ||||||
|  |                 <div className={classes.summaryDiv}> | ||||||
|  |                   <div className={classes.innerSumDiv}> | ||||||
|  |                     <Typography className={classes.col1}> | ||||||
|  |                       {t('createWorkflow.verifyCommit.summary.clustername')}: | ||||||
|  |                     </Typography> | ||||||
|  |                   </div> | ||||||
|  |                   <Typography className={classes.schCol2}> | ||||||
|  |                     {clustername} | ||||||
|  |                   </Typography> | ||||||
|  |                 </div> | ||||||
|  | 
 | ||||||
|  |                 <div className={classes.summaryDiv}> | ||||||
|  |                   <div className={classes.innerSumDiv}> | ||||||
|  |                     <Typography className={classes.col1}> | ||||||
|  |                       {t('createWorkflow.verifyCommit.summary.desc')}: | ||||||
|  |                     </Typography> | ||||||
|  |                   </div> | ||||||
|  |                   <div className={classes.col2}> | ||||||
|  |                     <Typography>{workflow.description}</Typography> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div className={classes.summaryDiv}> | ||||||
|  |                   <div className={classes.innerSumDiv}> | ||||||
|  |                     <Typography className={classes.col1}> | ||||||
|  |                       {t('createWorkflow.verifyCommit.summary.schedule')}: | ||||||
|  |                     </Typography> | ||||||
|  |                   </div> | ||||||
|  |                   <div className={classes.schCol2}> | ||||||
|  |                     {cronSyntax === '' ? ( | ||||||
|  |                       <Typography> | ||||||
|  |                         {t('createWorkflow.verifyCommit.summary.schedulingNow')} | ||||||
|  |                       </Typography> | ||||||
|  |                     ) : ( | ||||||
|  |                       <Typography>{cronstrue.toString(cronSyntax)}</Typography> | ||||||
|  |                     )} | ||||||
|  | 
 | ||||||
|  |                     <ButtonOutlined | ||||||
|  |                       className={classes.editButton} | ||||||
|  |                       onClick={() => | ||||||
|  |                         history.push({ | ||||||
|  |                           pathname: `/workflows/schedule/${projectID}/${fetchWorkflowNameFromManifest( | ||||||
|  |                             manifest | ||||||
|  |                           )}/set`,
 | ||||||
|  |                           search: `?projectID=${projectID}&projectRole=${userRole}`, | ||||||
|  |                         }) | ||||||
|  |                       } | ||||||
|  |                     > | ||||||
|  |                       <EditIcon className={classes.editIcon} data-cy="edit" /> | ||||||
|  |                       {t('editSchedule.edit')} | ||||||
|  |                     </ButtonOutlined> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div className={classes.summaryDiv}> | ||||||
|  |                   <div className={classes.innerSumDiv}> | ||||||
|  |                     <Typography className={classes.col1}> | ||||||
|  |                       {t('createWorkflow.verifyCommit.summary.adjustedWeights')} | ||||||
|  |                       : | ||||||
|  |                     </Typography> | ||||||
|  |                   </div> | ||||||
|  |                   {weights.length === 0 ? ( | ||||||
|  |                     <div> | ||||||
|  |                       <Typography className={classes.col2}> | ||||||
|  |                         {t('createWorkflow.verifyCommit.error')} | ||||||
|  |                       </Typography> | ||||||
|  |                     </div> | ||||||
|  |                   ) : ( | ||||||
|  |                     <div className={classes.adjWeights}> | ||||||
|  |                       <div className={classes.progress}> | ||||||
|  |                         {weights.map((Test) => ( | ||||||
|  |                           <AdjustedWeights | ||||||
|  |                             key={Test.weight} | ||||||
|  |                             testName={`${Test.experimentName} ${t( | ||||||
|  |                               'createWorkflow.verifyCommit.test' | ||||||
|  |                             )}`}
 | ||||||
|  |                             testValue={Test.weight} | ||||||
|  |                             spacing={false} | ||||||
|  |                             icon={false} | ||||||
|  |                           /> | ||||||
|  |                         ))} | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                   )} | ||||||
|  |                 </div> | ||||||
|  |                 <div className={classes.summaryDiv}> | ||||||
|  |                   <div className={classes.innerSumDiv}> | ||||||
|  |                     <Typography className={classes.col1}> | ||||||
|  |                       {t('createWorkflow.verifyCommit.YAML')} | ||||||
|  |                     </Typography> | ||||||
|  |                   </div> | ||||||
|  |                   <div className={classes.yamlFlex}> | ||||||
|  |                     {weights.length === 0 ? ( | ||||||
|  |                       <Typography className={classes.spacingHorizontal}> | ||||||
|  |                         {t('createWorkflow.verifyCommit.errYaml')} | ||||||
|  |                       </Typography> | ||||||
|  |                     ) : ( | ||||||
|  |                       <Typography> | ||||||
|  |                         <b>{yamlStatus}</b> | ||||||
|  |                         <span className={classes.spacingHorizontal}> | ||||||
|  |                           {t('createWorkflow.verifyCommit.youCanMoveOn')} | ||||||
|  |                         </span> | ||||||
|  |                       </Typography> | ||||||
|  |                     )} | ||||||
|  |                     <br /> | ||||||
|  |                     <ButtonFilled | ||||||
|  |                       className={classes.verifyYAMLButton} | ||||||
|  |                       onClick={handleEditOpen} | ||||||
|  |                     > | ||||||
|  |                       {t('createWorkflow.verifyCommit.button.viewYaml')} | ||||||
|  |                     </ButtonFilled> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |           {/* Cancel and Save Button */} | ||||||
|  |           <div className={classes.buttonDiv} aria-label="buttons"> | ||||||
|  |             <ButtonOutlined | ||||||
|  |               onClick={() => { | ||||||
|  |                 history.push({ | ||||||
|  |                   pathname: `/workflows/`, | ||||||
|  |                   search: `?projectID=${projectID}&projectRole=${userRole}`, | ||||||
|  |                 }); | ||||||
|  |               }} | ||||||
|  |             > | ||||||
|  |               {t('editSchedule.cancel')} | ||||||
|  |             </ButtonOutlined> | ||||||
|  |             <ButtonFilled onClick={() => handleNext()}> | ||||||
|  |               {t('editSchedule.save')} | ||||||
|  |             </ButtonFilled> | ||||||
|  |           </div> | ||||||
|  | 
 | ||||||
|  |           <Modal | ||||||
|  |             open={open} | ||||||
|  |             onClose={handleEditClose} | ||||||
|  |             width="60%" | ||||||
|  |             modalActions={ | ||||||
|  |               <ButtonOutlined | ||||||
|  |                 onClick={handleEditClose} | ||||||
|  |                 className={classes.closeBtn} | ||||||
|  |               > | ||||||
|  |                 ✕ | ||||||
|  |               </ButtonOutlined> | ||||||
|  |             } | ||||||
|  |           > | ||||||
|  |             <YamlEditor content={manifest} filename={workflow.name} readOnly /> | ||||||
|  |           </Modal> | ||||||
|  | 
 | ||||||
|  |           {/* Finish Modal */} | ||||||
|  |           <div> | ||||||
|  |             <Modal | ||||||
|  |               data-cy="FinishModal" | ||||||
|  |               open={finishModalOpen} | ||||||
|  |               onClose={handleFinishModal} | ||||||
|  |               width="60%" | ||||||
|  |               aria-labelledby="simple-modal-title" | ||||||
|  |               aria-describedby="simple-modal-description" | ||||||
|  |               modalActions={ | ||||||
|  |                 <div data-cy="GoToWorkflowButton"> | ||||||
|  |                   <ButtonOutlined onClick={handleFinishModal}> | ||||||
|  |                     ✕ | ||||||
|  |                   </ButtonOutlined> | ||||||
|  |                 </div> | ||||||
|  |               } | ||||||
|  |             > | ||||||
|  |               <div className={classes.modal}> | ||||||
|  |                 <img src="/icons/finish.svg" alt="mark" /> | ||||||
|  |                 <div className={classes.heading}> | ||||||
|  |                   {t('editSchedule.theSchedule')} | ||||||
|  |                   <br /> | ||||||
|  |                   <span className={classes.successful}>{workflow.name}</span>, | ||||||
|  |                   <br /> | ||||||
|  |                   <span className={classes.bold}> | ||||||
|  |                     {t('editSchedule.successfullyCreated')} | ||||||
|  |                   </span> | ||||||
|  |                 </div> | ||||||
|  |                 <div className={classes.headWorkflow}> | ||||||
|  |                   {t('workflowStepper.congratulationsSub1')} <br />{' '} | ||||||
|  |                   {t('workflowStepper.congratulationsSub2')} | ||||||
|  |                 </div> | ||||||
|  |                 <div className={classes.button}> | ||||||
|  |                   <ButtonFilled | ||||||
|  |                     data-cy="selectFinish" | ||||||
|  |                     onClick={() => { | ||||||
|  |                       handleFinishModal(); | ||||||
|  |                       tabs.changeWorkflowsTabs(0); | ||||||
|  |                       history.push({ | ||||||
|  |                         pathname: '/workflows', | ||||||
|  |                         search: `?projectID=${projectID}&projectRole=${userRole}`, | ||||||
|  |                       }); | ||||||
|  |                     }} | ||||||
|  |                   > | ||||||
|  |                     <div>{t('workflowStepper.workflowBtn')}</div> | ||||||
|  |                   </ButtonFilled> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             </Modal> | ||||||
|  |             <Modal | ||||||
|  |               open={errorModal} | ||||||
|  |               onClose={handleErrorModalClose} | ||||||
|  |               width="60%" | ||||||
|  |               modalActions={ | ||||||
|  |                 <ButtonOutlined onClick={handleErrorModalClose}> | ||||||
|  |                   ✕ | ||||||
|  |                 </ButtonOutlined> | ||||||
|  |               } | ||||||
|  |             > | ||||||
|  |               <div className={classes.modal}> | ||||||
|  |                 <img src="/icons/red-cross.svg" alt="mark" /> | ||||||
|  |                 <div className={classes.heading}> | ||||||
|  |                   <strong>{t('workflowStepper.workflowFailed')}</strong> | ||||||
|  |                 </div> | ||||||
|  |                 <div className={classes.headWorkflow}> | ||||||
|  |                   <Typography> | ||||||
|  |                     {t('workflowStepper.error')} : {workflowError?.message} | ||||||
|  |                   </Typography> | ||||||
|  |                 </div> | ||||||
|  |                 <div className={classes.button}> | ||||||
|  |                   <ButtonFilled | ||||||
|  |                     data-cy="selectFinish" | ||||||
|  |                     onClick={() => { | ||||||
|  |                       setErrorModal(false); | ||||||
|  |                     }} | ||||||
|  |                   > | ||||||
|  |                     <div>{t('workflowStepper.back')}</div> | ||||||
|  |                   </ButtonFilled> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             </Modal> | ||||||
|  |           </div> | ||||||
|  |         </> | ||||||
|  |       )} | ||||||
|  |     </Scaffold> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export default EditSchedule; | ||||||
|  | @ -0,0 +1,217 @@ | ||||||
|  | import { makeStyles, Theme } from '@material-ui/core/styles'; | ||||||
|  | 
 | ||||||
|  | const useStyles = makeStyles((theme: Theme) => ({ | ||||||
|  |   horizontalLine: { | ||||||
|  |     background: theme.palette.border.main, | ||||||
|  |   }, | ||||||
|  |   title: { | ||||||
|  |     padding: theme.spacing(0, 2), | ||||||
|  |     fontWeight: 700, | ||||||
|  |     fontSize: '2rem', | ||||||
|  |     [theme.breakpoints.up('lg')]: { | ||||||
|  |       fontSize: '2.3rem', | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   root: { | ||||||
|  |     background: theme.palette.background.paper, | ||||||
|  |     color: theme.palette.text.primary, | ||||||
|  |     padding: theme.spacing(1, 2), | ||||||
|  |     margin: theme.spacing(2, 'auto'), | ||||||
|  |     width: '100%', | ||||||
|  |     flexDirection: 'column', | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   // Inner Container
 | ||||||
|  |   innerContainer: { | ||||||
|  |     margin: theme.spacing(4, 'auto'), | ||||||
|  |     width: '95%', // Inner width of the container
 | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   suHeader: { | ||||||
|  |     display: 'flex', | ||||||
|  |     justifyContent: 'space-between', | ||||||
|  |   }, | ||||||
|  |   headerText: { | ||||||
|  |     fontSize: '1.2rem', | ||||||
|  |     [theme.breakpoints.up('lg')]: { | ||||||
|  |       fontSize: '1.4rem', | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   description: { | ||||||
|  |     margin: theme.spacing(3, 0), | ||||||
|  |     fontSize: '1rem', | ||||||
|  |   }, | ||||||
|  |   bfinIcon: { | ||||||
|  |     width: '7rem', | ||||||
|  |     height: '6.31rem', | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   // Body
 | ||||||
|  |   outerSum: { | ||||||
|  |     display: 'flex', | ||||||
|  |     flexDirection: 'column', | ||||||
|  |   }, | ||||||
|  |   summaryDiv: { | ||||||
|  |     display: 'flex', | ||||||
|  |     flexDirection: 'row', | ||||||
|  |     justifyContent: 'flex-start', | ||||||
|  |     alignItems: 'baseline', | ||||||
|  |     margin: theme.spacing(1, 0), | ||||||
|  |   }, | ||||||
|  |   innerSumDiv: { | ||||||
|  |     alignContent: 'center', | ||||||
|  |     display: 'table-cell', | ||||||
|  |     verticalAlign: 'middle', | ||||||
|  |     width: '20%', | ||||||
|  |     [theme.breakpoints.up('lg')]: { | ||||||
|  |       width: '10%', | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   sumText: { | ||||||
|  |     width: '100%', | ||||||
|  |     margin: theme.spacing(2, 0), | ||||||
|  |     fontWeight: 700, | ||||||
|  |     fontSize: '1.2rem', | ||||||
|  |     [theme.breakpoints.up('lg')]: { | ||||||
|  |       fontSize: '1.4rem', | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   col1: { | ||||||
|  |     alignContent: 'center', | ||||||
|  |     color: theme.palette.highlight, | ||||||
|  |     fontSize: '1rem', | ||||||
|  |     paddingTop: theme.spacing(0.5), | ||||||
|  |     verticalAlign: 'middle', | ||||||
|  |   }, | ||||||
|  |   schedule: { | ||||||
|  |     fontSize: '0.85rem', | ||||||
|  |     padding: theme.spacing(0.75, 0, 2, 0), | ||||||
|  |   }, | ||||||
|  |   col2: { | ||||||
|  |     color: theme.palette.text.primary, | ||||||
|  |     marginLeft: theme.spacing(5), | ||||||
|  |     fontWeight: 700, | ||||||
|  |     width: '75%', | ||||||
|  |   }, | ||||||
|  |   schCol2: { | ||||||
|  |     width: '75%', | ||||||
|  |     marginLeft: theme.spacing(5), | ||||||
|  |     display: 'flex', | ||||||
|  |     flexDirection: 'row', | ||||||
|  |     justifyContent: 'space-between', | ||||||
|  |   }, | ||||||
|  |   clusterName: { | ||||||
|  |     fontSize: '0.85rem', | ||||||
|  |     marginLeft: theme.spacing(7), | ||||||
|  |     paddingTop: theme.spacing(0.5), | ||||||
|  |   }, | ||||||
|  |   editButton: { | ||||||
|  |     height: '1rem', | ||||||
|  |   }, | ||||||
|  |   editIcon: { | ||||||
|  |     color: theme.palette.text.primary, | ||||||
|  |     height: '0.8rem', | ||||||
|  |   }, | ||||||
|  |   link: { | ||||||
|  |     fontSize: '0.875rem', | ||||||
|  |     color: theme.palette.secondary.dark, | ||||||
|  |   }, | ||||||
|  |   adjWeights: { | ||||||
|  |     display: 'flex', | ||||||
|  |     flexDirection: 'row', | ||||||
|  |     justifyContent: 'space-between', | ||||||
|  | 
 | ||||||
|  |     width: '80%', | ||||||
|  |     [theme.breakpoints.up('lg')]: { | ||||||
|  |       width: '90%', | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   config: { | ||||||
|  |     height: '3rem', | ||||||
|  |     fontSize: '0.9375rem', | ||||||
|  |     color: theme.palette.text.disabled, | ||||||
|  |     width: '30rem', | ||||||
|  |     margin: theme.spacing(3.75, 0, 30, 0), | ||||||
|  |   }, | ||||||
|  |   typoCol2: { | ||||||
|  |     fontSize: '1rem', | ||||||
|  |   }, | ||||||
|  |   textEdit: { | ||||||
|  |     marginTop: theme.spacing(7.5), | ||||||
|  |   }, | ||||||
|  |   buttonOutlineText: { | ||||||
|  |     padding: theme.spacing(1.5), | ||||||
|  |   }, | ||||||
|  |   errorText: { | ||||||
|  |     color: theme.palette.error.main, | ||||||
|  |     fontSize: '1rem', | ||||||
|  |     marginLeft: theme.spacing(5), | ||||||
|  |   }, | ||||||
|  |   yamlFlex: { | ||||||
|  |     display: 'flex', | ||||||
|  |     flexDirection: 'column', | ||||||
|  |     width: '75%', | ||||||
|  |     marginLeft: theme.spacing(5), | ||||||
|  |   }, | ||||||
|  |   progress: { | ||||||
|  |     display: 'flex', | ||||||
|  |     flexDirection: 'row', | ||||||
|  |     flexWrap: 'wrap', | ||||||
|  |     flexGrow: 1, | ||||||
|  |     marginLeft: theme.spacing(5), | ||||||
|  |   }, | ||||||
|  |   spacingHorizontal: { | ||||||
|  |     margin: theme.spacing(0, 1), | ||||||
|  |   }, | ||||||
|  |   buttomPad: { | ||||||
|  |     paddingBottom: theme.spacing(3.75), | ||||||
|  |   }, | ||||||
|  |   closeBtn: { | ||||||
|  |     color: theme.palette.secondary.contrastText, | ||||||
|  |   }, | ||||||
|  |   buttonDiv: { | ||||||
|  |     display: 'flex', | ||||||
|  |     justifyContent: 'space-between', | ||||||
|  |     width: '100%', | ||||||
|  |   }, | ||||||
|  |   verifyYAMLButton: { | ||||||
|  |     width: '20%', | ||||||
|  |   }, | ||||||
|  |   bold: { | ||||||
|  |     fontWeight: 700, | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   // Modal
 | ||||||
|  |   modal: { | ||||||
|  |     [theme.breakpoints.up('lg')]: { | ||||||
|  |       padding: theme.spacing(10), | ||||||
|  |     }, | ||||||
|  |     padding: theme.spacing(3), | ||||||
|  |   }, | ||||||
|  |   heading: { | ||||||
|  |     fontSize: '2rem', | ||||||
|  |     textalign: 'center', | ||||||
|  |     marginTop: theme.spacing(3), | ||||||
|  |     color: theme.palette.text.primary, | ||||||
|  |   }, | ||||||
|  |   headWorkflow: { | ||||||
|  |     fontsize: '2rem', | ||||||
|  |     textalign: 'center', | ||||||
|  |     color: theme.palette.text.primary, | ||||||
|  |     marginTop: theme.spacing(3), | ||||||
|  |   }, | ||||||
|  |   button: { | ||||||
|  |     color: theme.palette.text.primary, | ||||||
|  |     textAlign: 'center', | ||||||
|  |     marginTop: theme.spacing(5), | ||||||
|  |   }, | ||||||
|  |   closeButton: { | ||||||
|  |     borderColor: theme.palette.border.main, | ||||||
|  |   }, | ||||||
|  |   successful: { | ||||||
|  |     fontSize: '2.2rem', | ||||||
|  |     fontWeight: 'bold', | ||||||
|  |     margin: theme.spacing(2, 0), | ||||||
|  |   }, | ||||||
|  | })); | ||||||
|  | export default useStyles; | ||||||
|  | @ -8,9 +8,6 @@ import { | ||||||
| import createReducer from './createReducer'; | import createReducer from './createReducer'; | ||||||
| 
 | 
 | ||||||
| const initialState: WorkflowData = { | const initialState: WorkflowData = { | ||||||
|   id: '', |  | ||||||
|   isRecurring: false, |  | ||||||
|   isDisabled: false, |  | ||||||
|   chaosEngineChanged: false, |   chaosEngineChanged: false, | ||||||
|   namespace: 'litmus', |   namespace: 'litmus', | ||||||
|   clusterid: '', |   clusterid: '', | ||||||
|  |  | ||||||
|  | @ -70,6 +70,10 @@ const parsed = (yaml: string) => { | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | export const fetchWorkflowNameFromManifest = (manifest: string) => { | ||||||
|  |   return YAML.parse(manifest).metadata.name; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| export const getWorkflowParameter = (parameterString: string) => { | export const getWorkflowParameter = (parameterString: string) => { | ||||||
|   return parameterString |   return parameterString | ||||||
|     .substring(1, parameterString.length - 1) |     .substring(1, parameterString.length - 1) | ||||||
|  |  | ||||||
|  | @ -24,7 +24,6 @@ import { RERUN_CHAOS_WORKFLOW } from '../../../graphql/mutations'; | ||||||
| import { ScheduleWorkflow } from '../../../models/graphql/scheduleData'; | import { ScheduleWorkflow } from '../../../models/graphql/scheduleData'; | ||||||
| import useActions from '../../../redux/actions'; | import useActions from '../../../redux/actions'; | ||||||
| import * as TabActions from '../../../redux/actions/tabs'; | import * as TabActions from '../../../redux/actions/tabs'; | ||||||
| import * as WorkflowActions from '../../../redux/actions/workflow'; |  | ||||||
| import { history } from '../../../redux/configureStore'; | import { history } from '../../../redux/configureStore'; | ||||||
| import { ReactComponent as CrossMarkIcon } from '../../../svg/crossmark.svg'; | import { ReactComponent as CrossMarkIcon } from '../../../svg/crossmark.svg'; | ||||||
| import timeDifferenceForDate from '../../../utils/datesModifier'; | import timeDifferenceForDate from '../../../utils/datesModifier'; | ||||||
|  | @ -63,8 +62,6 @@ const TableData: React.FC<TableDataProps> = ({ | ||||||
|     setPopAnchorEl(null); |     setPopAnchorEl(null); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   const workflow = useActions(WorkflowActions); |  | ||||||
| 
 |  | ||||||
|   const handlePopOverClick = (event: React.MouseEvent<HTMLElement>) => { |   const handlePopOverClick = (event: React.MouseEvent<HTMLElement>) => { | ||||||
|     setPopAnchorEl(event.currentTarget); |     setPopAnchorEl(event.currentTarget); | ||||||
|   }; |   }; | ||||||
|  | @ -125,13 +122,6 @@ const TableData: React.FC<TableDataProps> = ({ | ||||||
|     }); |     }); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   // If regularity is not Once then set recurring schedule state to true
 |  | ||||||
|   if (data.cronSyntax !== '') { |  | ||||||
|     workflow.setWorkflowDetails({ |  | ||||||
|       isRecurring: true, |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   const [reRunChaosWorkFlow] = useMutation(RERUN_CHAOS_WORKFLOW, { |   const [reRunChaosWorkFlow] = useMutation(RERUN_CHAOS_WORKFLOW, { | ||||||
|     onCompleted: () => { |     onCompleted: () => { | ||||||
|       tabs.changeWorkflowsTabs(0); |       tabs.changeWorkflowsTabs(0); | ||||||
|  |  | ||||||
|  | @ -18,11 +18,14 @@ import { useSelector } from 'react-redux'; | ||||||
| import YAML from 'yaml'; | import YAML from 'yaml'; | ||||||
| import CustomDate from '../../../components/DateTime/CustomDate/index'; | import CustomDate from '../../../components/DateTime/CustomDate/index'; | ||||||
| import CustomTime from '../../../components/DateTime/CustomTime/index'; | import CustomTime from '../../../components/DateTime/CustomTime/index'; | ||||||
|  | import { constants } from '../../../constants'; | ||||||
| import { WorkflowData } from '../../../models/redux/workflow'; | import { WorkflowData } from '../../../models/redux/workflow'; | ||||||
| import useActions from '../../../redux/actions'; | import useActions from '../../../redux/actions'; | ||||||
| import * as TemplateSelectionActions from '../../../redux/actions/template'; | import * as TemplateSelectionActions from '../../../redux/actions/template'; | ||||||
| import * as WorkflowActions from '../../../redux/actions/workflow'; | import * as WorkflowActions from '../../../redux/actions/workflow'; | ||||||
| import { RootState } from '../../../redux/reducers'; | import { RootState } from '../../../redux/reducers'; | ||||||
|  | import { cronWorkflow, workflowOnce } from '../../../utils/workflowTemplate'; | ||||||
|  | import { fetchWorkflowNameFromManifest } from '../../../utils/yamlUtils'; | ||||||
| import SetTime from './SetTime/index'; | import SetTime from './SetTime/index'; | ||||||
| import useStyles from './styles'; | import useStyles from './styles'; | ||||||
| 
 | 
 | ||||||
|  | @ -54,6 +57,10 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|   ); |   ); | ||||||
|   const workflow = useActions(WorkflowActions); |   const workflow = useActions(WorkflowActions); | ||||||
|   const template = useActions(TemplateSelectionActions); |   const template = useActions(TemplateSelectionActions); | ||||||
|  | 
 | ||||||
|  |   const scheduleOnce = workflowOnce; | ||||||
|  |   const scheduleMore = cronWorkflow; | ||||||
|  | 
 | ||||||
|   // Controls Radio Buttons
 |   // Controls Radio Buttons
 | ||||||
|   const [value, setValue] = React.useState( |   const [value, setValue] = React.useState( | ||||||
|     workflowData.scheduleType.scheduleOnce |     workflowData.scheduleType.scheduleOnce | ||||||
|  | @ -81,10 +88,6 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|       workflow.setWorkflowDetails({ |       workflow.setWorkflowDetails({ | ||||||
|         cronSyntax, |         cronSyntax, | ||||||
|       }); |       }); | ||||||
|     if (value === 'disable') |  | ||||||
|       workflow.setWorkflowDetails({ |  | ||||||
|         isDisabled: true, |  | ||||||
|       }); |  | ||||||
|   }, [cronValue]); |   }, [cronValue]); | ||||||
| 
 | 
 | ||||||
|   const classes = useStyles(); |   const classes = useStyles(); | ||||||
|  | @ -163,6 +166,76 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|     validateTime(selectedTime, date); |     validateTime(selectedTime, date); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  |   function EditYaml() { | ||||||
|  |     const oldParsedYaml = YAML.parse(manifest); | ||||||
|  |     let NewYaml: string; | ||||||
|  |     if ( | ||||||
|  |       oldParsedYaml.kind === 'Workflow' && | ||||||
|  |       workflowData.scheduleType.scheduleOnce !== 'now' | ||||||
|  |     ) { | ||||||
|  |       const oldParsedYaml = YAML.parse(manifest); | ||||||
|  |       const newParsedYaml = YAML.parse(scheduleMore); | ||||||
|  |       delete newParsedYaml.spec.workflowSpec; | ||||||
|  |       newParsedYaml.spec.schedule = workflowData.cronSyntax; | ||||||
|  |       delete newParsedYaml.metadata.generateName; | ||||||
|  |       newParsedYaml.metadata.name = fetchWorkflowNameFromManifest(manifest); | ||||||
|  |       newParsedYaml.metadata.labels = { | ||||||
|  |         workflow_id: workflowData.workflow_id, | ||||||
|  |       }; | ||||||
|  |       newParsedYaml.spec.workflowSpec = oldParsedYaml.spec; | ||||||
|  |       const tz = { | ||||||
|  |         timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC', | ||||||
|  |       }; | ||||||
|  |       Object.entries(tz).forEach(([key, value]) => { | ||||||
|  |         newParsedYaml.spec[key] = value; | ||||||
|  |       }); | ||||||
|  |       NewYaml = YAML.stringify(newParsedYaml); | ||||||
|  |       workflow.setWorkflowManifest({ | ||||||
|  |         manifest: NewYaml, | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     if ( | ||||||
|  |       oldParsedYaml.kind === 'CronWorkflow' && | ||||||
|  |       workflowData.scheduleType.scheduleOnce === 'now' | ||||||
|  |     ) { | ||||||
|  |       const oldParsedYaml = YAML.parse(manifest); | ||||||
|  |       const newParsedYaml = YAML.parse(scheduleOnce); | ||||||
|  |       delete newParsedYaml.spec; | ||||||
|  |       delete newParsedYaml.metadata.generateName; | ||||||
|  |       newParsedYaml.metadata.name = fetchWorkflowNameFromManifest(manifest); | ||||||
|  |       newParsedYaml.spec = oldParsedYaml.spec.workflowSpec; | ||||||
|  |       newParsedYaml.metadata.labels = { | ||||||
|  |         workflow_id: workflowData.workflow_id, | ||||||
|  |       }; | ||||||
|  |       NewYaml = YAML.stringify(newParsedYaml); | ||||||
|  |       workflow.setWorkflowManifest({ | ||||||
|  |         manifest: NewYaml, | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     if ( | ||||||
|  |       oldParsedYaml.kind === 'CronWorkflow' && | ||||||
|  |       workflowData.scheduleType.scheduleOnce !== 'now' | ||||||
|  |       //   && !isDisabled
 | ||||||
|  |     ) { | ||||||
|  |       const newParsedYaml = YAML.parse(manifest); | ||||||
|  |       newParsedYaml.spec.schedule = workflowData.cronSyntax; | ||||||
|  |       //   newParsedYaml.spec.suspend = false;
 | ||||||
|  |       delete newParsedYaml.metadata.generateName; | ||||||
|  |       newParsedYaml.metadata.name = fetchWorkflowNameFromManifest(manifest); | ||||||
|  |       newParsedYaml.metadata.labels = { workflow_id: workflowData.workflow_id }; | ||||||
|  |       const tz = { | ||||||
|  |         timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC', | ||||||
|  |       }; | ||||||
|  |       Object.entries(tz).forEach(([key, value]) => { | ||||||
|  |         newParsedYaml.spec[key] = value; | ||||||
|  |       }); | ||||||
|  |       NewYaml = YAML.stringify(newParsedYaml); | ||||||
|  |       workflow.setWorkflowManifest({ | ||||||
|  |         manifest: NewYaml, | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   // Function for recurring date change
 |   // Function for recurring date change
 | ||||||
|   const reccuringDateChange = (date: Date | null) => { |   const reccuringDateChange = (date: Date | null) => { | ||||||
|     setSelectedTime(date); |     setSelectedTime(date); | ||||||
|  | @ -202,9 +275,6 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|   // UseEffect to update the values of CronSyntax on radio button change
 |   // UseEffect to update the values of CronSyntax on radio button change
 | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     if (value === 'now') { |     if (value === 'now') { | ||||||
|       workflow.setWorkflowDetails({ |  | ||||||
|         isDisabled: false, |  | ||||||
|       }); |  | ||||||
|       setValueDef(''); |       setValueDef(''); | ||||||
|       setCronValue({ |       setCronValue({ | ||||||
|         minute: '', |         minute: '', | ||||||
|  | @ -214,11 +284,6 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|         day_week: '', |         day_week: '', | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|     if (value === 'disable') { |  | ||||||
|       workflow.setWorkflowDetails({ |  | ||||||
|         isDisabled: true, |  | ||||||
|       }); |  | ||||||
|     } |  | ||||||
|     if (value === 'specificTime') { |     if (value === 'specificTime') { | ||||||
|       setValueDef(''); |       setValueDef(''); | ||||||
|       setCronValue({ |       setCronValue({ | ||||||
|  | @ -247,10 +312,7 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|         }); |         }); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     if (valueDef === 'everyHr') { |     if (valueDef === constants.recurringEveryHour) { | ||||||
|       workflow.setWorkflowDetails({ |  | ||||||
|         isDisabled: false, |  | ||||||
|       }); |  | ||||||
|       setCronValue({ |       setCronValue({ | ||||||
|         minute: minute.toString(), |         minute: minute.toString(), | ||||||
|         hour: '0-23', |         hour: '0-23', | ||||||
|  | @ -259,10 +321,7 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|         day_week: '*', |         day_week: '*', | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|     if (valueDef === 'everyDay') { |     if (valueDef === constants.recurringEveryDay) { | ||||||
|       workflow.setWorkflowDetails({ |  | ||||||
|         isDisabled: false, |  | ||||||
|       }); |  | ||||||
|       setCronValue({ |       setCronValue({ | ||||||
|         minute: selectedTime?.getMinutes().toString(), |         minute: selectedTime?.getMinutes().toString(), | ||||||
|         hour: selectedTime?.getHours().toString(), |         hour: selectedTime?.getHours().toString(), | ||||||
|  | @ -271,10 +330,7 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|         day_week: '0-6', |         day_week: '0-6', | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|     if (valueDef === 'everyWeek') { |     if (valueDef === constants.recurringEveryWeek) { | ||||||
|       workflow.setWorkflowDetails({ |  | ||||||
|         isDisabled: false, |  | ||||||
|       }); |  | ||||||
|       setCronValue({ |       setCronValue({ | ||||||
|         minute: selectedTime?.getMinutes().toString(), |         minute: selectedTime?.getMinutes().toString(), | ||||||
|         hour: selectedTime?.getHours().toString(), |         hour: selectedTime?.getHours().toString(), | ||||||
|  | @ -283,10 +339,7 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|         day_week: days.slice(0, 3), |         day_week: days.slice(0, 3), | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|     if (valueDef === 'everyMonth') { |     if (valueDef === constants.recurringEveryMonth) { | ||||||
|       workflow.setWorkflowDetails({ |  | ||||||
|         isDisabled: false, |  | ||||||
|       }); |  | ||||||
|       setCronValue({ |       setCronValue({ | ||||||
|         minute: selectedTime?.getMinutes().toString(), |         minute: selectedTime?.getMinutes().toString(), | ||||||
|         hour: selectedTime?.getHours().toString(), |         hour: selectedTime?.getHours().toString(), | ||||||
|  | @ -296,9 +349,6 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|     if (value === 'recurringSchedule' && valueDef === '') { |     if (value === 'recurringSchedule' && valueDef === '') { | ||||||
|       workflow.setWorkflowDetails({ |  | ||||||
|         isDisabled: false, |  | ||||||
|       }); |  | ||||||
|       template.selectTemplate({ isDisable: true }); |       template.selectTemplate({ isDisable: true }); | ||||||
|     } else { |     } else { | ||||||
|       template.selectTemplate({ isDisable: false }); |       template.selectTemplate({ isDisable: false }); | ||||||
|  | @ -312,6 +362,7 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|   }, [valueDef, value]); |   }, [valueDef, value]); | ||||||
| 
 | 
 | ||||||
|   function onNext() { |   function onNext() { | ||||||
|  |     EditYaml(); | ||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | @ -354,7 +405,6 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|               onChange={handleChange} |               onChange={handleChange} | ||||||
|             > |             > | ||||||
|               {/* options to choose schedule */} |               {/* options to choose schedule */} | ||||||
|               {!workflowData.isRecurring ? ( |  | ||||||
|               <FormControlLabel |               <FormControlLabel | ||||||
|                 value="now" |                 value="now" | ||||||
|                 control={ |                 control={ | ||||||
|  | @ -371,39 +421,7 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|                   </Typography> |                   </Typography> | ||||||
|                 } |                 } | ||||||
|               /> |               /> | ||||||
|               ) : YAML.parse(manifest).spec.suspend === true ? ( |               {value === 'specificTime' && ( | ||||||
|                 <></> |  | ||||||
|               ) : workflowData.isRecurring ? ( |  | ||||||
|                 <FormControlLabel |  | ||||||
|                   value="disable" |  | ||||||
|                   control={ |  | ||||||
|                     <Radio |  | ||||||
|                       classes={{ |  | ||||||
|                         root: classes.radio, |  | ||||||
|                         checked: classes.checked, |  | ||||||
|                       }} |  | ||||||
|                     /> |  | ||||||
|                   } |  | ||||||
|                   label={ |  | ||||||
|                     <Typography className={classes.radioText}> |  | ||||||
|                       Disable Schedule |  | ||||||
|                     </Typography> |  | ||||||
|                   } |  | ||||||
|                 /> |  | ||||||
|               ) : ( |  | ||||||
|                 <></> |  | ||||||
|               )} |  | ||||||
|               {/* <FormControlLabel |  | ||||||
|                 value="specificTime" |  | ||||||
|                 disabled |  | ||||||
|                 control={<Radio classes={{ root: classes.radio, checked: classes.checked }}/>} |  | ||||||
|                 label={ |  | ||||||
|                   <Typography className={classes.radioText}> |  | ||||||
|                     {t('createWorkflow.scheduleWorkflow.radio.specific')} |  | ||||||
|                   </Typography> |  | ||||||
|                 } |  | ||||||
|               /> */} |  | ||||||
|               {value === 'specificTime' ? ( |  | ||||||
|                 <div className={classes.schLater}> |                 <div className={classes.schLater}> | ||||||
|                   <Typography className={classes.captionText}> |                   <Typography className={classes.captionText}> | ||||||
|                     {t('createWorkflow.scheduleWorkflow.radio.future')} |                     {t('createWorkflow.scheduleWorkflow.radio.future')} | ||||||
|  | @ -426,8 +444,6 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|                     /> |                     /> | ||||||
|                   </div> |                   </div> | ||||||
|                 </div> |                 </div> | ||||||
|               ) : ( |  | ||||||
|                 <></> |  | ||||||
|               )} |               )} | ||||||
|               <FormControlLabel |               <FormControlLabel | ||||||
|                 value="recurringSchedule" |                 value="recurringSchedule" | ||||||
|  | @ -442,7 +458,7 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|                   </Typography> |                   </Typography> | ||||||
|                 } |                 } | ||||||
|               /> |               /> | ||||||
|               {value === 'recurringSchedule' ? ( |               {value === 'recurringSchedule' && ( | ||||||
|                 <div className={classes.schLater}> |                 <div className={classes.schLater}> | ||||||
|                   <Typography className={classes.captionText}> |                   <Typography className={classes.captionText}> | ||||||
|                     {t('createWorkflow.scheduleWorkflow.radio.rightRecurr')} |                     {t('createWorkflow.scheduleWorkflow.radio.rightRecurr')} | ||||||
|  | @ -460,7 +476,7 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|                         }} |                         }} | ||||||
|                       > |                       > | ||||||
|                         <FormControlLabel |                         <FormControlLabel | ||||||
|                           value="everyHr" |                           value={constants.recurringEveryHour} | ||||||
|                           control={ |                           control={ | ||||||
|                             <Radio |                             <Radio | ||||||
|                               classes={{ |                               classes={{ | ||||||
|  | @ -471,7 +487,7 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|                           } |                           } | ||||||
|                           label={t('createWorkflow.scheduleWorkflow.every.hr')} |                           label={t('createWorkflow.scheduleWorkflow.every.hr')} | ||||||
|                         /> |                         /> | ||||||
|                         {valueDef === 'everyHr' ? ( |                         {valueDef === constants.recurringEveryHour && ( | ||||||
|                           <div> |                           <div> | ||||||
|                             <div className={classes.scRandom}> |                             <div className={classes.scRandom}> | ||||||
|                               <Typography className={classes.scRandsub1}> |                               <Typography className={classes.scRandsub1}> | ||||||
|  | @ -508,11 +524,9 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|                               )} |                               )} | ||||||
|                             </div> |                             </div> | ||||||
|                           </div> |                           </div> | ||||||
|                         ) : ( |  | ||||||
|                           <></> |  | ||||||
|                         )} |                         )} | ||||||
|                         <FormControlLabel |                         <FormControlLabel | ||||||
|                           value="everyDay" |                           value={constants.recurringEveryDay} | ||||||
|                           control={ |                           control={ | ||||||
|                             <Radio |                             <Radio | ||||||
|                               classes={{ |                               classes={{ | ||||||
|  | @ -523,7 +537,7 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|                           } |                           } | ||||||
|                           label={t('createWorkflow.scheduleWorkflow.every.day')} |                           label={t('createWorkflow.scheduleWorkflow.every.day')} | ||||||
|                         /> |                         /> | ||||||
|                         {valueDef === 'everyDay' ? ( |                         {valueDef === constants.recurringEveryDay && ( | ||||||
|                           <div> |                           <div> | ||||||
|                             <div className={classes.scRandom}> |                             <div className={classes.scRandom}> | ||||||
|                               <Typography className={classes.scRandsub1}> |                               <Typography className={classes.scRandsub1}> | ||||||
|  | @ -551,11 +565,9 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|                               /> |                               /> | ||||||
|                             </div> |                             </div> | ||||||
|                           </div> |                           </div> | ||||||
|                         ) : ( |  | ||||||
|                           <></> |  | ||||||
|                         )} |                         )} | ||||||
|                         <FormControlLabel |                         <FormControlLabel | ||||||
|                           value="everyWeek" |                           value={constants.recurringEveryWeek} | ||||||
|                           control={ |                           control={ | ||||||
|                             <Radio |                             <Radio | ||||||
|                               classes={{ |                               classes={{ | ||||||
|  | @ -568,7 +580,7 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|                             'createWorkflow.scheduleWorkflow.every.week' |                             'createWorkflow.scheduleWorkflow.every.week' | ||||||
|                           )} |                           )} | ||||||
|                         /> |                         /> | ||||||
|                         {valueDef === 'everyWeek' ? ( |                         {valueDef === constants.recurringEveryWeek && ( | ||||||
|                           <div> |                           <div> | ||||||
|                             <div className={classes.scRandom}> |                             <div className={classes.scRandom}> | ||||||
|                               <Typography className={classes.scRandsub1}> |                               <Typography className={classes.scRandsub1}> | ||||||
|  | @ -633,11 +645,9 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|                               /> |                               /> | ||||||
|                             </div> |                             </div> | ||||||
|                           </div> |                           </div> | ||||||
|                         ) : ( |  | ||||||
|                           <></> |  | ||||||
|                         )} |                         )} | ||||||
|                         <FormControlLabel |                         <FormControlLabel | ||||||
|                           value="everyMonth" |                           value={constants.recurringEveryMonth} | ||||||
|                           control={ |                           control={ | ||||||
|                             <Radio |                             <Radio | ||||||
|                               classes={{ |                               classes={{ | ||||||
|  | @ -650,7 +660,7 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|                             'createWorkflow.scheduleWorkflow.every.month' |                             'createWorkflow.scheduleWorkflow.every.month' | ||||||
|                           )} |                           )} | ||||||
|                         /> |                         /> | ||||||
|                         {valueDef === 'everyMonth' ? ( |                         {valueDef === constants.recurringEveryMonth && ( | ||||||
|                           <div> |                           <div> | ||||||
|                             <div className={classes.scRandom}> |                             <div className={classes.scRandom}> | ||||||
|                               <Typography className={classes.scRandsub1}> |                               <Typography className={classes.scRandsub1}> | ||||||
|  | @ -687,15 +697,11 @@ const ScheduleWorkflow = forwardRef((_, ref) => { | ||||||
|                               /> |                               /> | ||||||
|                             </div> |                             </div> | ||||||
|                           </div> |                           </div> | ||||||
|                         ) : ( |  | ||||||
|                           <></> |  | ||||||
|                         )} |                         )} | ||||||
|                       </RadioGroup> |                       </RadioGroup> | ||||||
|                     </FormControl> |                     </FormControl> | ||||||
|                   </div> |                   </div> | ||||||
|                 </div> |                 </div> | ||||||
|               ) : ( |  | ||||||
|                 <></> |  | ||||||
|               )} |               )} | ||||||
|             </RadioGroup> |             </RadioGroup> | ||||||
|           </FormControl> |           </FormControl> | ||||||
|  |  | ||||||
|  | @ -5,15 +5,23 @@ const useStyles = makeStyles((theme: Theme) => ({ | ||||||
|     background: theme.palette.background.paper, |     background: theme.palette.background.paper, | ||||||
|     color: theme.palette.text.primary, |     color: theme.palette.text.primary, | ||||||
|     padding: theme.spacing(0, 2), |     padding: theme.spacing(0, 2), | ||||||
|     margin: '0 auto', |     margin: '1rem auto', | ||||||
|     width: '98%', |     width: '98%', | ||||||
|     height: '100%', |  | ||||||
|     flexDirection: 'column', |     flexDirection: 'column', | ||||||
|     [theme.breakpoints.up('lg')]: { |     [theme.breakpoints.up('lg')]: { | ||||||
|       width: '99%', |       width: '99%', | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
| 
 | 
 | ||||||
|  |   title: { | ||||||
|  |     padding: theme.spacing(0, 2), | ||||||
|  |     fontWeight: 700, | ||||||
|  |     fontSize: '2rem', | ||||||
|  |     [theme.breakpoints.up('lg')]: { | ||||||
|  |       fontSize: '2.3rem', | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|   // Inner Container
 |   // Inner Container
 | ||||||
|   innerContainer: { |   innerContainer: { | ||||||
|     margin: theme.spacing(4, 'auto'), |     margin: theme.spacing(4, 'auto'), | ||||||
|  | @ -28,7 +36,10 @@ const useStyles = makeStyles((theme: Theme) => ({ | ||||||
| 
 | 
 | ||||||
|   headerText: { |   headerText: { | ||||||
|     marginTop: theme.spacing(1.25), |     marginTop: theme.spacing(1.25), | ||||||
|     fontSize: '1.5625rem', |     fontSize: '1.2rem', | ||||||
|  |     [theme.breakpoints.up('lg')]: { | ||||||
|  |       fontSize: '1.4rem', | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
|   schBody: { |   schBody: { | ||||||
|     width: '32.18rem', |     width: '32.18rem', | ||||||
|  | @ -68,6 +79,11 @@ const useStyles = makeStyles((theme: Theme) => ({ | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
|   checked: {}, |   checked: {}, | ||||||
|  |   buttonDiv: { | ||||||
|  |     display: 'flex', | ||||||
|  |     justifyContent: 'space-between', | ||||||
|  |     width: '100%', | ||||||
|  |   }, | ||||||
| 
 | 
 | ||||||
|   /* For recurring schedule options */ |   /* For recurring schedule options */ | ||||||
|   scRandom: { |   scRandom: { | ||||||
|  |  | ||||||
|  | @ -31,6 +31,7 @@ import * as WorkflowActions from '../../../redux/actions/workflow'; | ||||||
| import { history } from '../../../redux/configureStore'; | import { history } from '../../../redux/configureStore'; | ||||||
| import { RootState } from '../../../redux/reducers'; | import { RootState } from '../../../redux/reducers'; | ||||||
| import { getProjectID, getProjectRole } from '../../../utils/getSearchParams'; | import { getProjectID, getProjectRole } from '../../../utils/getSearchParams'; | ||||||
|  | import { fetchWorkflowNameFromManifest } from '../../../utils/yamlUtils'; | ||||||
| import useStyles from './styles'; | import useStyles from './styles'; | ||||||
| 
 | 
 | ||||||
| interface WorkflowProps { | interface WorkflowProps { | ||||||
|  | @ -67,7 +68,7 @@ const VerifyCommit = forwardRef((_, ref) => { | ||||||
|     (state: RootState) => state.workflowData |     (state: RootState) => state.workflowData | ||||||
|   ); |   ); | ||||||
| 
 | 
 | ||||||
|   const { clusterid, cronSyntax, isDisabled, clustername } = workflowData; |   const { clusterid, cronSyntax, clustername } = workflowData; | ||||||
| 
 | 
 | ||||||
|   const manifest = useSelector( |   const manifest = useSelector( | ||||||
|     (state: RootState) => state.workflowManifest.manifest |     (state: RootState) => state.workflowManifest.manifest | ||||||
|  | @ -85,9 +86,6 @@ const VerifyCommit = forwardRef((_, ref) => { | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|   const fetchWorkflowNameFromManifest = (manifest: string) => { |  | ||||||
|     return YAML.parse(manifest).metadata.name; |  | ||||||
|   }; |  | ||||||
| 
 | 
 | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     saveWorkflowGenerateName(manifest); |     saveWorkflowGenerateName(manifest); | ||||||
|  | @ -111,7 +109,7 @@ const VerifyCommit = forwardRef((_, ref) => { | ||||||
|   }, []); |   }, []); | ||||||
| 
 | 
 | ||||||
|   const [yamlStatus, setYamlStatus] = React.useState( |   const [yamlStatus, setYamlStatus] = React.useState( | ||||||
|     'Your code is fine. You can move on!' |     `${t('createWorkflow.verifyCommit.codeIsFine')}` | ||||||
|   ); |   ); | ||||||
| 
 | 
 | ||||||
|   const [modified, setModified] = React.useState(false); |   const [modified, setModified] = React.useState(false); | ||||||
|  | @ -245,6 +243,7 @@ const VerifyCommit = forwardRef((_, ref) => { | ||||||
|     localforage.removeItem('hasSetWorkflowData'); |     localforage.removeItem('hasSetWorkflowData'); | ||||||
|     localforage.removeItem('weights'); |     localforage.removeItem('weights'); | ||||||
|     localforage.removeItem('selectedHub'); |     localforage.removeItem('selectedHub'); | ||||||
|  |     localforage.removeItem('editSchedule'); | ||||||
|     setFinishModalOpen(false); |     setFinishModalOpen(false); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  | @ -265,7 +264,7 @@ const VerifyCommit = forwardRef((_, ref) => { | ||||||
|           <div className={classes.suHeader}> |           <div className={classes.suHeader}> | ||||||
|             <div> |             <div> | ||||||
|               <Typography className={classes.headerText}> |               <Typography className={classes.headerText}> | ||||||
|                 <strong> {t('createWorkflow.verifyCommit.header')}</strong> |                 {t('createWorkflow.verifyCommit.header')} | ||||||
|               </Typography> |               </Typography> | ||||||
|               <Typography className={classes.description}> |               <Typography className={classes.description}> | ||||||
|                 {t('createWorkflow.verifyCommit.info')} |                 {t('createWorkflow.verifyCommit.info')} | ||||||
|  | @ -280,7 +279,7 @@ const VerifyCommit = forwardRef((_, ref) => { | ||||||
|           <Divider /> |           <Divider /> | ||||||
| 
 | 
 | ||||||
|           <Typography className={classes.sumText}> |           <Typography className={classes.sumText}> | ||||||
|             <strong>{t('createWorkflow.verifyCommit.summary.header')}</strong> |             {t('createWorkflow.verifyCommit.summary.header')} | ||||||
|           </Typography> |           </Typography> | ||||||
| 
 | 
 | ||||||
|           <div className={classes.outerSum}> |           <div className={classes.outerSum}> | ||||||
|  | @ -298,7 +297,6 @@ const VerifyCommit = forwardRef((_, ref) => { | ||||||
|                   onChange={(e) => |                   onChange={(e) => | ||||||
|                     handleNameChange({ changedName: e.target.value }) |                     handleNameChange({ changedName: e.target.value }) | ||||||
|                   } |                   } | ||||||
|                   disabled={workflowData.isRecurring} |  | ||||||
|                 /> |                 /> | ||||||
|               </div> |               </div> | ||||||
|             </div> |             </div> | ||||||
|  | @ -339,18 +337,7 @@ const VerifyCommit = forwardRef((_, ref) => { | ||||||
|                 </Typography> |                 </Typography> | ||||||
|               </div> |               </div> | ||||||
|               <div className={classes.schCol2}> |               <div className={classes.schCol2}> | ||||||
|                 {/* <CustomDate disabled={edit} /> |                 {cronSyntax === '' ? ( | ||||||
|               <CustomTime |  | ||||||
|                 handleDateChange={handleDateChange} |  | ||||||
|                 value={selectedDate} |  | ||||||
|                 ampm |  | ||||||
|                 disabled={edit} |  | ||||||
|               /> */} |  | ||||||
|                 {isDisabled ? ( |  | ||||||
|                   <Typography className={classes.schedule}> |  | ||||||
|                     {t('createWorkflow.verifyCommit.summary.disabled')} |  | ||||||
|                   </Typography> |  | ||||||
|                 ) : cronSyntax === '' ? ( |  | ||||||
|                   <Typography className={classes.schedule}> |                   <Typography className={classes.schedule}> | ||||||
|                     {t('createWorkflow.verifyCommit.summary.schedulingNow')} |                     {t('createWorkflow.verifyCommit.summary.schedulingNow')} | ||||||
|                   </Typography> |                   </Typography> | ||||||
|  | @ -360,9 +347,9 @@ const VerifyCommit = forwardRef((_, ref) => { | ||||||
|                   </Typography> |                   </Typography> | ||||||
|                 )} |                 )} | ||||||
| 
 | 
 | ||||||
|                 <div className={classes.editButton1}> |                 <div className={classes.editButton}> | ||||||
|                   <IconButton> |                   <IconButton> | ||||||
|                     <EditIcon className={classes.editbtn} data-cy="edit" /> |                     <EditIcon className={classes.editIcon} data-cy="edit" /> | ||||||
|                   </IconButton> |                   </IconButton> | ||||||
|                 </div> |                 </div> | ||||||
|               </div> |               </div> | ||||||
|  | @ -376,29 +363,25 @@ const VerifyCommit = forwardRef((_, ref) => { | ||||||
|               {weights.length === 0 ? ( |               {weights.length === 0 ? ( | ||||||
|                 <div> |                 <div> | ||||||
|                   <Typography className={classes.errorText}> |                   <Typography className={classes.errorText}> | ||||||
|                     <strong>{t('createWorkflow.verifyCommit.error')}</strong> |                     {t('createWorkflow.verifyCommit.error')} | ||||||
|                   </Typography> |                   </Typography> | ||||||
|                 </div> |                 </div> | ||||||
|               ) : ( |               ) : ( | ||||||
|                 <div className={classes.adjWeights}> |                 <div className={classes.adjWeights}> | ||||||
|                   <div |                   <div className={classes.progress}> | ||||||
|                     className={classes.progress} |  | ||||||
|                     style={{ flexWrap: 'wrap' }} |  | ||||||
|                   > |  | ||||||
|                     {WorkflowTestData.map((Test) => ( |                     {WorkflowTestData.map((Test) => ( | ||||||
|                       <AdjustedWeights |                       <AdjustedWeights | ||||||
|                         key={Test.weight} |                         key={Test.weight} | ||||||
|                         testName={`${Test.experimentName} test`} |                         testName={`${Test.experimentName} ${t( | ||||||
|  |                           'createWorkflow.verifyCommit.test' | ||||||
|  |                         )}`}
 | ||||||
|                         testValue={Test.weight} |                         testValue={Test.weight} | ||||||
|                         spacing={false} |                         spacing={false} | ||||||
|                         icon={false} |                         icon={false} | ||||||
|                       /> |                       /> | ||||||
|                     ))} |                     ))} | ||||||
|                   </div> |                   </div> | ||||||
|                   <ButtonOutlined |                   <ButtonOutlined data-cy="testRunButton"> | ||||||
|                     disabled={workflowData.isRecurring} |  | ||||||
|                     data-cy="testRunButton" |  | ||||||
|                   > |  | ||||||
|                     {t('createWorkflow.verifyCommit.button.edit')} |                     {t('createWorkflow.verifyCommit.button.edit')} | ||||||
|                   </ButtonOutlined> |                   </ButtonOutlined> | ||||||
|                 </div> |                 </div> | ||||||
|  | @ -406,22 +389,28 @@ const VerifyCommit = forwardRef((_, ref) => { | ||||||
|             </div> |             </div> | ||||||
|             <div className={classes.summaryDiv}> |             <div className={classes.summaryDiv}> | ||||||
|               <div className={classes.innerSumDiv}> |               <div className={classes.innerSumDiv}> | ||||||
|                 <Typography className={classes.col1}>YAML:</Typography> |                 <Typography className={classes.col1}> | ||||||
|  |                   {t('createWorkflow.verifyCommit.YAML')} | ||||||
|  |                 </Typography> | ||||||
|               </div> |               </div> | ||||||
|               <div className={classes.yamlFlex}> |               <div className={classes.yamlFlex}> | ||||||
|                 {weights.length === 0 ? ( |                 {weights.length === 0 ? ( | ||||||
|                   <Typography> |                   <Typography className={classes.spacingHorizontal}> | ||||||
|                     {' '} |                     {t('createWorkflow.verifyCommit.errYaml')} | ||||||
|                     {t('createWorkflow.verifyCommit.errYaml')}{' '} |  | ||||||
|                   </Typography> |                   </Typography> | ||||||
|                 ) : ( |                 ) : ( | ||||||
|                   <Typography> |                   <Typography> | ||||||
|                     <b>{yamlStatus}</b>{' '} |                     <b>{yamlStatus}</b> | ||||||
|  |                     <span className={classes.spacingHorizontal}> | ||||||
|                       {t('createWorkflow.verifyCommit.youCanMoveOn')} |                       {t('createWorkflow.verifyCommit.youCanMoveOn')} | ||||||
|  |                     </span> | ||||||
|                   </Typography> |                   </Typography> | ||||||
|                 )} |                 )} | ||||||
|                 <br /> |                 <br /> | ||||||
|                 <ButtonFilled style={{ width: '60%' }} onClick={handleOpen}> |                 <ButtonFilled | ||||||
|  |                   className={classes.verifyYAMLButton} | ||||||
|  |                   onClick={handleOpen} | ||||||
|  |                 > | ||||||
|                   {t('createWorkflow.verifyCommit.button.viewYaml')} |                   {t('createWorkflow.verifyCommit.button.viewYaml')} | ||||||
|                 </ButtonFilled> |                 </ButtonFilled> | ||||||
|               </div> |               </div> | ||||||
|  | @ -467,7 +456,9 @@ const VerifyCommit = forwardRef((_, ref) => { | ||||||
|               <br /> |               <br /> | ||||||
|               <span className={classes.successful}>{workflow.name}</span>, |               <span className={classes.successful}>{workflow.name}</span>, | ||||||
|               <br /> |               <br /> | ||||||
|               <strong>{t('workflowStepper.successful')}</strong> |               <span className={classes.bold}> | ||||||
|  |                 {t('workflowStepper.successful')} | ||||||
|  |               </span> | ||||||
|             </div> |             </div> | ||||||
|             <div className={classes.headWorkflow}> |             <div className={classes.headWorkflow}> | ||||||
|               {t('workflowStepper.congratulationsSub1')} <br />{' '} |               {t('workflowStepper.congratulationsSub1')} <br />{' '} | ||||||
|  |  | ||||||
|  | @ -28,6 +28,7 @@ const useStyles = makeStyles((theme: Theme) => ({ | ||||||
|     justifyContent: 'space-between', |     justifyContent: 'space-between', | ||||||
|   }, |   }, | ||||||
|   headerText: { |   headerText: { | ||||||
|  |     fontWeight: 700, | ||||||
|     fontSize: '1.2rem', |     fontSize: '1.2rem', | ||||||
|     [theme.breakpoints.up('lg')]: { |     [theme.breakpoints.up('lg')]: { | ||||||
|       fontSize: '1.4rem', |       fontSize: '1.4rem', | ||||||
|  | @ -64,8 +65,8 @@ const useStyles = makeStyles((theme: Theme) => ({ | ||||||
|   }, |   }, | ||||||
|   sumText: { |   sumText: { | ||||||
|     width: '100%', |     width: '100%', | ||||||
|     marginTop: theme.spacing(4.5), |     margin: theme.spacing(2, 0), | ||||||
|     marginBottom: theme.spacing(3), |     fontWeight: 700, | ||||||
|     fontSize: '1.2rem', |     fontSize: '1.2rem', | ||||||
|     [theme.breakpoints.up('lg')]: { |     [theme.breakpoints.up('lg')]: { | ||||||
|       fontSize: '1.4rem', |       fontSize: '1.4rem', | ||||||
|  | @ -98,11 +99,12 @@ const useStyles = makeStyles((theme: Theme) => ({ | ||||||
|     marginLeft: theme.spacing(7), |     marginLeft: theme.spacing(7), | ||||||
|     paddingTop: theme.spacing(0.5), |     paddingTop: theme.spacing(0.5), | ||||||
|   }, |   }, | ||||||
|   editButton1: { |   editButton: { | ||||||
|     marginLeft: theme.spacing(1), |     height: '1rem', | ||||||
|   }, |   }, | ||||||
|   editbtn: { |   editIcon: { | ||||||
|     color: theme.palette.text.secondary, |     color: theme.palette.text.primary, | ||||||
|  |     height: '0.8rem', | ||||||
|   }, |   }, | ||||||
|   link: { |   link: { | ||||||
|     fontSize: '0.875rem', |     fontSize: '0.875rem', | ||||||
|  | @ -135,8 +137,12 @@ const useStyles = makeStyles((theme: Theme) => ({ | ||||||
|   buttonOutlineText: { |   buttonOutlineText: { | ||||||
|     padding: theme.spacing(1.5), |     padding: theme.spacing(1.5), | ||||||
|   }, |   }, | ||||||
|  |   spacingHorizontal: { | ||||||
|  |     margin: theme.spacing(0, 1), | ||||||
|  |   }, | ||||||
|   errorText: { |   errorText: { | ||||||
|     color: theme.palette.error.main, |     color: theme.palette.error.main, | ||||||
|  |     fontWeight: 700, | ||||||
|     fontSize: '1rem', |     fontSize: '1rem', | ||||||
|     marginLeft: theme.spacing(5), |     marginLeft: theme.spacing(5), | ||||||
|   }, |   }, | ||||||
|  | @ -148,6 +154,7 @@ const useStyles = makeStyles((theme: Theme) => ({ | ||||||
|   progress: { |   progress: { | ||||||
|     display: 'flex', |     display: 'flex', | ||||||
|     flexDirection: 'row', |     flexDirection: 'row', | ||||||
|  |     flexWrap: 'wrap', | ||||||
|     flexGrow: 1, |     flexGrow: 1, | ||||||
|     marginLeft: theme.spacing(5), |     marginLeft: theme.spacing(5), | ||||||
|   }, |   }, | ||||||
|  | @ -159,6 +166,9 @@ const useStyles = makeStyles((theme: Theme) => ({ | ||||||
|     marginTop: theme.spacing(-6), |     marginTop: theme.spacing(-6), | ||||||
|     marginRight: theme.spacing(-2.5), |     marginRight: theme.spacing(-2.5), | ||||||
|   }, |   }, | ||||||
|  |   verifyYAMLButton: { | ||||||
|  |     width: '60%', | ||||||
|  |   }, | ||||||
| 
 | 
 | ||||||
|   // Modal
 |   // Modal
 | ||||||
|   modal: { |   modal: { | ||||||
|  | @ -190,6 +200,10 @@ const useStyles = makeStyles((theme: Theme) => ({ | ||||||
|   successful: { |   successful: { | ||||||
|     fontSize: '2.2rem', |     fontSize: '2.2rem', | ||||||
|     fontWeight: 'bold', |     fontWeight: 'bold', | ||||||
|  |     margin: theme.spacing(2, 0), | ||||||
|  |   }, | ||||||
|  |   bold: { | ||||||
|  |     fontWeight: 700, | ||||||
|   }, |   }, | ||||||
| })); | })); | ||||||
| export default useStyles; | export default useStyles; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue