From 1b424623457f2ca869457f478df16225cd662ab9 Mon Sep 17 00:00:00 2001 From: Sayan Mondal Date: Wed, 2 Jun 2021 13:15:04 +0530 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20type(bugfix):=20Fixed=20Editor?= =?UTF-8?q?=20for=20Verify=20&=20Commit=20and=20Tune=20Workflow=20page=20?= =?UTF-8?q?=F0=9F=94=A8=20(#2857)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added Updated Editor * Replaced Editor in Verify & Commit Page * Fixing Editor cursor * Added validation to Editor Signed-off-by: Sayan Mondal --- .../frontend/public/icons/terminal.svg | 12 + litmus-portal/frontend/public/index.css | 1 + litmus-portal/frontend/public/index.html | 1 + .../src/components/YamlEditor/Editor.tsx | 419 +++++++----------- .../src/components/YamlEditor/styles.ts | 241 +--------- .../src/containers/layouts/Scaffold/styles.ts | 1 + litmus-portal/frontend/src/utils/yamlUtils.ts | 32 +- .../TuneWorkflow/WorkflowTable.tsx | 10 +- .../CreateWorkflow/TuneWorkflow/index.tsx | 398 +++++++++-------- .../CreateWorkflow/TuneWorkflow/styles.ts | 46 +- .../CreateWorkflow/VerifyCommit/index.tsx | 393 ++++++++-------- .../CreateWorkflow/VerifyCommit/styles.ts | 29 ++ .../CreateWorkflow/WorkflowSettings/index.tsx | 5 +- 13 files changed, 682 insertions(+), 906 deletions(-) create mode 100644 litmus-portal/frontend/public/icons/terminal.svg diff --git a/litmus-portal/frontend/public/icons/terminal.svg b/litmus-portal/frontend/public/icons/terminal.svg new file mode 100644 index 000000000..0703096d2 --- /dev/null +++ b/litmus-portal/frontend/public/icons/terminal.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/litmus-portal/frontend/public/index.css b/litmus-portal/frontend/public/index.css index b27df4047..b40c26e0a 100644 --- a/litmus-portal/frontend/public/index.css +++ b/litmus-portal/frontend/public/index.css @@ -1,5 +1,6 @@ .root { background: #f5f6f8; + font-family: 'Ubuntu', sans-serif; } .loaderContainer { diff --git a/litmus-portal/frontend/public/index.html b/litmus-portal/frontend/public/index.html index 092f03608..9cd2b62e0 100644 --- a/litmus-portal/frontend/public/index.html +++ b/litmus-portal/frontend/public/index.html @@ -38,6 +38,7 @@ href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet" /> + Litmus Portal diff --git a/litmus-portal/frontend/src/components/YamlEditor/Editor.tsx b/litmus-portal/frontend/src/components/YamlEditor/Editor.tsx index 4b555b6fe..c177efbb6 100644 --- a/litmus-portal/frontend/src/components/YamlEditor/Editor.tsx +++ b/litmus-portal/frontend/src/components/YamlEditor/Editor.tsx @@ -1,6 +1,7 @@ /* eslint-disable no-param-reassign */ -import { Box, Button, Typography, useTheme } from '@material-ui/core'; -import Divider from '@material-ui/core/Divider'; +/* eslint-disable jsx-a11y/click-events-have-key-events */ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +import { useTheme } from '@material-ui/core'; import Fade from '@material-ui/core/Fade'; import Tooltip from '@material-ui/core/Tooltip'; import ErrorTwoToneIcon from '@material-ui/icons/ErrorTwoTone'; @@ -13,9 +14,9 @@ import SelectAllTwoToneIcon from '@material-ui/icons/SelectAllTwoTone'; import UndoTwoToneIcon from '@material-ui/icons/UndoTwoTone'; import UnfoldLessTwoToneIcon from '@material-ui/icons/UnfoldLessTwoTone'; import UnfoldMoreTwoToneIcon from '@material-ui/icons/UnfoldMoreTwoTone'; +import FullscreenIcon from '@material-ui/icons/Fullscreen'; import React, { useEffect, useState } from 'react'; import AceEditor from 'react-ace'; -import { useTranslation } from 'react-i18next'; import useStyles from './styles'; import { AceValidations, parseYamlValidations } from './Validations'; import 'ace-builds/src-min-noconflict/ext-beautify'; @@ -39,7 +40,7 @@ import 'ace-builds/src-min-noconflict/ext-textarea'; import 'ace-builds/src-min-noconflict/ext-themelist'; import 'ace-builds/src-min-noconflict/ext-whitespace'; import 'brace/mode/yaml'; -import 'brace/theme/cobalt'; +import 'brace/theme/solarized_dark'; interface YamlEditorProps { content: string; @@ -47,7 +48,6 @@ interface YamlEditorProps { readOnly: boolean; setButtonState?: (btnState: boolean) => void; saveWorkflowChange?: (updatedManifest: string) => void; - className?: Object; } const YamlEditor: React.FC = ({ @@ -56,23 +56,13 @@ const YamlEditor: React.FC = ({ readOnly, setButtonState, saveWorkflowChange, - className, }) => { const classes = useStyles(); const { palette } = useTheme(); - const { t } = useTranslation(); - const [isValid, setIsValid] = useState(true); - const [errors, setErrors] = useState({ - errorLine: ' ', - errorPosition: ' ', - errorType: ' ', - errorInfo: ' ', - }); - - const [editorState, setEditorState] = React.useState({ + const [editorState, setEditorState] = useState({ markers: [], annotations: [], content, @@ -94,12 +84,6 @@ const YamlEditor: React.FC = ({ }; if (stateObject.annotations.length > 0) { setIsValid(false); - setErrors({ - errorLine: (stateObject.annotations[0].row as unknown) as string, - errorPosition: (stateObject.annotations[0].column as unknown) as string, - errorType: stateObject.annotations[0].type as string, - errorInfo: stateObject.annotations[0].text as string, - }); const nodeStyleError = (document.getElementsByClassName( 'ace_gutter-cell' )[stateObject.annotations[0].row - 1] as any).style; @@ -107,12 +91,6 @@ const YamlEditor: React.FC = ({ nodeStyleError.color = palette.secondary.contrastText; } else { setIsValid(true); - setErrors({ - errorLine: ' ', - errorPosition: ' ', - errorType: ' ', - errorInfo: ' ', - }); const nodeStyleErrorList = document.getElementsByClassName( 'ace_gutter-cell' ); @@ -181,8 +159,8 @@ const YamlEditor: React.FC = ({ (YamlAce.current!.editor as any).execCommand('goToNextError'); }; - const fullscreentrigger = () => { - const i: any = document.getElementById('resize-editor'); + const fullScreenTrigger = () => { + const i: any = document.getElementById('yaml-editor'); (YamlAce.current!.editor as any).setOption( 'maxLines', document.body.clientHeight @@ -199,31 +177,18 @@ const YamlEditor: React.FC = ({ }; useEffect(() => { - let editorValidations: AceValidations = { - markers: [], - annotations: [], - }; - editorValidations = parseYamlValidations(content, classes); + const editorValidations: AceValidations = parseYamlValidations( + content, + classes + ); const stateObject = { markers: editorValidations.markers, annotations: editorValidations.annotations, }; if (stateObject.annotations.length > 0) { setIsValid(false); - setErrors({ - errorLine: (stateObject.annotations[0].row as unknown) as string, - errorPosition: (stateObject.annotations[0].column as unknown) as string, - errorType: stateObject.annotations[0].type as string, - errorInfo: stateObject.annotations[0].text as string, - }); } else { setIsValid(true); - setErrors({ - errorLine: ' ', - errorPosition: ' ', - errorType: ' ', - errorInfo: ' ', - }); } setEditorState(stateObject as any); }, []); @@ -233,318 +198,232 @@ const YamlEditor: React.FC = ({ }, [isValid]); return ( -
- - {t('editor.status')} - -     - - - - {isValid ? '\u2713' : '\u274C'} - - - -   - {isValid ? 'Correct' : 'Incorrect'} - - - - - - {isValid - ? ' ' - : `Pay attention to Line ${errors.errorLine}'s ` + - ` character ${errors.errorPosition}. Type: ${errors.errorType} -> ${errors.errorInfo}.`} -   - {isValid - ? 'Your code is fine. You can move on!' - : 'Correct this error and keep moving forward!'} - -
- +
+ <> {!readOnly && (
-
-
)} -
+ +
- { - editor.setReadOnly(readOnly); - editor.setOptions({ - fontFamily: 'monospace', - highlightGutterLine: false, - autoScrollEditorIntoView: true, - tooltipFollowsMouse: true, - displayIndentGuides: false, - }); - editor.focus(); - editor.setHighlightSelectedWord(true); - editor.session.setFoldStyle('markbeginend'); - editor.setShowFoldWidgets(true); - editor.setAnimatedScroll(true); - editor.setShowInvisibles(false); - editor.setFontSize('0.98rem'); - editor.container.style.background = palette.common.black; - editor.container.style.lineHeight = '160%'; - const nodeStyle = (document.getElementsByClassName( - 'ace_gutter' - )[0] as any).style; - nodeStyle.color = palette.secondary.contrastText; - nodeStyle.borderRight = 0; - nodeStyle.background = palette.common.black; - }} - onCursorChange={(selection) => { - (YamlAce.current!.editor as any).setOptions({ - autoScrollEditorIntoView: true, - tooltipFollowsMouse: true, - }); +
+           {
+              editor.setReadOnly(readOnly);
+              editor.setOptions({
+                fontFamily: 'monospace',
+                highlightGutterLine: false,
+                autoScrollEditorIntoView: true,
+                tooltipFollowsMouse: true,
+                displayIndentGuides: false,
+              });
+              editor.focus();
+              editor.setHighlightSelectedWord(true);
+              editor.session.setFoldStyle('markbeginend');
+              editor.setShowFoldWidgets(true);
+              editor.setAnimatedScroll(true);
+              editor.setShowInvisibles(false);
+              editor.setFontSize('0.98rem');
+              editor.container.style.lineHeight = '160%';
+              const nodeStyle = (document.getElementsByClassName(
+                'ace_gutter'
+              )[0] as any).style;
+              nodeStyle.color = palette.secondary.contrastText;
+              nodeStyle.borderRight = 0;
+            }}
+            onCursorChange={(selection) => {
+              (YamlAce.current!.editor as any).setOptions({
+                autoScrollEditorIntoView: true,
+                tooltipFollowsMouse: true,
+              });
 
-            const nodeStyleActiveList = document.getElementsByClassName(
-              'ace_gutter-cell'
-            );
-            for (let i = 0; i < nodeStyleActiveList.length; i += 1) {
-              (nodeStyleActiveList[i] as any).style.backgroundColor =
-                palette.common.black;
-              (nodeStyleActiveList[i] as any).style.color =
-                palette.secondary.contrastText;
-            }
-
-            if (
-              document.getElementsByClassName('ace_gutter-cell')[
-                selection.cursor.row
-              ] as any
-            ) {
-              const nodeStyleActive = (document.getElementsByClassName(
+              const nodeStyleActiveList = document.getElementsByClassName(
                 'ace_gutter-cell'
-              )[selection.cursor.row] as any).style;
-              nodeStyleActive.backgroundColor = palette.primary.main;
-              nodeStyleActive.color = palette.secondary.contrastText;
-            }
-          }}
-          annotations={editorState.annotations}
-          markers={editorState.markers}
-        />
-        
-          
-            
); diff --git a/litmus-portal/frontend/src/components/YamlEditor/styles.ts b/litmus-portal/frontend/src/components/YamlEditor/styles.ts index 235b0f2b0..6cbdcbb72 100644 --- a/litmus-portal/frontend/src/components/YamlEditor/styles.ts +++ b/litmus-portal/frontend/src/components/YamlEditor/styles.ts @@ -3,59 +3,15 @@ import { makeStyles, Theme } from '@material-ui/core'; const useStyles = makeStyles((theme: Theme) => ({ // Editor - statusHeadingInModal: { - marginTop: theme.spacing(-2.5), - fontSize: '1rem', - marginLeft: theme.spacing(2.5), - fontWeight: 500, - lineHeight: '130%', - paddingTop: theme.spacing(-4), - }, - - statusHeadingOutModal: { - marginTop: theme.spacing(-2.5), - fontSize: '1rem', - marginLeft: theme.spacing(2.5), - fontWeight: 500, - lineHeight: '130%', - paddingTop: theme.spacing(4), - }, - - statusDescription: { - width: '95%', - marginTop: theme.spacing(1.875), - fontSize: '0.875rem', - marginLeft: theme.spacing(2), - marginRight: theme.spacing(2), - lineHeight: '160%', - }, - - editorBackgroundFull: { - backgroundColor: theme.palette.common.black, - color: theme.palette.secondary.contrastText, - width: '100%', - }, - - horizontalLineWhite: { - marginTop: theme.spacing(4), - backgroundColor: theme.palette.border.main, - }, - - widthManager: { - width: '98.5%', - }, - editorButtonGrid: { - marginTop: theme.spacing(3), display: 'flex', flexWrap: 'wrap', - justifyContent: 'space-between', + width: '95%', + margin: '0 auto', }, editor: { - overflowY: 'auto', - margin: theme.spacing(2, 0), - height: '40vh', + height: '50vh', '&::-webkit-scrollbar': { width: '0.2em', @@ -66,186 +22,23 @@ const useStyles = makeStyles((theme: Theme) => ({ '&::-webkit-scrollbar-thumb': { backgroundColor: theme.palette.primary.main, }, + + '& #code': { + padding: '1rem 0', + }, + + '& #yaml-editor': { + overflowY: 'auto', + width: '100%', + height: '100%', + position: 'relative', + }, }, editorButtons: { - borderRadius: 3, - backgroundColor: theme.palette.common.black, - boxSizing: 'border-box', - color: theme.palette.secondary.contrastText, - borderColor: theme.palette.border.main, - paddingLeft: theme.spacing(3.125), - width: '4rem', - height: '2.75rem', - marginLeft: theme.spacing(1.25), - }, - - editorButtonGotoCopyUnfold: { - [theme.breakpoints.down('xs')]: { - marginLeft: 0, - marginTop: theme.spacing(1.5), - }, - }, - - editorButtonFind: { - [theme.breakpoints.down('sm')]: { - marginLeft: theme.spacing(4.25), - }, - [theme.breakpoints.down('xs')]: { - marginLeft: theme.spacing(0.1), - marginTop: theme.spacing(1.5), - }, - }, - - editorButtonFold: { - [theme.breakpoints.down('xs')]: { - marginLeft: theme.spacing(2.5), - marginTop: theme.spacing(1.5), - }, - }, - - editorButtonUndo: { - marginLeft: theme.spacing(2.5), - [theme.breakpoints.down('sm')]: { - marginLeft: theme.spacing(4.25), - }, - [theme.breakpoints.down('xs')]: { - marginLeft: theme.spacing(0.1), - }, - }, - - editorButtonDownload: { - marginLeft: theme.spacing(6.25), - [theme.breakpoints.down('sm')]: { - marginLeft: theme.spacing(1.5), - }, - [theme.breakpoints.down('md')]: { - marginLeft: theme.spacing(1), - }, - }, - - editorButtonReplace: { - marginLeft: theme.spacing(15.625), - [theme.breakpoints.down('xs')]: { - marginLeft: theme.spacing(-0.5), - marginTop: theme.spacing(1.5), - }, - [theme.breakpoints.down('sm')]: { - marginLeft: theme.spacing(1.3), - }, - [theme.breakpoints.down('md')]: { - display: 'none', - }, - [theme.breakpoints.down('lg')]: { - marginLeft: theme.spacing(5), - }, - }, - - editorButtonSelectAll: { - marginLeft: theme.spacing(7.5), - [theme.breakpoints.down('sm')]: { - marginLeft: theme.spacing(1.4), - }, - [theme.breakpoints.down('md')]: { - marginLeft: theme.spacing(1), - }, - [theme.breakpoints.down('lg')]: { - marginRight: theme.spacing(2.5), - }, - [theme.breakpoints.down('xs')]: { - marginLeft: theme.spacing(1.5), - marginTop: theme.spacing(1.5), - }, - [theme.breakpoints.down('xl')]: { - marginRight: theme.spacing(2), - }, - }, - - editorButtonFullScreen: { - borderRadius: 3, - backgroundColor: theme.palette.common.black, - boxSizing: 'border-box', - color: theme.palette.text.primary, - borderColor: theme.palette.common.black, - paddingLeft: theme.spacing(3.75), - paddingBottom: theme.spacing(1.875), - marginTop: theme.spacing(-2), - width: '1.875rem', - height: '1.875rem', - marginLeft: theme.spacing(-7.5), - [theme.breakpoints.down('sm')]: { - marginLeft: theme.spacing(-2), - width: 0, - height: 0, - padding: 0, - border: 0, - }, - [theme.breakpoints.down('xl')]: { - width: 0, - height: 0, - padding: 0, - border: 0, - marginLeft: theme.spacing(-7.5), - }, - [theme.breakpoints.down('lg')]: { - width: 0, - height: 0, - padding: 0, - border: 0, - marginLeft: theme.spacing(-7.5), - }, - [theme.breakpoints.down('md')]: { - width: 0, - height: 0, - padding: 0, - border: 0, - marginLeft: theme.spacing(-7.5), - }, - }, - - saved: { - width: '25rem', - marginTop: theme.spacing(6), - fontFamily: 'Ubuntu', - fontSize: '1rem', - color: theme.palette.success.main, - display: 'inline', - }, - - markStyleCorrect: { - display: 'inline-block', - fontFamily: 'Ubuntu', - fontSize: '1rem', - color: theme.palette.success.main, - }, - - markStyleWrong: { - display: 'inline-block', - fontFamily: 'Ubuntu', - fontSize: '1rem', - color: theme.palette.error.main, - }, - - fullScreenGrid: { - width: 0, - }, - - fullWidth: { - width: '100%', - height: '100%', - }, - - fullScreenIcon: { - width: '1.5625rem', - height: '1.5625rem', - marginRight: '1.5625rem', - }, - - // Validations - - validationError: { - position: 'absolute', - background: theme.palette.error.light, + width: '2rem', + height: '1rem', + margin: theme.spacing(0, 1, 0, 0), }, })); diff --git a/litmus-portal/frontend/src/containers/layouts/Scaffold/styles.ts b/litmus-portal/frontend/src/containers/layouts/Scaffold/styles.ts index bccbbb4f7..5a08e1285 100644 --- a/litmus-portal/frontend/src/containers/layouts/Scaffold/styles.ts +++ b/litmus-portal/frontend/src/containers/layouts/Scaffold/styles.ts @@ -10,6 +10,7 @@ const useStyles = makeStyles((theme: Theme) => ({ gridTemplateColumns: '20.5em auto', gridTemplateRows: '6.5em auto', gridTemplateAreas: '"header header" "sidebar content"', + fontFamily: 'Ubuntu', '& ::-webkit-scrollbar': { width: '0.4rem', diff --git a/litmus-portal/frontend/src/utils/yamlUtils.ts b/litmus-portal/frontend/src/utils/yamlUtils.ts index a6383d91b..6b4fda214 100644 --- a/litmus-portal/frontend/src/utils/yamlUtils.ts +++ b/litmus-portal/frontend/src/utils/yamlUtils.ts @@ -6,6 +6,17 @@ import { v4 as uuidv4 } from 'uuid'; import { constants } from '../constants'; import { ImageRegistryInfo } from '../models/redux/image_registry'; +const validateNamespace = (chaosEngine: any) => { + // Condition to check the namespace + if (typeof chaosEngine.metadata.namespace === 'object') { + // Removes any whitespace in '{{workflow.parameters.adminModeNamespace}}' + const namespace = Object.keys(chaosEngine.metadata.namespace)[0].replace( + /\s/g, + '' + ); + chaosEngine.metadata.namespace = `{${namespace}}`; + } +}; const nameextractor = (val: any) => { const embeddedworkflowyamlstring = val; const parsedEmbeddedYaml = YAML.parse(embeddedworkflowyamlstring as string); @@ -32,6 +43,7 @@ export const updateEngineName = (parsedYaml: any) => { if (template.inputs && template.inputs.artifacts) { template.inputs.artifacts.forEach((artifact: any) => { const chaosEngine = YAML.parse(artifact.raw.data); + validateNamespace(chaosEngine); // Condition to check for the kind as ChaosEngine if (chaosEngine.kind === 'ChaosEngine') { if (chaosEngine.metadata.generateName === undefined) { @@ -42,14 +54,7 @@ export const updateEngineName = (parsedYaml: any) => { chaosEngine.metadata['labels'] = { instance_id: uuidv4(), }; - // Condition to check the namespace - if (typeof chaosEngine.metadata.namespace === 'object') { - // Removes any whitespace in '{{workflow.parameters.adminModeNamespace}}' - const namespace = Object.keys( - chaosEngine.metadata.namespace - )[0].replace(/\s/g, ''); - chaosEngine.metadata.namespace = `{${namespace}}`; - } + validateNamespace(chaosEngine); // Edge Case: Condition to check the appns // Required because while parsing the chaos engine @@ -97,6 +102,7 @@ export const updateWorkflowNameLabel = ( if (template.inputs && template.inputs.artifacts) { template.inputs.artifacts.forEach((artifact: any) => { const chaosEngine = YAML.parse(artifact.raw.data); + validateNamespace(chaosEngine); // Condition to check for the kind as ChaosEngine if (chaosEngine.kind === 'ChaosEngine') { if (chaosEngine.metadata.labels !== undefined) { @@ -106,14 +112,8 @@ export const updateWorkflowNameLabel = ( workflow_name: workflowName, }; } - // Condition to check the namespace - if (typeof chaosEngine.metadata.namespace === 'object') { - // Removes any whitespace in '{{workflow.parameters.adminModeNamespace}}' - const namespace = Object.keys( - chaosEngine.metadata.namespace - )[0].replace(/\s/g, ''); - chaosEngine.metadata.namespace = `{${namespace}}`; - } + + validateNamespace(chaosEngine); // Edge Case: Condition to check the appns // Required because while parsing the chaos engine diff --git a/litmus-portal/frontend/src/views/CreateWorkflow/TuneWorkflow/WorkflowTable.tsx b/litmus-portal/frontend/src/views/CreateWorkflow/TuneWorkflow/WorkflowTable.tsx index a4776e3e5..bd62e69f4 100644 --- a/litmus-portal/frontend/src/views/CreateWorkflow/TuneWorkflow/WorkflowTable.tsx +++ b/litmus-portal/frontend/src/views/CreateWorkflow/TuneWorkflow/WorkflowTable.tsx @@ -87,11 +87,11 @@ const WorkflowTable = forwardRef( expData.push({ StepIndex: index, Name: chaosEngine.metadata.generateName, - Namespace: - chaosEngine.spec.appinfo?.appns === - '{{workflow.parameters.adminModeNamespace}}' - ? namespace - : chaosEngine.spec.appinfo?.appns ?? '', + Namespace: chaosEngine.spec.appinfo?.appns + .toLowerCase() + .includes('namespace') + ? namespace + : chaosEngine.spec.appinfo?.appns ?? '', Application: chaosEngine.spec.appinfo?.applabel ?? '', Probes: chaosEngine.spec.experiments[0].spec.probe?.length ?? 0, ChaosEngine: artifact.raw.data, diff --git a/litmus-portal/frontend/src/views/CreateWorkflow/TuneWorkflow/index.tsx b/litmus-portal/frontend/src/views/CreateWorkflow/TuneWorkflow/index.tsx index 1f9b1d273..433edc349 100644 --- a/litmus-portal/frontend/src/views/CreateWorkflow/TuneWorkflow/index.tsx +++ b/litmus-portal/frontend/src/views/CreateWorkflow/TuneWorkflow/index.tsx @@ -1,5 +1,6 @@ import { useLazyQuery } from '@apollo/client'; -import { Typography } from '@material-ui/core'; +import { Snackbar, Typography } from '@material-ui/core'; +import { Alert } from '@material-ui/lab'; import { ButtonFilled, ButtonOutlined, Modal } from 'litmus-ui'; import localforage from 'localforage'; import React, { @@ -36,6 +37,7 @@ import { RootState } from '../../../redux/reducers'; import capitalize from '../../../utils/capitalize'; import { getProjectID } from '../../../utils/getSearchParams'; import { + fetchWorkflowNameFromManifest, updateEngineName, updateManifestImage, updateNamespace, @@ -95,6 +97,7 @@ const TuneWorkflow = forwardRef((_, ref) => { const [addExpModal, setAddExpModal] = useState(false); const [editManifest, setEditManifest] = useState(''); const [confirmEdit, setConfirmEdit] = useState(false); + const [isAlertOpen, setIsAlertOpen] = useState(false); const [yamlValid, setYamlValid] = useState(true); const [editSequence, setEditSequence] = useState(false); const [steps, setSteps] = useState({}); @@ -374,6 +377,18 @@ const TuneWorkflow = forwardRef((_, ref) => { setAddExpModal(false); }; + const AlertBox: React.FC = () => ( + setIsAlertOpen(false)} + > + setIsAlertOpen(false)} severity="error"> + The YAML contains errors, resolve them first to proceed + + + ); + /** * UpdateCRD is used to updated the manifest while adding experiments from MyHub */ @@ -496,6 +511,17 @@ const TuneWorkflow = forwardRef((_, ref) => { } }, [experiment]); + const saveManifestChanges = () => { + if (yamlValid) { + workflowAction.setWorkflowManifest({ + manifest: editManifest, + }); + setYAMLModal(false); + } else { + setIsAlertOpen(true); + } + }; + useEffect(() => { const parsedManifest = manifest !== '' ? YAML.parse(manifest) : generatedYAML; @@ -577,41 +603,24 @@ const TuneWorkflow = forwardRef((_, ref) => { })); const LeftButtonWrapper = () => ( + { + setYAMLModal(true); + setConfirmEdit(false); + }} + className={classes.editBtn} + > + view YAML + {t('createWorkflow.tuneWorkflow.edit')} + + ); + + return ( <> - { - setYAMLModal(true); - setConfirmEdit(false); - }} - className={classes.editBtn} - > - view YAML - {t('createWorkflow.tuneWorkflow.edit')} - - { - setYAMLModal(false); - }} - width="90%" - height="90%" - modalActions={ - { - if (editManifest === '') { - setYAMLModal(false); - } else { - setConfirmEdit(true); - } - }} - className={classes.closeBtn} - > - cross - - } - > -
- {confirmEdit ? ( + + {YAMLModal ? ( + <> + {}} width="50%" height="30%">
{t('createWorkflow.tuneWorkflow.confirmText')} @@ -636,167 +645,184 @@ const TuneWorkflow = forwardRef((_, ref) => { {t('createWorkflow.tuneWorkflow.continue')}
- ) : ( - <> - - {t('createWorkflow.tuneWorkflow.updateChanges')} - - { - setYamlValid(btnState); - }} - saveWorkflowChange={(updatedManifest: string) => { - setEditManifest(updatedManifest); - }} - /> - { - workflowAction.setWorkflowManifest({ - manifest: editManifest === '' ? manifest : editManifest, - }); - setEditManifest(''); - setYAMLModal(false); - }} - > - {t('createWorkflow.tuneWorkflow.saveChange')} - - - )} -
-
- - ); - - return ( -
- {/* Header */} -
- - {t('createWorkflow.tuneWorkflow.header')} - - - - {selectedRadio === 'A' - ? t('createWorkflow.tuneWorkflow.selectedPreDefinedWorkflowInfo') - : selectedRadio === 'B' - ? t('createWorkflow.tuneWorkflow.selectedTemplateInfo') - : selectedRadio === 'C' - ? t('createWorkflow.tuneWorkflow.selectedCustomWorkflowInfo') - : t('createWorkflow.tuneWorkflow.selectedUploadYAML')}{' '} - - - {workflow.name.split('-').map((text) => `${capitalize(text)} `)} - - -
- {t('createWorkflow.tuneWorkflow.description')} -
- {selectedRadio === 'C' ? ( -
- {LeftButtonWrapper()} - { - setSelectedExp(''); - setAddExpModal(true); - }} - > - {t('createWorkflow.tuneWorkflow.addANewExperiment')} - + +
+
+
+ Terminal Icon + + {fetchWorkflowNameFromManifest(manifest)}.yaml + +
+
+ { + saveManifestChanges(); + }} + className={classes.editorTopBtn} + > + Save Changes + +
+ + yamlValid ? setConfirmEdit(true) : setIsAlertOpen(true) + } + className={classes.editorCloseBtn} + > + x + +
- ) : ( - <>{LeftButtonWrapper()} - )} - -
+ { + setYamlValid(btnState); + }} + saveWorkflowChange={(updatedManifest: string) => { + setEditManifest(updatedManifest); + }} + /> +
+ + ) : ( +
+ {/* Header */} +
+ + {t('createWorkflow.tuneWorkflow.header')} + + + + {selectedRadio === 'A' + ? t( + 'createWorkflow.tuneWorkflow.selectedPreDefinedWorkflowInfo' + ) + : selectedRadio === 'B' + ? t('createWorkflow.tuneWorkflow.selectedTemplateInfo') + : selectedRadio === 'C' + ? t('createWorkflow.tuneWorkflow.selectedCustomWorkflowInfo') + : t('createWorkflow.tuneWorkflow.selectedUploadYAML')}{' '} + + + {workflow.name + .split('-') + .map((text) => `${capitalize(text)} `)} + + +
+ {t('createWorkflow.tuneWorkflow.description')} +
+ {selectedRadio === 'C' ? ( +
+ {LeftButtonWrapper()} + { + setSelectedExp(''); + setAddExpModal(true); + }} + > + {t('createWorkflow.tuneWorkflow.addANewExperiment')} + +
+ ) : ( + <>{LeftButtonWrapper()} + )} +
+
- {/* Add Experiment Modal */} - + {/* Add Experiment Modal */} + - {/* Experiment Details */} -
- {/* Edit Button */} - {manifest !== '' && ( - setEditSequence(true)}> - Edit Sequence{' '} - - {t('createWorkflow.tuneWorkflow.editSequence')} - - )} - { - setEditSequence(false); - }} - width="60%" - modalActions={ - { + {/* Experiment Details */} +
+ {/* Edit Button */} + {manifest !== '' && ( + setEditSequence(true)}> + Edit Sequence{' '} + + {t('createWorkflow.tuneWorkflow.editSequence')} + + )} + { setEditSequence(false); }} - className={classes.closeBtn} - > - cross - - } - > -
-
- - {t('createWorkflow.tuneWorkflow.editSequence')} - - - {t('createWorkflow.tuneWorkflow.dragndrop')} - -
- - - - - - { - setEditSequence(sequenceState); + width="60%" + modalActions={ + { + setEditSequence(false); }} + className={classes.closeBtn} + > + cross + + } + > +
+
+ + {t('createWorkflow.tuneWorkflow.editSequence')} + + + {t('createWorkflow.tuneWorkflow.dragndrop')} + +
+ + + + + + { + setEditSequence(sequenceState); + }} + /> + + +
+ + {/* Details Section -> Graph on the Left and Table on the Right */} + + {/* Details Section -> Graph on the Left and Table on the Right */} + + {/* Argo Workflow Graph */} + + + + {/* Workflow Table */} + +
-
- {/* Details Section -> Graph on the Left and Table on the Right */} - - {/* Argo Workflow Graph */} - - - - {/* Workflow Table */} - - - - -
-
+
+ )} + ); }); diff --git a/litmus-portal/frontend/src/views/CreateWorkflow/TuneWorkflow/styles.ts b/litmus-portal/frontend/src/views/CreateWorkflow/TuneWorkflow/styles.ts index 9a9d15716..75c58b649 100644 --- a/litmus-portal/frontend/src/views/CreateWorkflow/TuneWorkflow/styles.ts +++ b/litmus-portal/frontend/src/views/CreateWorkflow/TuneWorkflow/styles.ts @@ -10,6 +10,10 @@ const useStyles = makeStyles((theme) => ({ height: '100%', }, + editorWrapper: { + marginBottom: theme.spacing(-4), + }, + // Header headerWrapper: { padding: theme.spacing(0, 7), @@ -27,10 +31,10 @@ const useStyles = makeStyles((theme) => ({ headerBtn: { display: 'flex', justifyContent: 'space-between', - width: '40%', - [theme.breakpoints.up('lg')]: { - width: '25%', - }, + width: '23rem', + // [theme.breakpoints.up('lg')]: { + // width: '30rem', + // }, }, descriptionWrapper: { @@ -152,15 +156,34 @@ const useStyles = makeStyles((theme) => ({ }, // Editor - editor: { - height: '100%', + flex: { + display: 'flex', + }, + additional: { + width: '95%', + margin: '0rem auto', + justifyContent: 'space-between', + }, + name: { + margin: theme.spacing(1, 0, 2, 2), + fontWeight: 'bold', + }, + editorTopBtn: { + padding: '0.4rem', + fontSize: '0.8rem', + }, + editorCloseBtn: { + width: '0.5rem', + borderColor: theme.palette.disabledBackground, + color: theme.palette.text.disabled, + minWidth: '2rem', + padding: '0.2rem', + fontSize: '1rem', }, // Confirmation Modal confirmDiv: { - margin: 'auto', - marginTop: theme.spacing(31.25), - width: '30rem', + margin: '2rem auto', }, confirmText: { fontSize: '2.25rem', @@ -171,11 +194,6 @@ const useStyles = makeStyles((theme) => ({ continueBtn: { marginTop: theme.spacing(2.5), }, - updateText: { - fontSize: '1.6rem', - marginBottom: theme.spacing(3.75), - textAlign: 'left', - }, // Sequence Modal sequenceMainDiv: { diff --git a/litmus-portal/frontend/src/views/CreateWorkflow/VerifyCommit/index.tsx b/litmus-portal/frontend/src/views/CreateWorkflow/VerifyCommit/index.tsx index b257cc36b..13b8e2e90 100644 --- a/litmus-portal/frontend/src/views/CreateWorkflow/VerifyCommit/index.tsx +++ b/litmus-portal/frontend/src/views/CreateWorkflow/VerifyCommit/index.tsx @@ -139,11 +139,6 @@ const VerifyCommit = forwardRef( setOpen(true); }; - const handleClose = () => { - setModified(true); - setOpen(false); - }; - const handleNameChange = ({ changedName }: { changedName: string }) => { setWorkflow({ ...workflow, @@ -343,224 +338,242 @@ const VerifyCommit = forwardRef( return ( <> -
-
-
-
- - {t('createWorkflow.verifyCommit.header')} - - - {t('createWorkflow.verifyCommit.info')} + {open ? ( +
+
+
+ Terminal Icon + + {fetchWorkflowNameFromManifest(manifest)}.yaml
- bfinance + + setOpen(false)} + className={classes.editorCloseBtn} + > + x +
- - - - {t('createWorkflow.verifyCommit.summary.header')} - - -
-
- - {t('createWorkflow.verifyCommit.summary.workflowName')}: - - -
-
- - handleNameChange({ changedName: value }) - } - helperText={ - checkNameValidation() - ? `${t( - `createWorkflow.verifyCommit.workflowNameValidationMessage` - )}` - : undefined - } - /> -
-
-
-
- - {t('createWorkflow.verifyCommit.summary.clustername')}: - - - {clustername} -
-
- - {t('createWorkflow.verifyCommit.summary.desc')}: - - -
- {workflow.description !== '' ? ( -
- - handleDescChange({ changedDesc: value }) - } - /> -
- ) : null} -
-
-
-
- - {t('createWorkflow.verifyCommit.summary.subject')}: + +
+ ) : ( +
+
+
+
+ + {t('createWorkflow.verifyCommit.header')} + + + {t('createWorkflow.verifyCommit.info')} - - {t('createWorkflow.verifyCommit.summary.subjectDesc')} - - } - > - -
+ bfinance +
+ -
- {subject !== '' ? ( + + {t('createWorkflow.verifyCommit.summary.header')} + + +
+
+ + {t('createWorkflow.verifyCommit.summary.workflowName')}: + + +
- handleSubjectChange({ changedSubject: value }) + handleNameChange({ changedName: value }) } helperText={ - checkSubjectValidation() + checkNameValidation() ? `${t( - 'createWorkflow.verifyCommit.subjectValidationMessage' + `createWorkflow.verifyCommit.workflowNameValidationMessage` )}` : undefined } />
- ) : null} -
-
-
- - {t('createWorkflow.verifyCommit.summary.schedule')}: - - -
-
- {cronSyntax === '' ? ( - - {t('createWorkflow.verifyCommit.summary.schedulingNow')} - - ) : ( - {cronstrue.toString(cronSyntax)} - )} - - handleGoToStep(5)} - className={classes.editIcon} - data-cy="edit" - />
-
-
- - {t('createWorkflow.verifyCommit.summary.adjustedWeights')}: - - {weights.length === 0 ? ( - - {t('createWorkflow.verifyCommit.error')} +
+ + {t('createWorkflow.verifyCommit.summary.clustername')}: - ) : ( + + + {clustername} + +
+
+ + {t('createWorkflow.verifyCommit.summary.desc')}: + +
-
- {WorkflowTestData.map((Test) => ( - + + handleDescChange({ changedDesc: value }) + } /> - ))} -
- handleGoToStep(4)} - data-cy="testRunButton" - > - {t('createWorkflow.verifyCommit.button.edit')} - +
+ ) : null}
- )} -
-
- - {t('createWorkflow.verifyCommit.YAML')} - -
+
+
+
+ + {t('createWorkflow.verifyCommit.summary.subject')}: + + + {t('createWorkflow.verifyCommit.summary.subjectDesc')} + + } + > + + +
+ +
+ {subject !== '' ? ( +
+ + handleSubjectChange({ changedSubject: value }) + } + helperText={ + checkSubjectValidation() + ? `${t( + 'createWorkflow.verifyCommit.subjectValidationMessage' + )}` + : undefined + } + /> +
+ ) : null} +
+
+
+ + {t('createWorkflow.verifyCommit.summary.schedule')}: + + +
+
+ {cronSyntax === '' ? ( + + {t( + 'createWorkflow.verifyCommit.summary.schedulingNow' + )} + + ) : ( + + {cronstrue.toString(cronSyntax)} + + )} + + handleGoToStep(5)} + className={classes.editIcon} + data-cy="edit" + /> +
+
+
+
+ + {t('createWorkflow.verifyCommit.summary.adjustedWeights')}: + {weights.length === 0 ? ( - - {t('createWorkflow.verifyCommit.errYaml')} + + {t('createWorkflow.verifyCommit.error')} ) : ( - - {yamlStatus} - - {t('createWorkflow.verifyCommit.youCanMoveOn')} - - +
+
+ {WorkflowTestData.map((Test) => ( + + ))} +
+ handleGoToStep(4)} + data-cy="testRunButton" + > + {t('createWorkflow.verifyCommit.button.edit')} + +
)} -
- - {t('createWorkflow.verifyCommit.button.viewYaml')} - +
+
+ + {t('createWorkflow.verifyCommit.YAML')} + +
+ {weights.length === 0 ? ( + + {t('createWorkflow.verifyCommit.errYaml')} + + ) : ( + + {yamlStatus} + + {t('createWorkflow.verifyCommit.youCanMoveOn')} + + + )} +
+ + {t('createWorkflow.verifyCommit.button.viewYaml')} + +
-
- - - ✕ - - } - > - - + )} {/* Finish Modal */}
diff --git a/litmus-portal/frontend/src/views/CreateWorkflow/VerifyCommit/styles.ts b/litmus-portal/frontend/src/views/CreateWorkflow/VerifyCommit/styles.ts index 82fd30882..e1066aecf 100644 --- a/litmus-portal/frontend/src/views/CreateWorkflow/VerifyCommit/styles.ts +++ b/litmus-portal/frontend/src/views/CreateWorkflow/VerifyCommit/styles.ts @@ -166,5 +166,34 @@ const useStyles = makeStyles((theme: Theme) => ({ bold: { fontWeight: 700, }, + + // Editor + editorWrapper: { + marginBottom: theme.spacing(-4), + }, + flex: { + display: 'flex', + }, + additional: { + width: '95%', + margin: '0rem auto', + justifyContent: 'space-between', + }, + name: { + margin: theme.spacing(1, 0, 2, 2), + fontWeight: 'bold', + }, + editorTopBtn: { + padding: '0.4rem', + fontSize: '0.8rem', + }, + editorCloseBtn: { + width: '0.5rem', + borderColor: theme.palette.disabledBackground, + color: theme.palette.text.disabled, + minWidth: '2rem', + padding: '0.2rem', + fontSize: '1rem', + }, })); export default useStyles; diff --git a/litmus-portal/frontend/src/views/CreateWorkflow/WorkflowSettings/index.tsx b/litmus-portal/frontend/src/views/CreateWorkflow/WorkflowSettings/index.tsx index 908c2f67f..31d7b6904 100644 --- a/litmus-portal/frontend/src/views/CreateWorkflow/WorkflowSettings/index.tsx +++ b/litmus-portal/frontend/src/views/CreateWorkflow/WorkflowSettings/index.tsx @@ -35,6 +35,9 @@ const WorkflowSettings = forwardRef((_, ref) => { // Actions const workflowAction = useActions(WorkflowActions); const workflowData = useSelector((state: RootState) => state.workflowData); + const { manifest } = useSelector( + (state: RootState) => state.workflowManifest + ); const { t } = useTranslation(); const alert = useActions(AlertActions); @@ -95,7 +98,7 @@ const WorkflowSettings = forwardRef((_, ref) => { } if ((value as ChooseWorkflowRadio).selected === 'C') { setName('custom-chaos-workflow'); - workflowAction.setWorkflowManifest({ manifest: '' }); + workflowAction.setWorkflowManifest({ manifest: manifest ?? '' }); setDescription('Custom Chaos Workflow'); setIcon('./avatars/litmus.svg'); }