remove old form builder and references to it w/ burnettk (#985)
Co-authored-by: jasquat <jasquat@users.noreply.github.com>
This commit is contained in:
parent
cf03d6e8a8
commit
9f188c1204
|
@ -367,23 +367,6 @@ export interface PermissionCheckResponseBody {
|
|||
results: PermissionCheckResult;
|
||||
}
|
||||
|
||||
export interface FormField {
|
||||
id: string;
|
||||
title: string;
|
||||
required?: boolean;
|
||||
type: string;
|
||||
enum?: string[];
|
||||
default?: any;
|
||||
pattern?: string;
|
||||
}
|
||||
|
||||
export interface JsonSchemaForm {
|
||||
file_contents: string;
|
||||
name: string;
|
||||
process_model_id: string;
|
||||
required: string[];
|
||||
}
|
||||
|
||||
export interface ProcessInstanceEventErrorDetail {
|
||||
id: number;
|
||||
message: string;
|
||||
|
|
|
@ -1,445 +0,0 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
// @ts-ignore
|
||||
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
|
||||
import {
|
||||
Button,
|
||||
Select,
|
||||
SelectItem,
|
||||
TextInput,
|
||||
TextArea,
|
||||
Grid,
|
||||
Column,
|
||||
// @ts-ignore
|
||||
} from '@carbon/react';
|
||||
import validator from '@rjsf/validator-ajv8';
|
||||
import { FormField, JsonSchemaForm } from '../interfaces';
|
||||
import { Form } from '../rjsf/carbon_theme';
|
||||
import {
|
||||
modifyProcessIdentifierForPathParam,
|
||||
slugifyString,
|
||||
underscorizeString,
|
||||
} from '../helpers';
|
||||
import HttpService from '../services/HttpService';
|
||||
import { Notification } from '../components/Notification';
|
||||
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
||||
import ButtonWithConfirmation from '../components/ButtonWithConfirmation';
|
||||
|
||||
export default function JsonSchemaFormBuilder() {
|
||||
const params = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [searchParams] = useSearchParams();
|
||||
const formFieldTypes = ['textbox', 'checkbox', 'select'];
|
||||
|
||||
const [formTitle, setFormTitle] = useState<string>('');
|
||||
const [formDescription, setFormDescription] = useState<string>('');
|
||||
const [formId, setFormId] = useState<string>('');
|
||||
const [formFields, setFormFields] = useState<FormField[]>([]);
|
||||
const [showNewFormField, setShowNewFormField] = useState<boolean>(false);
|
||||
const [formFieldSelectOptions, setFormFieldSelectOptions] =
|
||||
useState<string>('');
|
||||
const [formIdHasBeenUpdatedByUser, setFormIdHasBeenUpdatedByUser] =
|
||||
useState<boolean>(false);
|
||||
const [formFieldIdHasBeenUpdatedByUser, setFormFieldIdHasBeenUpdatedByUser] =
|
||||
useState<boolean>(false);
|
||||
const [showFormFieldSelectTextField, setShowFormFieldSelectTextField] =
|
||||
useState<boolean>(false);
|
||||
|
||||
const [formFieldId, setFormFieldId] = useState<string>('');
|
||||
const [formFieldTitle, setFormFieldTitle] = useState<string>('');
|
||||
const [formFieldType, setFormFieldType] = useState<string>('');
|
||||
const [requiredFields, setRequiredFields] = useState<string[]>([]);
|
||||
const [savedJsonSchema, setSavedJsonSchema] = useState<boolean>(false);
|
||||
|
||||
const modifiedProcessModelId = modifyProcessIdentifierForPathParam(
|
||||
`${params.process_model_id}`
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const processResult = (result: JsonSchemaForm) => {
|
||||
const jsonForm = JSON.parse(result.file_contents);
|
||||
setFormTitle(jsonForm.title);
|
||||
setFormDescription(jsonForm.description);
|
||||
setRequiredFields(jsonForm.required);
|
||||
const newFormId = (searchParams.get('file_name') || '').replace(
|
||||
'-schema.json',
|
||||
''
|
||||
);
|
||||
setFormId(newFormId);
|
||||
const newFormFields: FormField[] = [];
|
||||
Object.keys(jsonForm.properties).forEach((propertyId: string) => {
|
||||
const propertyDetails = jsonForm.properties[propertyId];
|
||||
newFormFields.push({
|
||||
id: propertyId,
|
||||
title: propertyDetails.title,
|
||||
required: propertyDetails.required,
|
||||
type: propertyDetails.type,
|
||||
enum: propertyDetails.enum,
|
||||
default: propertyDetails.default,
|
||||
pattern: propertyDetails.pattern,
|
||||
});
|
||||
});
|
||||
setFormFields(newFormFields);
|
||||
};
|
||||
if (searchParams.get('file_name')) {
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models/${modifiedProcessModelId}/files/${searchParams.get(
|
||||
'file_name'
|
||||
)}`,
|
||||
successCallback: processResult,
|
||||
});
|
||||
}
|
||||
}, [modifiedProcessModelId, searchParams]);
|
||||
|
||||
const formSubmitResultElement = () => {
|
||||
if (savedJsonSchema) {
|
||||
return (
|
||||
<Notification
|
||||
title="Form Saved"
|
||||
onClose={() => setSavedJsonSchema(false)}
|
||||
>
|
||||
It saved
|
||||
</Notification>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const renderFormJson = () => {
|
||||
const formJson = {
|
||||
title: formTitle,
|
||||
description: formDescription,
|
||||
properties: {},
|
||||
required: requiredFields,
|
||||
};
|
||||
|
||||
formFields.forEach((formField: FormField) => {
|
||||
let jsonSchemaFieldType = formField.type;
|
||||
if (['checkbox'].includes(formField.type)) {
|
||||
jsonSchemaFieldType = 'boolean';
|
||||
}
|
||||
const formJsonObject: any = {
|
||||
type: jsonSchemaFieldType || 'string',
|
||||
title: formField.title,
|
||||
};
|
||||
|
||||
if (formField.enum) {
|
||||
formJsonObject.enum = formField.enum;
|
||||
}
|
||||
if (formField.default !== undefined) {
|
||||
formJsonObject.default = formField.default;
|
||||
}
|
||||
if (formField.pattern) {
|
||||
formJsonObject.pattern = formField.pattern;
|
||||
}
|
||||
(formJson.properties as any)[formField.id] = formJsonObject;
|
||||
});
|
||||
|
||||
return JSON.stringify(formJson, null, 2);
|
||||
};
|
||||
|
||||
const renderFormUiJson = () => {
|
||||
const uiOrder = formFields.map((formField: FormField) => {
|
||||
return formField.id;
|
||||
});
|
||||
return JSON.stringify({ 'ui:order': uiOrder }, null, 2);
|
||||
};
|
||||
|
||||
const onFormFieldTitleChange = (newFormFieldTitle: string) => {
|
||||
if (!formFieldIdHasBeenUpdatedByUser) {
|
||||
setFormFieldId(underscorizeString(newFormFieldTitle));
|
||||
}
|
||||
setFormFieldTitle(newFormFieldTitle);
|
||||
};
|
||||
|
||||
const onFormTitleChange = (newFormTitle: string) => {
|
||||
if (!formIdHasBeenUpdatedByUser) {
|
||||
setFormId(slugifyString(newFormTitle));
|
||||
}
|
||||
setFormTitle(newFormTitle);
|
||||
};
|
||||
|
||||
const getFormFieldType = (indicatedType: string) => {
|
||||
if (indicatedType === 'checkbox') {
|
||||
return 'boolean';
|
||||
}
|
||||
// undefined or 'select' or 'textbox'
|
||||
return 'string';
|
||||
};
|
||||
|
||||
const addFormField = () => {
|
||||
const newFormField: FormField = {
|
||||
id: formFieldId,
|
||||
title: formFieldTitle,
|
||||
required: false,
|
||||
type: getFormFieldType(formFieldType),
|
||||
enum: showFormFieldSelectTextField
|
||||
? formFieldSelectOptions.split(',')
|
||||
: undefined,
|
||||
};
|
||||
|
||||
setFormFieldIdHasBeenUpdatedByUser(false);
|
||||
setShowNewFormField(false);
|
||||
setFormFields([...formFields, newFormField]);
|
||||
};
|
||||
|
||||
const handleFormFieldTypeChange = (event: any) => {
|
||||
setFormFieldType(event.srcElement.value);
|
||||
|
||||
if (event.srcElement.value === 'select') {
|
||||
setShowFormFieldSelectTextField(true);
|
||||
} else {
|
||||
setShowFormFieldSelectTextField(false);
|
||||
}
|
||||
};
|
||||
|
||||
const newFormFieldComponent = () => {
|
||||
if (showNewFormField) {
|
||||
return (
|
||||
<>
|
||||
<TextInput
|
||||
id="form-field-title"
|
||||
name="title"
|
||||
labelText="Title"
|
||||
value={formFieldTitle}
|
||||
onChange={(event: any) => {
|
||||
onFormFieldTitleChange(event.srcElement.value);
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
id="json-form-field-id"
|
||||
name="id"
|
||||
labelText="ID"
|
||||
value={formFieldId}
|
||||
onChange={(event: any) => {
|
||||
setFormFieldIdHasBeenUpdatedByUser(true);
|
||||
setFormFieldId(event.srcElement.value);
|
||||
}}
|
||||
/>
|
||||
<Select
|
||||
id="form-field-type"
|
||||
labelText="Type"
|
||||
onChange={handleFormFieldTypeChange}
|
||||
>
|
||||
{formFieldTypes.map((fft: string) => {
|
||||
return <SelectItem text={fft} value={fft} />;
|
||||
})}
|
||||
</Select>
|
||||
{showFormFieldSelectTextField ? (
|
||||
<TextInput
|
||||
id="json-form-field-select-options"
|
||||
name="select-options"
|
||||
labelText="Select Options"
|
||||
onChange={(event: any) => {
|
||||
setFormFieldSelectOptions(event.srcElement.value);
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
<Button onClick={addFormField}>Add Field</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const formFieldArea = () => {
|
||||
if (formFields.length > 0) {
|
||||
return formFields.map((formField: FormField) => {
|
||||
return <p>Form Field: {formField.id}</p>;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const handleSaveCallback = () => {
|
||||
setSavedJsonSchema(true);
|
||||
};
|
||||
|
||||
const uploadFile = (file: File) => {
|
||||
const url = `/process-models/${modifiedProcessModelId}/files`;
|
||||
const httpMethod = 'POST';
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
formData.append('fileName', file.name);
|
||||
|
||||
HttpService.makeCallToBackend({
|
||||
path: url,
|
||||
successCallback: handleSaveCallback,
|
||||
httpMethod,
|
||||
postBody: formData,
|
||||
});
|
||||
};
|
||||
|
||||
const saveFile = () => {
|
||||
setSavedJsonSchema(false);
|
||||
let formJsonFileName = `${formId}-schema.json`;
|
||||
let formUiJsonFileName: string | null = `${formId}-uischema.json`;
|
||||
if (searchParams.get('file_name')) {
|
||||
formJsonFileName = searchParams.get('file_name') as any;
|
||||
if (formJsonFileName.match(/-schema\.json$/)) {
|
||||
formUiJsonFileName = (searchParams.get('file_name') as any).replace(
|
||||
'-schema.json',
|
||||
'-uischema.json'
|
||||
);
|
||||
} else {
|
||||
formUiJsonFileName = null;
|
||||
}
|
||||
}
|
||||
|
||||
uploadFile(new File([renderFormJson()], formJsonFileName));
|
||||
if (formUiJsonFileName) {
|
||||
uploadFile(new File([renderFormUiJson()], formUiJsonFileName));
|
||||
}
|
||||
};
|
||||
|
||||
const deleteFile = () => {
|
||||
const url = `/process-models/${modifiedProcessModelId}/files/${params.file_name}`;
|
||||
const httpMethod = 'DELETE';
|
||||
|
||||
const navigateToProcessModelShow = (_httpResult: any) => {
|
||||
navigate(`/process-models/${modifiedProcessModelId}`);
|
||||
};
|
||||
|
||||
HttpService.makeCallToBackend({
|
||||
path: url,
|
||||
successCallback: navigateToProcessModelShow,
|
||||
httpMethod,
|
||||
});
|
||||
};
|
||||
|
||||
const formIdTextField = () => {
|
||||
if (searchParams.get('file_name')) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<TextInput
|
||||
id="json-form-id"
|
||||
name="id"
|
||||
labelText="ID"
|
||||
value={formId}
|
||||
onChange={(event: any) => {
|
||||
setFormIdHasBeenUpdatedByUser(true);
|
||||
setFormId(event.srcElement.value);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const jsonFormButton = () => {
|
||||
if (!searchParams.get('file_name')) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<ButtonWithConfirmation
|
||||
data-qa="delete-process-model-file"
|
||||
description={`Delete file ${searchParams.get('file_name')}?`}
|
||||
onConfirmation={deleteFile}
|
||||
buttonLabel="Delete"
|
||||
/>
|
||||
<Button
|
||||
onClick={() =>
|
||||
navigate(
|
||||
`/process-models/${
|
||||
params.process_model_id
|
||||
}/form/${searchParams.get('file_name')}`
|
||||
)
|
||||
}
|
||||
variant="danger"
|
||||
data-qa="form-builder-button"
|
||||
>
|
||||
View Json
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
const processModelFileName = searchParams.get('file_name') || '';
|
||||
|
||||
const topOfPageElements = () => {
|
||||
return (
|
||||
<>
|
||||
<ProcessBreadcrumb
|
||||
hotCrumbs={[
|
||||
['Process Groups', '/process-groups'],
|
||||
{
|
||||
entityToExplode: params.process_model_id || '',
|
||||
entityType: 'process-model-id',
|
||||
linkLastItem: true,
|
||||
},
|
||||
[processModelFileName],
|
||||
]}
|
||||
/>
|
||||
<h1>
|
||||
Process Model File{processModelFileName ? ': ' : ''}
|
||||
{processModelFileName}
|
||||
</h1>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const jsonFormArea = () => {
|
||||
return (
|
||||
<>
|
||||
{formSubmitResultElement()}
|
||||
<Button onClick={saveFile}>Save</Button>
|
||||
{jsonFormButton()}
|
||||
<TextInput
|
||||
id="json-form-title"
|
||||
name="title"
|
||||
labelText="Title"
|
||||
value={formTitle}
|
||||
onChange={(event: any) => {
|
||||
onFormTitleChange(event.srcElement.value);
|
||||
}}
|
||||
/>
|
||||
{formIdTextField()}
|
||||
<TextArea
|
||||
id="form-description"
|
||||
name="description"
|
||||
labelText="Description"
|
||||
value={formDescription}
|
||||
onChange={(event: any) => {
|
||||
setFormDescription(event.srcElement.value);
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setFormFieldId('');
|
||||
setFormFieldTitle('');
|
||||
setFormFieldType('');
|
||||
setFormFieldSelectOptions('');
|
||||
setShowFormFieldSelectTextField(false);
|
||||
setShowNewFormField(true);
|
||||
}}
|
||||
>
|
||||
New Field
|
||||
</Button>
|
||||
{formFieldArea()}
|
||||
{newFormFieldComponent()}
|
||||
</>
|
||||
);
|
||||
};
|
||||
const schemaString = renderFormJson();
|
||||
const uiSchemaString = renderFormUiJson();
|
||||
const schema = JSON.parse(schemaString);
|
||||
const uiSchema = JSON.parse(uiSchemaString);
|
||||
|
||||
return (
|
||||
<>
|
||||
{topOfPageElements()}
|
||||
<Grid fullWidth>
|
||||
<Column md={5} lg={8} sm={4}>
|
||||
{jsonFormArea()}
|
||||
</Column>
|
||||
<Column md={5} lg={8} sm={4}>
|
||||
<h2>Form Preview</h2>
|
||||
<Form
|
||||
formData={{}}
|
||||
schema={schema}
|
||||
uiSchema={uiSchema}
|
||||
validator={validator}
|
||||
/>
|
||||
</Column>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
import { Route, Routes } from 'react-router-dom';
|
||||
import JsonSchemaFormBuilder from './JsonSchemaFormBuilder';
|
||||
import ProcessModelEdit from './ProcessModelEdit';
|
||||
import ProcessModelNew from './ProcessModelNew';
|
||||
import ProcessModelNewExperimental from './ProcessModelNewExperimental';
|
||||
|
@ -21,10 +20,6 @@ export default function ProcessModelRoutes() {
|
|||
path=":process_model_id/form/:file_name"
|
||||
element={<ReactFormEditor />}
|
||||
/>
|
||||
<Route
|
||||
path=":process_model_id/form-builder"
|
||||
element={<JsonSchemaFormBuilder />}
|
||||
/>
|
||||
</Routes>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -57,7 +57,6 @@ export default function ReactFormEditor() {
|
|||
})();
|
||||
|
||||
const hasDiagram = fileExtension === 'bpmn' || fileExtension === 'dmn';
|
||||
const hasFormBuilder = fileExtension === 'json';
|
||||
const defaultFileName = searchParams.get('default_file_name');
|
||||
|
||||
const editorDefaultLanguage = (() => {
|
||||
|
@ -248,9 +247,6 @@ export default function ReactFormEditor() {
|
|||
|
||||
if (processModelFile || !params.file_name) {
|
||||
const processModelFileName = processModelFile ? processModelFile.name : '';
|
||||
const formBuildFileParam = params.file_name
|
||||
? `?file_name=${params.file_name}`
|
||||
: '';
|
||||
return (
|
||||
<main>
|
||||
<ProcessBreadcrumb
|
||||
|
@ -299,25 +295,6 @@ export default function ReactFormEditor() {
|
|||
/>
|
||||
) : null}
|
||||
</Can>
|
||||
<Can
|
||||
I="PUT"
|
||||
a={targetUris.processModelFileShowPath}
|
||||
ability={ability}
|
||||
>
|
||||
{hasFormBuilder ? (
|
||||
<Button
|
||||
onClick={() =>
|
||||
navigate(
|
||||
`/process-models/${params.process_model_id}/form-builder${formBuildFileParam}`
|
||||
)
|
||||
}
|
||||
variant="danger"
|
||||
data-qa="form-builder-button"
|
||||
>
|
||||
Form Builder
|
||||
</Button>
|
||||
) : null}
|
||||
</Can>
|
||||
<Can
|
||||
I="GET"
|
||||
a={targetUris.processModelFileShowPath}
|
||||
|
|
Loading…
Reference in New Issue