From 693c540b22e0eea8702b6e5e26aeb6e61d21aab3 Mon Sep 17 00:00:00 2001 From: "EP\\qang2" Date: Mon, 18 Dec 2023 15:34:16 +0700 Subject: [PATCH] Add multi step submission Fixes: AFORM-3800 --- .../forms-react/src/components/FormBody.tsx | 23 +++++++++++++++---- .../src/components/FormStepNavigation.tsx | 12 ++++++---- .../forms-sdk/src/form-submit/formSubmit.ts | 5 ++++ .../src/models/enums/FormConstants.ts | 3 ++- 4 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/@episerver/forms-react/src/components/FormBody.tsx b/src/@episerver/forms-react/src/components/FormBody.tsx index 8c5740d..617c869 100644 --- a/src/@episerver/forms-react/src/components/FormBody.tsx +++ b/src/@episerver/forms-react/src/components/FormBody.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useRef } from "react"; -import { useForms, useFormsDispatch } from "../context/store"; -import { FormContainer, FormSubmitter, IdentityInfo, SubmitButtonType, equals, isInArray, isNull, isNullOrEmpty, FormSubmitModel, FormSubmitResult, SubmitButton, ElementValidationResult, FormValidationResult } from "@episerver/forms-sdk"; +import { useForms } from "../context/store"; +import { FormContainer, FormSubmitter, IdentityInfo, equals, isInArray, isNull, isNullOrEmpty, FormSubmitModel, FormSubmitResult, SubmitButton, FormValidationResult, FormCache, FormConstants } from "@episerver/forms-sdk"; import { RenderElementInStep } from "./RenderElementInStep"; import { DispatchFunctions } from "../context/dispatchFunctions"; import { FormStepNavigation } from "./FormStepNavigation"; @@ -21,6 +21,9 @@ export const FormBody = (props: FormBodyProps) => { const statusMessage = useRef(""); const statusDisplay = useRef("hide"); + const formCache = new FormCache(); + const localFormCache = new FormCache(window.localStorage); + //TODO: these variables should be get from api or sdk const validateFail = useRef(false), isFormFinalized = useRef(false), @@ -70,7 +73,7 @@ export const FormBody = (props: FormBodyProps) => { } //Find submit button, if found then check property 'finalizeForm' of submit button. Otherwise, button Next/Previous was clicked. - let buttonId = e.nativeEvent.submitter.id; + let buttonId = e.nativeEvent.submitter?.id; let submitButton = form.formElements.find(fe => fe.key === buttonId) as SubmitButton; if (!isNull(submitButton)) { //when submitting by SubmitButton, isProgressiveSubmit default is true @@ -96,10 +99,11 @@ export const FormBody = (props: FormBodyProps) => { formKey: form.key, locale: form.locale, isFinalized: submitButton?.properties?.finalizeForm || isLastStep, - partialSubmissionKey: formContext?.submissionKey ?? "", + partialSubmissionKey: localFormCache.get(FormConstants.FormSubmissionId + form.key) ?? "", hostedPageUrl: window.location.pathname, submissionData: formSubmissions, - accessToken: formContext?.identityInfo?.accessToken + accessToken: formContext?.identityInfo?.accessToken, + currentStepIndex: currentStepIndex } dispatchFunctions.updateIsSubmitting(true); @@ -131,11 +135,19 @@ export const FormBody = (props: FormBodyProps) => { //set focus on the 1st invalid element of current step dispatchFunctions.updateFocusOn(getFirstInvalidElement(formValidationResults)); } + validateFail.current = response.validationFail; isSuccess.current = response.success; isFormFinalized.current = isLastStep && response.success; dispatchFunctions.updateSubmissionKey(response.submissionKey); dispatchFunctions.updateIsSubmitting(false); + + localFormCache.set(FormConstants.FormSubmissionId + form.key, response.submissionKey) + + if (isFormFinalized.current) { + formCache.remove(FormConstants.FormCurrentStep + form.key) + localFormCache.remove(FormConstants.FormSubmissionId + form.key) + } }); } @@ -202,6 +214,7 @@ export const FormBody = (props: FormBodyProps) => { diff --git a/src/@episerver/forms-react/src/components/FormStepNavigation.tsx b/src/@episerver/forms-react/src/components/FormStepNavigation.tsx index 5b69c41..b2abaea 100644 --- a/src/@episerver/forms-react/src/components/FormStepNavigation.tsx +++ b/src/@episerver/forms-react/src/components/FormStepNavigation.tsx @@ -7,6 +7,7 @@ import { useHistory } from "react-router-dom"; interface FormStepNavigationProps { isFormFinalized: boolean history?: any + handleSubmit: (e: any) => void } export const FormStepNavigation = (props: FormStepNavigationProps) => { @@ -14,9 +15,9 @@ export const FormStepNavigation = (props: FormStepNavigationProps) => { const formCache = new FormCache(); const form = formContext?.formContainer ?? {} as FormContainer; const depend = new StepDependCondition(form, formContext?.dependencyInactiveElements ?? []); - const { isFormFinalized, history } = props; + const { isFormFinalized, history, handleSubmit } = props; const dispatchFuncs = new DispatchFunctions(); - const stepLocalizations = useRef>(form.steps?.filter(s => !isNull(s.formStep.localizations))[0]?.formStep.localizations); + const stepLocalizations = useRef>(form.steps?.filter(s => !isNull(s.formStep.localizations))[0]?.formStep.localizations).current; const submittable = true const stepCount = form.steps.length; @@ -36,6 +37,7 @@ export const FormStepNavigation = (props: FormStepNavigationProps) => { const handleNextStep = (event: React.MouseEvent) => { event.preventDefault() + handleSubmit(event) goToStep(depend.findNextStep(currentStepIndex) ?? 0) } @@ -63,13 +65,13 @@ export const FormStepNavigation = (props: FormStepNavigationProps) => { disabled={prevButtonDisableState} onClick={(event) => handlePrevStep(event)} > - {stepLocalizations.current["previousButtonLabel"]} + {stepLocalizations["previousButtonLabel"]}
- {stepLocalizations.current["pageButtonLabel"]} + {stepLocalizations["pageButtonLabel"]} {currentDisplayStepIndex}/ {stepCount}
@@ -83,7 +85,7 @@ export const FormStepNavigation = (props: FormStepNavigationProps) => { disabled={nextButtonDisableState} onClick={handleNextStep} > - {stepLocalizations.current["nextButtonLabel"]} + {stepLocalizations["nextButtonLabel"]} } diff --git a/src/@episerver/forms-sdk/src/form-submit/formSubmit.ts b/src/@episerver/forms-sdk/src/form-submit/formSubmit.ts index 732a99f..7489221 100644 --- a/src/@episerver/forms-sdk/src/form-submit/formSubmit.ts +++ b/src/@episerver/forms-sdk/src/form-submit/formSubmit.ts @@ -33,6 +33,10 @@ export interface FormSubmitModel { * The access token to identify login user */ accessToken?: string; + /** + * The current index of submitted step + */ + currentStepIndex: number; } export interface FormSubmitResult { @@ -99,6 +103,7 @@ export class FormSubmitter { formData.append("IsFinalized", model.isFinalized.toString()); formData.append("PartialSubmissionKey", model.partialSubmissionKey); formData.append("HostedPageUrl", model.hostedPageUrl); + formData.append("CurrentStep", model.currentStepIndex.toString()); //append form submission to FormData object model.submissionData.forEach(data => { diff --git a/src/@episerver/forms-sdk/src/models/enums/FormConstants.ts b/src/@episerver/forms-sdk/src/models/enums/FormConstants.ts index c28722e..fe85602 100644 --- a/src/@episerver/forms-sdk/src/models/enums/FormConstants.ts +++ b/src/@episerver/forms-sdk/src/models/enums/FormConstants.ts @@ -1,5 +1,6 @@ export enum FormConstants { FormAccessToken = "form_access_token", FormFieldPrefix = "__field_", - FormCurrentStep = "form_current_step_" + FormCurrentStep = "form_current_step_", + FormSubmissionId = "form_submission_id_" } \ No newline at end of file