Files
gpustack-ui/src/pages/_components/yaml-editor/editor.tsx
T

142 lines
3.3 KiB
TypeScript

import EditorWrap from '@/components/editor-wrap';
import { LoadingOutlined } from '@ant-design/icons';
import Editor, { loader } from '@monaco-editor/react';
import * as monaco from 'monaco-editor';
import { configureMonacoYaml } from 'monaco-yaml';
import React, {
forwardRef,
useEffect,
useImperativeHandle,
useRef
} from 'react';
loader.config({ monaco });
interface ViewerProps {
ref?: any;
defaultLang?: string;
config?: any;
value: string;
height?: string | number;
theme?: string;
header?: React.ReactNode;
placeholder?: string;
variant?: 'bordered' | 'borderless';
schema?: any;
}
const path = 'inmemory://model/config.yaml';
const EditorInner: React.FC<ViewerProps> = forwardRef((props, ref) => {
const {
value,
height = 380,
theme = 'vs-dark',
header,
variant = 'borderless',
schema,
placeholder
} = props;
const editorRef = useRef<any>(null);
const monacoRef = useRef<any>(null);
const monacoYamlRef = useRef<any>(null);
const handleBeforeMount = (monaco: any) => {
const yamlUri = monaco.Uri.parse(path);
configureMonacoYaml(monaco, {
hover: false,
schemas: [
{
uri: 'http://example.com/schema-name.json',
fileMatch: [yamlUri.toString()],
schema: schema
}
]
});
};
const handleEditorDidMount = (editor: any, monaco: any) => {
editorRef.current = editor;
monacoRef.current = monaco;
};
const formatCode = () => {
if (editorRef.current) {
setTimeout(() => {
editorRef.current
?.getAction?.('editor.action.formatDocument')
?.run()
.then(() => {
console.log('format success');
});
}, 100);
}
};
// Currently, do not use this function, but keep it for future validation needs
const getMarkers = () => {
const uri = editorRef.current?.getModel()?.uri;
const markers = monacoRef.current?.editor.getModelMarkers({
resource: uri
});
return markers;
};
useImperativeHandle(ref, () => ({
format: () => {
formatCode();
},
getValue: () => {
return editorRef.current?.getValue?.();
},
setValue: (val: string) => {
editorRef.current?.setValue?.(val);
},
dispose: () => {
editorRef.current?.dispose?.();
monacoYamlRef.current?.dispose?.();
},
validate() {
return getMarkers();
},
editor: editorRef.current
}));
useEffect(() => {
formatCode();
}, [value]);
return (
<EditorWrap header={header} variant={variant}>
<Editor
path={path}
defaultPath={path}
height={height}
theme={theme}
className="monaco-editor"
defaultLanguage={'yaml'}
language={'yaml'}
value={value}
options={{
minimap: { enabled: false },
quickSuggestions: true,
suggestOnTriggerCharacters: true,
fontSize: 14,
scrollbar: {
verticalScrollbarSize: 6,
horizontalScrollbarSize: 6
},
placeholder: placeholder
}}
loading={<LoadingOutlined style={{ fontSize: 24 }}></LoadingOutlined>}
beforeMount={handleBeforeMount}
onMount={handleEditorDidMount}
/>
</EditorWrap>
);
});
export default EditorInner;