Skip to content

Commit

Permalink
Merge pull request #163 from episerver/release/1.0.1
Browse files Browse the repository at this point in the history
Release/1.0.1
  • Loading branch information
linhhoangOpti authored Nov 7, 2024
2 parents b505e68 + 5385a2a commit 8026c7b
Show file tree
Hide file tree
Showing 20 changed files with 79 additions and 39 deletions.
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @episerver/addons-developers @longle91
* @episerver/cms-addons
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ coverage/
/samples/epiCloud/
/samples/musicfestival-frontend-react/build/
/samples/musicfestival-backend-dotnet/App_Data/

.env.local
appsettings.development.json
2 changes: 1 addition & 1 deletion .npmrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ always-auth=true
//pkgs.dev.azure.com/EpiserverEngineering/netCore/_packaging/HeadlessForms/npm/:username=${AZURE_USERNAME}
//pkgs.dev.azure.com/EpiserverEngineering/netCore/_packaging/HeadlessForms/npm/:_password=${AZURE_TOKEN}
//pkgs.dev.azure.com/EpiserverEngineering/netCore/_packaging/HeadlessForms/npm/:email=${AZURE_EMAIL}
; end auth token
; end auth token
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "content-headless-form-js-sdk",
"version": "1.0.0",
"version": "1.0.1",
"description": "Workspace root",
"workspaces": [
"src/@episerver/forms-react",
Expand Down
4 changes: 3 additions & 1 deletion samples/musicfestival-backend-dotnet/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Runtime.InteropServices;
using EPiServer.Cms.Shell;
using EPiServer.Cms.Shell.UI;
using EPiServer.Cms.UI.AspNetIdentity;
using EPiServer.ContentApi.Cms;
using EPiServer.ContentApi.Core.DependencyInjection;
Expand Down Expand Up @@ -59,7 +60,8 @@ public void ConfigureServices(IServiceCollection services)
services
.AddCmsAspNetIdentity<ApplicationUser>()
.AddCms()
.AddAdminUserRegistration()
.AddAdminUserRegistration(options => options.Behavior = RegisterAdminUserBehaviors.Enabled |
RegisterAdminUserBehaviors.LocalRequestsOnly)
.AddEmbeddedLocalization<Program>()
.ConfigureForExternalTemplates()
.Configure<ExternalApplicationOptions>(options => options.OptimizeForDelivery = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useNavigate, useLocation } from 'react-router-dom';

export const useHistoryCompatible = () => {
const navigate = useNavigate();
const location = useLocation();

return {
push: (path: any, state: any) => navigate(path, { state }),
replace: (path: any, state: any) => navigate(path, { replace: true, state }),
location: location,
goBack: () => navigate(-1),
goForward: () => navigate(1),
};
};
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { Form, FormContainerBlock, FormLogin } from '@episerver/forms-react';
import { FormCache, FormConstants, IdentityInfo, extractParams } from '@episerver/forms-sdk';
import { useEffect, useState } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { useFetch } from '../useFetch';
import { useHistoryCompatible } from '../hooks/useHistoryCompatible';
import SearchButton from '../components/SearchButton';
import { getImageUrl } from '../helpers/urlHelper';
import authService from '../authService';

type BuyTicketPageProps = {
content: any,
Expand All @@ -24,7 +21,7 @@ function BuyTicketPage({ content }: BuyTicketPageProps) {
} as IdentityInfo)
}, [formCache.get<string>(FormConstants.FormAccessToken)]);

