Skip to content

Commit

Permalink
fix: more advanced conditional logic edge cases
Browse files Browse the repository at this point in the history
  • Loading branch information
jmikrut authored and denolfe committed Aug 2, 2021
1 parent 12cba62 commit 33983de
Show file tree
Hide file tree
Showing 19 changed files with 69 additions and 18 deletions.
22 changes: 13 additions & 9 deletions src/admin/components/forms/Form/buildStateFromSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,33 @@ const buildStateFromSchema = async (fieldSchema: FieldSchema[], fullData: Data =
if (fieldSchema) {
const validationPromises = [];

const structureFieldState = (field, data = {}) => {
const structureFieldState = (field, passesCondition, data = {}) => {
const value = typeof data?.[field.name] !== 'undefined' ? data[field.name] : field.defaultValue;

const fieldState = {
value,
initialValue: value,
valid: true,
validate: field.validate,
condition: field.admin?.condition,
passesCondition,
};

validationPromises.push(buildValidationPromise(fieldState, field));

return fieldState;
};

const iterateFields = (fields: FieldSchema[], data: Data, path = '') => fields.reduce((state, field) => {
const iterateFields = (fields: FieldSchema[], data: Data, parentPassesCondition: boolean, path = '') => fields.reduce((state, field) => {
let initialData = data;

if (!field?.admin?.disabled) {
if (field.name && field.defaultValue && typeof initialData?.[field.name] === 'undefined') {
initialData = { [field.name]: field.defaultValue };
}

const passesCondition = (field?.admin?.condition ? field.admin.condition(fullData || {}, initialData || {}) : true) && parentPassesCondition;

if (field.name) {
if (field.type === 'relationship' && initialData?.[field.name] === null) {
initialData[field.name] = 'null';
Expand All @@ -68,7 +72,7 @@ const buildStateFromSchema = async (fieldSchema: FieldSchema[], fullData: Data =
initialValue: row.id || new ObjectID().toHexString(),
valid: true,
},
...iterateFields(field.fields, row, rowPath),
...iterateFields(field.fields, row, passesCondition, rowPath),
};
}, {}),
};
Expand Down Expand Up @@ -97,7 +101,7 @@ const buildStateFromSchema = async (fieldSchema: FieldSchema[], fullData: Data =
initialValue: row.id || new ObjectID().toHexString(),
valid: true,
},
...(block?.fields ? iterateFields(block.fields, row, rowPath) : {}),
...(block?.fields ? iterateFields(block.fields, row, passesCondition, rowPath) : {}),
};
}, {}),
};
Expand All @@ -113,35 +117,35 @@ const buildStateFromSchema = async (fieldSchema: FieldSchema[], fullData: Data =

return {
...state,
...iterateFields(field.fields, subFieldData, `${path}${field.name}.`),
...iterateFields(field.fields, subFieldData, passesCondition, `${path}${field.name}.`),
};
}

return {
...state,
[`${path}${field.name}`]: structureFieldState(field, data),
[`${path}${field.name}`]: structureFieldState(field, passesCondition, data),
};
}

// Handle field types that do not use names (row, etc)
if (field.type === 'row') {
return {
...state,
...iterateFields(field.fields, data, path),
...iterateFields(field.fields, data, passesCondition, path),
};
}

// Handle normal fields
return {
...state,
[`${path}${field.name}`]: structureFieldState(field, data),
[`${path}${field.name}`]: structureFieldState(field, passesCondition, data),
};
}

return state;
}, {});

const resultingState = iterateFields(fieldSchema, fullData);
const resultingState = iterateFields(fieldSchema, fullData, true);
await Promise.all(validationPromises);
return resultingState;
}
Expand Down
27 changes: 20 additions & 7 deletions src/admin/components/forms/Form/fieldReducer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { unflatten, flatten } from 'flatley';
import flattenFilters from './flattenFilters';
import getSiblingData from './getSiblingData';
import reduceFieldsToValues from './reduceFieldsToValues';
import { Fields } from './types';

