🔨 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 UndoTwoToneIcon from '@material-ui/icons/UndoTwoTone';
|
||||||
import UnfoldLessTwoToneIcon from '@material-ui/icons/UnfoldLessTwoTone';
|
import UnfoldLessTwoToneIcon from '@material-ui/icons/UnfoldLessTwoTone';
|
||||||
import UnfoldMoreTwoToneIcon from '@material-ui/icons/UnfoldMoreTwoTone';
|
import UnfoldMoreTwoToneIcon from '@material-ui/icons/UnfoldMoreTwoTone';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
import AceEditor from 'react-ace';
|
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-beautify';
|
||||||
import 'ace-builds/src-min-noconflict/ext-code_lens';
|
import 'ace-builds/src-min-noconflict/ext-code_lens';
|
||||||
import 'ace-builds/src-min-noconflict/ext-elastic_tabstops_lite';
|
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 'ace-builds/src-min-noconflict/ext-whitespace';
|
||||||
import 'brace/mode/yaml';
|
import 'brace/mode/yaml';
|
||||||
import 'brace/theme/cobalt';
|
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 {
|
interface YamlEditorProps {
|
||||||
content: string;
|
content: string;
|
||||||
|
|
@ -47,6 +47,7 @@ interface YamlEditorProps {
|
||||||
readOnly: boolean;
|
readOnly: boolean;
|
||||||
setButtonState?: (btnState: boolean) => void;
|
setButtonState?: (btnState: boolean) => void;
|
||||||
saveWorkflowChange?: (updatedManifest: string) => void;
|
saveWorkflowChange?: (updatedManifest: string) => void;
|
||||||
|
className?: Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
const YamlEditor: React.FC<YamlEditorProps> = ({
|
const YamlEditor: React.FC<YamlEditorProps> = ({
|
||||||
|
|
@ -55,6 +56,7 @@ const YamlEditor: React.FC<YamlEditorProps> = ({
|
||||||
readOnly,
|
readOnly,
|
||||||
setButtonState,
|
setButtonState,
|
||||||
saveWorkflowChange,
|
saveWorkflowChange,
|
||||||
|
className,
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const { palette } = useTheme();
|
const { palette } = useTheme();
|
||||||
|
|
@ -232,7 +234,7 @@ const YamlEditor: React.FC<YamlEditorProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classes.editorBackgroundFull}
|
className={`${classes.editorBackgroundFull} ${className}`}
|
||||||
id="editor"
|
id="editor"
|
||||||
data-cy="WorkflowEditor"
|
data-cy="WorkflowEditor"
|
||||||
>
|
>
|
||||||
|
|
@ -439,14 +441,7 @@ const YamlEditor: React.FC<YamlEditorProps> = ({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.fullWidth}>
|
<div className={classes.editor}>
|
||||||
<Box display="flex" p={1} className={classes.editorContainer}>
|
|
||||||
<Box
|
|
||||||
p={1}
|
|
||||||
flexGrow={1}
|
|
||||||
className={classes.editorGrid}
|
|
||||||
id="resize-editor"
|
|
||||||
>
|
|
||||||
<AceEditor
|
<AceEditor
|
||||||
mode="yaml"
|
mode="yaml"
|
||||||
theme="cobalt"
|
theme="cobalt"
|
||||||
|
|
@ -527,7 +522,6 @@ const YamlEditor: React.FC<YamlEditorProps> = ({
|
||||||
annotations={editorState.annotations}
|
annotations={editorState.annotations}
|
||||||
markers={editorState.markers}
|
markers={editorState.markers}
|
||||||
/>
|
/>
|
||||||
</Box>
|
|
||||||
<Box p={1} flexGrow={0} className={classes.fullScreenGrid}>
|
<Box p={1} flexGrow={0} className={classes.fullScreenGrid}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title="Full Screen (Press Escape to End)"
|
title="Full Screen (Press Escape to End)"
|
||||||
|
|
@ -551,9 +545,7 @@ const YamlEditor: React.FC<YamlEditorProps> = ({
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.extraSpace} />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -52,14 +52,11 @@ const useStyles = makeStyles((theme: Theme) => ({
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
},
|
},
|
||||||
|
|
||||||
editorContainer: {
|
editor: {
|
||||||
marginTop: theme.spacing(4),
|
overflowY: 'auto',
|
||||||
},
|
margin: theme.spacing(2, 0),
|
||||||
|
height: '40vh',
|
||||||
|
|
||||||
editorGrid: {
|
|
||||||
overflow: 'auto',
|
|
||||||
height: '50vh',
|
|
||||||
width: '100%',
|
|
||||||
'&::-webkit-scrollbar': {
|
'&::-webkit-scrollbar': {
|
||||||
width: '0.2em',
|
width: '0.2em',
|
||||||
},
|
},
|
||||||
|
|
@ -69,28 +66,6 @@ const useStyles = makeStyles((theme: Theme) => ({
|
||||||
'&::-webkit-scrollbar-thumb': {
|
'&::-webkit-scrollbar-thumb': {
|
||||||
backgroundColor: theme.palette.primary.main,
|
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: {
|
editorButtons: {
|
||||||
|
|
@ -257,6 +232,7 @@ const useStyles = makeStyles((theme: Theme) => ({
|
||||||
|
|
||||||
fullWidth: {
|
fullWidth: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
},
|
},
|
||||||
|
|
||||||
fullScreenIcon: {
|
fullScreenIcon: {
|
||||||
|
|
|
||||||
|
|
@ -9,20 +9,20 @@ import React, {
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
import { constants } from '../../../constants';
|
||||||
import {
|
import {
|
||||||
GET_CLUSTER,
|
GET_CLUSTER,
|
||||||
GET_IMAGE_REGISTRY,
|
GET_IMAGE_REGISTRY,
|
||||||
LIST_IMAGE_REGISTRY,
|
LIST_IMAGE_REGISTRY,
|
||||||
} from '../../../graphql';
|
} from '../../../graphql';
|
||||||
|
import { ImageRegistryInfo } from '../../../models/redux/image_registry';
|
||||||
import useActions from '../../../redux/actions';
|
import useActions from '../../../redux/actions';
|
||||||
import * as AlertActions from '../../../redux/actions/alert';
|
import * as AlertActions from '../../../redux/actions/alert';
|
||||||
import * as WorkflowActions from '../../../redux/actions/workflow';
|
|
||||||
import * as ImageRegistryActions from '../../../redux/actions/image_registry';
|
import * as ImageRegistryActions from '../../../redux/actions/image_registry';
|
||||||
|
import * as WorkflowActions from '../../../redux/actions/workflow';
|
||||||
import { RootState } from '../../../redux/reducers';
|
import { RootState } from '../../../redux/reducers';
|
||||||
import { getProjectID, getProjectRole } from '../../../utils/getSearchParams';
|
import { getProjectID, getProjectRole } from '../../../utils/getSearchParams';
|
||||||
import useStyles from './styles';
|
import useStyles from './styles';
|
||||||
import { ImageRegistryInfo } from '../../../models/redux/image_registry';
|
|
||||||
import { constants } from '../../../constants';
|
|
||||||
|
|
||||||
interface Cluster {
|
interface Cluster {
|
||||||
cluster_name: string;
|
cluster_name: string;
|
||||||
|
|
|
||||||
|
|
@ -100,11 +100,11 @@ const WorkflowPreview: React.FC<WorkflowPreviewProps> = ({
|
||||||
for (let j = 0; j < updatedSteps[i].length; j++) {
|
for (let j = 0; j < updatedSteps[i].length; j++) {
|
||||||
data.nodes.push({
|
data.nodes.push({
|
||||||
id: k.toString(),
|
id: k.toString(),
|
||||||
class: `${'pending'} ${'steps'}`,
|
class: `${'succeeded'} ${'steps'}`,
|
||||||
label: createLabel({
|
label: createLabel({
|
||||||
label: updatedSteps[i][j].name,
|
label: updatedSteps[i][j].name,
|
||||||
tooltip: updatedSteps[i][j].name,
|
tooltip: updatedSteps[i][j].name,
|
||||||
phase: 'pending',
|
phase: 'succeeded',
|
||||||
horizontal,
|
horizontal,
|
||||||
}),
|
}),
|
||||||
labelType:
|
labelType:
|
||||||
|
|
@ -120,7 +120,7 @@ const WorkflowPreview: React.FC<WorkflowPreviewProps> = ({
|
||||||
label: createLabel({
|
label: createLabel({
|
||||||
label: updatedSteps[i][0].name,
|
label: updatedSteps[i][0].name,
|
||||||
tooltip: updatedSteps[i][0].name,
|
tooltip: updatedSteps[i][0].name,
|
||||||
phase: 'pending',
|
phase: 'succeeded',
|
||||||
horizontal,
|
horizontal,
|
||||||
}),
|
}),
|
||||||
labelType:
|
labelType:
|
||||||
|
|
@ -148,7 +148,7 @@ const WorkflowPreview: React.FC<WorkflowPreviewProps> = ({
|
||||||
data.links.push({
|
data.links.push({
|
||||||
source: nodeID.toString(),
|
source: nodeID.toString(),
|
||||||
target: (nodeID + j + 1).toString(),
|
target: (nodeID + j + 1).toString(),
|
||||||
class: 'pending',
|
class: 'succeeded',
|
||||||
config: {
|
config: {
|
||||||
arrowhead:
|
arrowhead:
|
||||||
updatedSteps[i][0].name !== 'StepGroup'
|
updatedSteps[i][0].name !== 'StepGroup'
|
||||||
|
|
@ -170,7 +170,7 @@ const WorkflowPreview: React.FC<WorkflowPreviewProps> = ({
|
||||||
data.links.push({
|
data.links.push({
|
||||||
source: (nodeID + j + 1).toString(),
|
source: (nodeID + j + 1).toString(),
|
||||||
target: (nodeID + updatedSteps[i].length + 1).toString(),
|
target: (nodeID + updatedSteps[i].length + 1).toString(),
|
||||||
class: 'pending',
|
class: 'succeeded',
|
||||||
config: {
|
config: {
|
||||||
arrowhead:
|
arrowhead:
|
||||||
updatedSteps[i][0].name !== 'StepGroup'
|
updatedSteps[i][0].name !== 'StepGroup'
|
||||||
|
|
@ -191,7 +191,7 @@ const WorkflowPreview: React.FC<WorkflowPreviewProps> = ({
|
||||||
data.links.push({
|
data.links.push({
|
||||||
source: nodeID.toString(),
|
source: nodeID.toString(),
|
||||||
target: (nodeID + 1).toString(),
|
target: (nodeID + 1).toString(),
|
||||||
class: 'pending',
|
class: 'succeeded',
|
||||||
config: {
|
config: {
|
||||||
arrowhead:
|
arrowhead:
|
||||||
updatedSteps[i][0].name !== 'StepGroup' ? 'undirected' : 'vee',
|
updatedSteps[i][0].name !== 'StepGroup' ? 'undirected' : 'vee',
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ const useStyles = makeStyles((theme: Theme) => ({
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
fill: 'none',
|
fill: 'none',
|
||||||
'& circle': {
|
'& circle': {
|
||||||
fill: theme.palette.status.pending.text,
|
fill: theme.palette.status.completed.text,
|
||||||
},
|
},
|
||||||
'& g.label g': {
|
'& g.label g': {
|
||||||
transform: (props: StyleProps) =>
|
transform: (props: StyleProps) =>
|
||||||
|
|
@ -31,20 +31,20 @@ const useStyles = makeStyles((theme: Theme) => ({
|
||||||
fill: theme.palette.text.primary,
|
fill: theme.palette.text.primary,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'& path.pendingIcon': {
|
'& path.succeededIcon': {
|
||||||
transform: (props: StyleProps) =>
|
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': {
|
'& g.StepGroup.Succeeded': {
|
||||||
fill: theme.palette.status.pending.text,
|
fill: theme.palette.status.completed.text,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// Styles for edges
|
// Styles for edges
|
||||||
'& g g.edgePaths': {
|
'& g g.edgePaths': {
|
||||||
'& g.pending': {
|
'& g.succeeded': {
|
||||||
fill: theme.palette.status.pending.text,
|
fill: theme.palette.status.completed.text,
|
||||||
stroke: theme.palette.status.pending.text,
|
stroke: theme.palette.status.completed.text,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -593,7 +593,8 @@ const TuneWorkflow = forwardRef((_, ref) => {
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setYAMLModal(false);
|
setYAMLModal(false);
|
||||||
}}
|
}}
|
||||||
width="60%"
|
width="90%"
|
||||||
|
height="90%"
|
||||||
modalActions={
|
modalActions={
|
||||||
<ButtonOutlined
|
<ButtonOutlined
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
@ -643,6 +644,7 @@ const TuneWorkflow = forwardRef((_, ref) => {
|
||||||
<YamlEditor
|
<YamlEditor
|
||||||
content={manifest}
|
content={manifest}
|
||||||
filename={workflow.name}
|
filename={workflow.name}
|
||||||
|
className={classes.editor}
|
||||||
readOnly={false}
|
readOnly={false}
|
||||||
setButtonState={(btnState: boolean) => {
|
setButtonState={(btnState: boolean) => {
|
||||||
setYamlValid(btnState);
|
setYamlValid(btnState);
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,11 @@ const useStyles = makeStyles((theme) => ({
|
||||||
margin: theme.spacing(8, 5, 5, 5),
|
margin: theme.spacing(8, 5, 5, 5),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Editor
|
||||||
|
editor: {
|
||||||
|
height: '100%',
|
||||||
|
},
|
||||||
|
|
||||||
// Confirmation Modal
|
// Confirmation Modal
|
||||||
confirmDiv: {
|
confirmDiv: {
|
||||||
margin: 'auto',
|
margin: 'auto',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue