Skip to content

Commit

Permalink
Add handler submit api exception, and add some description
Browse files Browse the repository at this point in the history
  • Loading branch information
hungoptimizely committed Dec 19, 2023
1 parent 5e05efb commit 7a78d32
Show file tree
Hide file tree
Showing 20 changed files with 89 additions and 28 deletions.
2 changes: 1 addition & 1 deletion samples/ManagementSite/Alloy.ManagementSite.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<PackageReference Include="EPiServer.CMS.UI.VisitorGroups" Version="12.23.0" />
<PackageReference Include="EPiServer.CMS.UI.AspNetIdentity" Version="12.23.0" />
<PackageReference Include="EPiServer.ImageLibrary.ImageSharp" Version="2.0.1" />
<PackageReference Include="Optimizely.Headless.Form.Service" Version="0.1.0--inte-173" />
<PackageReference Include="Optimizely.Headless.Form.Service" Version="0.1.0--inte-188" />
<PackageReference Include="Optimizely.Cms.Content.EPiServer" Version="0.3.1" />
<PackageReference Include="EPiServer.Forms" Version="5.8.0-ci-021201" />
<PackageReference Include="EPiServer.OpenIDConnect" Version="3.2.0"/>
Expand Down
10 changes: 5 additions & 5 deletions samples/sample-react-app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -44,7 +44,7 @@ function App() {
/>
))}
</div>
<div className={`right ${!isNullOrEmpty(identityInfo.accessToken) ? "hide" : ""}`}>
<div className={`right`}>
<h2>Login</h2>
<FormLogin
clientId='TestClient'
Expand Down
2 changes: 1 addition & 1 deletion src/@episerver/forms-react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@episerver/forms-react",
"version": "1.0.0",
"version": "0.1.0",
"description": "Forms react components render a form from JSON data",
"author": "Optimizely",
"license": "ISC",
Expand Down
14 changes: 13 additions & 1 deletion src/@episerver/forms-react/src/FormLogin.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FormAuthenticate, FormAuthenticateConfig, FormCache, FormConstants, IdentityInfo, isNullOrEmpty } from "@episerver/forms-sdk";
import React, { useState } from "react";
import React, { useEffect, useState } from "react";

interface FormLoginProps{
/**
Expand Down Expand Up @@ -43,6 +43,18 @@ export const FormLogin = (props: FormLoginProps) => {
});
}

useEffect(()=>{
let intervalId = setInterval(()=>{
let accessToken = formCache.get<string>(FormConstants.FormAccessToken);
if(isNullOrEmpty(accessToken)){
setIsAuthenticated(false);
}
},1000);
return ()=>{
clearInterval(intervalId);
}
},[]);

return (
<>
{isAuthenticated ? (<div className="Form__Authenticated">Authenticated</div>) : (
Expand Down
33 changes: 23 additions & 10 deletions src/@episerver/forms-react/src/components/FormBody.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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;
}
Expand All @@ -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";

Expand All @@ -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();

Expand Down Expand Up @@ -114,9 +123,8 @@ export const FormBody = (props: FormBodyProps) => {
message.current = response.messages.map(m => m.message).join("<br>");
}
else {
submissionWarning.current = true;
//ignore validation message
message.current = response.messages.filter(m => isNullOrEmpty(m.identifier)).map(m => m.message).join("<br>");
showError(response.messages.filter(m => isNullOrEmpty(m.identifier)).map(m => m.message).join("<br>"));
}
//update validation message
if(response.validationFail){
Expand All @@ -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]);

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/@episerver/forms-sdk/package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
7 changes: 4 additions & 3 deletions src/@episerver/forms-sdk/src/form-submit/formSubmit.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -149,16 +149,17 @@ 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();
}
resolve(result);
}
else {
reject(response);
reject(json as ProblemDetail);
}
})
.catch((error: any) => {
Expand Down
3 changes: 3 additions & 0 deletions src/@episerver/forms-sdk/src/models/IdentityInfo.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* Represent type of object that is identity information
*/
export interface IdentityInfo {
username: string,
accessToken: string
Expand Down
11 changes: 11 additions & 0 deletions src/@episerver/forms-sdk/src/models/ProblemDetail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Represent type of API exception
*/
export interface ProblemDetail {
type: string;
title: string;
status: number;
detail: string;
instance: string;
traceId: string;
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* How to combine result of all condition satisfy
*/
export enum ConditionCombinationType{
All = "All",
Any = "Any"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* enum represent a dependent condition Operator (in the Rule to evaluate depend value).
*/
export enum ConditionFunctionType {
MatchRegularExpression = "MatchRegularExpression",
Contains = "Contains",
Expand Down
3 changes: 3 additions & 0 deletions src/@episerver/forms-sdk/src/models/enums/FormConstants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* The list of constants is the keyword used for cached values
*/
export enum FormConstants {
FormAccessToken = "form_access_token",
FormFieldPrefix = "__field_",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* The action when condition is satisfied
*/
export enum SatisfiedActionType{
Show = "show",
Hide = "hide"
Expand Down
3 changes: 3 additions & 0 deletions src/@episerver/forms-sdk/src/models/enums/SubmitButtonType.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* Enum represent type name of step navigation
*/
export enum SubmitButtonType {
PreviousStep = "PreviousStep",
NextStep = "NextStep"
Expand Down
3 changes: 3 additions & 0 deletions src/@episerver/forms-sdk/src/models/enums/ValidatorType.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* The list of validator type
*/
export enum ValidatorType{
RequiredValidator = "RequiredValidator",
EmailValidator = "EmailValidator",
Expand Down
3 changes: 2 additions & 1 deletion src/@episerver/forms-sdk/src/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export * from "./elements";
export * from "./validators";
export * from "./enums";
export * from "./states";
export * from "./IdentityInfo";
export * from "./IdentityInfo";
export * from "./ProblemDetail";
2 changes: 1 addition & 1 deletion src/@episerver/forms-sdk/src/models/states/FormState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions src/@episerver/forms-sdk/src/models/states/FormSubmission.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* Represent type of object that is form submission
*/
export interface FormSubmission {
elementKey: string
value: any
Expand Down
4 changes: 2 additions & 2 deletions src/@episerver/forms-sdk/src/models/states/FormValidation.ts
Original file line number Diff line number Diff line change
@@ -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
{
Expand All @@ -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
Expand Down

0 comments on commit 7a78d32

Please sign in to comment.