diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/DataManagerProvider/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/DataManagerProvider/index.js index 378089a930..bc21643c75 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/DataManagerProvider/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/DataManagerProvider/index.js @@ -99,6 +99,24 @@ const DataManagerProvider = ({ children }) => { uid, }); }; + const removeAttribute = ( + mainDataKey, + attributeToRemoveName, + componentUid = '' + ) => { + const type = + mainDataKey === 'components' + ? 'REMOVE_FIELD_FROM_DISPLAYED_COMPONENT' + : 'REMOVE_FIELD'; + + dispatch({ + type, + mainDataKey, + attributeToRemoveName, + componentUid, + }); + }; + const sortedContentTypesList = sortBy( Object.keys(contentTypes) .map(uid => ({ @@ -161,6 +179,7 @@ const DataManagerProvider = ({ children }) => { initialData, isInContentTypeView, modifiedData, + removeAttribute, setModifiedData, sortedContentTypesList, }} diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/DataManagerProvider/reducer.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/DataManagerProvider/reducer.js index 366aac7514..61a29e295a 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/DataManagerProvider/reducer.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/DataManagerProvider/reducer.js @@ -79,6 +79,20 @@ const reducer = (state, action) => { } ); } + case 'CREATE_SCHEMA': { + const newSchema = { + uid: action.uid, + isTemporary: true, + schema: { + ...action.data, + attributes: {}, + }, + }; + const key = + action.schemaType === 'contentType' ? 'contentTypes' : 'components'; + + return state.updateIn([key, action.uid], () => fromJS(newSchema)); + } case 'EDIT_ATTRIBUTE': { const { attributeToSet: { name, ...rest }, @@ -228,26 +242,78 @@ const reducer = (state, action) => { .update('components', () => fromJS(action.components)) .update('contentTypes', () => fromJS(action.contentTypes)) .update('isLoading', () => false); - case 'CREATE_SCHEMA': { - const newSchema = { - uid: action.uid, - isTemporary: true, - schema: { - ...action.data, - attributes: {}, - }, - }; - const key = - action.schemaType === 'contentType' ? 'contentTypes' : 'components'; + case 'REMOVE_FIELD_FROM_DISPLAYED_COMPONENT': { + const { attributeToRemoveName, componentUid } = action; - return state.updateIn([key, action.uid], () => fromJS(newSchema)); + console.log({ componentUid, attributeToRemoveName }); + console.log( + state + .getIn([ + 'modifiedData', + 'components', + componentUid, + 'schema', + 'attributes', + attributeToRemoveName, + ]) + .toJS() + ); + + return state.removeIn([ + 'modifiedData', + 'components', + componentUid, + 'schema', + 'attributes', + attributeToRemoveName, + ]); } + case 'REMOVE_FIELD': { + const { mainDataKey, attributeToRemoveName } = action; + const pathToAttributes = [ + 'modifiedData', + mainDataKey, + 'schema', + 'attributes', + ]; + const pathToAttributeToRemove = [ + ...pathToAttributes, + attributeToRemoveName, + ]; + const attributeToRemoveData = state.getIn(pathToAttributeToRemove); + const isRemovingRelationAttribute = + attributeToRemoveData.get('nature') !== undefined; + // Only content types can have relations that with themselves since, components can only have oneWay or manyWay relations + const canTheAttributeToRemoveHaveARelationWithItself = + mainDataKey === 'contentType'; + if ( + isRemovingRelationAttribute && + canTheAttributeToRemoveHaveARelationWithItself + ) { + const { + target, + nature, + targetAttribute, + } = attributeToRemoveData.toJS(); + const uid = state.getIn(['modifiedData', 'contentType', 'uid']); + const shouldRemoveOppositeAttribute = + target === uid && !ONE_SIDE_RELATIONS.includes(nature); + + if (shouldRemoveOppositeAttribute) { + return state + .removeIn(pathToAttributeToRemove) + .removeIn([...pathToAttributes, targetAttribute]); + } + } + + return state.removeIn(pathToAttributeToRemove); + } case 'SET_MODIFIED_DATA': { return state .update('isLoadingForDataToBeSet', () => false) - .update('initialData', () => action.schemaToSet) - .update('modifiedData', () => action.schemaToSet); + .update('initialData', () => fromJS(action.schemaToSet)) + .update('modifiedData', () => fromJS(action.schemaToSet)); } default: return state; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/DataManagerProvider/utils/createModifiedDataSchema.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/DataManagerProvider/utils/createModifiedDataSchema.js index 2aac3a7472..a93d0761df 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/DataManagerProvider/utils/createModifiedDataSchema.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/DataManagerProvider/utils/createModifiedDataSchema.js @@ -39,7 +39,7 @@ const orderAllDataAttributesWithImmutable = ( const currentAttributes = get(currentSchema, attributesPath, {}); const currentImmutableSchemas = fromJS(currentSchema).setIn( ['schema', 'attributes'], - OrderedMap(currentAttributes) + OrderedMap(fromJS(currentAttributes)) ); acc[current] = fromJS(currentImmutableSchemas); @@ -52,7 +52,7 @@ const orderAllDataAttributesWithImmutable = ( const mainSchema = get(allDataSchema, [keyName], {}); const mainImmutableSchema = fromJS(mainSchema).setIn( attributesPath, - OrderedMap(get(mainSchema, attributesPath, {})) + OrderedMap(fromJS(get(mainSchema, attributesPath, {}))) ); const immutableData = fromJS({ diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/index.js index b9c3e1c445..b0eaf4ca14 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/index.js @@ -64,7 +64,6 @@ const FormModal = () => { useEffect(() => { if (!isEmpty(search)) { - console.log('up'); // Return 'null' if there isn't any attributeType search params const attributeType = query.get('attributeType'); const modalType = query.get('modalType'); @@ -164,7 +163,7 @@ const FormModal = () => { ) { const type = state.attributeType === 'relation' ? 'relation' : modifiedData.type; - console.log({ pathToSchema: state.pathToSchema }); + schema = forms[state.modalType].schema( get(allDataSchema, state.pathToSchema, {}), type, diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/forms.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/forms.js index b004a0ff95..7860adeef6 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/forms.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/forms.js @@ -54,12 +54,6 @@ const forms = { attributeToEditName, initialData ) { - console.log({ currentSchema }); - console.log({ attributeType }); - console.log({ dataToValidate }); - console.log({ isEditing }); - console.log({ attributeToEditName }); - console.log({ initialData }); const alreadyTakenAttributes = Object.keys( get(currentSchema, ['schema', 'attributes'], {}) ).filter(attribute => { @@ -70,6 +64,7 @@ const forms = { return true; }); + // For relations let targetAttributeAlreadyTakenValue = dataToValidate.name ? [...alreadyTakenAttributes, dataToValidate.name] : alreadyTakenAttributes; @@ -84,6 +79,7 @@ const forms = { ); } + // Common yup shape for most attributes const commonShape = { name: yup .string() diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/ListPage/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/ListPage/index.js index b71d926ac8..cea1fa8a57 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/ListPage/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/ListPage/index.js @@ -6,7 +6,12 @@ import useDataManager from '../../hooks/useDataManager'; import LeftMenu from '../LeftMenu'; const ListPage = () => { - const { initialData, modifiedData, isInContentTypeView } = useDataManager(); + const { + initialData, + modifiedData, + isInContentTypeView, + removeAttribute, + } = useDataManager(); const { push } = useHistory(); const firstMainDataPath = isInContentTypeView ? 'contentType' : 'component'; const mainDataTypeAttributesPath = [ @@ -134,9 +139,26 @@ const ListPage = () => { return (