const unflattenRowsFromState = (state: Fields, path) => {
Expand Down Expand Up @@ -106,21 +108,31 @@ function fieldReducer(state: Fields, action): Fields {
case 'MODIFY_CONDITION': {
const { path, result } = action;

return Object.entries(state).reduce((newState, [key, val]) => {
if (key === path || key.indexOf(`${path}.`) === 0) {
return Object.entries(state).reduce((newState, [fieldPath, field]) => {
if (fieldPath === path || fieldPath.indexOf(`${path}.`) === 0) {
let passesCondition = result;

// If a condition is being set to true,
// Set all conditions to true
// Besides those who still fail their own conditions

if (passesCondition && field.condition) {
passesCondition = field.condition(reduceFieldsToValues(state), getSiblingData(state, path));
}

return {
...newState,
[key]: {
...val,
passesCondition: result,
[fieldPath]: {
...field,
passesCondition,
},
};
}

return {
...newState,
[key]: {
...val,
[fieldPath]: {
...field,
},
};
}, {});
Expand All @@ -136,6 +148,7 @@ function fieldReducer(state: Fields, action): Fields {
initialValue: action.initialValue,
stringify: action.stringify,
validate: action.validate,
condition: action.condition,
passesCondition: action.passesCondition,
};

Expand Down
3 changes: 3 additions & 0 deletions src/admin/components/forms/Form/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Condition } from '../../../../fields/config/types';

export type Field = {
value: unknown
initialValue: unknown
Expand All @@ -7,6 +9,7 @@ export type Field = {
disableFormData?: boolean
ignoreWhileFlattening?: boolean
stringify?: boolean
condition?: Condition
passesCondition?: boolean
}

Expand Down
2 changes: 2 additions & 0 deletions src/admin/components/forms/field-types/Array/Array.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const ArrayFieldType: React.FC<Props> = (props) => {
admin: {
readOnly,
description,
condition,
},
} = props;

Expand Down Expand Up @@ -70,6 +71,7 @@ const ArrayFieldType: React.FC<Props> = (props) => {
validate: memoizedValidate,
disableFormData,
ignoreWhileFlattening: true,
condition,
});

const addRow = useCallback(async (rowIndex) => {
Expand Down
2 changes: 2 additions & 0 deletions src/admin/components/forms/field-types/Blocks/Blocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const Blocks: React.FC<Props> = (props) => {
admin: {
readOnly,
description,
condition,
},
} = props;

Expand Down Expand Up @@ -80,6 +81,7 @@ const Blocks: React.FC<Props> = (props) => {
validate: memoizedValidate,
disableFormData,
ignoreWhileFlattening: true,
condition,
});

const addRow = useCallback(async (rowIndex, blockType) => {
Expand Down
2 changes: 2 additions & 0 deletions src/admin/components/forms/field-types/Checkbox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const Checkbox: React.FC<Props> = (props) => {
style,
width,
description,
condition,
} = {},
} = props;

Expand All @@ -44,6 +45,7 @@ const Checkbox: React.FC<Props> = (props) => {
path,
validate: memoizedValidate,
disableFormData,
condition,
});

return (
Expand Down
2 changes: 2 additions & 0 deletions src/admin/components/forms/field-types/Code/Code.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const Code: React.FC<Props> = (props) => {
width,
language,
description,
condition,
} = {},
label,
minLength,
Expand Down Expand Up @@ -55,6 +56,7 @@ const Code: React.FC<Props> = (props) => {
path,
validate: memoizedValidate,
enableDebouncedValue: true,
condition,
});

const classes = [
Expand Down
2 changes: 2 additions & 0 deletions src/admin/components/forms/field-types/DateTime/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const DateTime: React.FC<Props> = (props) => {
width,
date,
description,
condition,
} = {},
} = props;

Expand All @@ -45,6 +46,7 @@ const DateTime: React.FC<Props> = (props) => {
} = useFieldType({
path,
validate: memoizedValidate,
condition,
});

const classes = [
Expand Down
2 changes: 2 additions & 0 deletions src/admin/components/forms/field-types/Email/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const Email: React.FC<Props> = (props) => {
placeholder,
autoComplete,
description,
condition,
} = {},
label,
} = props;
Expand All @@ -37,6 +38,7 @@ const Email: React.FC<Props> = (props) => {
path,
validate: memoizedValidate,
enableDebouncedValue: true,
condition,
});

const {
Expand Down
2 changes: 2 additions & 0 deletions src/admin/components/forms/field-types/Number/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const NumberField: React.FC<Props> = (props) => {
step,
placeholder,
description,
condition,
} = {},
} = props;

Expand All @@ -44,6 +45,7 @@ const NumberField: React.FC<Props> = (props) => {
path,
validate: memoizedValidate,
enableDebouncedValue: true,
condition,
});

const handleChange = useCallback((e) => {
Expand Down
2 changes: 2 additions & 0 deletions src/admin/components/forms/field-types/RadioGroup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const RadioGroup: React.FC<Props> = (props) => {
style,
width,
description,
condition,
} = {},
options,
} = props;
Expand All @@ -46,6 +47,7 @@ const RadioGroup: React.FC<Props> = (props) => {
} = useFieldType({
path,
validate: memoizedValidate,
condition,
});

const classes = [
Expand Down
2 changes: 2 additions & 0 deletions src/admin/components/forms/field-types/Relationship/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const Relationship: React.FC<Props> = (props) => {
style,
width,
description,
condition,
} = {},
} = props;

Expand Down Expand Up @@ -73,6 +74,7 @@ const Relationship: React.FC<Props> = (props) => {
} = useFieldType({
path: path || name,
validate: memoizedValidate,
condition,
});

const addOptions = useCallback((data, relation) => {
Expand Down
2 changes: 2 additions & 0 deletions src/admin/components/forms/field-types/RichText/RichText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const RichText: React.FC<Props> = (props) => {
placeholder,
description,
hideGutter,
condition,
} = {},
} = props;

Expand Down Expand Up @@ -106,6 +107,7 @@ const RichText: React.FC<Props> = (props) => {
path,
validate: memoizedValidate,
stringify: true,
condition,
});

const {
Expand Down
2 changes: 2 additions & 0 deletions src/admin/components/forms/field-types/Select/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const Select: React.FC<Props> = (props) => {
style,
width,
description,
condition,
} = {},
} = props;

Expand All @@ -58,6 +59,7 @@ const Select: React.FC<Props> = (props) => {
} = useFieldType({
path,
validate: memoizedValidate,
condition,
});

const classes = [
Expand Down
2 changes: 2 additions & 0 deletions src/admin/components/forms/field-types/Text/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const Text: React.FC<Props> = (props) => {
style,
width,
description,
condition,
} = {},
} = props;

Expand All @@ -31,6 +32,7 @@ const Text: React.FC<Props> = (props) => {
path,
validate,
enableDebouncedValue: true,
condition,
});

const {
Expand Down
2 changes: 2 additions & 0 deletions src/admin/components/forms/field-types/Textarea/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const Textarea: React.FC<Props> = (props) => {
placeholder,
rows,
description,
condition,
} = {},
label,
minLength,
Expand All @@ -44,6 +45,7 @@ const Textarea: React.FC<Props> = (props) => {
path,
validate: memoizedValidate,
enableDebouncedValue: true,
condition,
});

const classes = [
Expand Down
2 changes: 2 additions & 0 deletions src/admin/components/forms/field-types/Upload/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const Upload: React.FC<Props> = (props) => {
style,
width,
description,
condition,
} = {},
label,
validate = upload,
Expand All @@ -53,6 +54,7 @@ const Upload: React.FC<Props> = (props) => {
const fieldType = useFieldType({
path,
validate: memoizedValidate,
condition,
});

const {
Expand Down
Loading

0 comments on commit 33983de

Please sign in to comment.