Merge pull request #9282 from strapi/i18n/refacto-plugin-options

Refacto with pluginsOptions
This commit is contained in:
Alexandre BODIN 2021-02-10 17:33:14 +01:00 committed by GitHub
commit 2b342ec69d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 199 additions and 186 deletions

View File

@ -7,6 +7,14 @@
"options": {
"timestamps": true
},
"pluginOptions": {
"content-manager": {
"visible": false
},
"content-type-builder": {
"visible": false
}
},
"attributes": {
"action": {
"type": "string",
@ -38,4 +46,4 @@
"plugin": "admin"
}
}
}
}

View File

@ -7,6 +7,14 @@
"options": {
"timestamps": true
},
"pluginOptions": {
"content-manager": {
"visible": false
},
"content-type-builder": {
"visible": false
}
},
"attributes": {
"name": {
"type": "string",

View File

@ -4,6 +4,14 @@
"name": "User",
"description": ""
},
"pluginOptions": {
"content-manager": {
"visible": false
},
"content-type-builder": {
"visible": false
}
},
"attributes": {
"firstname": {
"type": "string",

View File

@ -289,7 +289,6 @@ module.exports = async ({ models, target }, ctx) => {
target[model]._attributes = definition.attributes;
target[model].updateRelations = relations.update;
target[model].deleteRelations = relations.deleteRelations;
target[model].privateAttributes = contentTypesUtils.getPrivateAttributes(target[model]);
}

View File

@ -1,6 +1,6 @@
'use strict';
const { startsWith, upperFirst, has, prop, pick } = require('lodash/fp');
const { upperFirst, has, prop, pick, getOr } = require('lodash/fp');
const pluralize = require('pluralize');
const { contentTypes: contentTypesUtils } = require('strapi-utils');
@ -20,7 +20,7 @@ module.exports = {
return {
...contentType,
apiID: contentType.modelName,
isDisplayed: !isHidden(contentType),
isDisplayed: isVisible(contentType),
info: {
...contentType.info,
label: formatContentTypeLabel(contentType),
@ -94,11 +94,4 @@ const toRelation = (attribute, relation) => {
};
};
const HIDDEN_CONTENT_TYPES = [
'plugins::upload.file',
'plugins::users-permissions.permission',
'plugins::users-permissions.role',
'plugins::i18n.locale',
];
const isHidden = ({ uid }) => startsWith('strapi::', uid) || HIDDEN_CONTENT_TYPES.includes(uid);
const isVisible = model => getOr(true, 'pluginOptions.content-manager.visible', model) === true;

View File

@ -401,7 +401,7 @@ const DataManagerProvider = ({ allIcons, children }) => {
const redirectEndpoint = useMemo(() => {
const allowedEndpoints = Object.keys(contentTypes)
.filter(uid => get(contentTypes, [uid, 'schema', 'editable'], true))
.filter(uid => get(contentTypes, [uid, 'schema', 'visible'], true))
.sort();
return get(allowedEndpoints, '0', '');

View File

@ -61,7 +61,7 @@ const formatMainDataType = (data, isComponent = false) => {
delete formattedContentType.uid;
delete formattedContentType.isTemporary;
delete formattedContentType.editable;
delete formattedContentType.visible;
delete formattedContentType.restrictRelationsTo;
return formattedContentType;
@ -145,7 +145,7 @@ const sortContentType = types =>
sortBy(
Object.keys(types)
.map(uid => ({
editable: types[uid].schema.editable,
visible: types[uid].schema.visible,
name: uid,
title: types[uid].schema.name,
plugin: types[uid].plugin || null,

View File

@ -99,7 +99,7 @@ const expectedData = {
title: 'plugins::myplugins.atest',
to: '/plugins/content-type-builder/content-types/plugins::myplugins.atest',
kind: 'collectionType',
editable: true,
visible: true,
plugin: null,
restrictRelationsTo: [],
},
@ -109,7 +109,7 @@ const expectedData = {
title: 'plugins::myplugins.btest',
to: '/plugins/content-type-builder/content-types/plugins::myplugins.btest',
kind: 'collectionType',
editable: true,
visible: true,
plugin: null,
restrictRelationsTo: null,
},
@ -119,7 +119,7 @@ const expectedData = {
title: 'plugins::myplugins.ctest',
to: '/plugins/content-type-builder/content-types/plugins::myplugins.ctest',
kind: 'collectionType',
editable: true,
visible: true,
plugin: null,
restrictRelationsTo: ['oneWay'],
},
@ -129,7 +129,7 @@ const expectedData = {
title: 'plugins::myplugins.test',
to: '/plugins/content-type-builder/content-types/plugins::myplugins.test',
kind: 'singleType',
editable: true,
visible: true,
plugin: null,
restrictRelationsTo: null,
},

View File

@ -153,7 +153,7 @@ const data = {
schema: {
name: 'plugins::myplugins.test',
kind: 'singleType',
editable: true,
visible: true,
restrictRelationsTo: null,
},
},
@ -162,7 +162,7 @@ const data = {
schema: {
name: 'plugins::myplugins.btest',
kind: 'collectionType',
editable: true,
visible: true,
restrictRelationsTo: null,
},
},
@ -171,7 +171,7 @@ const data = {
schema: {
name: 'plugins::myplugins.atest',
kind: 'collectionType',
editable: true,
visible: true,
restrictRelationsTo: [],
},
},
@ -180,7 +180,7 @@ const data = {
schema: {
name: 'plugins::myplugins.ctest',
kind: 'collectionType',
editable: true,
visible: true,
restrictRelationsTo: ['oneWay'],
},
},

View File

@ -113,7 +113,7 @@ function LeftMenu({ wait }) {
const displayedContentTypes = useMemo(() => {
return sortedContentTypesList
.filter(obj => obj.editable)
.filter(obj => obj.visible)
.map(obj => {
if (obj.plugin) {
return {

View File

@ -1,6 +1,7 @@
'use strict';
const _ = require('lodash');
const { getOr } = require('lodash/fp');
const pluralize = require('pluralize');
const generator = require('strapi-generate');
@ -10,10 +11,8 @@ const createBuilder = require('./schema-builder');
const apiHandler = require('./api-handler');
const { coreUids, pluginsUids } = require('./constants');
const isContentTypeEditable = (contentType = {}) => {
const { uid } = contentType;
return !uid.startsWith(coreUids.PREFIX) && uid !== pluginsUids.UPLOAD_FILE;
};
const isContentTypeVisible = model =>
getOr(true, 'pluginOptions.content-type-builder.visible', model) === true;
const getRestrictRelationsTo = (contentType = {}) => {
const { uid } = contentType;
@ -54,7 +53,7 @@ const formatContentType = contentType => {
kind: kind || 'collectionType',
collectionName,
attributes: formatAttributes(contentType),
editable: isContentTypeEditable(contentType),
visible: isContentTypeVisible(contentType),
restrictRelationsTo: getRestrictRelationsTo(contentType),
},
};

View File

@ -14,10 +14,10 @@ Object {
"connection": "default",
"description": "My description",
"draftAndPublish": false,
"editable": true,
"kind": "singleType",
"name": "My name",
"restrictRelationsTo": null,
"visible": true,
},
"uid": "test-uid",
}

View File

@ -234,6 +234,7 @@ module.exports = function createSchemaHandler(infos) {
collectionName: state.schema.collectionName,
info: state.schema.info,
options: state.schema.options,
pluginOptions: state.schema.pluginOptions,
attributes: state.schema.attributes,
},
{ spaces: 2 }

View File

@ -1,73 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Content Type Builder - Content types Collection Types Get collection type returns full schema and informations 1`] = `
Object {
"data": Object {
"apiID": "test-collection-type",
"schema": Object {
"attributes": Object {
"title": Object {
"type": "string",
},
},
"collectionName": "test_collection_types",
"connection": "default",
"description": "",
"draftAndPublish": false,
"editable": true,
"kind": "collectionType",
"name": "Test Collection Type",
"restrictRelationsTo": null,
},
"uid": "application::test-collection-type.test-collection-type",
},
}
`;
exports[`Content Type Builder - Content types Collection Types Get collection type returns full schema and informations with draftAndPublish 1`] = `
Object {
"data": Object {
"apiID": "ct-with-dp",
"schema": Object {
"attributes": Object {
"title": Object {
"type": "string",
},
},
"collectionName": "ct_with_dps",
"connection": "default",
"description": "",
"draftAndPublish": true,
"editable": true,
"kind": "collectionType",
"name": "CT with DP",
"restrictRelationsTo": null,
},
"uid": "application::ct-with-dp.ct-with-dp",
},
}
`;
exports[`Content Type Builder - Content types Single Types Get single type returns full schema and informations 1`] = `
Object {
"data": Object {
"apiID": "test-single-type",
"schema": Object {
"attributes": Object {
"title": Object {
"type": "string",
},
},
"collectionName": "test_single_types",
"connection": "default",
"description": "",
"draftAndPublish": false,
"editable": true,
"kind": "singleType",
"name": "Test Single Type",
"restrictRelationsTo": null,
},
"uid": "application::test-single-type.test-single-type",
},
}
`;

View File

@ -15,24 +15,8 @@ module.exports = {
initializeLoader() {
this.resetLoaders();
// Create loaders for each relational field (exclude core models).
Object.keys(strapi.models)
.filter(model => model.internal !== true)
.forEach(modelKey => {
const model = strapi.models[modelKey];
this.createLoader(model.uid);
});
// Reproduce the same pattern for each plugin.
Object.keys(strapi.plugins).forEach(plugin => {
Object.keys(strapi.plugins[plugin].models).forEach(modelKey => {
const model = strapi.plugins[plugin].models[modelKey];
this.createLoader(model.uid);
});
});
// Add the loader for the AdminUser as well, so we can query `created_by` and `updated_by` AdminUsers
this.createLoader('strapi::user');
// Create loaders for each relational field (exclude core models & plugins).
Object.values(strapi.contentTypes).forEach(model => this.createLoader(model.uid));
},
resetLoaders() {

View File

@ -65,12 +65,13 @@ const generateSchema = () => {
.join('\n');
// Concatenate.
// Manually defined to avoid exposing all attributes (like password etc.)
let typeDefs = `
${definition}
${shadowCRUD.definition}
${polymorphicSchema.definition}
${Types.addInput()}
${PublicationState.definition}
type AdminUser {
id: ID!
@ -132,18 +133,11 @@ const writeGenerateSchema = schema => {
};
const buildModelsShadowCRUD = () => {
const models = Object.values(strapi.models).filter(model => model.internal !== true);
const pluginModels = Object.values(strapi.plugins)
.map(plugin => Object.values(plugin.models) || [])
.reduce((acc, arr) => acc.concat(arr), []);
const models = Object.values(strapi.contentTypes).filter(model => model.plugin !== 'admin');
const components = Object.values(strapi.components);
return mergeSchemas(
createDefaultSchema(),
...buildModels([...models, ...pluginModels, ...components])
);
return mergeSchemas(createDefaultSchema(), ...buildModels([...models, ...components]));
};
const buildResolvers = resolvers => {

View File

@ -7,6 +7,14 @@
"options": {
"timestamps": true
},
"pluginOptions": {
"content-manager": {
"visible": false
},
"content-type-builder": {
"visible": false
}
},
"attributes": {
"name": {
"type": "string",

View File

@ -6,6 +6,14 @@
"options": {
"timestamps": true
},
"pluginOptions": {
"content-manager": {
"visible": false
},
"content-type-builder": {
"visible": false
}
},
"attributes": {
"name": {
"type": "string",

View File

@ -3,6 +3,11 @@
"name": "permission",
"description": ""
},
"pluginOptions": {
"content-manager": {
"visible": false
}
},
"attributes": {
"type": {
"type": "string",
@ -35,4 +40,4 @@
"configurable": false
}
}
}
}

View File

@ -3,6 +3,11 @@
"name": "role",
"description": ""
},
"pluginOptions": {
"content-manager": {
"visible": false
}
},
"attributes": {
"name": {
"type": "string",

View File

@ -6,9 +6,11 @@ const {
getVisibleAttributes,
getNonWritableAttributes,
constants,
getGlobalId,
} = require('../content-types');
const createModelWithPrivates = (privateAttributes = []) => ({
uid: 'myModel',
options: {
privateAttributes,
},
@ -253,4 +255,25 @@ describe('Content types utils', () => {
expect(strapi.config.get).toHaveBeenCalledWith('api.responses.privateAttributes', []);
});
});
describe('getGlobalId', () => {
const testData = [
[{ globalId: 'customId' }, 'modelName', 'admin', 'customId'],
[{}, 'modelName', undefined, 'ModelName'],
[{}, 'modelName', null, 'ModelName'],
[{}, 'modelName', '', 'ModelName'],
[{}, 'modelName', 'admin', 'AdminModelName'],
[{}, 'MODELNAME', '', 'Modelname'],
[{}, 'MODEL-NAME', '', 'ModelName'],
];
test.each(testData)(
'getGlobalId(%p, %p, %p) = %p',
(model, modelName, prefix, expectedResult) => {
const result = getGlobalId(model, modelName, prefix);
expect(result).toBe(expectedResult);
}
);
});
});

View File

@ -108,6 +108,71 @@ const isMediaAttribute = attr => {
return (attr.collection || attr.model) === 'file' && attr.plugin === 'upload';
};
const getKind = obj => obj.kind || 'collectionType';
const pickSchema = model => {
const schema = _.cloneDeep(
_.pick(model, [
'connection',
'collectionName',
'info',
'options',
'pluginOptions',
'attributes',
])
);
schema.kind = getKind(model);
return schema;
};
const createContentType = (
model,
{ modelName, defaultConnection },
{ apiName, pluginName } = {}
) => {
if (apiName) {
Object.assign(model, {
uid: `application::${apiName}.${modelName}`,
apiName,
collectionName: model.collectionName || modelName.toLocaleLowerCase(),
globalId: getGlobalId(model, modelName),
});
} else if (pluginName) {
Object.assign(model, {
uid: `plugins::${pluginName}.${modelName}`,
plugin: pluginName,
collectionName: model.collectionName || `${pluginName}_${modelName}`.toLowerCase(),
globalId: getGlobalId(model, modelName, pluginName),
});
} else {
Object.assign(model, {
uid: `strapi::${modelName}`,
plugin: 'admin',
globalId: getGlobalId(model, modelName, 'admin'),
});
}
Object.assign(model, {
__schema__: pickSchema(model),
kind: getKind(model),
modelType: 'contentType',
modelName,
connection: model.connection || defaultConnection,
});
Object.defineProperty(model, 'privateAttributes', {
get() {
return strapi.getModel(model.uid).privateAttributes;
},
});
};
const getGlobalId = (model, modelName, prefix) => {
let globalId = prefix ? `${prefix}-${modelName}` : modelName;
return model.globalId || _.upperFirst(_.camelCase(globalId));
};
module.exports = {
isScalarAttribute,
isMediaAttribute,
@ -124,4 +189,6 @@ module.exports = {
isSingleType,
isCollectionType,
isKind,
createContentType,
getGlobalId,
};

View File

@ -1,21 +1,10 @@
'use strict';
const _ = require('lodash');
const { getConfigUrls } = require('strapi-utils');
const { getConfigUrls, contentTypes: contentTypesUtils } = require('strapi-utils');
const { createCoreApi } = require('../core-api');
const getKind = obj => obj.kind || 'collectionType';
const pickSchema = model => {
const schema = _.cloneDeep(
_.pick(model, ['connection', 'collectionName', 'info', 'options', 'attributes'])
);
schema.kind = getKind(model);
return schema;
};
module.exports = function(strapi) {
// Set connections.
strapi.connections = {};
@ -34,17 +23,8 @@ module.exports = function(strapi) {
for (let modelName in api.models) {
let model = strapi.api[apiName].models[modelName];
Object.assign(model, {
__schema__: pickSchema(model),
kind: getKind(model),
modelType: 'contentType',
uid: `application::${apiName}.${modelName}`,
apiName,
modelName,
globalId: model.globalId || _.upperFirst(_.camelCase(modelName)),
collectionName: model.collectionName || `${modelName}`.toLocaleLowerCase(),
connection: model.connection || defaultConnection,
});
// mutate model
contentTypesUtils.createContentType(model, { modelName, defaultConnection }, { apiName });
strapi.contentTypes[model.uid] = model;
@ -97,20 +77,11 @@ module.exports = function(strapi) {
});
// Init admin models.
Object.keys(strapi.admin.models || []).forEach(key => {
let model = strapi.admin.models[key];
Object.keys(strapi.admin.models || []).forEach(modelName => {
let model = strapi.admin.models[modelName];
Object.assign(model, {
__schema__: pickSchema(model),
modelType: 'contentType',
kind: getKind(model),
uid: `strapi::${key}`,
plugin: 'admin',
modelName: key,
identity: model.identity || _.upperFirst(key),
globalId: model.globalId || _.upperFirst(_.camelCase(`admin-${key}`)),
connection: model.connection || defaultConnection,
});
// mutate model
contentTypesUtils.createContentType(model, { modelName, defaultConnection });
strapi.contentTypes[model.uid] = model;
});
@ -131,20 +102,11 @@ module.exports = function(strapi) {
});
});
Object.keys(plugin.models || []).forEach(key => {
let model = plugin.models[key];
Object.keys(plugin.models || []).forEach(modelName => {
let model = plugin.models[modelName];
Object.assign(model, {
__schema__: pickSchema(model),
modelType: 'contentType',
kind: getKind(model),
modelName: key,
uid: `plugins::${pluginName}.${key}`,
plugin: pluginName,
collectionName: model.collectionName || `${pluginName}_${key}`.toLowerCase(),
globalId: model.globalId || _.upperFirst(_.camelCase(`${pluginName}-${key}`)),
connection: model.connection || defaultConnection,
});
// mutate model
contentTypesUtils.createContentType(model, { modelName, defaultConnection }, { pluginName });
strapi.contentTypes[model.uid] = model;
});

View File

@ -3,11 +3,18 @@
const coreStoreModel = config => ({
connection: config.get('database.defaultConnection'),
uid: 'strapi::core-store',
internal: true,
info: {
name: 'core_store',
description: '',
},
pluginOptions: {
'content-manager': {
visible: false,
},
'content-type-builder': {
visible: false,
},
},
attributes: {
key: {
type: 'string',

View File

@ -6,13 +6,20 @@
const webhookModel = config => ({
connection: config.get('database.defaultConnection'),
uid: 'strapi::webhooks',
internal: true,
globalId: 'StrapiWebhooks',
collectionName: 'strapi_webhooks',
info: {
name: 'Strapi webhooks',
description: '',
},
pluginOptions: {
'content-manager': {
visible: false,
},
'content-type-builder': {
visible: false,
},
},
attributes: {
name: {
type: 'string',

View File

@ -324,10 +324,10 @@ Object {
"connection": "default",
"description": "",
"draftAndPublish": false,
"editable": true,
"kind": "collectionType",
"name": "Test Collection Type",
"restrictRelationsTo": null,
"visible": true,
},
"uid": "application::test-collection-type.test-collection-type",
},
@ -348,10 +348,10 @@ Object {
"connection": "default",
"description": "",
"draftAndPublish": true,
"editable": true,
"kind": "collectionType",
"name": "CT with DP",
"restrictRelationsTo": null,
"visible": true,
},
"uid": "application::ct-with-dp.ct-with-dp",
},
@ -372,10 +372,10 @@ Object {
"connection": "default",
"description": "",
"draftAndPublish": false,
"editable": true,
"kind": "singleType",
"name": "Test Single Type",
"restrictRelationsTo": null,
"visible": true,
},
"uid": "application::test-single-type.test-single-type",
},