diff --git a/examples/getstarted/api/address/models/Address.settings.json b/examples/getstarted/api/address/models/Address.settings.json index 30f81a1e2c..2d8af9f09b 100755 --- a/examples/getstarted/api/address/models/Address.settings.json +++ b/examples/getstarted/api/address/models/Address.settings.json @@ -7,14 +7,17 @@ }, "options": { "increments": true, - "timestamps": ["created_at", "updated_at"], + "timestamps": [ + "created_at", + "updated_at" + ], "comment": "" }, "attributes": { "full_name": { "type": "string" }, - "postal_code": { + "postal_coder": { "type": "string" }, "city": { @@ -24,18 +27,30 @@ "type": "json", "required": true }, - "country": { - "model": "country" + "addresses": { + "collection": "address", + "via": "address" + }, + "address": { + "model": "address", + "via": "addresses" }, "cover": { "model": "file", "via": "related", - "plugin": "upload" + "plugin": "upload", + "required": false }, "images": { "collection": "file", "via": "related", - "plugin": "upload" + "plugin": "upload", + "required": false + }, + "teter": { + "type": "component", + "repeatable": false, + "component": "default.teter" } } } diff --git a/examples/getstarted/api/category/models/Category.settings.json b/examples/getstarted/api/category/models/Category.settings.json index 12752bfe5c..cb28080489 100755 --- a/examples/getstarted/api/category/models/Category.settings.json +++ b/examples/getstarted/api/category/models/Category.settings.json @@ -13,6 +13,10 @@ "attributes": { "name": { "type": "string" + }, + "toto": { + "via": "category", + "model": "toto" } } -} \ No newline at end of file +} diff --git a/examples/getstarted/api/country/models/Country.settings.json b/examples/getstarted/api/country/models/Country.settings.json index da8fef908e..f444b1fe13 100755 --- a/examples/getstarted/api/country/models/Country.settings.json +++ b/examples/getstarted/api/country/models/Country.settings.json @@ -7,7 +7,10 @@ }, "options": { "increments": true, - "timestamps": ["created_at", "updated_at"], + "timestamps": [ + "created_at", + "updated_at" + ], "comment": "" }, "attributes": { @@ -21,6 +24,10 @@ "maxLength": 3, "unique": true, "minLength": 2 + }, + "toto": { + "via": "countries", + "model": "toto" } } } diff --git a/examples/getstarted/api/like/models/Like.settings.json b/examples/getstarted/api/like/models/Like.settings.json index 8be0a41644..5dca51d6eb 100755 --- a/examples/getstarted/api/like/models/Like.settings.json +++ b/examples/getstarted/api/like/models/Like.settings.json @@ -26,6 +26,10 @@ "like_right": { "model": "like", "via": "like_left" + }, + "totos": { + "via": "like", + "collection": "toto" } } } diff --git a/examples/getstarted/api/menu/models/Menu.settings.json b/examples/getstarted/api/menu/models/Menu.settings.json index 70e169f4d8..5d04016df8 100755 --- a/examples/getstarted/api/menu/models/Menu.settings.json +++ b/examples/getstarted/api/menu/models/Menu.settings.json @@ -21,6 +21,10 @@ "restaurant": { "model": "restaurant", "via": "menu" + }, + "totos": { + "via": "menus", + "collection": "toto" } } -} \ No newline at end of file +} diff --git a/examples/getstarted/api/toto/config/routes.json b/examples/getstarted/api/toto/config/routes.json new file mode 100644 index 0000000000..27b70700a1 --- /dev/null +++ b/examples/getstarted/api/toto/config/routes.json @@ -0,0 +1,52 @@ +{ + "routes": [ + { + "method": "GET", + "path": "/totos", + "handler": "toto.find", + "config": { + "policies": [] + } + }, + { + "method": "GET", + "path": "/totos/count", + "handler": "toto.count", + "config": { + "policies": [] + } + }, + { + "method": "GET", + "path": "/totos/:id", + "handler": "toto.findOne", + "config": { + "policies": [] + } + }, + { + "method": "POST", + "path": "/totos", + "handler": "toto.create", + "config": { + "policies": [] + } + }, + { + "method": "PUT", + "path": "/totos/:id", + "handler": "toto.update", + "config": { + "policies": [] + } + }, + { + "method": "DELETE", + "path": "/totos/:id", + "handler": "toto.delete", + "config": { + "policies": [] + } + } + ] +} diff --git a/examples/getstarted/api/toto/controllers/toto.js b/examples/getstarted/api/toto/controllers/toto.js new file mode 100644 index 0000000000..f94f22736f --- /dev/null +++ b/examples/getstarted/api/toto/controllers/toto.js @@ -0,0 +1,8 @@ +'use strict'; + +/** + * Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/concepts/controllers.html#core-controllers) + * to customize this controller + */ + +module.exports = {}; diff --git a/examples/getstarted/api/toto/models/toto.js b/examples/getstarted/api/toto/models/toto.js new file mode 100644 index 0000000000..3a09faae1e --- /dev/null +++ b/examples/getstarted/api/toto/models/toto.js @@ -0,0 +1,44 @@ +'use strict'; + +/** + * Lifecycle callbacks for the `toto` model. + */ + +module.exports = { + // Before saving a value. + // Fired before an `insert` or `update` query. + // beforeSave: async (model, attrs, options) => {}, + // After saving a value. + // Fired after an `insert` or `update` query. + // afterSave: async (model, response, options) => {}, + // Before fetching a value. + // Fired before a `fetch` operation. + // beforeFetch: async (model, columns, options) => {}, + // After fetching a value. + // Fired after a `fetch` operation. + // afterFetch: async (model, response, options) => {}, + // Before fetching all values. + // Fired before a `fetchAll` operation. + // beforeFetchAll: async (model, columns, options) => {}, + // After fetching all values. + // Fired after a `fetchAll` operation. + // afterFetchAll: async (model, response, options) => {}, + // Before creating a value. + // Fired before an `insert` query. + // beforeCreate: async (model, attrs, options) => {}, + // After creating a value. + // Fired after an `insert` query. + // afterCreate: async (model, attrs, options) => {}, + // Before updating a value. + // Fired before an `update` query. + // beforeUpdate: async (model, attrs, options) => {}, + // After updating a value. + // Fired after an `update` query. + // afterUpdate: async (model, attrs, options) => {}, + // Before destroying a value. + // Fired before a `delete` query. + // beforeDestroy: async (model, attrs, options) => {}, + // After destroying a value. + // Fired after a `delete` query. + // afterDestroy: async (model, attrs, options) => {} +}; diff --git a/examples/getstarted/api/toto/models/toto.settings.json b/examples/getstarted/api/toto/models/toto.settings.json new file mode 100644 index 0000000000..bf9ad97718 --- /dev/null +++ b/examples/getstarted/api/toto/models/toto.settings.json @@ -0,0 +1,86 @@ +{ + "connection": "default", + "collectionName": "totos", + "info": { + "name": "toto" + }, + "attributes": { + "totosmanytomanyright": { + "collection": "toto", + "via": "totosmanytomany" + }, + "totoonewayLeft": { + "model": "toto", + "via": "totoonewayRight" + }, + "totosonetomanyLeft": { + "collection": "toto", + "via": "totoonetomanyRight" + }, + "name": { + "type": "string", + "default": "something" + }, + "menusections": { + "collection": "menusection" + }, + "totosmanytooneright": { + "collection": "toto", + "via": "totomanytooneleft" + }, + "totoonetomanyRight": { + "model": "toto", + "via": "totosonetomanyLeft" + }, + "totosmanyway": { + "collection": "toto" + }, + "countries": { + "collection": "country", + "via": "toto" + }, + "menus": { + "collection": "menu", + "via": "totos", + "dominant": true + }, + "address": { + "model": "address" + }, + "toto": { + "model": "toto" + }, + "totosmanytomany": { + "collection": "toto", + "via": "totosmanytomanyright", + "dominant": true + }, + "like": { + "model": "like", + "via": "totos" + }, + "compoField": { + "type": "component", + "repeatable": false, + "component": "compo.newcompo" + }, + "totoonewayRight": { + "model": "toto", + "via": "totoonewayLeft" + }, + "totomanytooneleft": { + "model": "toto", + "via": "totosmanytooneright" + }, + "category": { + "model": "category", + "via": "toto" + }, + "mainCompoField": { + "type": "component", + "repeatable": true, + "component": "nested.compo-with-nested", + "max": 2 + } + } +} diff --git a/examples/getstarted/api/toto/services/toto.js b/examples/getstarted/api/toto/services/toto.js new file mode 100644 index 0000000000..d0dcc88381 --- /dev/null +++ b/examples/getstarted/api/toto/services/toto.js @@ -0,0 +1,8 @@ +'use strict'; + +/** + * Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/concepts/services.html#core-services) + * to customize this service + */ + +module.exports = {}; diff --git a/examples/getstarted/components/compo/newcompo.json b/examples/getstarted/components/compo/newcompo.json new file mode 100644 index 0000000000..5a4d310114 --- /dev/null +++ b/examples/getstarted/components/compo/newcompo.json @@ -0,0 +1,14 @@ +{ + "connection": "default", + "collectionName": "components_compo_newcompos", + "info": { + "name": "newcompo", + "icon": "address-book" + }, + "attributes": { + "name": { + "type": "string", + "default": "something" + } + } +} diff --git a/examples/getstarted/components/default/teter.json b/examples/getstarted/components/default/teter.json new file mode 100644 index 0000000000..8012e202cb --- /dev/null +++ b/examples/getstarted/components/default/teter.json @@ -0,0 +1,13 @@ +{ + "connection": "default", + "collectionName": "components_default_teters", + "info": { + "name": "teter", + "icon": "arrow-alt-circle-up" + }, + "attributes": { + "terttterterter": { + "type": "string" + } + } +} diff --git a/examples/getstarted/components/nested/compo-with-nested.json b/examples/getstarted/components/nested/compo-with-nested.json new file mode 100644 index 0000000000..be742e0b29 --- /dev/null +++ b/examples/getstarted/components/nested/compo-with-nested.json @@ -0,0 +1,21 @@ +{ + "connection": "default", + "collectionName": "components_nested_compo_with_nesteds", + "info": { + "name": "compo with nested", + "icon": "address-card" + }, + "attributes": { + "something": { + "type": "string", + "default": "default value", + "required": true, + "unique": true + }, + "nestcompofield": { + "type": "component", + "repeatable": false, + "component": "nested.nested-compo" + } + } +} diff --git a/examples/getstarted/components/nested/nested-compo.json b/examples/getstarted/components/nested/nested-compo.json new file mode 100644 index 0000000000..a9aa35a230 --- /dev/null +++ b/examples/getstarted/components/nested/nested-compo.json @@ -0,0 +1,18 @@ +{ + "connection": "default", + "collectionName": "components_nested_nested_compos", + "info": { + "name": "nested compo", + "icon": "angle-double-down" + }, + "attributes": { + "name": { + "type": "string", + "default": "nested default", + "unique": true + }, + "email": { + "type": "email" + } + } +} diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentList/index.js b/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentList/index.js index 255c6cbead..7ad5aebe48 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentList/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentList/index.js @@ -12,26 +12,37 @@ import List from '../List'; import convertAttrObjToArray from '../../utils/convertAttrObjToArray'; import useDataManager from '../../hooks/useDataManager'; -function ComponentList({ customRowComponent, component }) { +function ComponentList({ + customRowComponent, + component, + mainTypeName, + + firstLoopComponentName, + firstLoopComponentUid, +}) { const { modifiedData } = useDataManager(); - - const getComponentSchema = componentName => { - return get(modifiedData, ['components', componentName], { - schema: { attributes: {} }, - }); - }; - const { - schema: { attributes }, - } = getComponentSchema(component); + schema: { name: componentName, attributes }, + } = get(modifiedData, ['components', component], { + schema: { attributes: {} }, + }); return ( - {List({ - customRowComponent, - items: convertAttrObjToArray(attributes), - })} + ); @@ -45,6 +56,10 @@ ComponentList.defaultProps = { ComponentList.propTypes = { component: PropTypes.string, customRowComponent: PropTypes.func, + firstLoopComponentName: PropTypes.string, + firstLoopComponentUid: PropTypes.string, + mainTypeName: PropTypes.string.isRequired, + targetUid: PropTypes.string.isRequired, }; export default ComponentList; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/List/index.js b/packages/strapi-plugin-content-type-builder/admin/src/components/List/index.js index d5f73b89ab..32b8b40a3f 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/components/List/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/List/index.js @@ -21,6 +21,14 @@ function List({ items, addField, addComponentToDZ, + targetUid, + + mainTypeName, + editTarget, + firstLoopComponentName, + firstLoopComponentUid, + secondLoopComponentName, + secondLoopComponentUid, }) { const { formatMessage } = useGlobalContext(); const addButtonProps = { @@ -36,14 +44,36 @@ function List({ {items.map(item => { const { type } = item; + + const CustomRow = customRowComponent; + return ( - {customRowComponent(item)} + {type === 'component' && ( )} @@ -70,6 +100,11 @@ List.defaultProps = { className: null, customRowComponent: null, items: [], + + firstLoopComponentName: null, + firstLoopComponentUid: null, + secondLoopComponentName: null, + secondLoopComponentUid: null, }; List.propTypes = { @@ -77,7 +112,16 @@ List.propTypes = { addComponentToDZ: PropTypes.func, className: PropTypes.string, customRowComponent: PropTypes.func, + // dataType: PropTypes.string.isRequired, + // dataTypeName: PropTypes.string.isRequired, + editTarget: PropTypes.string.isRequired, + firstLoopComponentName: PropTypes.string, + firstLoopComponentUid: PropTypes.string, items: PropTypes.instanceOf(Array), + mainTypeName: PropTypes.string.isRequired, + secondLoopComponentName: PropTypes.string, + secondLoopComponentUid: PropTypes.string, + targetUid: PropTypes.string.isRequired, }; export default List; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/ListRow/index.js b/packages/strapi-plugin-content-type-builder/admin/src/components/ListRow/index.js index 1973c41e2a..70f4651371 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/components/ListRow/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/ListRow/index.js @@ -14,11 +14,19 @@ function ListRow({ attributeName, configurable, name, + nature, onClick, onClickDelete, plugin, target, + targetUid, type, + mainTypeName, + editTarget, + firstLoopComponentName, + firstLoopComponentUid, + secondLoopComponentName, + secondLoopComponentUid, }) { const ico = ['integer', 'biginteger', 'float', 'decimal'].includes(type) ? 'number' @@ -35,7 +43,31 @@ function ListRow({ const handleClick = () => { if (configurable !== false) { - onClick(attributeName, name, type, name); + const attrType = nature ? 'relation' : type; + let headerDisplayName = mainTypeName; + + if (firstLoopComponentName) { + headerDisplayName = firstLoopComponentName; + } + + if (secondLoopComponentUid) { + headerDisplayName = secondLoopComponentName; + } + + onClick( + // Tells where the attribute is located in the main modifiedData object : contentType, component or components + editTarget, + // main data type uid + secondLoopComponentUid || firstLoopComponentUid || targetUid, + // Name of the attribute + name, + // Type of the attribute + attrType, + headerDisplayName, + firstLoopComponentUid ? mainTypeName : null, + secondLoopComponentName ? firstLoopComponentName : null, + secondLoopComponentUid ? firstLoopComponentUid : null + ); } }; @@ -102,21 +134,35 @@ function ListRow({ ListRow.defaultProps = { configurable: true, + firstLoopComponentName: null, + firstLoopComponentUid: null, + nature: null, onClick: () => {}, onClickDelete: () => {}, plugin: null, + secondLoopComponentName: null, + secondLoopComponentUid: null, target: null, + targetUid: null, type: null, }; ListRow.propTypes = { attributeName: PropTypes.string.isRequired, configurable: PropTypes.bool, + editTarget: PropTypes.string.isRequired, + firstLoopComponentName: PropTypes.string, + firstLoopComponentUid: PropTypes.string, + mainTypeName: PropTypes.string.isRequired, name: PropTypes.string.isRequired, + nature: PropTypes.string, onClick: PropTypes.func, onClickDelete: PropTypes.func, plugin: PropTypes.string, + secondLoopComponentName: PropTypes.string, + secondLoopComponentUid: PropTypes.string, target: PropTypes.string, + targetUid: PropTypes.string, type: PropTypes.string, }; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/ModalHeader/index.js b/packages/strapi-plugin-content-type-builder/admin/src/components/ModalHeader/index.js index 9bd5b13ceb..ae18f65c2e 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/components/ModalHeader/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/ModalHeader/index.js @@ -34,8 +34,6 @@ const ModalHeader = ({ // iconName = toLower(iconType); } - console.log(iconName); - return (
diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/WrapperSelect/index.js b/packages/strapi-plugin-content-type-builder/admin/src/components/WrapperSelect/index.js index 15333eb795..a6a989ee6c 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/components/WrapperSelect/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/WrapperSelect/index.js @@ -29,7 +29,6 @@ const WrapperSelect = ({ error, label, name, type, ...rest }) => { }; }, option: (base, state) => { - console.log({ base, state }); return { ...base, // backgroundColor: state.isSelected ? '#DEEBFF' : base.backgroundColor, 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 7da34e00b4..13a5a95337 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 @@ -316,6 +316,7 @@ const DataManagerProvider = ({ allIcons, children }) => { components, isInContentTypeView ); + const dataShape = orderAllDataAttributesWithImmutable( newSchemaToSet, isInContentTypeView 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 1a9d93dea3..8919aaac98 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 @@ -202,6 +202,7 @@ const reducer = (state, action) => { initialAttribute, } = action; let newState = state; + const initialAttributeName = get(initialAttribute, ['name'], ''); const pathToDataToEdit = ['component', 'contentType'].includes(forTarget) ? [forTarget] @@ -270,6 +271,10 @@ const reducer = (state, action) => { hadInternalRelation && didCreateInternalRelation && isEditingRelation; + const shouldCreateOppositeAttributeBecauseOfTargetChange = + didChangeTargetRelation && + didCreateInternalRelation && + !ONE_SIDE_RELATIONS.includes(nature); // Update the opposite attribute name so it is removed at the end of the loop if ( @@ -283,7 +288,8 @@ const reducer = (state, action) => { // Set the opposite attribute that will be updated when the loop attribute matches the name if ( shouldUpdateOppositeAttributeBecauseOfNatureChange || - shouldCreateOppositeAttributeBecauseOfNatureChange + shouldCreateOppositeAttributeBecauseOfNatureChange || + shouldCreateOppositeAttributeBecauseOfTargetChange ) { oppositeAttributeNameToUpdate = initialAttribute.targetAttribute; @@ -308,7 +314,10 @@ const reducer = (state, action) => { // Then (if needed) create the opposite attribute the case is changing the relation from // We do it here so keep the order of the attributes // oneWay || manyWay to something another relation - if (shouldCreateOppositeAttributeBecauseOfNatureChange) { + if ( + shouldCreateOppositeAttributeBecauseOfNatureChange || + shouldCreateOppositeAttributeBecauseOfTargetChange + ) { acc[ oppositeAttributeNameToCreateBecauseOfNatureChange ] = fromJS(oppositeAttributeToCreate); 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 654bdd7511..8ce4e9533c 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 @@ -93,8 +93,6 @@ const FormModal = () => { ? [forTarget] : [forTarget, targetUid]; - console.log({ modalType }); - setState({ actionType, attributeName, @@ -271,9 +269,7 @@ const FormModal = () => { // TODO improve icon logic let iconType = ['component', 'contentType'].includes(state.modalType) ? state.modalType - : state.attributeType; - - console.log({ modalType: state }); + : state.forTarget; if (state.modalType === 'addComponentToDynamicZone') { iconType = 'dynamiczone'; @@ -660,6 +656,8 @@ const FormModal = () => { push({ search: nextSearch }); + return; + // Adding an existing component } else { if (isInFirstComponentStep) { @@ -928,8 +926,7 @@ const FormModal = () => { ? { paddingTop: '0.5rem', paddingBottom: '3rem' } : {}; - console.log({ iconType }); - + console.log({ modifiedData }); return ( { 'attributes', ]; const targetUid = get(modifiedData, [firstMainDataPath, 'uid']); + const attributes = get(modifiedData, mainDataTypeAttributesPath, {}); const attributesLength = Object.keys(attributes).length; const currentDataName = get( @@ -87,17 +88,25 @@ const ListPage = () => { }; const handleClickEditField = async ( + forTarget, targetUid, - attrName, + attributeName, type, headerDisplayName, - headerDisplayCategory = null + headerDisplayCategory = null, + headerDisplaySubCategory = null, + subTargetUid = null // TODO ADD LOGIC headerDisplaySubCategory when editing a field // It should be the same one as adding a field ) => { let attributeType; - console.log('ooo'); + console.log({ + headerDisplayName, + headerDisplayCategory, + headerDisplaySubCategory, + subTargetUid, + }); switch (type) { case 'integer': @@ -117,16 +126,35 @@ const ListPage = () => { attributeType = type; } - const step = type === 'component' ? '&step=2' : ''; - const displayCategory = headerDisplayCategory - ? `&headerDisplayCategory=${headerDisplayCategory}` - : ''; + // const step = type === 'component' ? '&step=2' : ''; + // const displayCategory = headerDisplayCategory + // ? `&headerDisplayCategory=${headerDisplayCategory}` + // : ''; await wait(); - push({ - search: `modalType=attribute&actionType=edit&settingType=base&forTarget=${forTarget}&targetUid=${targetUid}&attributeName=${attrName}&attributeType=${attributeType}&headerDisplayName=${headerDisplayName}${step}${displayCategory}`, - }); + const search = { + modalType: 'attribute', + actionType: 'edit', + settingType: 'base', + forTarget, + targetUid, + attributeName, + attributeType, + headerDisplayName, + headerDisplayCategory, + headerDisplaySubCategory, + step: type === 'component' ? '2' : null, + subTargetUid, + }; + + await wait(); + + push({ search: makeSearch(search, true) }); + + // push({ + // search: `modalType=attribute&actionType=edit&settingType=base&forTarget=${forTarget}&targetUid=${targetUid}&attributeName=${attrName}&attributeType=${attributeType}&headerDisplayName=${headerDisplayName}${step}${displayCategory}`, + // }); }; // const handleClickEditMain = () => { @@ -235,6 +263,7 @@ const ListPage = () => { const CustomRow = props => { const { name } = props; + return ( { customRowComponent={props => } addField={handleClickAddAttributeMainData} addComponentToDZ={handleClickAddComponentToDZ} + targetUid={targetUid} + dataType={forTarget} + dataTypeName={currentDataName} + // + mainTypeName={currentDataName} + editTarget={forTarget} + // parentTarget={forTarget} >