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
|
||||
************************** */
|
||||
@ -377,6 +462,26 @@ const deleteComponent = async (uid, componentToDelete) => {
|
||||
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 = {
|
||||
omitComponentData,
|
||||
getComponents,
|
||||
@ -384,4 +489,5 @@ module.exports = {
|
||||
updateComponents,
|
||||
deleteComponents,
|
||||
deleteComponent,
|
||||
cloneComponents,
|
||||
};
|
||||
|
@ -16,6 +16,7 @@ const {
|
||||
createComponents,
|
||||
updateComponents,
|
||||
deleteComponents,
|
||||
cloneComponents,
|
||||
} = require('./components');
|
||||
const { pickSelectionParams } = require('./params');
|
||||
const { applyTransforms } = require('./attributes');
|
||||
@ -291,9 +292,7 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
||||
const query = transformParamsToQuery(uid, pickSelectionParams(wrappedParams));
|
||||
|
||||
// TODO: wrap into transaction
|
||||
// TODO: Implement cloneComponents
|
||||
// const componentData = await cloneComponents(uid, validData);
|
||||
const componentData = await createComponents(uid, validData);
|
||||
const componentData = await cloneComponents(uid, entityToClone, validData);
|
||||
|
||||
const entityData = creationPipeline(
|
||||
Object.assign(omitComponentData(model, validData), componentData),
|
||||
|
Loading…
x
Reference in New Issue
Block a user