mirror of
https://github.com/ostris/ai-toolkit.git
synced 2026-01-26 16:39:47 +00:00
145 lines
4.3 KiB
TypeScript
145 lines
4.3 KiB
TypeScript
'use client';
|
|
import { useEffect, useState, useRef } from 'react';
|
|
import { JobConfig } from '@/types';
|
|
import YAML from 'yaml';
|
|
import Editor, { OnMount } from '@monaco-editor/react';
|
|
import type { editor } from 'monaco-editor';
|
|
import { Settings } from '@/hooks/useSettings';
|
|
|
|
type Props = {
|
|
jobConfig: JobConfig;
|
|
setJobConfig: (value: any, key?: string) => void;
|
|
status: 'idle' | 'saving' | 'success' | 'error';
|
|
handleSubmit: (event: React.FormEvent<HTMLFormElement>) => void;
|
|
runId: string | null;
|
|
gpuIDs: string | null;
|
|
setGpuIDs: (value: string | null) => void;
|
|
gpuList: any;
|
|
datasetOptions: any;
|
|
settings: Settings;
|
|
};
|
|
|
|
const isDev = process.env.NODE_ENV === 'development';
|
|
|
|
const yamlConfig: YAML.DocumentOptions &
|
|
YAML.SchemaOptions &
|
|
YAML.ParseOptions &
|
|
YAML.CreateNodeOptions &
|
|
YAML.ToStringOptions = {
|
|
indent: 2,
|
|
lineWidth: 999999999999,
|
|
defaultStringType: 'QUOTE_DOUBLE',
|
|
defaultKeyType: 'PLAIN',
|
|
directives: true,
|
|
};
|
|
|
|
export default function AdvancedJob({ jobConfig, setJobConfig, settings }: Props) {
|
|
const [editorValue, setEditorValue] = useState<string>('');
|
|
const lastJobConfigUpdateStringRef = useRef('');
|
|
const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null);
|
|
|
|
// Track if the editor has been mounted
|
|
const isEditorMounted = useRef(false);
|
|
|
|
// Handler for editor mounting
|
|
const handleEditorDidMount: OnMount = editor => {
|
|
editorRef.current = editor;
|
|
isEditorMounted.current = true;
|
|
|
|
// Initial content setup
|
|
try {
|
|
const yamlContent = YAML.stringify(jobConfig, yamlConfig);
|
|
setEditorValue(yamlContent);
|
|
lastJobConfigUpdateStringRef.current = JSON.stringify(jobConfig);
|
|
} catch (e) {
|
|
console.warn(e);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
const lastUpdate = lastJobConfigUpdateStringRef.current;
|
|
const currentUpdate = JSON.stringify(jobConfig);
|
|
|
|
// Skip if no changes or editor not yet mounted
|
|
if (lastUpdate === currentUpdate || !isEditorMounted.current) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// Preserve cursor position and selection
|
|
const editor = editorRef.current;
|
|
if (editor) {
|
|
// Save current editor state
|
|
const position = editor.getPosition();
|
|
const selection = editor.getSelection();
|
|
const scrollTop = editor.getScrollTop();
|
|
|
|
// Update content
|
|
const yamlContent = YAML.stringify(jobConfig, yamlConfig);
|
|
|
|
// Only update if the content is actually different
|
|
if (yamlContent !== editor.getValue()) {
|
|
// Set value directly on the editor model instead of using React state
|
|
editor.getModel()?.setValue(yamlContent);
|
|
|
|
// Restore cursor position and selection
|
|
if (position) editor.setPosition(position);
|
|
if (selection) editor.setSelection(selection);
|
|
editor.setScrollTop(scrollTop);
|
|
}
|
|
|
|
lastJobConfigUpdateStringRef.current = currentUpdate;
|
|
}
|
|
} catch (e) {
|
|
console.warn(e);
|
|
}
|
|
}, [jobConfig]);
|
|
|
|
const handleChange = (value: string | undefined) => {
|
|
if (value === undefined) return;
|
|
|
|
try {
|
|
const parsed = YAML.parse(value);
|
|
// Don't update jobConfig if the change came from the editor itself
|
|
// to avoid a circular update loop
|
|
if (JSON.stringify(parsed) !== lastJobConfigUpdateStringRef.current) {
|
|
lastJobConfigUpdateStringRef.current = JSON.stringify(parsed);
|
|
|
|
// We have to ensure certain things are always set
|
|
try {
|
|
parsed.config.process[0].type = 'ui_trainer';
|
|
parsed.config.process[0].sqlite_db_path = './aitk_db.db';
|
|
parsed.config.process[0].training_folder = settings.TRAINING_FOLDER;
|
|
parsed.config.process[0].device = 'cuda';
|
|
parsed.config.process[0].performance_log_every = 10;
|
|
} catch (e) {
|
|
console.warn(e);
|
|
}
|
|
setJobConfig(parsed);
|
|
}
|
|
} catch (e) {
|
|
// Don't update on parsing errors
|
|
console.warn(e);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<Editor
|
|
height="100%"
|
|
width="100%"
|
|
defaultLanguage="yaml"
|
|
value={editorValue}
|
|
theme="vs-dark"
|
|
onChange={handleChange}
|
|
onMount={handleEditorDidMount}
|
|
options={{
|
|
minimap: { enabled: true },
|
|
scrollBeyondLastLine: false,
|
|
automaticLayout: true,
|
|
}}
|
|
/>
|
|
</>
|
|
);
|
|
}
|