mirror of
https://github.com/strapi/strapi.git
synced 2025-09-26 00:39:49 +00:00
clone components
This commit is contained in:
parent
460099408b
commit
1cc853a5eb
@ -322,6 +322,91 @@ const deleteComponents = async (uid, entityToDelete, { loadComponents = true } =
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cloneComponents = async (uid, entityToClone, data) => {
|
||||||
|
const { attributes = {} } = strapi.getModel(uid);
|
||||||
|
|
||||||
|
const componentBody = {};
|
||||||
|
const componentData = await getComponents(uid, entityToClone);
|
||||||
|
|
||||||
|
for (const attributeName of Object.keys(attributes)) {
|
||||||
|
const attribute = attributes[attributeName];
|
||||||
|
|
||||||
|
// If the attribute is not set or on the component to clone, skip it
|
||||||
|
if (!has(attributeName, data) && !has(attributeName, componentData)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute.type === 'component') {
|
||||||
|
const { component: componentUID, repeatable = false } = attribute;
|
||||||
|
|
||||||
|
const componentValue = has(attributeName, data)
|
||||||
|
? data[attributeName]
|
||||||
|
: componentData[attributeName];
|
||||||
|
|
||||||
|
if (repeatable === true) {
|
||||||
|
if (!Array.isArray(componentValue)) {
|
||||||
|
throw new Error('Expected an array to create repeatable component');
|
||||||
|
}
|
||||||
|
|
||||||
|
// MySQL/MariaDB can cause deadlocks here if concurrency higher than 1
|
||||||
|
const components = await mapAsync(
|
||||||
|
componentValue,
|
||||||
|
(value) => cloneComponent(componentUID, value),
|
||||||
|
{ concurrency: isDialectMySQL() ? 1 : Infinity }
|
||||||
|
);
|
||||||
|
|
||||||
|
componentBody[attributeName] = components.filter(_.negate(_.isNil)).map(({ id }) => {
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
__pivot: {
|
||||||
|
field: attributeName,
|
||||||
|
component_type: componentUID,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const component = await cloneComponent(componentUID, componentValue);
|
||||||
|
componentBody[attributeName] = component && {
|
||||||
|
id: component.id,
|
||||||
|
__pivot: {
|
||||||
|
field: attributeName,
|
||||||
|
component_type: componentUID,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute.type === 'dynamiczone') {
|
||||||
|
const dynamiczoneValues = has(attributeName, data)
|
||||||
|
? data[attributeName]
|
||||||
|
: componentData[attributeName];
|
||||||
|
|
||||||
|
if (!Array.isArray(dynamiczoneValues)) {
|
||||||
|
throw new Error('Expected an array to create repeatable component');
|
||||||
|
}
|
||||||
|
// MySQL/MariaDB can cause deadlocks here if concurrency higher than 1
|
||||||
|
componentBody[attributeName] = await mapAsync(
|
||||||
|
dynamiczoneValues,
|
||||||
|
async (value) => {
|
||||||
|
const { id } = await cloneComponent(value.__component, value);
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
__component: value.__component,
|
||||||
|
__pivot: {
|
||||||
|
field: attributeName,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
{ concurrency: isDialectMySQL() ? 1 : Infinity }
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return componentBody;
|
||||||
|
};
|
||||||
/** *************************
|
/** *************************
|
||||||
Component queries
|
Component queries
|
||||||
************************** */
|
************************** */
|
||||||
@ -377,6 +462,26 @@ const deleteComponent = async (uid, componentToDelete) => {
|
|||||||
await strapi.query(uid).delete({ where: { id: componentToDelete.id } });
|
await strapi.query(uid).delete({ where: { id: componentToDelete.id } });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cloneComponent = async (uid, data) => {
|
||||||
|
const model = strapi.getModel(uid);
|
||||||
|
|
||||||
|
if (!has('id', data)) {
|
||||||
|
return createComponent(uid, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
const componentData = await cloneComponents(uid, { id: data.id }, data);
|
||||||
|
const transform = pipe(
|
||||||
|
// Make sure we don't save the component with a pre-defined ID
|
||||||
|
omit('id'),
|
||||||
|
// Remove the component data from the original data object ...
|
||||||
|
(payload) => omitComponentData(model, payload),
|
||||||
|
// ... and assign the newly created component instead
|
||||||
|
assign(componentData)
|
||||||
|
);
|
||||||
|
|
||||||
|
return strapi.query(uid).clone(data.id, { data: transform(data) });
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
omitComponentData,
|
omitComponentData,
|
||||||
getComponents,
|
getComponents,
|
||||||
@ -384,4 +489,5 @@ module.exports = {
|
|||||||
updateComponents,
|
updateComponents,
|
||||||
deleteComponents,
|
deleteComponents,
|
||||||
deleteComponent,
|
deleteComponent,
|
||||||
|
cloneComponents,
|
||||||
};
|
};
|
||||||
|
@ -16,6 +16,7 @@ const {
|
|||||||
createComponents,
|
createComponents,
|
||||||
updateComponents,
|
updateComponents,
|
||||||
deleteComponents,
|
deleteComponents,
|
||||||
|
cloneComponents,
|
||||||
} = require('./components');
|
} = require('./components');
|
||||||
const { pickSelectionParams } = require('./params');
|
const { pickSelectionParams } = require('./params');
|
||||||
const { applyTransforms } = require('./attributes');
|
const { applyTransforms } = require('./attributes');
|
||||||
@ -291,9 +292,7 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|||||||
const query = transformParamsToQuery(uid, pickSelectionParams(wrappedParams));
|
const query = transformParamsToQuery(uid, pickSelectionParams(wrappedParams));
|
||||||
|
|
||||||
// TODO: wrap into transaction
|
// TODO: wrap into transaction
|
||||||
// TODO: Implement cloneComponents
|
const componentData = await cloneComponents(uid, entityToClone, validData);
|
||||||
// const componentData = await cloneComponents(uid, validData);
|
|
||||||
const componentData = await createComponents(uid, validData);
|
|
||||||
|
|
||||||
const entityData = creationPipeline(
|
const entityData = creationPipeline(
|
||||||
Object.assign(omitComponentData(model, validData), componentData),
|
Object.assign(omitComponentData(model, validData), componentData),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user