do not run validations on save and close on a form w/ burnettk

This commit is contained in:
jasquat 2023-05-17 12:14:44 -04:00
parent 2737052c84
commit 46bdff6342
No known key found for this signature in database
3 changed files with 36 additions and 8 deletions

View File

@ -40,7 +40,8 @@ def setup_database_configs(app: Flask) -> None:
if pool_size is not None: if pool_size is not None:
pool_size = int(pool_size) pool_size = int(pool_size)
else: else:
# this one doesn't come from app config and isn't documented in default.py because we don't want to give people the impression # this one doesn't come from app config and isn't documented in default.py
# because we don't want to give people the impression
# that setting it in flask python configs will work. on the contrary, it's used by a bash # that setting it in flask python configs will work. on the contrary, it's used by a bash
# script that starts the backend, so it can only be set in the environment. # script that starts the backend, so it can only be set in the environment.
threads_per_worker_config = os.environ.get("SPIFFWORKFLOW_BACKEND_THREADS_PER_WORKER") threads_per_worker_config = os.environ.get("SPIFFWORKFLOW_BACKEND_THREADS_PER_WORKER")
@ -50,8 +51,9 @@ def setup_database_configs(app: Flask) -> None:
# this is a sqlalchemy default, if we don't have any better ideas # this is a sqlalchemy default, if we don't have any better ideas
pool_size = 5 pool_size = 5
app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {} app.config["SQLALCHEMY_ENGINE_OPTIONS"] = {}
app.config['SQLALCHEMY_ENGINE_OPTIONS']['pool_size'] = pool_size app.config["SQLALCHEMY_ENGINE_OPTIONS"]["pool_size"] = pool_size
def load_config_file(app: Flask, env_config_module: str) -> None: def load_config_file(app: Flask, env_config_module: str) -> None:
"""Load_config_file.""" """Load_config_file."""

View File

@ -94,6 +94,9 @@ export default function TaskShow() {
const params = useParams(); const params = useParams();
const navigate = useNavigate(); const navigate = useNavigate();
const [disabled, setDisabled] = useState(false); const [disabled, setDisabled] = useState(false);
const [noValidate, setNoValidate] = useState<boolean>(false);
const [taskData, setTaskData] = useState<any>(null);
const { addError, removeError } = useAPIError(); const { addError, removeError } = useAPIError();
@ -108,6 +111,7 @@ export default function TaskShow() {
useEffect(() => { useEffect(() => {
const processResult = (result: Task) => { const processResult = (result: Task) => {
setTask(result); setTask(result);
setTaskData(result.data);
setDisabled(false); setDisabled(false);
if (!result.can_complete) { if (!result.can_complete) {
navigateToInterstitial(result); navigateToInterstitial(result);
@ -160,22 +164,30 @@ export default function TaskShow() {
} }
}; };
const handleFormSubmit = (formObject: any, event: any) => { const handleFormSubmit = (formObject: any, _event: any) => {
if (disabled) { if (disabled) {
return; return;
} }
const dataToSubmit = formObject?.formData; const dataToSubmit = formObject?.formData;
if (!dataToSubmit) { if (!dataToSubmit) {
navigate(`/tasks`); navigate(`/tasks`);
return; return;
} }
let queryParams = ''; let queryParams = '';
if (event && event.submitter.id === 'close-button') {
// if validations are turned off then save as draft
if (noValidate) {
queryParams = '?save_as_draft=true'; queryParams = '?save_as_draft=true';
} }
setDisabled(true); setDisabled(true);
removeError(); removeError();
delete dataToSubmit.isManualTask; delete dataToSubmit.isManualTask;
// NOTE: rjsf sets blanks values to undefined and JSON.stringify removes keys with undefined values
// so there is no way to clear out a field that previously had a value.
// To resolve this, we could potentially go through the object that we are posting (either in here or in
// HttpService) and translate all undefined values to null.
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/tasks/${params.process_instance_id}/${params.task_id}${queryParams}`, path: `/tasks/${params.process_instance_id}/${params.task_id}${queryParams}`,
successCallback: processSubmitResult, successCallback: processSubmitResult,
@ -290,17 +302,27 @@ export default function TaskShow() {
return errors; return errors;
}; };
// This turns off validations and then dispatches the click event after
// waiting a second to give the state time to update.
// This is to allow saving the form without validations causing issues.
const handleSaveAndCloseButton = () => {
setNoValidate(true);
setTimeout(() => {
(document.getElementById('our-very-own-form') as any).dispatchEvent(
new Event('submit', { cancelable: true, bubbles: true })
);
}, 1000);
};
const formElement = () => { const formElement = () => {
if (!task) { if (!task) {
return null; return null;
} }
let formUiSchema; let formUiSchema;
let taskData = task.data;
let jsonSchema = task.form_schema; let jsonSchema = task.form_schema;
let reactFragmentToHideSubmitButton = null; let reactFragmentToHideSubmitButton = null;
if (task.typename === 'ManualTask') { if (task.typename === 'ManualTask') {
taskData = {};
jsonSchema = { jsonSchema = {
type: 'object', type: 'object',
required: [], required: [],
@ -341,7 +363,7 @@ export default function TaskShow() {
closeButton = ( closeButton = (
<Button <Button
id="close-button" id="close-button"
type="submit" onClick={handleSaveAndCloseButton}
disabled={disabled} disabled={disabled}
kind="secondary" kind="secondary"
title="Save changes without submitting." title="Save changes without submitting."
@ -381,14 +403,17 @@ export default function TaskShow() {
<Grid fullWidth condensed> <Grid fullWidth condensed>
<Column sm={4} md={5} lg={8}> <Column sm={4} md={5} lg={8}>
<Form <Form
id="our-very-own-form"
disabled={disabled} disabled={disabled}
formData={taskData} formData={taskData}
onChange={(obj: any) => setTaskData(obj.formData)}
onSubmit={handleFormSubmit} onSubmit={handleFormSubmit}
schema={jsonSchema} schema={jsonSchema}
uiSchema={formUiSchema} uiSchema={formUiSchema}
widgets={widgets} widgets={widgets}
validator={validator} validator={validator}
customValidate={customValidate} customValidate={customValidate}
noValidate={noValidate}
omitExtraData omitExtraData
> >
{reactFragmentToHideSubmitButton} {reactFragmentToHideSubmitButton}

View File

@ -56,6 +56,7 @@ backendCallProps) => {
Object.assign(httpArgs, { body: postBody }); Object.assign(httpArgs, { body: postBody });
} else if (typeof postBody === 'object') { } else if (typeof postBody === 'object') {
if (!objectIsEmpty(postBody)) { if (!objectIsEmpty(postBody)) {
// NOTE: stringify strips out keys with value undefined
Object.assign(httpArgs, { body: JSON.stringify(postBody) }); Object.assign(httpArgs, { body: JSON.stringify(postBody) });
Object.assign(headers, { 'Content-Type': 'application/json' }); Object.assign(headers, { 'Content-Type': 'application/json' });
} }