From 32821d8a2f36721708bb3c8d056089abf05ea991 Mon Sep 17 00:00:00 2001 From: soupette Date: Thu, 8 Jul 2021 10:49:37 +0200 Subject: [PATCH] Remove immutable in FormModal reducer Signed-off-by: soupette --- .../components/AllowedTypesSelect/index.js | 2 +- .../components/DataManagerProvider/index.js | 1 - .../components/FormModal/attributes/types.js | 4 - .../admin/src/components/FormModal/index.js | 6 +- .../admin/src/components/FormModal/reducer.js | 511 ++++++++-------- .../FormModal/tests/reducer.test.js | 559 +++++++++++------- .../RelationFormNaturePicker/index.js | 1 - 7 files changed, 610 insertions(+), 474 deletions(-) diff --git a/packages/core/content-type-builder/admin/src/components/AllowedTypesSelect/index.js b/packages/core/content-type-builder/admin/src/components/AllowedTypesSelect/index.js index ad5475311d..7a120e963f 100644 --- a/packages/core/content-type-builder/admin/src/components/AllowedTypesSelect/index.js +++ b/packages/core/content-type-builder/admin/src/components/AllowedTypesSelect/index.js @@ -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(', '); diff --git a/packages/core/content-type-builder/admin/src/components/DataManagerProvider/index.js b/packages/core/content-type-builder/admin/src/components/DataManagerProvider/index.js index b1e9b99532..60402452db 100644 --- a/packages/core/content-type-builder/admin/src/components/DataManagerProvider/index.js +++ b/packages/core/content-type-builder/admin/src/components/DataManagerProvider/index.js @@ -69,7 +69,6 @@ const DataManagerProvider = ({ const dispatch = useDispatch(); const toggleNotification = useNotification(); const { lockAppWithAutoreload, unlockAppWithAutoreload } = useAutoReloadOverlayBlocker(); - console.log({ modifiedData }); const { getPlugin } = useStrapiApp(); diff --git a/packages/core/content-type-builder/admin/src/components/FormModal/attributes/types.js b/packages/core/content-type-builder/admin/src/components/FormModal/attributes/types.js index c26bad34a2..aa9c6edad2 100644 --- a/packages/core/content-type-builder/admin/src/components/FormModal/attributes/types.js +++ b/packages/core/content-type-builder/admin/src/components/FormModal/attributes/types.js @@ -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({ diff --git a/packages/core/content-type-builder/admin/src/components/FormModal/index.js b/packages/core/content-type-builder/admin/src/components/FormModal/index.js index 2fb25267ca..8e02c27780 100644 --- a/packages/core/content-type-builder/admin/src/components/FormModal/index.js +++ b/packages/core/content-type-builder/admin/src/components/FormModal/index.js @@ -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, diff --git a/packages/core/content-type-builder/admin/src/components/FormModal/reducer.js b/packages/core/content-type-builder/admin/src/components/FormModal/reducer.js index 45bd083e08..86607576b9 100644 --- a/packages/core/content-type-builder/admin/src/components/FormModal/reducer.js +++ b/packages/core/content-type-builder/admin/src/components/FormModal/reducer.js @@ -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 }; diff --git a/packages/core/content-type-builder/admin/src/components/FormModal/tests/reducer.test.js b/packages/core/content-type-builder/admin/src/components/FormModal/tests/reducer.test.js index 748101dd14..586d7fa185 100644 --- a/packages/core/content-type-builder/admin/src/components/FormModal/tests/reducer.test.js +++ b/packages/core/content-type-builder/admin/src/components/FormModal/tests/reducer.test.js @@ -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); }); diff --git a/packages/core/content-type-builder/admin/src/components/RelationFormNaturePicker/index.js b/packages/core/content-type-builder/admin/src/components/RelationFormNaturePicker/index.js index 4693861098..4eed81fa09 100644 --- a/packages/core/content-type-builder/admin/src/components/RelationFormNaturePicker/index.js +++ b/packages/core/content-type-builder/admin/src/components/RelationFormNaturePicker/index.js @@ -26,7 +26,6 @@ const relations = { }; const RelationFormNaturePicker = ({ - // nature, naturePickerType, oneThatIsCreatingARelationWithAnother, relationType,