我想从数据库中另一条记录的克隆开始,而不必再次填写所有这些字段。目前这是非常乏味的,必须打开两个选项卡(一个带有现有记录,另一个带有新记录)并复制粘贴数据。
如何在 Strapi 中克隆/复制记录?
您需要按照编辑扩展指南编辑此文件
????admin
? ????src
? ????containers
? ? ????EditView
? ? ? Header.js
? ? ????EditViewDataManagerProvider
? ? ? index.js
? ? ????utils
? ? cleanData.js
? ? index.js
? ????translations
? en.json
????config
? routes.json
????controllers
? ContentManager.js
????services
ContentManager.js
Run Code Online (Sandbox Code Playgroud)
头文件.js
????admin
? ????src
? ????containers
? ? ????EditView
? ? ? Header.js
? ? ????EditViewDataManagerProvider
? ? ? index.js
? ? ????utils
? ? cleanData.js
? ? index.js
? ????translations
? en.json
????config
? routes.json
????controllers
? ContentManager.js
????services
ContentManager.js
Run Code Online (Sandbox Code Playgroud)
并通过handleClone
这里
if (!isCreatingEntry) {
headerActions.unshift(
{
label: formatMessage({
id: `${pluginId}.containers.Edit.clone`,
}),
color: 'primary',
onClick: (e) => {
handleClone(e);
},
type: 'button',
style: {
paddingLeft: 15,
paddingRight: 15,
fontWeight: 600,
},
},
{
label: formatMessage({
id: 'app.utils.delete',
}),
color: 'delete',
onClick: () => {
toggleWarningDelete();
},
type: 'button',
style: {
paddingLeft: 15,
paddingRight: 15,
fontWeight: 600,
},
},
);
}
Run Code Online (Sandbox Code Playgroud)
EditViewDataManagerProvider/index.js
const {
deleteSuccess,
initialData,
layout,
redirectToPreviousPage,
resetData,
handleClone,
setIsSubmitting,
slug,
clearData,
} = useDataManager();
Run Code Online (Sandbox Code Playgroud)
并提供handleClone
给 EditViewDataManagerContext.Provider.value
EditViewDataManagerProvider/utils/cleanData.js
const handleClone = async (event) => {
event.preventDefault();
// Create yup schema
const schema = createYupSchema(
currentContentTypeLayout,
{
components: get(allLayoutData, 'components', {}),
},
true
);
try {
// Validate the form using yup
await schema.validate(modifiedData, { abortEarly: false });
// Set the loading state in the plugin header
const filesToUpload = getFilesToUpload(modifiedData);
// Remove keys that are not needed
// Clean relations
const cleanedData = cleanData(
cloneDeep(modifiedData),
currentContentTypeLayout,
allLayoutData.components,
true
);
const formData = new FormData();
formData.append('data', JSON.stringify(cleanedData));
Object.keys(filesToUpload).forEach((key) => {
const files = filesToUpload[key];
files.forEach((file) => {
formData.append(`files.${key}`, file);
});
});
// Change the request helper default headers so we can pass a FormData
const headers = {};
const method = 'POST';
const endPoint = `${slug}/clone/${modifiedData.id}`;
emitEvent(isCreatingEntry ? 'willCloneEntry' : 'willCloneEntry');
try {
// Time to actually send the data
await request(
getRequestUrl(endPoint),
{
method,
headers,
body: formData,
signal,
},
false,
false
);
emitEvent(isCreatingEntry ? 'didCloneEntry' : 'didCloneEntry');
dispatch({
type: 'CLONE_SUCCESS',
});
strapi.notification.success(`${pluginId}.success.record.clone`);
// strapi.notification.success('Entry cloned!');
redirectToPreviousPage();
} catch (err) {
console.error({ err });
const error = get(
err,
['response', 'payload', 'message', '0', 'messages', '0', 'id'],
'SERVER ERROR'
);
setIsSubmitting(false);
emitEvent(isCreatingEntry ? 'didNotCloneEntry' : 'didNotCloneEntry', {
error: err,
});
strapi.notification.error(error);
}
} catch (err) {
const errors = getYupInnerErrors(err);
console.error({ err, errors });
dispatch({
type: 'CLONE_ERRORS',
errors,
});
}
};
Run Code Online (Sandbox Code Playgroud)
只需复制 EditViewDataManagerProvider/utils/index.js
添加在 config/routes.json
{
"method": "POST",
"path": "/explorer/:model/clone/:id",
"handler": "ContentManager.clone",
"config": {
"policies": ["routing"]
}
}
Run Code Online (Sandbox Code Playgroud)
在controllers/ContentManager.js 中添加类似于 create clone 的方法
const cleanData = (retrievedData, currentSchema, componentsSchema, clone = false) => {
const getType = (schema, attrName) =>
get(schema, ['attributes', attrName, 'type'], '');
const getSchema = (schema, attrName) =>
get(schema, ['attributes', attrName], '');
const getOtherInfos = (schema, arr) =>
get(schema, ['attributes', ...arr], '');
const recursiveCleanData = (data, schema) => Object.keys(data).reduce((acc, current) => {
const attrType = getType(schema.schema, current);
const valueSchema = getSchema(schema.schema, current);
const value = get(data, current);
const component = getOtherInfos(schema.schema, [current, 'component']);
const isRepeatable = getOtherInfos(schema.schema, [
current,
'repeatable',
]);
let cleanedData;
switch (attrType) {
case 'string': {
if (clone && valueSchema.unique) {
cleanedData = `${value}_clone`;
} else {
cleanedData = value;
}
break;
}
case 'json':
try {
cleanedData = JSON.parse(value);
} catch (err) {
cleanedData = value;
}
break;
case 'date':
case 'datetime':
cleanedData =
value && value._isAMomentObject === true
? value.toISOString()
: value;
break;
case 'media':
if (getOtherInfos(schema.schema, [current, 'multiple']) === true) {
cleanedData = value
? helperCleanData(
value.filter(file => !(file instanceof File)),
'id'
)
: null;
} else {
cleanedData =
get(value, 0) instanceof File ? null : get(value, 'id', null);
}
break;
case 'component':
if (isRepeatable) {
cleanedData = value
? value.map((data) => {
const subCleanedData = recursiveCleanData(
data,
componentsSchema[component]
);
return subCleanedData;
})
: value;
} else {
cleanedData = value
? recursiveCleanData(value, componentsSchema[component])
: value;
}
break;
case 'dynamiczone':
cleanedData = value.map((componentData) => {
const subCleanedData = recursiveCleanData(
componentData,
componentsSchema[componentData.__component]
);
return subCleanedData;
});
break;
default:
cleanedData = helperCleanData(value, 'id');
}
acc[current] = cleanedData;
if (clone && (current === '_id' || current === 'id')) {
acc[current] = undefined;
}
return acc;
}, {});
return recursiveCleanData(retrievedData, currentSchema);
};
Run Code Online (Sandbox Code Playgroud)
最后是 services/ContentManager.js
{
"method": "POST",
"path": "/explorer/:model/clone/:id",
"handler": "ContentManager.clone",
"config": {
"policies": ["routing"]
}
}
Run Code Online (Sandbox Code Playgroud)
不要忘记更新 translations/:lang.json 中的翻译
"containers.Edit.clone": "clone button",
"success.record.clone": "notification"
Run Code Online (Sandbox Code Playgroud)
不要忘记重建您的管理 UI
npm run build
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2733 次 |
最近记录: |