expanded functionality of the form builder
This commit is contained in:
parent
5a2db8e040
commit
ea8d310299
|
@ -84,8 +84,10 @@ class GitService:
|
|||
repo_path_to_use = current_app.config["BPMN_SPEC_ABSOLUTE_DIR"]
|
||||
if repo_path_to_use is None:
|
||||
raise ConfigurationError("BPMN_SPEC_ABSOLUTE_DIR config must be set")
|
||||
if current_app.config['GIT_SSH_PRIVATE_KEY']:
|
||||
os.environ['GIT_SSH_PRIVATE_KEY'] = current_app.config['GIT_SSH_PRIVATE_KEY']
|
||||
if current_app.config["GIT_SSH_PRIVATE_KEY"]:
|
||||
os.environ["GIT_SSH_PRIVATE_KEY"] = current_app.config[
|
||||
"GIT_SSH_PRIVATE_KEY"
|
||||
]
|
||||
|
||||
git_username = ""
|
||||
git_email = ""
|
||||
|
@ -222,7 +224,7 @@ class GitService:
|
|||
destination_process_root = f"/tmp/{clone_dir}" # noqa
|
||||
|
||||
git_clone_url = current_app.config["GIT_CLONE_URL_FOR_PUBLISHING"]
|
||||
if git_clone_url.startswith('https://'):
|
||||
if git_clone_url.startswith("https://"):
|
||||
git_clone_url = git_clone_url.replace(
|
||||
"https://",
|
||||
f"https://{current_app.config['GIT_USERNAME']}:{current_app.config['GIT_USER_PASSWORD']}@",
|
||||
|
|
|
@ -228,4 +228,13 @@ export interface FormField {
|
|||
required: boolean;
|
||||
type: string;
|
||||
enum: string[];
|
||||
default: any;
|
||||
pattern: string;
|
||||
}
|
||||
|
||||
export interface JsonSchemaForm {
|
||||
file_contents: string;
|
||||
name: string;
|
||||
process_model_id: string;
|
||||
required: string[];
|
||||
}
|
||||
|
|
|
@ -1,17 +1,22 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
// @ts-ignore
|
||||
import { Button, Select, SelectItem, TextInput } from '@carbon/react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { FormField } from '../interfaces';
|
||||
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
|
||||
import { FormField, JsonSchemaForm } from '../interfaces';
|
||||
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>('');
|
||||
|
@ -31,34 +36,90 @@ export default function JsonSchemaFormBuilder() {
|
|||
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(() => {}, []);
|
||||
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: [],
|
||||
required: requiredFields,
|
||||
};
|
||||
|
||||
formFields.forEach((formField: FormField) => {
|
||||
let jsonSchemaFieldType = 'string';
|
||||
if (formField.type === 'checkbox') {
|
||||
let jsonSchemaFieldType = formField.type;
|
||||
if (['checkbox'].includes(formField.type)) {
|
||||
jsonSchemaFieldType = 'boolean';
|
||||
}
|
||||
const formJsonObject: any = {
|
||||
type: jsonSchemaFieldType,
|
||||
type: jsonSchemaFieldType || 'string',
|
||||
title: formField.title,
|
||||
};
|
||||
|
||||
if (formField.type === 'select') {
|
||||
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;
|
||||
});
|
||||
|
||||
|
@ -93,6 +154,8 @@ export default function JsonSchemaFormBuilder() {
|
|||
required: false,
|
||||
type: formFieldType,
|
||||
enum: formFieldSelectOptions.split(','),
|
||||
pattern: '',
|
||||
default: null,
|
||||
};
|
||||
|
||||
setFormFieldIdHasBeenUpdatedByUser(false);
|
||||
|
@ -168,8 +231,8 @@ export default function JsonSchemaFormBuilder() {
|
|||
return null;
|
||||
};
|
||||
|
||||
const handleSaveCallback = (result: any) => {
|
||||
console.log('result', result);
|
||||
const handleSaveCallback = () => {
|
||||
setSavedJsonSchema(true);
|
||||
};
|
||||
|
||||
const uploadFile = (file: File) => {
|
||||
|
@ -188,26 +251,47 @@ export default function JsonSchemaFormBuilder() {
|
|||
};
|
||||
|
||||
const saveFile = () => {
|
||||
const formJsonFileName = `${formId}-schema.json`;
|
||||
const formUiJsonFileName = `${formId}-uischema.json`;
|
||||
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 jsonFormArea = () => {
|
||||
const deleteFile = () => {
|
||||
const url = `/process-models/${modifiedProcessModelId}/files/${params.file_name}`;
|
||||
const httpMethod = 'DELETE';
|
||||
|
||||
const navigateToProcessModelShow = (_httpResult: any) => {
|
||||
navigate(`/admin/process-models/${modifiedProcessModelId}`);
|
||||
};
|
||||
|
||||
HttpService.makeCallToBackend({
|
||||
path: url,
|
||||
successCallback: navigateToProcessModelShow,
|
||||
httpMethod,
|
||||
});
|
||||
};
|
||||
|
||||
const formIdTextField = () => {
|
||||
if (searchParams.get('file_name')) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Button onClick={saveFile}>Save</Button>
|
||||
<TextInput
|
||||
id="json-form-title"
|
||||
name="title"
|
||||
labelText="Title"
|
||||
value={formTitle}
|
||||
onChange={(event: any) => {
|
||||
onFormTitleChange(event.srcElement.value);
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
id="json-form-id"
|
||||
name="id"
|
||||
|
@ -218,6 +302,70 @@ export default function JsonSchemaFormBuilder() {
|
|||
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(
|
||||
`/admin/process-models/${
|
||||
params.process_model_id
|
||||
}/form/${searchParams.get('file_name')}`
|
||||
)
|
||||
}
|
||||
variant="danger"
|
||||
data-qa="form-builder-button"
|
||||
>
|
||||
View Json
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const jsonFormArea = () => {
|
||||
const processModelFileName = searchParams.get('file_name') || '';
|
||||
return (
|
||||
<>
|
||||
<ProcessBreadcrumb
|
||||
hotCrumbs={[
|
||||
['Process Groups', '/admin'],
|
||||
{
|
||||
entityToExplode: params.process_model_id || '',
|
||||
entityType: 'process-model-id',
|
||||
linkLastItem: true,
|
||||
},
|
||||
[processModelFileName],
|
||||
]}
|
||||
/>
|
||||
<h1>
|
||||
Process Model File{processModelFileName ? ': ' : ''}
|
||||
{processModelFileName}
|
||||
</h1>
|
||||
{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()}
|
||||
<TextInput
|
||||
id="form-description"
|
||||
name="description"
|
||||
|
|
|
@ -190,6 +190,9 @@ 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
|
||||
|
@ -212,19 +215,7 @@ export default function ReactFormEditor() {
|
|||
<Button onClick={saveFile} variant="danger" data-qa="file-save-button">
|
||||
Save
|
||||
</Button>
|
||||
{params.file_name ? null : (
|
||||
<Button
|
||||
onClick={() =>
|
||||
navigate(
|
||||
`/admin/process-models/${params.process_model_id}/form-builder`
|
||||
)
|
||||
}
|
||||
variant="danger"
|
||||
data-qa="form-builder-button"
|
||||
>
|
||||
Form Builder
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{params.file_name ? (
|
||||
<ButtonWithConfirmation
|
||||
data-qa="delete-process-model-file"
|
||||
|
@ -233,6 +224,17 @@ export default function ReactFormEditor() {
|
|||
buttonLabel="Delete"
|
||||
/>
|
||||
) : null}
|
||||
<Button
|
||||
onClick={() =>
|
||||
navigate(
|
||||
`/admin/process-models/${params.process_model_id}/form-builder${formBuildFileParam}`
|
||||
)
|
||||
}
|
||||
variant="danger"
|
||||
data-qa="form-builder-button"
|
||||
>
|
||||
Form Builder
|
||||
</Button>
|
||||
{hasDiagram ? (
|
||||
<Button
|
||||
onClick={() =>
|
||||
|
|
Loading…
Reference in New Issue