Merge pull request #10593 from strapi/ctb/remove-immutable-form-modal-reducer

Ctb/remove immutable in form modal reducer
This commit is contained in:
cyril lopez 2021-07-08 12:06:33 +02:00 committed by GitHub
commit 12c1a47dcf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 610 additions and 474 deletions

View File

@ -19,7 +19,7 @@ const AllowedTypesSelect = ({ name, changeMediaAllowedTypes, styles, value }) =>
const displayedValue =
value === null || value.length === 0
? formatMessage({ id: getTrad('form.attribute.media.allowed-types.none') })
: value
: [...value]
.sort()
.map(v => upperFirst(v))
.join(', ');

View File

@ -69,7 +69,6 @@ const DataManagerProvider = ({
const dispatch = useDispatch();
const toggleNotification = useNotification();
const { lockAppWithAutoreload, unlockAppWithAutoreload } = useAutoReloadOverlayBlocker();
console.log({ modifiedData });
const { getPlugin } = useStrapiApp();

View File

@ -260,10 +260,6 @@ const types = {
val => val !== initialData.targetAttribute
);
// if (!['oneWay', 'manyWay'].includes(relationType)) {
// schema = schema
// }
return schema
.matches(NAME_REGEX, errorsTrads.regex)
.test({

View File

@ -109,7 +109,7 @@ const FormModal = () => {
initialData,
isCreatingComponentWhileAddingAField,
modifiedData,
} = reducerState.toJS();
} = reducerState;
useEffect(() => {
if (!isEmpty(search)) {
@ -357,10 +357,6 @@ const FormModal = () => {
}
}
// if (attributeType === 'relation' && !has(attributeToEdit, ['targetAttribute'])) {
// set(attributeToEdit, ['targetAttribute'], '-');
// }
dispatch({
type: SET_ATTRIBUTE_DATA_SCHEMA,
attributeType,

View File

@ -1,58 +1,61 @@
import { fromJS, List } from 'immutable';
import produce from 'immer';
import pluralize from 'pluralize';
import { snakeCase } from 'lodash';
import set from 'lodash/set';
import snakeCase from 'lodash/snakeCase';
import getRelationType from '../../utils/getRelationType';
import makeUnique from '../../utils/makeUnique';
import { createComponentUid } from './utils/createUid';
import { shouldPluralizeName, shouldPluralizeTargetAttribute } from './utils/relations';
import * as actions from './constants';
const initialState = fromJS({
const initialState = {
formErrors: {},
modifiedData: {},
initialData: {},
componentToCreate: {},
isCreatingComponentWhileAddingAField: false,
});
};
const reducer = (state = initialState, action) => {
switch (action.type) {
case actions.ADD_COMPONENTS_TO_DYNAMIC_ZONE: {
const { name, components, shouldAddComponents } = action;
return state.updateIn(['modifiedData', name], list => {
let updatedList = list;
const reducer = (state = initialState, action) =>
// eslint-disable-next-line consistent-return
produce(state, draftState => {
switch (action.type) {
case actions.ADD_COMPONENTS_TO_DYNAMIC_ZONE: {
const { components, shouldAddComponents } = action;
let currentList = [];
if (shouldAddComponents) {
updatedList = list.concat(components);
currentList = [...state.modifiedData.components, ...components];
} else {
updatedList = list.filter(comp => {
currentList = state.modifiedData.components.filter(comp => {
return components.indexOf(comp) === -1;
});
}
return List(makeUnique(updatedList.toJS()));
});
}
case actions.ON_CHANGE:
return state.update('modifiedData', obj => {
draftState.modifiedData.components = makeUnique(currentList);
break;
}
case actions.ON_CHANGE: {
const { keys, value } = action;
const hasDefaultValue = Boolean(obj.getIn(['default']));
const obj = state.modifiedData;
const hasDefaultValue = Boolean(obj.default);
// There is no need to remove the default key if the default value isn't defined
if (hasDefaultValue && keys.length === 1 && keys.includes('type')) {
const previousType = obj.getIn(['type']);
const previousType = obj.type;
if (previousType && ['date', 'datetime', 'time'].includes(previousType)) {
return obj.updateIn(keys, () => value).remove('default');
// return obj.updateIn(keys, () => value).remove('default');
delete draftState.modifiedData.default;
}
}
return obj.updateIn(keys, () => value);
});
set(draftState, ['modifiedData', ...keys], value);
case actions.ON_CHANGE_RELATION_TARGET: {
return state.update('modifiedData', obj => {
break;
}
case actions.ON_CHANGE_RELATION_TARGET: {
const {
target: {
oneThatIsCreatingARelationWithAnother,
@ -65,256 +68,288 @@ const reducer = (state = initialState, action) => {
let didChangeRelationTypeBecauseOfRestrictedRelation = false;
let changedRelationType = null;
return obj
.update('target', () => value)
.update('relation', currentRelation => {
const currentRelationType = getRelationType(
currentRelation,
obj.get('targetAttribute')
);
set(draftState, ['modifiedData', 'target'], value);
// Don't change the relation type if the allowed relations are not restricted
// TODO: replace with an obj { relation: 'x', bidirctional: true|false } when BE ready
if (targetContentTypeAllowedRelations === null) {
return currentRelation;
const modifiedData = state.modifiedData;
// Don't change the relation type if the allowed relations are not restricted
// TODO: replace with an obj { relation: 'x', bidirctional: true|false } when BE ready
if (Array.isArray(targetContentTypeAllowedRelations)) {
const currentRelationType = getRelationType(
modifiedData.relation,
modifiedData.targetAttribute
);
if (!targetContentTypeAllowedRelations.includes(currentRelationType)) {
const relationToSet = targetContentTypeAllowedRelations[0];
didChangeRelationTypeBecauseOfRestrictedRelation = true;
changedRelationType = relationToSet;
if (relationToSet === 'oneWay') {
set(draftState, ['modifiedData', 'relation'], 'oneToOne');
} else if (relationToSet === 'manyWay') {
set(draftState, ['modifiedData', 'relation'], 'oneToMany');
} else {
set(draftState, ['modifiedData', 'relation'], relationToSet);
}
}
}
if (!targetContentTypeAllowedRelations.includes(currentRelationType)) {
const relationToSet = targetContentTypeAllowedRelations[0];
didChangeRelationTypeBecauseOfRestrictedRelation = true;
changedRelationType = relationToSet;
let nameToSet;
if (relationToSet === 'oneWay') {
return 'oneToOne';
}
if (didChangeRelationTypeBecauseOfRestrictedRelation) {
nameToSet = pluralize(
snakeCase(selectedContentTypeFriendlyName),
shouldPluralizeName(changedRelationType)
);
} else {
nameToSet = pluralize(
snakeCase(selectedContentTypeFriendlyName),
if (relationToSet === 'manyWay') {
return 'oneToMany';
}
shouldPluralizeName(modifiedData.relation)
);
}
return relationToSet;
}
set(draftState, ['modifiedData', 'name'], nameToSet);
return currentRelation;
})
.update('name', () => {
if (didChangeRelationTypeBecauseOfRestrictedRelation) {
return pluralize(
snakeCase(selectedContentTypeFriendlyName),
shouldPluralizeName(changedRelationType)
);
}
const currentTargetAttribute = state.modifiedData.targetAttribute;
return pluralize(
snakeCase(selectedContentTypeFriendlyName),
if (currentTargetAttribute === null) {
break;
}
shouldPluralizeName(obj.get('relation'))
);
})
.update('targetAttribute', oldValue => {
// Changing the target and the relation is either oneWay or manyWay
// Doing !oldValue will change the relation type if the target attribute is an empty string
if (oldValue === null) {
return null;
}
// Changing the target and the relation is either oneWay or manyWay
// Case when we need to change the relation to oneWay (ex: admin user)
if (
didChangeRelationTypeBecauseOfRestrictedRelation &&
['oneWay', 'manyWay'].includes(changedRelationType)
) {
set(draftState, ['modifiedData', 'targetAttribute'], null);
// Case when we need to change the relation to oneWay (ex: admin user)
if (
didChangeRelationTypeBecauseOfRestrictedRelation &&
['oneWay', 'manyWay'].includes(changedRelationType)
) {
return null;
}
break;
}
return pluralize(
snakeCase(oneThatIsCreatingARelationWithAnother),
shouldPluralizeTargetAttribute(obj.get('relation'))
);
});
});
}
case actions.ON_CHANGE_RELATION_TYPE: {
const {
target: { oneThatIsCreatingARelationWithAnother, value },
} = action;
const targetAttributeToSet = pluralize(
snakeCase(oneThatIsCreatingARelationWithAnother),
shouldPluralizeTargetAttribute(modifiedData.relation)
);
set(draftState, ['modifiedData', 'targetAttribute'], targetAttributeToSet);
break;
}
case actions.ON_CHANGE_RELATION_TYPE: {
const {
target: { oneThatIsCreatingARelationWithAnother, value },
} = action;
const currentName = state.modifiedData.name;
return state.update('modifiedData', obj => {
// Switching from oneWay
if (!['oneWay', 'manyWay'].includes(value)) {
return obj
.update('relation', () => value)
.update('name', oldValue => {
return pluralize(snakeCase(oldValue), shouldPluralizeName(value));
})
.update('targetAttribute', oldValue => {
return pluralize(
oldValue || snakeCase(oneThatIsCreatingARelationWithAnother),
shouldPluralizeTargetAttribute(value)
);
});
set(draftState, ['modifiedData', 'relation'], value);
const currentTargetAttribute = state.modifiedData.targetAttribute;
set(
draftState,
['modifiedData', 'name'],
pluralize(snakeCase(currentName), shouldPluralizeName(value))
);
set(
draftState,
['modifiedData', 'targetAttribute'],
pluralize(
currentTargetAttribute || snakeCase(oneThatIsCreatingARelationWithAnother),
shouldPluralizeTargetAttribute(value)
)
);
break;
}
if (value === 'oneWay') {
return obj
.update('relation', () => 'oneToOne')
.update('targetAttribute', () => null)
.update('name', oldValue => pluralize(snakeCase(oldValue), 1));
set(draftState, ['modifiedData', 'relation'], 'oneToOne');
set(draftState, ['modifiedData', 'targetAttribute'], null);
set(draftState, ['modifiedData', 'name'], pluralize(snakeCase(currentName), 1));
break;
}
// manyWay
return obj
.update('relation', () => 'oneToMany')
.update('targetAttribute', () => null)
.update('name', oldValue => pluralize(snakeCase(oldValue), 2));
});
}
case actions.ON_CHANGE_ALLOWED_TYPE: {
if (action.name === 'all') {
return state.updateIn(['modifiedData', 'allowedTypes'], () => {
if (action.value) {
return fromJS(['images', 'videos', 'files']);
}
set(draftState, ['modifiedData', 'relation'], 'oneToMany');
set(draftState, ['modifiedData', 'targetAttribute'], null);
set(draftState, ['modifiedData', 'name'], pluralize(snakeCase(currentName), 2));
return null;
});
break;
}
return state.updateIn(['modifiedData', 'allowedTypes'], currentList => {
let list = currentList || fromJS([]);
if (list.includes(action.name)) {
list = list.filter(v => v !== action.name);
if (list.size === 0) {
return null;
case actions.ON_CHANGE_ALLOWED_TYPE: {
if (action.name === 'all') {
if (action.value) {
set(draftState, ['modifiedData', 'allowedTypes'], ['images', 'videos', 'files']);
break;
}
return list;
set(draftState, ['modifiedData', 'allowedTypes'], null);
break;
}
return list.push(action.name);
});
}
case actions.RESET_PROPS:
return initialState;
case actions.RESET_PROPS_AND_SET_FORM_FOR_ADDING_AN_EXISTING_COMPO: {
// This is run when the user doesn't want to create a new component
return initialState.update('modifiedData', () =>
fromJS({ type: 'component', repeatable: true, ...action.options })
);
}
case actions.RESET_PROPS_AND_SAVE_CURRENT_DATA: {
// This is run when the user has created a new component
const componentToCreate = state.getIn(['modifiedData', 'componentToCreate']);
const modifiedData = fromJS({
name: componentToCreate.get('name'),
type: 'component',
repeatable: false,
...action.options,
component: createComponentUid(
componentToCreate.get('name'),
componentToCreate.get('category')
),
});
const currentList = state.modifiedData.allowedTypes || [];
let updatedList = [...currentList];
return initialState
.update('componentToCreate', () => componentToCreate)
.update('modifiedData', () => modifiedData)
.update('isCreatingComponentWhileAddingAField', () =>
state.getIn(['modifiedData', 'createComponent'])
);
}
case actions.RESET_PROPS_AND_SET_THE_FORM_FOR_ADDING_A_COMPO_TO_A_DZ: {
const createdDZ = state.get('modifiedData');
const dataToSet = createdDZ
.set('createComponent', true)
.set('componentToCreate', fromJS({ type: 'component' }));
if (currentList.includes(action.name)) {
updatedList = updatedList.filter(v => v !== action.name);
return initialState.update('modifiedData', () => dataToSet);
}
case actions.SET_DATA_TO_EDIT: {
return state
.updateIn(['modifiedData'], () => fromJS(action.data))
.updateIn(['initialData'], () => fromJS(action.data));
}
case actions.SET_ATTRIBUTE_DATA_SCHEMA: {
const {
attributeType,
isEditing,
modifiedDataToSetForEditing,
nameToSetForRelation,
targetUid,
step,
options = {},
} = action;
if (updatedList.length === 0) {
set(draftState, ['modifiedData', 'allowedTypes'], null);
if (isEditing) {
return state
.update('modifiedData', () => fromJS(modifiedDataToSetForEditing))
.update('initialData', () => fromJS(modifiedDataToSetForEditing));
break;
}
set(draftState, ['modifiedData', 'allowedTypes'], updatedList);
break;
}
updatedList.push(action.name);
set(draftState, ['modifiedData', 'allowedTypes'], updatedList);
break;
}
case actions.RESET_PROPS:
return initialState;
case actions.RESET_PROPS_AND_SET_FORM_FOR_ADDING_AN_EXISTING_COMPO: {
// This is run when the user doesn't want to create a new component
let dataToSet;
if (attributeType === 'component') {
if (step === '1') {
dataToSet = {
type: 'component',
createComponent: true,
componentToCreate: { type: 'component' },
};
} else {
dataToSet = {
...options,
const nextState = {
...initialState,
modifiedData: {
type: 'component',
repeatable: true,
};
}
} else if (attributeType === 'dynamiczone') {
dataToSet = {
...options,
type: 'dynamiczone',
components: [],
...action.options,
},
};
} else if (attributeType === 'text') {
dataToSet = { ...options, type: 'string' };
} else if (attributeType === 'number' || attributeType === 'date') {
dataToSet = options;
} else if (attributeType === 'media') {
dataToSet = {
allowedTypes: ['images', 'files', 'videos'],
type: 'media',
multiple: true,
...options,
};
} else if (attributeType === 'enumeration') {
dataToSet = { ...options, type: 'enumeration', enum: [] };
} else if (attributeType === 'relation') {
dataToSet = {
name: snakeCase(nameToSetForRelation),
relation: 'oneToOne',
targetAttribute: null,
target: targetUid,
type: 'relation',
};
} else {
dataToSet = { ...options, type: attributeType, default: null };
return nextState;
}
case actions.RESET_PROPS_AND_SAVE_CURRENT_DATA: {
// This is run when the user has created a new component
const componentToCreate = state.modifiedData.componentToCreate;
const modifiedData = {
name: componentToCreate.name,
type: 'component',
repeatable: false,
...action.options,
component: createComponentUid(componentToCreate.name, componentToCreate.category),
};
return state.update('modifiedData', () => fromJS(dataToSet));
}
case actions.SET_DYNAMIC_ZONE_DATA_SCHEMA: {
return state
.update('modifiedData', () => fromJS(action.attributeToEdit))
.update('initialData', () => fromJS(action.attributeToEdit));
}
const nextState = {
...initialState,
componentToCreate,
modifiedData,
isCreatingComponentWhileAddingAField: state.modifiedData.createComponent,
};
case actions.SET_ERRORS:
return state.update('formErrors', () => fromJS(action.errors));
default:
return state;
}
};
return nextState;
}
case actions.RESET_PROPS_AND_SET_THE_FORM_FOR_ADDING_A_COMPO_TO_A_DZ: {
const createdDZ = state.modifiedData;
const dataToSet = {
...createdDZ,
createComponent: true,
componentToCreate: { type: 'component' },
};
return { ...initialState, modifiedData: dataToSet };
}
case actions.SET_DATA_TO_EDIT: {
draftState.modifiedData = action.data;
draftState.initialData = action.data;
break;
}
case actions.SET_ATTRIBUTE_DATA_SCHEMA: {
const {
attributeType,
isEditing,
modifiedDataToSetForEditing,
nameToSetForRelation,
targetUid,
step,
options = {},
} = action;
if (isEditing) {
draftState.modifiedData = modifiedDataToSetForEditing;
draftState.initialData = modifiedDataToSetForEditing;
break;
}
let dataToSet;
if (attributeType === 'component') {
if (step === '1') {
dataToSet = {
type: 'component',
createComponent: true,
componentToCreate: { type: 'component' },
};
} else {
dataToSet = {
...options,
type: 'component',
repeatable: true,
};
}
} else if (attributeType === 'dynamiczone') {
dataToSet = {
...options,
type: 'dynamiczone',
components: [],
};
} else if (attributeType === 'text') {
dataToSet = { ...options, type: 'string' };
} else if (attributeType === 'number' || attributeType === 'date') {
dataToSet = options;
} else if (attributeType === 'media') {
dataToSet = {
allowedTypes: ['images', 'files', 'videos'],
type: 'media',
multiple: true,
...options,
};
} else if (attributeType === 'enumeration') {
dataToSet = { ...options, type: 'enumeration', enum: [] };
} else if (attributeType === 'relation') {
dataToSet = {
name: snakeCase(nameToSetForRelation),
relation: 'oneToOne',
targetAttribute: null,
target: targetUid,
type: 'relation',
};
} else {
dataToSet = { ...options, type: attributeType, default: null };
}
draftState.modifiedData = dataToSet;
break;
}
case actions.SET_DYNAMIC_ZONE_DATA_SCHEMA: {
draftState.modifiedData = action.attributeToEdit;
draftState.initialData = action.attributeToEdit;
break;
}
case actions.SET_ERRORS: {
draftState.formErrors = action.errors;
break;
}
default:
return draftState;
}
});
export default reducer;
export { initialState };

View File

@ -1,4 +1,3 @@
import { fromJS } from 'immutable';
import reducer, { initialState } from '../reducer';
import * as actions from '../constants';
@ -12,22 +11,23 @@ describe('CTB | components | FormModal | reducer | actions', () => {
name: 'components',
};
const state = initialState.setIn(
['modifiedData'],
fromJS({
const state = {
initialData: {},
modifiedData: {
type: 'dynamiczone',
name: 'dz',
components: ['default.test'],
})
);
const expected = state.setIn(
['modifiedData'],
fromJS({
},
};
const expected = {
initialData: {},
modifiedData: {
type: 'dynamiczone',
name: 'dz',
components: ['default.test', 'default.test2', 'default.test3'],
})
);
},
};
expect(reducer(state, action)).toEqual(expected);
});
@ -40,22 +40,23 @@ describe('CTB | components | FormModal | reducer | actions', () => {
name: 'components',
};
const state = initialState.setIn(
['modifiedData'],
fromJS({
const state = {
initialData: {},
modifiedData: {
type: 'dynamiczone',
name: 'dz',
components: ['default.test', 'default.test2', 'default.test3'],
})
);
const expected = state.setIn(
['modifiedData'],
fromJS({
},
};
const expected = {
initialData: {},
modifiedData: {
type: 'dynamiczone',
name: 'dz',
components: ['default.test'],
})
);
},
};
expect(reducer(state, action)).toEqual(expected);
});
@ -68,51 +69,73 @@ describe('CTB | components | FormModal | reducer | actions', () => {
keys: ['name'],
value: 'test',
};
const state = initialState.setIn(['modifiedData', 'type'], 'string');
const expected = state.setIn(['modifiedData', 'name'], 'test');
const state = {
...initialState,
modifiedData: {
type: 'string',
},
};
const expected = {
...initialState,
modifiedData: {
name: 'test',
type: 'string',
},
};
expect(reducer(state, action)).toEqual(expected);
});
it('should remove the default value if the type of date input type has been changed', () => {
const state = initialState.setIn(
['modifiedData'],
fromJS({
const state = {
...initialState,
modifiedData: {
name: 'short_movie_time',
type: 'time',
default: '00:30:00',
})
);
},
};
const action = {
type: actions.ON_CHANGE,
keys: ['type'],
value: 'datetime',
};
const expected = state
.setIn(['modifiedData', 'name'], 'short_movie_time')
.setIn(['modifiedData', 'type'], 'datetime')
.removeIn(['modifiedData', 'default']);
const expected = {
...initialState,
modifiedData: {
name: 'short_movie_time',
type: 'datetime',
},
};
expect(reducer(state, action)).toEqual(expected);
});
it('should not remove the default value if the type of another input type has been changed', () => {
const state = initialState.setIn(
['modifiedData'],
fromJS({
const state = {
...initialState,
modifiedData: {
name: 'number_of_movies',
type: 'integer',
default: '0',
})
);
},
};
const action = {
type: actions.ON_CHANGE,
keys: ['type'],
value: 'biginteger',
};
const expected = state
.setIn(['modifiedData', 'name'], 'number_of_movies')
.setIn(['modifiedData', 'type'], 'biginteger');
const expected = {
...initialState,
modifiedData: {
name: 'number_of_movies',
type: 'biginteger',
default: '0',
},
};
expect(reducer(state, action)).toEqual(expected);
});
@ -120,79 +143,117 @@ describe('CTB | components | FormModal | reducer | actions', () => {
describe('ON_CHANGE_ALLOWED_TYPE', () => {
it('Should add the missing types', () => {
const state = initialState.setIn(
['modifiedData', 'allowedTypes'],
fromJS(['images', 'videos'])
);
const state = {
...initialState,
modifiedData: {
allowedTypes: ['images', 'videos'],
},
};
const action = {
name: 'all',
value: true,
type: actions.ON_CHANGE_ALLOWED_TYPE,
};
const expected = state.setIn(
['modifiedData', 'allowedTypes'],
fromJS(['images', 'videos', 'files'])
);
const expected = {
...initialState,
modifiedData: {
allowedTypes: ['images', 'videos', 'files'],
},
};
expect(reducer(state, action)).toEqual(expected);
});
it('Should remove the missing types', () => {
const state = initialState.setIn(
['modifiedData', 'allowedTypes'],
fromJS(['images', 'videos', 'files'])
);
const state = {
...initialState,
modifiedData: {
allowedTypes: ['images', 'videos', 'files'],
},
};
const action = {
name: 'all',
value: false,
type: actions.ON_CHANGE_ALLOWED_TYPE,
};
const expected = state.setIn(['modifiedData', 'allowedTypes'], null);
const expected = {
...initialState,
modifiedData: {
allowedTypes: null,
},
};
expect(reducer(state, action)).toEqual(expected);
});
it('Shoul add the missing type', () => {
const state = initialState.setIn(
['modifiedData', 'allowedTypes'],
fromJS(['videos', 'files'])
);
const state = {
...initialState,
modifiedData: {
allowedTypes: ['videos', 'files'],
},
};
const action = {
name: 'images',
value: null,
type: actions.ON_CHANGE_ALLOWED_TYPE,
};
const expected = state.setIn(
['modifiedData', 'allowedTypes'],
fromJS(['videos', 'files', 'images'])
);
const expected = {
...initialState,
modifiedData: {
allowedTypes: ['videos', 'files', 'images'],
},
};
expect(reducer(state, action)).toEqual(expected);
});
it('Should remove the type', () => {
const state = initialState.setIn(
['modifiedData', 'allowedTypes'],
fromJS(['videos', 'images', 'files'])
);
const state = {
...initialState,
modifiedData: {
allowedTypes: ['videos', 'images', 'files'],
},
};
const action = {
name: 'images',
value: null,
type: actions.ON_CHANGE_ALLOWED_TYPE,
};
const expected = state.setIn(['modifiedData', 'allowedTypes'], fromJS(['videos', 'files']));
const expected = {
...initialState,
modifiedData: {
allowedTypes: ['videos', 'files'],
},
};
expect(reducer(state, action)).toEqual(expected);
});
it('Should remove set the allowedTypes to null if removing the last type', () => {
const state = initialState.setIn(['modifiedData', 'allowedTypes'], fromJS(['videos']));
const state = {
...initialState,
modifiedData: {
allowedTypes: ['videos'],
},
};
const action = {
name: 'videos',
value: null,
type: actions.ON_CHANGE_ALLOWED_TYPE,
};
const expected = state.setIn(['modifiedData', 'allowedTypes'], null);
const expected = {
...initialState,
modifiedData: {
allowedTypes: null,
},
};
expect(reducer(state, action)).toEqual(expected);
});
@ -200,16 +261,16 @@ describe('CTB | components | FormModal | reducer | actions', () => {
describe('ON_CHANGE_RELATION_TARGET', () => {
it('Should handle the target change correctly for a one side relation (oneWay, manyWay)', () => {
const state = initialState.setIn(
['modifiedData'],
fromJS({
const state = {
...initialState,
modifiedData: {
name: 'category test',
relation: 'oneToOne',
targetAttribute: null,
target: 'application::category.category',
type: 'relation',
})
);
},
};
const action = {
type: actions.ON_CHANGE_RELATION_TARGET,
target: {
@ -219,24 +280,32 @@ describe('CTB | components | FormModal | reducer | actions', () => {
targetContentTypeAllowedRelations: null,
},
};
const expected = state
.setIn(['modifiedData', 'target'], 'application::address.address')
.setIn(['modifiedData', 'name'], 'address');
const expected = {
...initialState,
modifiedData: {
name: 'address',
relation: 'oneToOne',
targetAttribute: null,
target: 'application::address.address',
type: 'relation',
},
};
expect(reducer(state, action)).toEqual(expected);
});
it('Should handle the target change correctly for the manyToMany relation', () => {
const state = initialState.setIn(
['modifiedData'],
fromJS({
const state = {
...initialState,
modifiedData: {
name: 'categories',
relation: 'manyToMany',
targetAttribute: 'addresses',
target: 'application::category.category',
type: 'relation',
})
);
},
};
const action = {
type: actions.ON_CHANGE_RELATION_TARGET,
target: {
@ -246,24 +315,31 @@ describe('CTB | components | FormModal | reducer | actions', () => {
targetContentTypeAllowedRelations: null,
},
};
const expected = state
.setIn(['modifiedData', 'target'], 'application::country.country')
.setIn(['modifiedData', 'name'], 'countries');
const expected = {
...initialState,
modifiedData: {
name: 'countries',
relation: 'manyToMany',
targetAttribute: 'addresses',
target: 'application::country.country',
type: 'relation',
},
};
expect(reducer(state, action)).toEqual(expected);
});
it('Should handle the target change correctly if the target has restricted relations and the relation type is not correct', () => {
const state = initialState.setIn(
['modifiedData'],
fromJS({
const state = {
...initialState,
modifiedData: {
name: 'categories',
relation: 'manyToMany',
targetAttribute: 'addresses',
target: 'application::category.category',
type: 'relation',
})
);
},
};
const action = {
type: actions.ON_CHANGE_RELATION_TARGET,
target: {
@ -273,26 +349,32 @@ describe('CTB | components | FormModal | reducer | actions', () => {
targetContentTypeAllowedRelations: ['oneWay'],
},
};
const expected = state
.setIn(['modifiedData', 'target'], 'application::country.country')
.setIn(['modifiedData', 'name'], 'country')
.setIn(['modifiedData', 'targetAttribute'], null)
.setIn(['modifiedData', 'relation'], 'oneToOne');
const expected = {
...initialState,
modifiedData: {
name: 'country',
relation: 'oneToOne',
targetAttribute: null,
target: 'application::country.country',
type: 'relation',
},
};
expect(reducer(state, action)).toEqual(expected);
});
it('Should handle the target change correctly if the target has restricted relations and the relation type is correct', () => {
const state = initialState.setIn(
['modifiedData'],
fromJS({
const state = {
...initialState,
modifiedData: {
name: 'categories',
relation: 'oneToMany',
targetAttribute: null,
target: 'application::category.category',
type: 'relation',
})
);
},
};
const action = {
type: actions.ON_CHANGE_RELATION_TARGET,
target: {
@ -302,10 +384,17 @@ describe('CTB | components | FormModal | reducer | actions', () => {
targetContentTypeAllowedRelations: ['oneWay', 'manyWay'],
},
};
const expected = state
.setIn(['modifiedData', 'target'], 'application::country.country')
.setIn(['modifiedData', 'name'], 'countries')
.setIn(['modifiedData', 'targetAttribute'], null);
const expected = {
...initialState,
modifiedData: {
name: 'countries',
relation: 'oneToMany',
targetAttribute: null,
target: 'application::country.country',
type: 'relation',
},
};
expect(reducer(state, action)).toEqual(expected);
});
@ -313,16 +402,16 @@ describe('CTB | components | FormModal | reducer | actions', () => {
describe('ON_CHANGE_RELATION_TYPE', () => {
it('Should handle the relation type change correctly from oneWay to manyToMany', () => {
const state = initialState.setIn(
['modifiedData'],
fromJS({
const state = {
...initialState,
modifiedData: {
name: 'category test',
relation: 'oneToOne',
targetAttribute: null,
target: 'application::category.category',
type: 'relation',
})
);
},
};
const action = {
type: actions.ON_CHANGE_RELATION_TYPE,
target: {
@ -331,25 +420,32 @@ describe('CTB | components | FormModal | reducer | actions', () => {
oneThatIsCreatingARelationWithAnother: 'address',
},
};
const expected = state
.setIn(['modifiedData', 'relation'], 'manyToMany')
.setIn(['modifiedData', 'name'], 'category_tests')
.setIn(['modifiedData', 'targetAttribute'], 'addresses');
expect(reducer(state, action)).toEqual(expected);
});
it('Should handle the relation type change correctly from manyToMany to oneWay', () => {
const state = initialState.setIn(
['modifiedData'],
fromJS({
const expected = {
...initialState,
modifiedData: {
name: 'category_tests',
relation: 'manyToMany',
targetAttribute: 'addresses',
target: 'application::category.category',
type: 'relation',
})
);
},
};
expect(reducer(state, action)).toEqual(expected);
});
it('Should handle the relation type change correctly from manyToMany to oneWay', () => {
const state = {
...initialState,
modifiedData: {
name: 'category_tests',
relation: 'manyToMany',
targetAttribute: 'addresses',
target: 'application::category.category',
type: 'relation',
},
};
const action = {
type: actions.ON_CHANGE_RELATION_TYPE,
target: {
@ -358,25 +454,31 @@ describe('CTB | components | FormModal | reducer | actions', () => {
},
};
const expected = state
.setIn(['modifiedData', 'relation'], 'oneToOne')
.setIn(['modifiedData', 'name'], 'category_test')
.setIn(['modifiedData', 'targetAttribute'], null);
const expected = {
...initialState,
modifiedData: {
name: 'category_test',
relation: 'oneToOne',
targetAttribute: null,
target: 'application::category.category',
type: 'relation',
},
};
expect(reducer(state, action)).toEqual(expected);
});
it('Should handle the relation type change correctly from oneToOne to oneToMany', () => {
const state = initialState.setIn(
['modifiedData'],
fromJS({
const state = {
...initialState,
modifiedData: {
name: 'category_test',
relation: 'oneToOne',
targetAttribute: 'address',
target: 'application::category.category',
type: 'relation',
})
);
},
};
const action = {
type: actions.ON_CHANGE_RELATION_TYPE,
target: {
@ -384,9 +486,17 @@ describe('CTB | components | FormModal | reducer | actions', () => {
oneThatIsCreatingARelationWithAnother: 'address',
},
};
const expected = state
.setIn(['modifiedData', 'relation'], 'oneToMany')
.setIn(['modifiedData', 'name'], 'category_tests');
const expected = {
...initialState,
modifiedData: {
name: 'category_tests',
relation: 'oneToMany',
targetAttribute: 'address',
target: 'application::category.category',
type: 'relation',
},
};
expect(reducer(state, action)).toEqual(expected);
});
@ -394,7 +504,7 @@ describe('CTB | components | FormModal | reducer | actions', () => {
describe('RESET_PROPS', () => {
it('Should return the initialState', () => {
const state = initialState.setIn(['modifiedData'], 'test');
const state = { ...initialState, modifiedData: 'test' };
const action = { type: actions.RESET_PROPS };
expect(reducer(state, action)).toEqual(initialState);
@ -406,11 +516,14 @@ describe('CTB | components | FormModal | reducer | actions', () => {
const action = {
type: actions.RESET_PROPS_AND_SET_FORM_FOR_ADDING_AN_EXISTING_COMPO,
};
const state = initialState.setIn(['modifiedData'], 'test');
const expected = state.setIn(
['modifiedData'],
fromJS({ type: 'component', repeatable: true })
);
const state = { ...initialState, modifiedData: 'test' };
const expected = {
...initialState,
modifiedData: {
type: 'component',
repeatable: true,
},
};
expect(reducer(state, action)).toEqual(expected);
});
@ -420,9 +533,9 @@ describe('CTB | components | FormModal | reducer | actions', () => {
it('Should reset the state and update the modifiedData and componentToCreate objects correctly', () => {
const action = { type: actions.RESET_PROPS_AND_SAVE_CURRENT_DATA };
const state = initialState.setIn(
['modifiedData'],
fromJS({
const state = {
...initialState,
modifiedData: {
type: 'component',
createComponent: true,
componentToCreate: {
@ -431,29 +544,25 @@ describe('CTB | components | FormModal | reducer | actions', () => {
icon: 'air-freshener',
category: 'default',
},
})
);
},
};
const expected = initialState
.set(
'componentToCreate',
fromJS({
type: 'component',
name: 'compo',
icon: 'air-freshener',
category: 'default',
})
)
.set(
'modifiedData',
fromJS({
name: 'compo',
type: 'component',
repeatable: false,
component: 'default.compo',
})
)
.set('isCreatingComponentWhileAddingAField', true);
const expected = {
...initialState,
componentToCreate: {
type: 'component',
name: 'compo',
icon: 'air-freshener',
category: 'default',
},
modifiedData: {
name: 'compo',
type: 'component',
repeatable: false,
component: 'default.compo',
},
isCreatingComponentWhileAddingAField: true,
};
expect(reducer(state, action)).toEqual(expected);
});
@ -465,24 +574,26 @@ describe('CTB | components | FormModal | reducer | actions', () => {
type: actions.RESET_PROPS_AND_SET_THE_FORM_FOR_ADDING_A_COMPO_TO_A_DZ,
};
const state = initialState.set('initialData', 'test').set(
'modifiedData',
fromJS({
const state = {
...initialState,
initialData: 'test',
modifiedData: {
type: 'dynamiczone',
components: [],
name: 'dz',
})
);
const expected = initialState.set(
'modifiedData',
fromJS({
},
};
const expected = {
...initialState,
modifiedData: {
type: 'dynamiczone',
components: [],
name: 'dz',
createComponent: true,
componentToCreate: fromJS({ type: 'component' }),
})
);
componentToCreate: { type: 'component' },
},
};
expect(reducer(state, action)).toEqual(expected);
});
@ -496,9 +607,7 @@ describe('CTB | components | FormModal | reducer | actions', () => {
test: true,
},
};
const expected = initialState
.set('modifiedData', fromJS(action.data))
.set('initialData', fromJS(action.data));
const expected = { ...initialState, modifiedData: action.data, initialData: action.data };
expect(reducer(initialState, action)).toEqual(expected);
});
@ -506,9 +615,11 @@ describe('CTB | components | FormModal | reducer | actions', () => {
describe('SET_ATTRIBUTE_DATA_SCHEMA', () => {
it('Should handle the edition correcty', () => {
const expected = initialState
.setIn(['modifiedData'], fromJS({ test: true }))
.setIn(['initialData'], fromJS({ test: true }));
const expected = {
...initialState,
initialData: { test: true },
modifiedData: { test: true },
};
const action = {
type: actions.SET_ATTRIBUTE_DATA_SCHEMA,
isEditing: true,
@ -530,14 +641,14 @@ describe('CTB | components | FormModal | reducer | actions', () => {
modifiedDataToSetForEditing: { name: null },
step: '1',
};
const expected = initialState.setIn(
['modifiedData'],
fromJS({
const expected = {
...initialState,
modifiedData: {
type: 'component',
createComponent: true,
componentToCreate: { type: 'component' },
})
);
},
};
expect(reducer(initialState, action)).toEqual(expected);
});
@ -552,13 +663,13 @@ describe('CTB | components | FormModal | reducer | actions', () => {
modifiedDataToSetForEditing: { name: null },
step: '2',
};
const expected = initialState.setIn(
['modifiedData'],
fromJS({
const expected = {
...initialState,
modifiedData: {
type: 'component',
repeatable: true,
})
);
},
};
expect(reducer(initialState, action)).toEqual(expected);
});
@ -573,13 +684,13 @@ describe('CTB | components | FormModal | reducer | actions', () => {
modifiedDataToSetForEditing: { name: null },
step: '2',
};
const expected = initialState.setIn(
['modifiedData'],
fromJS({
const expected = {
...initialState,
modifiedData: {
type: 'dynamiczone',
components: [],
})
);
},
};
expect(reducer(initialState, action)).toEqual(expected);
});
@ -594,12 +705,12 @@ describe('CTB | components | FormModal | reducer | actions', () => {
modifiedDataToSetForEditing: { name: null },
step: null,
};
const expected = initialState.setIn(
['modifiedData'],
fromJS({
const expected = {
...initialState,
modifiedData: {
type: 'string',
})
);
},
};
expect(reducer(initialState, action)).toEqual(expected);
});
@ -614,7 +725,7 @@ describe('CTB | components | FormModal | reducer | actions', () => {
modifiedDataToSetForEditing: { name: null },
step: null,
};
const expected = initialState.setIn(['modifiedData'], fromJS({}));
const expected = { ...initialState, modifiedData: {} };
expect(reducer(initialState, action)).toEqual(expected);
});
@ -629,7 +740,7 @@ describe('CTB | components | FormModal | reducer | actions', () => {
modifiedDataToSetForEditing: { name: null },
step: null,
};
const expected = initialState.setIn(['modifiedData'], fromJS({}));
const expected = { ...initialState, modifiedData: {} };
expect(reducer(initialState, action)).toEqual(expected);
});
@ -644,10 +755,14 @@ describe('CTB | components | FormModal | reducer | actions', () => {
modifiedDataToSetForEditing: { name: null },
step: null,
};
const expected = initialState.setIn(
['modifiedData'],
fromJS({ type: 'media', multiple: true, allowedTypes: ['images', 'files', 'videos'] })
);
const expected = {
...initialState,
modifiedData: {
type: 'media',
multiple: true,
allowedTypes: ['images', 'files', 'videos'],
},
};
expect(reducer(initialState, action)).toEqual(expected);
});
@ -662,10 +777,7 @@ describe('CTB | components | FormModal | reducer | actions', () => {
modifiedDataToSetForEditing: { name: null },
step: null,
};
const expected = initialState.setIn(
['modifiedData'],
fromJS({ type: 'enumeration', enum: [] })
);
const expected = { ...initialState, modifiedData: { type: 'enumeration', enum: [] } };
expect(reducer(initialState, action)).toEqual(expected);
});
@ -680,16 +792,16 @@ describe('CTB | components | FormModal | reducer | actions', () => {
modifiedDataToSetForEditing: { name: null },
step: null,
};
const expected = initialState.set(
'modifiedData',
fromJS({
const expected = {
...initialState,
modifiedData: {
name: 'address_test',
relation: 'oneToOne',
targetAttribute: null,
target: 'application::address.address',
type: 'relation',
})
);
},
};
expect(reducer(initialState, action)).toEqual(expected);
});
@ -704,10 +816,7 @@ describe('CTB | components | FormModal | reducer | actions', () => {
modifiedDataToSetForEditing: { name: null },
step: null,
};
const expected = initialState.setIn(
['modifiedData'],
fromJS({ type: 'json', default: null })
);
const expected = { ...initialState, modifiedData: { type: 'json', default: null } };
expect(reducer(initialState, action)).toEqual(expected);
});
@ -725,9 +834,11 @@ describe('CTB | components | FormModal | reducer | actions', () => {
componentToCreate: { type: 'component' },
},
};
const expected = initialState
.setIn(['modifiedData'], fromJS(action.attributeToEdit))
.setIn(['initialData'], fromJS(action.attributeToEdit));
const expected = {
...initialState,
modifiedData: action.attributeToEdit,
initialData: action.attributeToEdit,
};
expect(reducer(initialState, action)).toEqual(expected);
});
@ -741,7 +852,7 @@ describe('CTB | components | FormModal | reducer | actions', () => {
test: 'this is required',
},
};
const expected = initialState.set('formErrors', fromJS(action.errors));
const expected = { ...initialState, formErrors: action.errors };
expect(reducer(initialState, action)).toEqual(expected);
});

View File

@ -26,7 +26,6 @@ const relations = {
};
const RelationFormNaturePicker = ({
// nature,
naturePickerType,
oneThatIsCreatingARelationWithAnother,
relationType,