Merge remote-tracking branch 'origin/main' into feature/process_model_unit_tests

This commit is contained in:
jasquat 2023-05-17 13:41:53 -04:00
commit f2439848c0
5 changed files with 46 additions and 7 deletions

View File

@ -15,6 +15,8 @@ import { AbilityContext } from './contexts/Can';
import UserService from './services/UserService'; import UserService from './services/UserService';
import ErrorDisplay from './components/ErrorDisplay'; import ErrorDisplay from './components/ErrorDisplay';
import APIErrorProvider from './contexts/APIErrorContext'; import APIErrorProvider from './contexts/APIErrorContext';
import ScrollToTop from "./components/ScrollToTop";
import React from "react";
export default function App() { export default function App() {
if (!UserService.isLoggedIn()) { if (!UserService.isLoggedIn()) {
@ -32,6 +34,7 @@ export default function App() {
<BrowserRouter> <BrowserRouter>
<NavigationBar /> <NavigationBar />
<Content> <Content>
<ScrollToTop />
<ErrorDisplay /> <ErrorDisplay />
<ErrorBoundary> <ErrorBoundary>
<Routes> <Routes>

View File

@ -109,7 +109,6 @@ export default function ErrorDisplay() {
if (errorObject) { if (errorObject) {
const title = 'Error:'; const title = 'Error:';
window.scrollTo(0, 0); // Scroll back to the top of the page
errorTag = ( errorTag = (
<Notification title={title} onClose={() => removeError()} type="error"> <Notification title={title} onClose={() => removeError()} type="error">

View File

@ -0,0 +1,12 @@
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
export default function ScrollToTop() {
const { pathname } = useLocation();
useEffect(() => {
window.scrollTo(0, 0);
}, [pathname]);
return null;
}

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,11 +111,11 @@ 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);
} }
window.scrollTo(0, 0); // Scroll back to the top of the page
/* Disable call to load previous tasks -- do not display menu. /* Disable call to load previous tasks -- do not display menu.
const url = `/v1.0/process-instances/for-me/${modifyProcessIdentifierForPathParam( const url = `/v1.0/process-instances/for-me/${modifyProcessIdentifierForPathParam(
@ -160,22 +163,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 +301,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 +362,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 +402,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' });
} }