🔨 Making Graph Visualization Green + Fixing Editor UI (#2833)
Signed-off-by: Sayan Mondal <sayan@chaosnative.com>
This commit is contained in:
parent
0c49869d10
commit
6563d0f435
|
|
@ -13,7 +13,11 @@ 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 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';
|
||||
import 'ace-builds/src-min-noconflict/ext-code_lens';
|
||||
import 'ace-builds/src-min-noconflict/ext-elastic_tabstops_lite';
|
||||
|
|
@ -36,10 +40,6 @@ 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 React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import useStyles from './styles';
|
||||
import { AceValidations, parseYamlValidations } from './Validations';
|
||||
|
||||
interface YamlEditorProps {
|
||||
content: string;
|
||||
|
|
@ -47,6 +47,7 @@ interface YamlEditorProps {
|
|||
readOnly: boolean;
|
||||
setButtonState?: (btnState: boolean) => void;
|
||||
saveWorkflowChange?: (updatedManifest: string) => void;
|
||||
className?: Object;
|
||||
}
|
||||
|
||||
const YamlEditor: React.FC<YamlEditorProps> = ({
|
||||
|
|
@ -55,6 +56,7 @@ const YamlEditor: React.FC<YamlEditorProps> = ({
|
|||
readOnly,
|
||||
setButtonState,
|
||||
saveWorkflowChange,
|
||||
className,
|
||||
}) => {
|
||||
const classes = useStyles();
|
||||
const { palette } = useTheme();
|
||||
|
|
@ -232,7 +234,7 @@ const YamlEditor: React.FC<YamlEditorProps> = ({
|
|||
|
||||
return (
|
||||
<div
|
||||
className={classes.editorBackgroundFull}
|
||||
className={`${classes.editorBackgroundFull} ${className}`}
|
||||
id="editor"
|
||||
data-cy="WorkflowEditor"
|
||||
>
|
||||
|
|
@ -439,121 +441,111 @@ const YamlEditor: React.FC<YamlEditorProps> = ({
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className={classes.fullWidth}>
|
||||
<Box display="flex" p={1} className={classes.editorContainer}>
|
||||
<Box
|
||||
p={1}
|
||||
flexGrow={1}
|
||||
className={classes.editorGrid}
|
||||
id="resize-editor"
|
||||
<div className={classes.editor}>
|
||||
<AceEditor
|
||||
mode="yaml"
|
||||
theme="cobalt"
|
||||
name="code"
|
||||
width="100%"
|
||||
height="100%"
|
||||
maxLines={12000}
|
||||
minLines={1}
|
||||
highlightActiveLine={false}
|
||||
readOnly={readOnly}
|
||||
tabSize={2}
|
||||
wrapEnabled
|
||||
ref={YamlAce}
|
||||
showGutter
|
||||
onChange={onEditorChange}
|
||||
showPrintMargin={false}
|
||||
enableBasicAutocompletion
|
||||
enableSnippets
|
||||
enableLiveAutocompletion
|
||||
value={editorState.content}
|
||||
editorProps={{
|
||||
$blockScrolling: Infinity,
|
||||
$useWorker: true,
|
||||
}}
|
||||
onLoad={(editor) => {
|
||||
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,
|
||||
});
|
||||
|
||||
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(
|
||||
'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}
|
||||
/>
|
||||
<Box p={1} flexGrow={0} className={classes.fullScreenGrid}>
|
||||
<Tooltip
|
||||
title="Full Screen (Press Escape to End)"
|
||||
placement="bottom"
|
||||
TransitionComponent={Fade}
|
||||
TransitionProps={{ timeout: 500 }}
|
||||
arrow
|
||||
>
|
||||
<AceEditor
|
||||
mode="yaml"
|
||||
theme="cobalt"
|
||||
name="code"
|
||||
width="100%"
|
||||
height="100%"
|
||||
maxLines={12000}
|
||||
minLines={1}
|
||||
highlightActiveLine={false}
|
||||
readOnly={readOnly}
|
||||
tabSize={2}
|
||||
wrapEnabled
|
||||
ref={YamlAce}
|
||||
showGutter
|
||||
onChange={onEditorChange}
|
||||
showPrintMargin={false}
|
||||
enableBasicAutocompletion
|
||||
enableSnippets
|
||||
enableLiveAutocompletion
|
||||
value={editorState.content}
|
||||
editorProps={{
|
||||
$blockScrolling: Infinity,
|
||||
$useWorker: true,
|
||||
}}
|
||||
onLoad={(editor) => {
|
||||
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,
|
||||
});
|
||||
|
||||
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(
|
||||
'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}
|
||||
<Button
|
||||
variant="outlined"
|
||||
className={classes.editorButtonFullScreen}
|
||||
onClick={fullscreentrigger}
|
||||
startIcon={
|
||||
<img
|
||||
src="/icons/fullscreen.svg"
|
||||
alt="Full Screen"
|
||||
color={palette.secondary.contrastText}
|
||||
className={classes.fullScreenIcon}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box p={1} flexGrow={0} className={classes.fullScreenGrid}>
|
||||
<Tooltip
|
||||
title="Full Screen (Press Escape to End)"
|
||||
placement="bottom"
|
||||
TransitionComponent={Fade}
|
||||
TransitionProps={{ timeout: 500 }}
|
||||
arrow
|
||||
>
|
||||
<Button
|
||||
variant="outlined"
|
||||
className={classes.editorButtonFullScreen}
|
||||
onClick={fullscreentrigger}
|
||||
startIcon={
|
||||
<img
|
||||
src="/icons/fullscreen.svg"
|
||||
alt="Full Screen"
|
||||
color={palette.secondary.contrastText}
|
||||
className={classes.fullScreenIcon}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
</div>
|
||||
<div className={classes.extraSpace} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -52,14 +52,11 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|||
justifyContent: 'space-between',
|
||||
},
|
||||
|
||||
editorContainer: {
|
||||
marginTop: theme.spacing(4),
|
||||
},
|
||||
editor: {
|
||||
overflowY: 'auto',
|
||||
margin: theme.spacing(2, 0),
|
||||
height: '40vh',
|
||||
|
||||
editorGrid: {
|
||||
overflow: 'auto',
|
||||
height: '50vh',
|
||||
width: '100%',
|
||||
'&::-webkit-scrollbar': {
|
||||
width: '0.2em',
|
||||
},
|
||||
|
|
@ -69,28 +66,6 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|||
'&::-webkit-scrollbar-thumb': {
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
},
|
||||
[theme.breakpoints.down('xl')]: {
|
||||
height: '84vh',
|
||||
},
|
||||
[theme.breakpoints.down('lg')]: {
|
||||
height: '56vh',
|
||||
},
|
||||
[theme.breakpoints.down('md')]: {
|
||||
height: '49vh',
|
||||
},
|
||||
|
||||
[theme.breakpoints.down('sm')]: {
|
||||
height: '40vh',
|
||||
},
|
||||
[theme.breakpoints.down('xs')]: {
|
||||
height: '30vh',
|
||||
},
|
||||
},
|
||||
|
||||
extraSpace: {
|
||||
backgroundColor: theme.palette.common.black,
|
||||
height: '2rem',
|
||||
width: '100%',
|
||||
},
|
||||
|
||||
editorButtons: {
|
||||
|
|
@ -257,6 +232,7 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|||
|
||||
fullWidth: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
|
||||
fullScreenIcon: {
|
||||
|
|
|
|||
|
|
@ -9,20 +9,20 @@ import React, {
|
|||
} from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { constants } from '../../../constants';
|
||||
import {
|
||||
GET_CLUSTER,
|
||||
GET_IMAGE_REGISTRY,
|
||||
LIST_IMAGE_REGISTRY,
|
||||
} from '../../../graphql';
|
||||
import { ImageRegistryInfo } from '../../../models/redux/image_registry';
|
||||
import useActions from '../../../redux/actions';
|
||||
import * as AlertActions from '../../../redux/actions/alert';
|
||||
import * as WorkflowActions from '../../../redux/actions/workflow';
|
||||
import * as ImageRegistryActions from '../../../redux/actions/image_registry';
|
||||
import * as WorkflowActions from '../../../redux/actions/workflow';
|
||||
import { RootState } from '../../../redux/reducers';
|
||||
import { getProjectID, getProjectRole } from '../../../utils/getSearchParams';
|
||||
import useStyles from './styles';
|
||||
import { ImageRegistryInfo } from '../../../models/redux/image_registry';
|
||||
import { constants } from '../../../constants';
|
||||
|
||||
interface Cluster {
|
||||
cluster_name: string;
|
||||
|
|
|
|||
|
|
@ -100,11 +100,11 @@ const WorkflowPreview: React.FC<WorkflowPreviewProps> = ({
|
|||
for (let j = 0; j < updatedSteps[i].length; j++) {
|
||||
data.nodes.push({
|
||||
id: k.toString(),
|
||||
class: `${'pending'} ${'steps'}`,
|
||||
class: `${'succeeded'} ${'steps'}`,
|
||||
label: createLabel({
|
||||
label: updatedSteps[i][j].name,
|
||||
tooltip: updatedSteps[i][j].name,
|
||||
phase: 'pending',
|
||||
phase: 'succeeded',
|
||||
horizontal,
|
||||
}),
|
||||
labelType:
|
||||
|
|
@ -120,7 +120,7 @@ const WorkflowPreview: React.FC<WorkflowPreviewProps> = ({
|
|||
label: createLabel({
|
||||
label: updatedSteps[i][0].name,
|
||||
tooltip: updatedSteps[i][0].name,
|
||||
phase: 'pending',
|
||||
phase: 'succeeded',
|
||||
horizontal,
|
||||
}),
|
||||
labelType:
|
||||
|
|
@ -148,7 +148,7 @@ const WorkflowPreview: React.FC<WorkflowPreviewProps> = ({
|
|||
data.links.push({
|
||||
source: nodeID.toString(),
|
||||
target: (nodeID + j + 1).toString(),
|
||||
class: 'pending',
|
||||
class: 'succeeded',
|
||||
config: {
|
||||
arrowhead:
|
||||
updatedSteps[i][0].name !== 'StepGroup'
|
||||
|
|
@ -170,7 +170,7 @@ const WorkflowPreview: React.FC<WorkflowPreviewProps> = ({
|
|||
data.links.push({
|
||||
source: (nodeID + j + 1).toString(),
|
||||
target: (nodeID + updatedSteps[i].length + 1).toString(),
|
||||
class: 'pending',
|
||||
class: 'succeeded',
|
||||
config: {
|
||||
arrowhead:
|
||||
updatedSteps[i][0].name !== 'StepGroup'
|
||||
|
|
@ -191,7 +191,7 @@ const WorkflowPreview: React.FC<WorkflowPreviewProps> = ({
|
|||
data.links.push({
|
||||
source: nodeID.toString(),
|
||||
target: (nodeID + 1).toString(),
|
||||
class: 'pending',
|
||||
class: 'succeeded',
|
||||
config: {
|
||||
arrowhead:
|
||||
updatedSteps[i][0].name !== 'StepGroup' ? 'undirected' : 'vee',
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|||
cursor: 'pointer',
|
||||
fill: 'none',
|
||||
'& circle': {
|
||||
fill: theme.palette.status.pending.text,
|
||||
fill: theme.palette.status.completed.text,
|
||||
},
|
||||
'& g.label g': {
|
||||
transform: (props: StyleProps) =>
|
||||
|
|
@ -31,20 +31,20 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|||
fill: theme.palette.text.primary,
|
||||
},
|
||||
},
|
||||
'& path.pendingIcon': {
|
||||
'& path.succeededIcon': {
|
||||
transform: (props: StyleProps) =>
|
||||
`scale(1.8) translate(-5px, ${props.horizontal ? -3.6 : -2.5}px)`,
|
||||
`scale(1.8) translate(-5px, ${props.horizontal ? -3.6 : -1}px)`,
|
||||
},
|
||||
'& g.StepGroup.Pending': {
|
||||
fill: theme.palette.status.pending.text,
|
||||
'& g.StepGroup.Succeeded': {
|
||||
fill: theme.palette.status.completed.text,
|
||||
},
|
||||
},
|
||||
|
||||
// Styles for edges
|
||||
'& g g.edgePaths': {
|
||||
'& g.pending': {
|
||||
fill: theme.palette.status.pending.text,
|
||||
stroke: theme.palette.status.pending.text,
|
||||
'& g.succeeded': {
|
||||
fill: theme.palette.status.completed.text,
|
||||
stroke: theme.palette.status.completed.text,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -593,7 +593,8 @@ const TuneWorkflow = forwardRef((_, ref) => {
|
|||
onClose={() => {
|
||||
setYAMLModal(false);
|
||||
}}
|
||||
width="60%"
|
||||
width="90%"
|
||||
height="90%"
|
||||
modalActions={
|
||||
<ButtonOutlined
|
||||
onClick={() => {
|
||||
|
|
@ -643,6 +644,7 @@ const TuneWorkflow = forwardRef((_, ref) => {
|
|||
<YamlEditor
|
||||
content={manifest}
|
||||
filename={workflow.name}
|
||||
className={classes.editor}
|
||||
readOnly={false}
|
||||
setButtonState={(btnState: boolean) => {
|
||||
setYamlValid(btnState);
|
||||
|
|
|
|||
|
|
@ -151,6 +151,11 @@ const useStyles = makeStyles((theme) => ({
|
|||
margin: theme.spacing(8, 5, 5, 5),
|
||||
},
|
||||
|
||||
// Editor
|
||||
editor: {
|
||||
height: '100%',
|
||||
},
|
||||
|
||||
// Confirmation Modal
|
||||
confirmDiv: {
|
||||
margin: 'auto',
|
||||
|
|
|
|||
Loading…
Reference in New Issue