const history = useNavigate()
const history = useHistoryCompatible()
return (
<>
{content &&
Expand Down Expand Up @@ -59,7 +56,7 @@ function BuyTicketPage({ content }: BuyTicketPageProps) {
<Form
key={key}
formKey={key}
language={c.ContentLink.Ex}
language={c.ContentLink.Expanded.Language.Name}
baseUrl={process.env.REACT_APP_HEADLESS_FORM_BASE_URL ?? "/"}
identityInfo={identityInfo}
history={history}
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": "1.0.1",
"description": "Forms react components render a form from JSON data",
"author": "Optimizely",
"license": "ISC",
Expand Down
8 changes: 6 additions & 2 deletions src/@episerver/forms-react/src/components/FormBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import React, { useEffect, useRef } from "react";
import { useForms } from "../context/store";
import { StepHelper, FormContainer, FormSubmitter, IdentityInfo, isInArray, isNull,
isNullOrEmpty, FormSubmitModel, FormSubmitResult, SubmitButton, FormCache,
FormConstants, ProblemDetail, StepDependCondition, getConfirmationData } from "@episerver/forms-sdk";
FormConstants, ProblemDetail, StepDependCondition, getConfirmationData,
SatisfiedActionType} from "@episerver/forms-sdk";
import { RenderElementInStep } from "./RenderElementInStep";
import { DispatchFunctions } from "../context/dispatchFunctions";
import { FormStepNavigation } from "./FormStepNavigation";
Expand Down Expand Up @@ -102,7 +103,10 @@ export const FormBody = (props: FormBodyProps) => {

//get inactives element
let inactives = (formContext?.elementDependencies ?? [])
.filter(dependency => !dependency.isSatisfied)
.filter(dependency =>
(!dependency.isSatisfied && dependency.sastisfiedAction === SatisfiedActionType.Show)
|| (dependency.isSatisfied && dependency.sastisfiedAction === SatisfiedActionType.Hide)
)
.map(dependency => dependency.elementKey);

//filter submissions by active elements and current step
Expand Down
5 changes: 3 additions & 2 deletions src/@episerver/forms-react/src/context/dispatchFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ export class DispatchFunctions {
});
}

UpdateElementDependencies = (elementKey: string, condition: boolean) => {
UpdateElementDependencies = (elementKey: string, condition: boolean, satisfiedAction: string) => {
this._dispatch({
type: ActionType.UpdateElementDependencies,
elementKey: elementKey,
condition
condition,
satisfiedAction
});
}

Expand Down
3 changes: 2 additions & 1 deletion src/@episerver/forms-react/src/context/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export function formReducer(formState: FormState, action: any) {
...formState,
elementDependencies: formState.elementDependencies.map(fs => equals(fs.elementKey, action.elementKey) ? {
elementKey: action.elementKey,
isSatisfied: action.condition
isSatisfied: action.condition,
sastisfiedAction: action.satisfiedAction
} as ElementDependencies : fs)
} as FormState;
}
Expand Down
24 changes: 14 additions & 10 deletions src/@episerver/forms-react/src/hooks/useElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,19 @@ export const useElement = (element: FormElementBase) => {
//update form state
dispatchFuncs.resetFormDone();
}
},[formContext?.isReset]);
}, [formContext?.isReset]);

