in frontend/apps/quantgrid/src/app/components/CodeEditorWrapper/CodeEditorWrapper.tsx [23:192]
export function CodeEditorWrapper() {
const codeRef = useRef('');
const setCode = useRef<SetCodeRefFunction>(null);
const {
functions,
parsedSheets,
projectName,
projectSheets,
sheetName,
sheetContent,
manuallyUpdateSheetContent,
projectVersion,
} = useContext(ProjectContext);
const { openTable, openField } = useContext(AppSpreadsheetInteractionContext);
const gridApi = useGridApi();
const { updateHasUnsavedChanges, hasUnsavedChanges, unsavedChangesVersion } =
useContext(CodeEditorContext);
const { append, undo, redo } = useContext(UndoRedoContext);
const { theme } = useContext(AppContext);
const { errors } = useDSLErrors();
useEffect(() => {
if (!projectName && !sheetName) {
setCode.current?.('');
}
}, [projectName, sheetName]);
useEffect(() => {
if (sheetName && !hasUnsavedChanges) {
setCode.current?.(sheetContent || '');
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [sheetContent]);
const updateCodeStatus = useCallback(
(currentCode: string, sheetContent = '') => {
if (!projectVersion) return;
const isCodeChanged =
currentCode.replaceAll('\r', '') !== sheetContent?.replaceAll('\r', '');
updateHasUnsavedChanges(isCodeChanged, projectVersion);
},
[projectVersion, updateHasUnsavedChanges]
);
const onEditorReady = useCallback(() => {
if (!hasUnsavedChanges) {
codeRef.current = sheetContent || '';
setCode.current?.(codeRef.current);
updateCodeStatus(codeRef.current, codeRef.current);
}
}, [hasUnsavedChanges, sheetContent, updateCodeStatus]);
const onCodeChange = useCallback(
(code: string) => {
codeRef.current = code;
updateCodeStatus(codeRef.current, sheetContent ?? undefined);
},
[sheetContent, updateCodeStatus]
);
const onSave = useCallback(() => {
if (
projectName &&
sheetName &&
projectSheets &&
codeRef.current !== sheetContent
) {
if (unsavedChangesVersion !== projectVersion) {
toast.error(
'Cannot save project, due to project version on the server changed during your edit.'
);
return;
}
let updatedSheetContent = autoRenameTables(
codeRef.current,
sheetName,
projectSheets
);
updatedSheetContent = autoRenameFields(updatedSheetContent);
updatedSheetContent = autoTablePlacement(updatedSheetContent);
updatedSheetContent = autoFunctionsToUppercase(
updatedSheetContent,
functions
);
updatedSheetContent = autoFixSheetTableOrFieldName(
updatedSheetContent,
parsedSheets
);
codeRef.current = updatedSheetContent;
setCode.current?.(updatedSheetContent);
updateCodeStatus(codeRef.current, codeRef.current);
manuallyUpdateSheetContent(sheetName, updatedSheetContent);
gridApi?.clearSelection();
const dslChangeText = getDSLChangeText(
sheetContent || '',
updatedSheetContent
);
append(dslChangeText, updatedSheetContent);
}
}, [
projectName,
sheetName,
projectSheets,
sheetContent,
gridApi,
unsavedChangesVersion,
projectVersion,
functions,
parsedSheets,
updateCodeStatus,
manuallyUpdateSheetContent,
append,
]);
const onUndo = useCallback(() => {
onSave();
undo();
}, [onSave, undo]);
const onGoToTable = useCallback(
(tableName: string) => {
if (!sheetName) return;
openTable(sheetName, tableName);
},
[openTable, sheetName]
);
const onGoToField = useCallback(
(tableName: string, fieldName: string) => {
if (!sheetName) return;
openField(sheetName, tableName, fieldName);
},
[openField, sheetName]
);
return (
<div className="h-[calc(100%-20px)] w-full pt-5 bg-bgLayer3">
<CodeEditor
codeEditorPlace="codeEditor"
errors={errors}
functions={functions}
language="code-editor"
parsedSheets={parsedSheets}
setCode={setCode}
sheetContent={sheetContent || ''}
theme={theme}
onBlur={onSave}
onCodeChange={onCodeChange}
onEditorReady={onEditorReady}
onGoToField={onGoToField}
onGoToTable={onGoToTable}
onRedo={redo}
onSaveButton={onSave}
onUndo={onUndo}
/>
</div>
);
}