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 = const displayedValue =
value === null || value.length === 0 value === null || value.length === 0
? formatMessage({ id: getTrad('form.attribute.media.allowed-types.none') }) ? formatMessage({ id: getTrad('form.attribute.media.allowed-types.none') })
: value : [...value]
.sort() .sort()
.map(v => upperFirst(v)) .map(v => upperFirst(v))
.join(', '); .join(', ');

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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