//update visible
useEffect(()=>{
useEffect(() => {
const conditionProps = (element.properties as unknown) as ConditionProperties;

if (isNull(conditionProps.satisfiedAction)) {
if (isNull(conditionProps.satisfiedAction) || isNull(conditionProps.conditions)) {
// No conditions and satisfied actions to take, no need to update dependencies
return;
}

//check form field dependencies
const checkConditions = formCondition.checkConditions(formContext?.formSubmissions as FormSubmission[]);
const checkConditions = formCondition.checkConditions(formContext?.formSubmissions as FormSubmission[], formContext?.elementDependencies);
if (checkConditions) {
//if isDependenciesSatisfied = true, and if SatisfiedAction = show, then show element. otherwise hide element.
isVisible.current = equals(conditionProps.satisfiedAction, SatisfiedActionType.Show);
Expand All @@ -102,16 +103,19 @@ export const useElement = (element: FormElementBase) => {
//if isDependenciesSatisfied = false, and if SatisfiedAction = hide, then show element. otherwise hide element.
isVisible.current = equals(conditionProps.satisfiedAction, SatisfiedActionType.Hide);
}
var currentCondition = formContext?.elementDependencies.find(e => e.elementKey === element.key)?.isSatisfied;

if (currentCondition != checkConditions) {
// Update element dependencies state
dispatchFuncs.UpdateElementDependencies(element.key, checkConditions, conditionProps.satisfiedAction);
}

// Update element dependencies state
dispatchFuncs.UpdateElementDependencies(element.key,checkConditions);

},[formContext?.formSubmissions]);
}, [formContext?.formSubmissions, formContext?.elementDependencies]);

//focus on element if validate fail before submitting
useEffect(()=>{
useEffect(() => {
let focusOn = formContext?.focusOn ?? "";
if(equals(focusOn, element.key)){
if (equals(focusOn, element.key)) {
elementRef.current && elementRef.current.focus();
dispatchFuncs.updateFocusOn("");
}
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": "1.0.1",
"description": "Forms SDK with client validation, step navigation, submit form, element depends",
"author": "Optimizely",
"license": "ISC",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function Equals(actualValue: any, dependencyFieldValue: string): boolean {
* @returns
*/
function NotEquals(actualValue: any, dependencyFieldValue: string): boolean {
const _actualValue = !actualValue ? "" : getConcatString(actualValue, ",").toLocaleUpperCase();
const _actualValue = !actualValue ? "" : getConcatString(actualValue.toString(), ",").toLocaleUpperCase();
dependencyFieldValue = !dependencyFieldValue ? "" : dependencyFieldValue.toLocaleUpperCase();
return _actualValue !== dependencyFieldValue;
}
Expand All @@ -40,7 +40,7 @@ function NotEquals(actualValue: any, dependencyFieldValue: string): boolean {
* @returns
*/
function Contains(actualValue: any, dependencyFieldValue: string): boolean {
const _actualValue = isNull(actualValue) ? "" : getConcatString(actualValue, ",").toLocaleUpperCase();
const _actualValue = isNull(actualValue) ? "" : getConcatString(actualValue.toString(), ",").toLocaleUpperCase();
dependencyFieldValue = !dependencyFieldValue ? "" : dependencyFieldValue.toLocaleUpperCase();
return _actualValue.indexOf(dependencyFieldValue) >= 0;
}
Expand All @@ -51,7 +51,7 @@ function Contains(actualValue: any, dependencyFieldValue: string): boolean {
* @returns
*/
function NotContains(actualValue: any, dependencyFieldValue: string): boolean {
const _actualValue = !actualValue ? "" : getConcatString(actualValue, ",").toLocaleUpperCase();
const _actualValue = !actualValue ? "" : getConcatString(actualValue.toString(), ",").toLocaleUpperCase();
const actualValueNull = isNullOrEmpty(_actualValue)
const dependencyFieldValueNull = isNullOrEmpty(dependencyFieldValue)
return (!actualValueNull && dependencyFieldValueNull) ||
Expand All @@ -66,6 +66,6 @@ function NotContains(actualValue: any, dependencyFieldValue: string): boolean {
*/
function MatchRegularExpression(actualValue: any, patternOfExpected: string): boolean {
var regex = new RegExp(patternOfExpected, "igm");
const _actualValue = !actualValue ? "" : getConcatString(actualValue, ",");
const _actualValue = !actualValue ? "" : getConcatString(actualValue.toString(), ",");
return isNullOrEmpty(patternOfExpected) || (!isNullOrEmpty(patternOfExpected) && regex.test(_actualValue));
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { equals, isNull } from "../helpers";
import { ConditionCombinationType, ConditionProperties, FormElementBase, FormSubmission } from "../models";
import { getValueOfDependeeElement } from "../helpers/dependencyHelper";
import { Condition, ConditionCombinationType, ConditionProperties, ElementDependencies, FormElementBase, FormSubmission } from "../models";
import { ConditionFunctions } from "./ConditionFunctions";
/**
* Class to check if a element conditions is met
Expand All @@ -14,7 +15,7 @@ export class FormDependConditions {
* @param formSubmissions
* @returns
*/
checkConditions = (formSubmissions: FormSubmission[]): boolean => {
checkConditions = (formSubmissions: FormSubmission[], elementDependencies: ElementDependencies[] = []): boolean => {
if (!isNull(formSubmissions)) {
const conditionProps = (this._element.properties as unknown) as ConditionProperties;
if (isNull(conditionProps?.conditions)) {
Expand All @@ -23,10 +24,10 @@ export class FormDependConditions {
}
for (let i = 0; i < conditionProps.conditions.length; i++) {
const condition = conditionProps.conditions[i]
const fieldValue = formSubmissions.filter(s => equals(s.elementKey, condition.field))[0]?.value;
const dependeeFieldValue = getValueOfDependeeElement(condition,formSubmissions,elementDependencies);
const conditionFunction = ConditionFunctions[condition.operator];
if (!isNull(conditionFunction)){
let checkResult = conditionFunction(fieldValue == null? "":fieldValue.toString(), condition.fieldValue)
let checkResult = conditionFunction(dependeeFieldValue == null? "" : dependeeFieldValue.toString(), condition.fieldValue)
if (conditionProps.conditionCombination === ConditionCombinationType.Any && checkResult) {
return true
}
Expand Down
1 change: 0 additions & 1 deletion src/@episerver/forms-sdk/src/form-loader/formLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ export class FormLoader<T extends FormContainer> {
if (response.ok) {
let json = await response.json();
let formStr = json.data.FormContainer.items[0];
console.log(formStr)
let convertedFormStr = this.convertFirstLetterToLowerCase(formStr) as T
resolve(convertedFormStr)
}
Expand Down
13 changes: 13 additions & 0 deletions src/@episerver/forms-sdk/src/helpers/dependencyHelper.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
import { Condition, ElementDependencies, FormSubmission } from "../models";
import { equals } from "./utils";

export function getConcatString(srcObject: any, seperator: string): string {
return (srcObject instanceof Array) ? srcObject.join(seperator) : srcObject as string;
}

export function getValueOfDependeeElement(condition: Condition ,formSubmissions: FormSubmission[], elementDependencies: ElementDependencies[]) : any {
var dependeeFieldValue = formSubmissions.filter(s => equals(s.elementKey, condition.field))[0]?.value;
const dependeeElement = elementDependencies.find(e => e.elementKey === condition.field)
if (dependeeElement && !dependeeElement.isSatisfied ) {
// if element is in the inactive list, consider its value as undefined
dependeeFieldValue = undefined;
}
return dependeeFieldValue;
}
2 changes: 1 addition & 1 deletion src/@episerver/forms-sdk/src/helpers/initFormState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function initFormState(formContainer: FormContainer, currentPageUrl?: str
//init form submission
formSubmissions = formSubmissions.concat({ elementKey: e.key, value: getDefaultValue(e) } as FormSubmission);
//init form elements dependencies
elementDependencies = elementDependencies.concat({ elementKey: e.key, isSatisfied: true });
elementDependencies = elementDependencies.concat({ elementKey: e.key, isSatisfied: true, sastisfiedAction : (e.properties as any).satisfiedAction });
}
});
stepDependencies = stepDependencies.concat({ elementKey: s.formStep.key, isSatisfied: false });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export interface ElementDependencies{
elementKey: string
isSatisfied: boolean
sastisfiedAction?: string
}

0 comments on commit 8026c7b

Please sign in to comment.