spiff-arena/spiffworkflow-frontend/src/routes/ReactFormEditor.tsx

194 lines
5.7 KiB
TypeScript
Raw Normal View History

import { useEffect, useState } from 'react';
import Editor from '@monaco-editor/react';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
// @ts-ignore
import { Button, Modal } from '@carbon/react';
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
import HttpService from '../services/HttpService';
import ButtonWithConfirmation from '../components/ButtonWithConfirmation';
2022-11-07 22:22:46 +00:00
import { modifyProcessModelPath } from '../helpers';
// NOTE: This is mostly the same as ProcessModelEditDiagram and if we go this route could
// possibly be merged into it. I'm leaving as a separate file now in case it does
// end up diverging greatly
export default function ReactFormEditor() {
const params = useParams();
const [showFileNameEditor, setShowFileNameEditor] = useState(false);
const [newFileName, setNewFileName] = useState('');
const searchParams = useSearchParams()[0];
const handleShowFileNameEditor = () => setShowFileNameEditor(true);
const navigate = useNavigate();
const [processModelFile, setProcessModelFile] = useState(null);
const [processModelFileContents, setProcessModelFileContents] = useState('');
const fileExtension = (() => {
if (params.file_name) {
const matches = params.file_name.match(/\.([a-z]+)/);
if (matches !== null && matches.length > 1) {
return matches[1];
}
}
return searchParams.get('file_ext') ?? 'json';
})();
const editorDefaultLanguage = fileExtension === 'md' ? 'markdown' : 'json';
2022-11-07 22:22:46 +00:00
const modifiedProcessModelId = modifyProcessModelPath(
`${params.process_model_id}`
);
useEffect(() => {
const processResult = (result: any) => {
setProcessModelFile(result);
setProcessModelFileContents(result.file_contents);
};
if (params.file_name) {
HttpService.makeCallToBackend({
2022-11-07 22:22:46 +00:00
path: `/process-models/${modifiedProcessModelId}/files/${params.file_name}`,
successCallback: processResult,
});
}
}, [params, modifiedProcessModelId]);
const navigateToProcessModelFile = (_result: any) => {
if (!params.file_name) {
const fileNameWithExtension = `${newFileName}.${fileExtension}`;
navigate(
2022-11-07 22:22:46 +00:00
`/admin/process-models/${modifiedProcessModelId}/form/${fileNameWithExtension}`
);
}
};
const saveFile = () => {
2022-11-07 22:22:46 +00:00
let url = `/process-models/${modifiedProcessModelId}/files`;
let httpMethod = 'PUT';
let fileNameWithExtension = params.file_name;
if (newFileName) {
fileNameWithExtension = `${newFileName}.${fileExtension}`;
httpMethod = 'POST';
} else {
url += `/${fileNameWithExtension}`;
}
if (!fileNameWithExtension) {
handleShowFileNameEditor();
return;
}
const file = new File(
[processModelFileContents],
fileNameWithExtension || ''
);
const formData = new FormData();
formData.append('file', file);
formData.append('fileName', file.name);
HttpService.makeCallToBackend({
path: url,
successCallback: navigateToProcessModelFile,
httpMethod,
postBody: formData,
});
};
const deleteFile = () => {
2022-11-07 22:22:46 +00:00
const url = `/process-models/${modifiedProcessModelId}/files/${params.file_name}`;
const httpMethod = 'DELETE';
const navigateToProcessModelShow = (_httpResult: any) => {
2022-11-07 22:22:46 +00:00
navigate(`/admin/process-models/${modifiedProcessModelId}`);
};
HttpService.makeCallToBackend({
path: url,
successCallback: navigateToProcessModelShow,
httpMethod,
});
};
const handleFileNameCancel = () => {
setShowFileNameEditor(false);
setNewFileName('');
};
const handleFileNameSave = (event: any) => {
event.preventDefault();
setShowFileNameEditor(false);
saveFile();
};
const newFileNameBox = () => {
return (
<Modal
open={showFileNameEditor}
modalHeading="Processs Model File Name"
primaryButtonText="Save Changes"
secondaryButtonText="Cancel"
onSecondarySubmit={handleFileNameCancel}
onRequestSubmit={handleFileNameSave}
>
<label>File Name:</label>
<span>
<input
name="file_name"
type="text"
value={newFileName}
onChange={(e) => setNewFileName(e.target.value)}
autoFocus
/>
{fileExtension}
</span>
</Modal>
);
};
2022-11-09 14:18:01 +00:00
const processModelFilePossibleNameString = processModelFile
? (processModelFile as any).name
: '';
if (processModelFile || !params.file_name) {
return (
<main>
<ProcessBreadcrumb
processGroupId={params.process_group_id}
processModelId={params.process_model_id}
linkProcessModel
hotCrumbs={[
['Process Groups', '/admin'],
[
`Process Model: ${params.process_model_id}`,
`process_model:${params.process_model_id}:link`,
],
2022-11-09 14:18:01 +00:00
[processModelFilePossibleNameString],
]}
/>
<h2>
Process Model File
{processModelFile ? `: ${(processModelFile as any).name}` : ''}
</h2>
{newFileNameBox()}
<Button onClick={saveFile} variant="danger" data-qa="file-save-button">
Save
</Button>
{params.file_name ? (
<ButtonWithConfirmation
description={`Delete file ${params.file_name}?`}
onConfirmation={deleteFile}
buttonLabel="Delete"
/>
) : null}
<Editor
height={600}
width="auto"
defaultLanguage={editorDefaultLanguage}
defaultValue={processModelFileContents || ''}
onChange={(value) => setProcessModelFileContents(value || '')}
/>
</main>
);
}
return <main />;
}