diff --git a/samples/ManagementSite/Alloy.ManagementSite.csproj b/samples/ManagementSite/Alloy.ManagementSite.csproj
index dffa3ef..e5b90e1 100644
--- a/samples/ManagementSite/Alloy.ManagementSite.csproj
+++ b/samples/ManagementSite/Alloy.ManagementSite.csproj
@@ -19,7 +19,7 @@
-
+
diff --git a/samples/sample-react-app/src/App.tsx b/samples/sample-react-app/src/App.tsx
index 85f0908..959936d 100644
--- a/samples/sample-react-app/src/App.tsx
+++ b/samples/sample-react-app/src/App.tsx
@@ -2,13 +2,13 @@ import './App.css';
import { useFetch } from './hooks/useFetch';
import { Form, FormLogin } from '@episerver/forms-react';
import { extractParams } from './helpers/urlHelper';
-import { FormCache, FormConstants, IdentityInfo, isNullOrEmpty } from '@episerver/forms-sdk';
-import { useEffect, useState } from 'react';
-import { BrowserRouter, useHistory, useLocation } from 'react-router-dom';
+import { FormCache, FormConstants, IdentityInfo } from '@episerver/forms-sdk';
+import { useState } from 'react';
+import { useHistory, useLocation } from 'react-router-dom';
function App() {
const location = useLocation();
- const { relativePath, language } = extractParams(window.location.pathname)
+ const { language } = extractParams(window.location.pathname)
const url = `${process.env.REACT_APP_ENDPOINT_GET_FORM_BY_PAGE_URL}${location.pathname}`;
const { data: pageData, loading } = useFetch(url);
@@ -44,7 +44,7 @@ function App() {
/>
))}
-
+
Login
{
});
}
+ useEffect(()=>{
+ let intervalId = setInterval(()=>{
+ let accessToken = formCache.get(FormConstants.FormAccessToken);
+ if(isNullOrEmpty(accessToken)){
+ setIsAuthenticated(false);
+ }
+ },1000);
+ return ()=>{
+ clearInterval(intervalId);
+ }
+ },[]);
+
return (
<>
{isAuthenticated ? (Authenticated
) : (
diff --git a/src/@episerver/forms-react/src/components/FormBody.tsx b/src/@episerver/forms-react/src/components/FormBody.tsx
index fdd71de..cb3c5ff 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 } from "../context/store";
-import { FormContainer, FormSubmitter, IdentityInfo, equals, isInArray, isNull, isNullOrEmpty, FormSubmitModel, FormSubmitResult, SubmitButton, FormValidationResult, FormCache, FormConstants } from "@episerver/forms-sdk";
+import { FormContainer, FormSubmitter, IdentityInfo, equals, isInArray, isNull, isNullOrEmpty, FormSubmitModel, FormSubmitResult, SubmitButton, FormValidationResult, FormCache, FormConstants, ProblemDetail } from "@episerver/forms-sdk";
import { RenderElementInStep } from "./RenderElementInStep";
import { DispatchFunctions } from "../context/dispatchFunctions";
import { FormStepNavigation } from "./FormStepNavigation";
@@ -39,7 +39,7 @@ export const FormBody = (props: FormBodyProps) => {
isStepValidToDisplay = true;
if((isFormFinalized.current || isProgressiveSubmit.current) && isSuccess.current)
- {
+ {
statusDisplay.current = "Form__Success__Message";
statusMessage.current = form.properties.submitSuccessMessage ?? message.current;
}
@@ -48,6 +48,10 @@ export const FormBody = (props: FormBodyProps) => {
statusDisplay.current = "Form__Warning__Message";
statusMessage.current = message.current;
}
+ else {
+ statusDisplay.current = "hide";
+ statusMessage.current = "";
+ }
const validationCssClass = validateFail.current ? "ValidationFail" : "ValidationSuccess";
@@ -66,6 +70,11 @@ export const FormBody = (props: FormBodyProps) => {
)[0]?.elementKey;
}
+ const showError = (error: string) => {
+ submissionWarning.current = !isNullOrEmpty(error);
+ message.current = error;
+ }
+
const handleSubmit = (e: any) => {
e.preventDefault();
@@ -114,9 +123,8 @@ export const FormBody = (props: FormBodyProps) => {
message.current = response.messages.map(m => m.message).join("
");
}
else {
- submissionWarning.current = true;
//ignore validation message
- message.current = response.messages.filter(m => isNullOrEmpty(m.identifier)).map(m => m.message).join("
");
+ showError(response.messages.filter(m => isNullOrEmpty(m.identifier)).map(m => m.message).join("
"));
}
//update validation message
if(response.validationFail){
@@ -141,26 +149,31 @@ export const FormBody = (props: FormBodyProps) => {
isSuccess.current = response.success;
isFormFinalized.current = isLastStep && response.success;
dispatchFunctions.updateSubmissionKey(response.submissionKey);
- dispatchFunctions.updateIsSubmitting(false);
-
localFormCache.set(submissionStorageKey, response.submissionKey)
if (isFormFinalized.current) {
formCache.remove(submissionStorageKey)
localFormCache.remove(submissionStorageKey)
}
+ }).catch((e: ProblemDetail) => {
+ if(e.status === 401) {
+ //clear access token to ask login again
+ dispatchFunctions.updateIdentity({} as IdentityInfo);
+ formCache.remove(FormConstants.FormAccessToken);
+ showError(e.detail);
+ }
+ }).finally(()=>{
+ dispatchFunctions.updateIsSubmitting(false);
});
}
useEffect(() => {
dispatchFunctions.updateIdentity(props.identityInfo);
if (isNullOrEmpty(props.identityInfo?.accessToken) && !form.properties.allowAnonymousSubmission) {
- statusDisplay.current = "Form__Warning__Message";
- statusMessage.current = "You must be logged in to submit this form. If you are logged in and still cannot post, make sure \"Do not track\" in your browser settings is disabled.";
+ showError(form.localizations["allowAnonymousSubmissionErrorMessage"]);
}
else {
- statusMessage.current = "";
- statusDisplay.current = "hide";
+ showError("");
}
}, [props.identityInfo?.accessToken]);
diff --git a/src/@episerver/forms-react/src/components/FormStepNavigation.tsx b/src/@episerver/forms-react/src/components/FormStepNavigation.tsx
index b2abaea..836b73a 100644
--- a/src/@episerver/forms-react/src/components/FormStepNavigation.tsx
+++ b/src/@episerver/forms-react/src/components/FormStepNavigation.tsx
@@ -1,8 +1,7 @@
import React, { useRef } from "react";
-import { useForms, useFormsDispatch } from "../context/store";
+import { useForms } from "../context/store";
import { FormCache, FormConstants, FormContainer, FormStep, StepDependCondition, SubmitButtonType, isNull } from "@episerver/forms-sdk";
import { DispatchFunctions } from "../context/dispatchFunctions";
-import { useHistory } from "react-router-dom";
interface FormStepNavigationProps {
isFormFinalized: boolean
diff --git a/src/@episerver/forms-sdk/package.json b/src/@episerver/forms-sdk/package.json
index 6f11bec..ded3b2c 100644
--- a/src/@episerver/forms-sdk/package.json
+++ b/src/@episerver/forms-sdk/package.json
@@ -1,6 +1,6 @@
{
"name": "@episerver/forms-sdk",
- "version": "1.0.0",
+ "version": "0.1.0",
"description": "Forms SDK with client validation, step navigation, submit form, element depends",
"author": "Optimizely",
"license": "ISC",
diff --git a/src/@episerver/forms-sdk/src/form-submit/formSubmit.ts b/src/@episerver/forms-sdk/src/form-submit/formSubmit.ts
index 7489221..f767970 100644
--- a/src/@episerver/forms-sdk/src/form-submit/formSubmit.ts
+++ b/src/@episerver/forms-sdk/src/form-submit/formSubmit.ts
@@ -1,7 +1,7 @@
import { FormStorage } from "../form-storage";
import { FormValidator } from "../form-validator";
import { equals, isNull } from "../helpers";
-import { FormConstants, FormContainer, FormSubmission, FormValidationResult } from "../models";
+import { FormConstants, FormContainer, FormSubmission, FormValidationResult, ProblemDetail } from "../models";
import { ApiConstant } from "../form-loader/apiConstant";
export interface FormSubmitModel {
@@ -149,8 +149,9 @@ export class FormSubmitter {
fetch(`${this._baseUrl}${ApiConstant.apiEndpoint}`, requestInit)
.then(async (response: Response) => {
+ let json = await response.json();
if(response.ok){
- let result = (await response.json()) as FormSubmitResult;
+ let result = json as FormSubmitResult;
if(result.success && model.isFinalized){
//clear cache of form submission
formStorage.removeFormDataInStorage();
@@ -158,7 +159,7 @@ export class FormSubmitter {
resolve(result);
}
else {
- reject(response);
+ reject(json as ProblemDetail);
}
})
.catch((error: any) => {
diff --git a/src/@episerver/forms-sdk/src/models/IdentityInfo.ts b/src/@episerver/forms-sdk/src/models/IdentityInfo.ts
index 8da8e1b..4bb1b74 100644
--- a/src/@episerver/forms-sdk/src/models/IdentityInfo.ts
+++ b/src/@episerver/forms-sdk/src/models/IdentityInfo.ts
@@ -1,3 +1,6 @@
+/**
+ * Represent type of object that is identity information
+ */
export interface IdentityInfo {
username: string,
accessToken: string
diff --git a/src/@episerver/forms-sdk/src/models/ProblemDetail.ts b/src/@episerver/forms-sdk/src/models/ProblemDetail.ts
new file mode 100644
index 0000000..b791729
--- /dev/null
+++ b/src/@episerver/forms-sdk/src/models/ProblemDetail.ts
@@ -0,0 +1,11 @@
+/**
+ * Represent type of API exception
+ */
+export interface ProblemDetail {
+ type: string;
+ title: string;
+ status: number;
+ detail: string;
+ instance: string;
+ traceId: string;
+}
\ No newline at end of file
diff --git a/src/@episerver/forms-sdk/src/models/enums/ConditionCombinationType.ts b/src/@episerver/forms-sdk/src/models/enums/ConditionCombinationType.ts
index 8747ec6..424092d 100644
--- a/src/@episerver/forms-sdk/src/models/enums/ConditionCombinationType.ts
+++ b/src/@episerver/forms-sdk/src/models/enums/ConditionCombinationType.ts
@@ -1,3 +1,6 @@
+/**
+ * How to combine result of all condition satisfy
+ */
export enum ConditionCombinationType{
All = "All",
Any = "Any"
diff --git a/src/@episerver/forms-sdk/src/models/enums/ConditionFunctionType.ts b/src/@episerver/forms-sdk/src/models/enums/ConditionFunctionType.ts
index db8f5eb..187533c 100644
--- a/src/@episerver/forms-sdk/src/models/enums/ConditionFunctionType.ts
+++ b/src/@episerver/forms-sdk/src/models/enums/ConditionFunctionType.ts
@@ -1,3 +1,6 @@
+/**
+ * enum represent a dependent condition Operator (in the Rule to evaluate depend value).
+ */
export enum ConditionFunctionType {
MatchRegularExpression = "MatchRegularExpression",
Contains = "Contains",
diff --git a/src/@episerver/forms-sdk/src/models/enums/FormConstants.ts b/src/@episerver/forms-sdk/src/models/enums/FormConstants.ts
index fe85602..45ef87e 100644
--- a/src/@episerver/forms-sdk/src/models/enums/FormConstants.ts
+++ b/src/@episerver/forms-sdk/src/models/enums/FormConstants.ts
@@ -1,3 +1,6 @@
+/**
+ * The list of constants is the keyword used for cached values
+ */
export enum FormConstants {
FormAccessToken = "form_access_token",
FormFieldPrefix = "__field_",
diff --git a/src/@episerver/forms-sdk/src/models/enums/SatisfiedActionType.ts b/src/@episerver/forms-sdk/src/models/enums/SatisfiedActionType.ts
index 99601c8..20d66f6 100644
--- a/src/@episerver/forms-sdk/src/models/enums/SatisfiedActionType.ts
+++ b/src/@episerver/forms-sdk/src/models/enums/SatisfiedActionType.ts
@@ -1,3 +1,6 @@
+/**
+ * The action when condition is satisfied
+ */
export enum SatisfiedActionType{
Show = "show",
Hide = "hide"
diff --git a/src/@episerver/forms-sdk/src/models/enums/SubmitButtonType.ts b/src/@episerver/forms-sdk/src/models/enums/SubmitButtonType.ts
index 3675590..f9bf872 100644
--- a/src/@episerver/forms-sdk/src/models/enums/SubmitButtonType.ts
+++ b/src/@episerver/forms-sdk/src/models/enums/SubmitButtonType.ts
@@ -1,3 +1,6 @@
+/**
+ * Enum represent type name of step navigation
+ */
export enum SubmitButtonType {
PreviousStep = "PreviousStep",
NextStep = "NextStep"
diff --git a/src/@episerver/forms-sdk/src/models/enums/ValidatorType.ts b/src/@episerver/forms-sdk/src/models/enums/ValidatorType.ts
index c6b3e1e..48516c6 100644
--- a/src/@episerver/forms-sdk/src/models/enums/ValidatorType.ts
+++ b/src/@episerver/forms-sdk/src/models/enums/ValidatorType.ts
@@ -1,3 +1,6 @@
+/**
+ * The list of validator type
+ */
export enum ValidatorType{
RequiredValidator = "RequiredValidator",
EmailValidator = "EmailValidator",
diff --git a/src/@episerver/forms-sdk/src/models/index.ts b/src/@episerver/forms-sdk/src/models/index.ts
index 5b84daf..db4bf95 100644
--- a/src/@episerver/forms-sdk/src/models/index.ts
+++ b/src/@episerver/forms-sdk/src/models/index.ts
@@ -4,4 +4,5 @@ export * from "./elements";
export * from "./validators";
export * from "./enums";
export * from "./states";
-export * from "./IdentityInfo";
\ No newline at end of file
+export * from "./IdentityInfo";
+export * from "./ProblemDetail";
\ No newline at end of file
diff --git a/src/@episerver/forms-sdk/src/models/states/FormState.ts b/src/@episerver/forms-sdk/src/models/states/FormState.ts
index 5224c7d..1b5ede9 100644
--- a/src/@episerver/forms-sdk/src/models/states/FormState.ts
+++ b/src/@episerver/forms-sdk/src/models/states/FormState.ts
@@ -5,7 +5,7 @@ import { FormValidationResult } from "./FormValidation"
import { StepDependencies } from "./StepDependencies"
/**
- * Interface to define type of object that is form context
+ * Represent type of object that is form context
*/
export interface FormState {
isReset: boolean
diff --git a/src/@episerver/forms-sdk/src/models/states/FormSubmission.ts b/src/@episerver/forms-sdk/src/models/states/FormSubmission.ts
index 21257f5..5ab107a 100644
--- a/src/@episerver/forms-sdk/src/models/states/FormSubmission.ts
+++ b/src/@episerver/forms-sdk/src/models/states/FormSubmission.ts
@@ -1,3 +1,6 @@
+/**
+ * Represent type of object that is form submission
+ */
export interface FormSubmission {
elementKey: string
value: any
diff --git a/src/@episerver/forms-sdk/src/models/states/FormValidation.ts b/src/@episerver/forms-sdk/src/models/states/FormValidation.ts
index b14aa71..6383623 100644
--- a/src/@episerver/forms-sdk/src/models/states/FormValidation.ts
+++ b/src/@episerver/forms-sdk/src/models/states/FormValidation.ts
@@ -1,5 +1,5 @@
/**
- * Interface to define type of object that is form validation result
+ * Represent type of object that is form validation result
*/
export interface FormValidationResult
{
@@ -8,7 +8,7 @@ export interface FormValidationResult
}
/**
- * Interface to define type of object that is element validation result
+ * Represent type of object that is element validation result
*/
export interface ElementValidationResult {
type: string