feat(code/run-javascript): run async code and introduce monaco editor

This commit is contained in:
Ali BARIN
2024-07-29 15:19:05 +00:00
parent c99b9dbe0a
commit 49d4071928
7 changed files with 164 additions and 351 deletions

View File

@@ -0,0 +1,104 @@
import PropTypes from 'prop-types';
import * as React from 'react';
import InputLabel from '@mui/material/InputLabel';
import { Controller, useFormContext } from 'react-hook-form';
import Editor from '@monaco-editor/react';
import { InputLabelWrapper } from './style';
function CodeEditor(props) {
const containerRef = React.useRef(null);
const editorRef = React.useRef(null);
const [containerHeight, setContainerHeight] = React.useState(20);
const { control } = useFormContext();
const {
required,
name,
label,
defaultValue,
shouldUnregister = false,
disabled,
'data-test': dataTest,
} = props;
const handleEditorOnMount = (editor, monaco) => {
editorRef.current = editor;
editor.onDidContentSizeChange((event) => {
const {
contentHeight,
contentHeightChanged,
} = event;
if (contentHeightChanged) {
// cap the editor height at 500px
const editorContentHeight = Math.min(500, contentHeight);
setContainerHeight(editorContentHeight);
};
});
};
return (
<Controller
rules={{ required }}
name={name}
defaultValue={defaultValue || ''}
control={control}
shouldUnregister={shouldUnregister}
render={({
field,
}) => (
<div style={{ paddingTop: 36, position:'relative' }}>
<InputLabelWrapper>
<InputLabel
shrink={true}
disabled={disabled}
variant="outlined"
sx={{ bgcolor: 'white', display: 'inline-block', px: 0.75 }}
>
{`${label}${required ? ' *' : ''}`}
</InputLabel>
</InputLabelWrapper>
<div style={{ height: containerHeight, width: '100%' }} data-test={dataTest}>
<Editor
{...field}
ref={containerRef}
defaultLanguage="javascript"
defaultValue={defaultValue}
onMount={handleEditorOnMount}
onChange={(value, event) => { field.onChange(value, event); }}
options={{
automaticLayout: true,
bracketPairColorization: true,
formatOnPaste: true,
minimap: {
enabled: false
},
overviewRulerLanes: 0,
readOnly: disabled,
scrollBeyondLastLine: false,
wordWrap: 'on',
wrappingStrategy: 'advanced',
}}
/>
</div>
</div>
)}
/>
);
}
CodeEditor.propTypes = {
required: PropTypes.bool,
defaultValue: PropTypes.string,
shouldUnregister: PropTypes.bool,
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
readOnly: PropTypes.bool,
'data-test': PropTypes.string,
disabled: PropTypes.bool,
};
export default CodeEditor;

View File

@@ -0,0 +1,9 @@
import { styled } from '@mui/material/styles';
export const InputLabelWrapper = styled('div')`
position: absolute;
top: ${({ theme }) => theme.spacing(1.75)};
inset: 0;
left: -6px;
top: 16px;
`;

View File

@@ -6,6 +6,7 @@ import PropTypes from 'prop-types';
import useDynamicFields from 'hooks/useDynamicFields';
import useDynamicData from 'hooks/useDynamicData';
import PowerInput from 'components/PowerInput';
import CodeEditor from 'components/CodeEditor';
import TextField from 'components/TextField';
import ControlledAutocomplete from 'components/ControlledAutocomplete';
import ControlledCustomAutocomplete from 'components/ControlledCustomAutocomplete';
@@ -126,6 +127,26 @@ function InputCreator(props) {
);
}
if (type === 'code') {
return (
<React.Fragment>
<CodeEditor
key={computedName}
defaultValue={value}
required={required}
readOnly={readOnly || disabled}
name={computedName}
data-test={`${computedName}-text`}
label={label}
fullWidth
helperText={description}
shouldUnregister={shouldUnregister}
disabled={disabled}
/>
</React.Fragment>
);
}
if (type === 'string') {
if (schema.variables) {
return (