mirror of
https://github.com/strapi/strapi.git
synced 2025-11-01 10:23:34 +00:00
Merge pull request #3672 from strapi/content-manager/group-layout-updates
Update content-manager schemas
This commit is contained in:
commit
175fba4441
@ -12,8 +12,7 @@ module.exports = {
|
||||
const userModels = Object.keys(strapi.models)
|
||||
.filter(key => key !== 'core_store')
|
||||
.map(uid => {
|
||||
const { info } = strapi.models[uid];
|
||||
return service.formatContentType({ uid, info });
|
||||
return service.formatContentType(uid, strapi.models[uid]);
|
||||
});
|
||||
|
||||
const shouldDisplayPluginModel = uid => {
|
||||
@ -28,11 +27,8 @@ module.exports = {
|
||||
const plugin = strapi.plugins[pluginKey];
|
||||
|
||||
return Object.keys(plugin.models || {}).map(uid => {
|
||||
const { info } = plugin.models[uid];
|
||||
|
||||
return service.formatContentType({
|
||||
return service.formatContentType(uid, plugin.models[uid], {
|
||||
uid,
|
||||
info,
|
||||
isDisplayed: shouldDisplayPluginModel(uid),
|
||||
source: pluginKey,
|
||||
});
|
||||
@ -41,11 +37,7 @@ module.exports = {
|
||||
.reduce((acc, models) => acc.concat(models), []);
|
||||
|
||||
const adminModels = Object.keys(strapi.admin.models).map(uid => {
|
||||
const { info } = strapi.admin.models[uid];
|
||||
|
||||
return service.formatContentType({
|
||||
uid,
|
||||
info,
|
||||
return service.formatContentType(uid, strapi.admin.models[uid], {
|
||||
isDisplayed: false,
|
||||
source: 'admin',
|
||||
});
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const pluralize = require('pluralize');
|
||||
const { createModelConfigurationSchema } = require('./validation');
|
||||
|
||||
module.exports = {
|
||||
@ -9,13 +7,11 @@ module.exports = {
|
||||
* Returns the list of available groups
|
||||
*/
|
||||
async listGroups(ctx) {
|
||||
const data = Object.keys(strapi.groups).map(uid => ({
|
||||
uid,
|
||||
source: null,
|
||||
isDisplayed: true,
|
||||
name: uid,
|
||||
label: _.upperFirst(pluralize(uid)),
|
||||
}));
|
||||
const ctService = strapi.plugins['content-manager'].services.contenttypes;
|
||||
|
||||
const data = Object.keys(strapi.groups).map(uid => {
|
||||
return ctService.formatContentType(uid, strapi.groups[uid]);
|
||||
});
|
||||
ctx.body = { data };
|
||||
},
|
||||
/**
|
||||
@ -35,12 +31,13 @@ module.exports = {
|
||||
return ctx.notFound('group.notFound');
|
||||
}
|
||||
|
||||
const ctService = strapi.plugins['content-manager'].services.contenttypes;
|
||||
const groupService = strapi.plugins['content-manager'].services.groups;
|
||||
const configurations = await groupService.getConfiguration(uid);
|
||||
|
||||
const data = {
|
||||
uid,
|
||||
schema: groupService.formatGroupSchema(group),
|
||||
schema: ctService.formatContentTypeSchema(group),
|
||||
...configurations,
|
||||
};
|
||||
|
||||
@ -80,12 +77,12 @@ module.exports = {
|
||||
const groupService = strapi.plugins['content-manager'].services.groups;
|
||||
await groupService.setConfiguration(uid, input);
|
||||
|
||||
const ctService = strapi.plugins['content-manager'].services.contenttypes;
|
||||
const configurations = await groupService.getConfiguration(uid);
|
||||
|
||||
const data = {
|
||||
uid,
|
||||
|
||||
schema: groupService.formatGroupSchema(group),
|
||||
schema: ctService.formatContentTypeSchema(group),
|
||||
...configurations,
|
||||
};
|
||||
|
||||
|
||||
@ -65,18 +65,19 @@ const createMetadasSchema = model => {
|
||||
edit: yup
|
||||
.object()
|
||||
.shape({
|
||||
label: yup.string().required(),
|
||||
label: yup.string(),
|
||||
description: yup.string(),
|
||||
editable: yup.boolean().required(),
|
||||
visible: yup.boolean().required(),
|
||||
mainField: yup.string(), // only for relations. TODO: to reset when the relation changes
|
||||
placeholder: yup.string(),
|
||||
editable: yup.boolean(),
|
||||
visible: yup.boolean(),
|
||||
mainField: yup.string(),
|
||||
})
|
||||
.noUnknown()
|
||||
.required(),
|
||||
list: yup
|
||||
.object()
|
||||
.shape({
|
||||
label: yup.string().required(),
|
||||
label: yup.string(),
|
||||
searchable: yup.boolean(),
|
||||
sortable: yup.boolean(),
|
||||
})
|
||||
|
||||
@ -40,15 +40,16 @@ module.exports = {
|
||||
return storeUtils.deleteKey(storeKey);
|
||||
},
|
||||
|
||||
formatContentType(opts) {
|
||||
const { uid, info, source = null, isDisplayed = true } = opts;
|
||||
formatContentType(uid, contentType, opts = {}) {
|
||||
const { source = null, isDisplayed = true } = opts;
|
||||
|
||||
return {
|
||||
uid,
|
||||
name: uid,
|
||||
label: formatContentTypeLabel(info.name || uid),
|
||||
label: formatContentTypeLabel(_.get(contentType, ['info', 'name'], uid)),
|
||||
isDisplayed,
|
||||
source,
|
||||
schema: this.formatContentTypeSchema(contentType),
|
||||
};
|
||||
},
|
||||
|
||||
@ -56,21 +57,41 @@ module.exports = {
|
||||
const { associations, allAttributes } = contentType;
|
||||
return {
|
||||
...pickSchemaFields(contentType),
|
||||
attributes: Object.keys(allAttributes).reduce((acc, key) => {
|
||||
const attr = allAttributes[key];
|
||||
const assoc = associations.find(assoc => assoc.alias === key);
|
||||
if (assoc) {
|
||||
acc[key] = {
|
||||
...attr,
|
||||
type: 'relation',
|
||||
targetModel: attr.model || attr.collection,
|
||||
relationType: assoc.nature,
|
||||
};
|
||||
} else {
|
||||
acc[key] = attr;
|
||||
}
|
||||
return acc;
|
||||
}, {}),
|
||||
attributes: {
|
||||
[contentType.primaryKey]: {
|
||||
type: contentType.primaryKeyType,
|
||||
},
|
||||
id: {
|
||||
type: contentType.primaryKeyType,
|
||||
},
|
||||
...Object.keys(allAttributes).reduce((acc, key) => {
|
||||
const attribute = allAttributes[key];
|
||||
const assoc = associations.find(assoc => assoc.alias === key);
|
||||
|
||||
if (assoc) {
|
||||
const { plugin } = attribute;
|
||||
let targetEntity = attribute.model || attribute.collection;
|
||||
|
||||
if (plugin === 'upload' && targetEntity === 'file') {
|
||||
acc[key] = {
|
||||
type: 'media',
|
||||
multiple: attribute.collection ? true : false,
|
||||
required: attribute.required ? true : false,
|
||||
};
|
||||
} else {
|
||||
acc[key] = {
|
||||
...attribute,
|
||||
type: 'relation',
|
||||
targetModel: targetEntity,
|
||||
relationType: assoc.nature,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
acc[key] = attribute;
|
||||
}
|
||||
return acc;
|
||||
}, {}),
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const storeUtils = require('./utils/store');
|
||||
const { pickSchemaFields } = require('./utils/schema');
|
||||
|
||||
const uidToStoreKey = uid => `groups::${uid}`;
|
||||
|
||||
@ -30,26 +29,4 @@ module.exports = {
|
||||
const storeKey = uidToStoreKey(uid);
|
||||
return storeUtils.deleteKey(storeKey);
|
||||
},
|
||||
|
||||
formatGroupSchema(group) {
|
||||
const { associations, allAttributes } = group;
|
||||
return {
|
||||
...pickSchemaFields(group),
|
||||
attributes: Object.keys(allAttributes).reduce((acc, key) => {
|
||||
const attr = allAttributes[key];
|
||||
const assoc = associations.find(assoc => assoc.alias === key);
|
||||
if (assoc) {
|
||||
acc[key] = {
|
||||
...attr,
|
||||
type: 'relation',
|
||||
targetModel: attr.model || attr.collection,
|
||||
relationType: assoc.nature,
|
||||
};
|
||||
} else {
|
||||
acc[key] = attr;
|
||||
}
|
||||
return acc;
|
||||
}, {}),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,217 +1,92 @@
|
||||
const {
|
||||
isSortable,
|
||||
isEditable,
|
||||
hasEditableAttribute,
|
||||
hasListableAttribute,
|
||||
hasRelationAttribute,
|
||||
} = require('../attributes');
|
||||
const { isSortable, isVisible } = require('../attributes');
|
||||
|
||||
const createMockSchema = (attrs, timestamps = true) => {
|
||||
return {
|
||||
options: {
|
||||
timestamps: timestamps ? ['createdAt', 'updatedAt'] : false,
|
||||
},
|
||||
attributes: {
|
||||
id: {
|
||||
type: 'integer',
|
||||
},
|
||||
...attrs,
|
||||
...(timestamps
|
||||
? {
|
||||
createdAt: {
|
||||
type: 'timestamp',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'timestampUpdate',
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
describe('attributesUtils', () => {
|
||||
describe('isSortable', () => {
|
||||
test('The id attribute is always sortable', () => {
|
||||
expect(isSortable({}, 'id')).toBe(true);
|
||||
expect(isSortable(createMockSchema({}), 'id')).toBe(true);
|
||||
});
|
||||
|
||||
test('Timestamps are sortable', () => {
|
||||
expect(isSortable(createMockSchema({}, true), 'createdAt')).toBe(true);
|
||||
expect(isSortable(createMockSchema({}, true), 'updatedAt')).toBe(true);
|
||||
expect(isSortable(createMockSchema({}, false), 'createdAt')).toBe(false);
|
||||
});
|
||||
|
||||
test('Group fields are not sortable', () => {
|
||||
expect(
|
||||
isSortable(
|
||||
{
|
||||
allAttributes: {
|
||||
someGroup: {
|
||||
type: 'group',
|
||||
},
|
||||
},
|
||||
},
|
||||
'someGroup'
|
||||
)
|
||||
).toBe(false);
|
||||
const schema = createMockSchema({
|
||||
someGroup: {
|
||||
type: 'group',
|
||||
},
|
||||
});
|
||||
|
||||
expect(isSortable(schema, 'someGroup')).toBe(false);
|
||||
});
|
||||
|
||||
test('Json fields are not sortable', () => {
|
||||
expect(
|
||||
isSortable(
|
||||
{
|
||||
allAttributes: {
|
||||
jsonInput: {
|
||||
type: 'json',
|
||||
},
|
||||
},
|
||||
},
|
||||
'jsonInput'
|
||||
)
|
||||
).toBe(false);
|
||||
const schema = createMockSchema({
|
||||
jsonInput: {
|
||||
type: 'json',
|
||||
},
|
||||
});
|
||||
|
||||
expect(isSortable(schema, 'jsonInput')).toBe(false);
|
||||
});
|
||||
|
||||
test('Relations are not sortable', () => {
|
||||
expect(
|
||||
isSortable(
|
||||
{
|
||||
allAttributes: {
|
||||
oneWayRel: {
|
||||
model: 'someModel',
|
||||
},
|
||||
},
|
||||
},
|
||||
'oneWayRel'
|
||||
)
|
||||
).toBe(false);
|
||||
const schema = createMockSchema({
|
||||
oneWayRel: {
|
||||
type: 'relation',
|
||||
targetModel: 'someModel',
|
||||
},
|
||||
manyWayRel: {
|
||||
type: 'relation',
|
||||
targetModel: 'someModel',
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
isSortable(
|
||||
{
|
||||
allAttributes: {
|
||||
manyWayRel: {
|
||||
collection: 'someModel',
|
||||
},
|
||||
},
|
||||
},
|
||||
'manyWayRel'
|
||||
)
|
||||
).toBe(false);
|
||||
expect(isSortable(schema, 'oneWayRel')).toBe(false);
|
||||
expect(isSortable(schema, 'manyWayRel')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isEditable', () => {
|
||||
describe('isVisible', () => {
|
||||
test('Check if the attribute is in a model attributes', () => {
|
||||
expect(
|
||||
isEditable(
|
||||
{
|
||||
attributes: {
|
||||
field: {
|
||||
type: 'string',
|
||||
},
|
||||
isVisible(
|
||||
createMockSchema({
|
||||
field: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
}),
|
||||
'field'
|
||||
)
|
||||
).toBe(true);
|
||||
|
||||
expect(
|
||||
isEditable(
|
||||
{
|
||||
attributes: {
|
||||
field: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
'createdAt'
|
||||
)
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasEditableAttribute', () => {
|
||||
test('Check if the attribute exists and is not a relation', () => {
|
||||
const model = {
|
||||
allAttributes: {
|
||||
rel1: {
|
||||
model: 'someModel',
|
||||
},
|
||||
rel2: {
|
||||
collection: 'someModel',
|
||||
},
|
||||
title: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(hasEditableAttribute(model, 'rel1')).toBe(false);
|
||||
expect(hasEditableAttribute(model, 'rel2')).toBe(false);
|
||||
expect(hasEditableAttribute(model, 'unkown')).toBe(false);
|
||||
expect(hasEditableAttribute(model, 'title')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasListableAttribute', () => {
|
||||
test('Ids are listable', () => {
|
||||
expect(hasListableAttribute({}, 'id')).toBe(true);
|
||||
});
|
||||
|
||||
test('Unknown attributes are not listable', () => {
|
||||
const model = {
|
||||
allAttributes: {
|
||||
rel1: {
|
||||
model: 'someModel',
|
||||
},
|
||||
rel2: {
|
||||
collection: 'someModel',
|
||||
},
|
||||
title: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(hasListableAttribute(model, 'unkown')).toBe(false);
|
||||
});
|
||||
|
||||
test('Group attributes are not listable', () => {
|
||||
const model = {
|
||||
allAttributes: {
|
||||
someGroup: {
|
||||
type: 'group',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(hasListableAttribute(model, 'someGroup')).toBe(false);
|
||||
});
|
||||
|
||||
test('JSON attributes are not listable', () => {
|
||||
const model = {
|
||||
allAttributes: {
|
||||
someJson: {
|
||||
type: 'json',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(hasListableAttribute(model, 'someJson')).toBe(false);
|
||||
});
|
||||
|
||||
test('Relations are not listable', () => {
|
||||
const model = {
|
||||
allAttributes: {
|
||||
rel1: {
|
||||
model: 'someModel',
|
||||
},
|
||||
rel2: {
|
||||
collection: 'someModel',
|
||||
},
|
||||
title: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(hasListableAttribute(model, 'rel1')).toBe(false);
|
||||
expect(hasListableAttribute(model, 'rel2')).toBe(false);
|
||||
expect(hasListableAttribute(model, 'title')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasRelationAttribute', () => {
|
||||
test('Only validate relational attributes', () => {
|
||||
const model = {
|
||||
allAttributes: {
|
||||
rel1: {
|
||||
model: 'someModel',
|
||||
},
|
||||
rel2: {
|
||||
collection: 'someModel',
|
||||
},
|
||||
title: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(hasRelationAttribute(model, 'rel1')).toBe(true);
|
||||
expect(hasRelationAttribute(model, 'rel2')).toBe(true);
|
||||
expect(hasRelationAttribute(model, 'unkown')).toBe(false);
|
||||
expect(hasRelationAttribute(model, 'title')).toBe(false);
|
||||
expect(isVisible(createMockSchema({}), 'createdAt')).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -2,15 +2,13 @@
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
const NON_SORTABLES = ['group', 'json'];
|
||||
const isSortable = (model, name) => {
|
||||
if (name === 'id') return true;
|
||||
|
||||
const attribute = model.allAttributes[name];
|
||||
if (!_.has(attribute, 'type')) {
|
||||
const NON_SORTABLES = ['group', 'json', 'relation'];
|
||||
const isSortable = (schema, name) => {
|
||||
if (!_.has(schema.attributes, name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const attribute = schema.attributes[name];
|
||||
if (NON_SORTABLES.includes(attribute.type)) {
|
||||
return false;
|
||||
}
|
||||
@ -18,51 +16,42 @@ const isSortable = (model, name) => {
|
||||
return true;
|
||||
};
|
||||
|
||||
// check it is in the attributes not in allAttributes
|
||||
const isEditable = (model, name) => _.has(model.attributes, name);
|
||||
|
||||
const hasRelationAttribute = (model, attr) => {
|
||||
return (
|
||||
_.has(model.allAttributes[attr], 'model') ||
|
||||
_.has(model.allAttributes[attr], 'collection')
|
||||
);
|
||||
const isSearchable = (schema, name) => {
|
||||
return isSortable(schema, name);
|
||||
};
|
||||
|
||||
const hasEditableAttribute = (model, attr) => {
|
||||
if (!_.has(model.allAttributes, attr)) {
|
||||
const isVisible = (schema, name) => {
|
||||
if (!_.has(schema.attributes, name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_.has(model.allAttributes[attr], 'type')) {
|
||||
if (isTimestamp(schema, name) || name === 'id') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const hasListableAttribute = (model, attr) => {
|
||||
if (attr === 'id') return true;
|
||||
|
||||
if (!_.has(model.allAttributes, attr)) {
|
||||
const isTimestamp = (schema, name) => {
|
||||
if (!_.has(schema.attributes, name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_.has(model.allAttributes[attr], 'type')) {
|
||||
const timestampsOpt = _.get(schema, ['options', 'timestamps']);
|
||||
if (!timestampsOpt || !Array.isArray(timestampsOpt)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NON_SORTABLES.includes(model.allAttributes[attr].type)) {
|
||||
return false;
|
||||
if (timestampsOpt.includes(name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const isRelation = attribute => attribute.type === 'relation';
|
||||
|
||||
module.exports = {
|
||||
isSortable,
|
||||
isEditable,
|
||||
|
||||
hasEditableAttribute,
|
||||
hasListableAttribute,
|
||||
hasRelationAttribute,
|
||||
isVisible,
|
||||
isSearchable,
|
||||
isRelation,
|
||||
};
|
||||
|
||||
@ -1,20 +1,29 @@
|
||||
const { createDefaultSettings, syncSettings } = require('./settings');
|
||||
const { createDefaultMetadatas, syncMetadatas } = require('./metadatas');
|
||||
const { createDefaultLayouts, syncLayouts } = require('./layouts');
|
||||
const { formatContentTypeSchema } = require('../../ContentTypes');
|
||||
|
||||
async function createDefaultConfiguration(model) {
|
||||
// convert model to schema
|
||||
|
||||
const schema = formatContentTypeSchema(model);
|
||||
|
||||
return {
|
||||
settings: await createDefaultSettings(),
|
||||
metadatas: await createDefaultMetadatas(model),
|
||||
layouts: await createDefaultLayouts(model),
|
||||
metadatas: await createDefaultMetadatas(schema),
|
||||
layouts: await createDefaultLayouts(schema),
|
||||
};
|
||||
}
|
||||
|
||||
async function syncConfiguration(conf, model) {
|
||||
// convert model to schema
|
||||
|
||||
const schema = formatContentTypeSchema(model);
|
||||
|
||||
return {
|
||||
settings: await syncSettings(conf, model),
|
||||
layouts: await syncLayouts(conf, model),
|
||||
metadatas: await syncMetadatas(conf, model),
|
||||
settings: await syncSettings(conf, schema),
|
||||
layouts: await syncLayouts(conf, schema),
|
||||
metadatas: await syncMetadatas(conf, schema),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const {
|
||||
hasListableAttribute,
|
||||
hasRelationAttribute,
|
||||
hasEditableAttribute,
|
||||
} = require('./attributes');
|
||||
const { isSortable, isVisible, isRelation } = require('./attributes');
|
||||
|
||||
const DEFAULT_LIST_LENGTH = 4;
|
||||
const MAX_ROW_SIZE = 12;
|
||||
@ -31,37 +27,39 @@ const typeToSize = type => {
|
||||
}
|
||||
};
|
||||
|
||||
async function createDefaultLayouts(model) {
|
||||
async function createDefaultLayouts(schema) {
|
||||
return {
|
||||
list: createDefaultListLayout(model),
|
||||
editRelations: createDefaultEditRelationsLayout(model),
|
||||
edit: createDefaultEditLayout(model),
|
||||
list: createDefaultListLayout(schema),
|
||||
editRelations: createDefaultEditRelationsLayout(schema),
|
||||
edit: createDefaultEditLayout(schema),
|
||||
};
|
||||
}
|
||||
|
||||
function createDefaultListLayout(model) {
|
||||
return ['id']
|
||||
.concat(Object.keys(model.allAttributes))
|
||||
.filter(name => hasListableAttribute(model, name))
|
||||
function createDefaultListLayout(schema) {
|
||||
return Object.keys(schema.attributes)
|
||||
.filter(name => isSortable(schema, name))
|
||||
.slice(0, DEFAULT_LIST_LENGTH);
|
||||
}
|
||||
|
||||
function createDefaultEditRelationsLayout(model) {
|
||||
return Object.keys(model.allAttributes).filter(name =>
|
||||
hasRelationAttribute(model, name)
|
||||
function createDefaultEditRelationsLayout(schema) {
|
||||
if (schema.modelType === 'group') return [];
|
||||
|
||||
return Object.keys(schema.attributes).filter(name =>
|
||||
hasRelationAttribute(schema, name)
|
||||
);
|
||||
}
|
||||
|
||||
const rowSize = els => els.reduce((sum, el) => sum + el.size, 0);
|
||||
function createDefaultEditLayout(model) {
|
||||
const keys = Object.keys(model.attributes).filter(name =>
|
||||
hasEditableAttribute(model, name)
|
||||
|
||||
function createDefaultEditLayout(schema) {
|
||||
const keys = Object.keys(schema.attributes).filter(name =>
|
||||
hasEditableAttribute(schema, name)
|
||||
);
|
||||
|
||||
let layout = [[]];
|
||||
let currentRowIndex = 0;
|
||||
for (let key of keys) {
|
||||
const attribute = model.attributes[key];
|
||||
const attribute = schema.attributes[key];
|
||||
const attributeSize = typeToSize(attribute.type);
|
||||
let currenRowSize = rowSize(layout[currentRowIndex]);
|
||||
|
||||
@ -81,20 +79,22 @@ function createDefaultEditLayout(model) {
|
||||
|
||||
/** Synchronisation functions */
|
||||
|
||||
function syncLayouts(configuration, model) {
|
||||
if (_.isEmpty(configuration.layouts)) return createDefaultLayouts(model);
|
||||
function syncLayouts(configuration, schema) {
|
||||
if (_.isEmpty(configuration.layouts)) return createDefaultLayouts(schema);
|
||||
|
||||
const { list = [], editRelations = [], edit = [] } =
|
||||
configuration.layouts || {};
|
||||
|
||||
const cleanList = list.filter(attr => hasListableAttribute(model, attr));
|
||||
const cleanList = list.filter(attr => isSortable(schema, attr));
|
||||
|
||||
const cleanEditRelations = editRelations.filter(attr =>
|
||||
hasRelationAttribute(model, attr)
|
||||
hasRelationAttribute(schema, attr)
|
||||
);
|
||||
|
||||
const cleanEdit = edit.reduce((acc, row) => {
|
||||
let newRow = row.filter(el => hasEditableAttribute(model, el.name));
|
||||
let newRow = row.filter(el => hasEditableAttribute(schema, el.name));
|
||||
|
||||
// TODO: recompute row sizes
|
||||
|
||||
if (newRow.length > 0) {
|
||||
acc.push(newRow);
|
||||
@ -103,16 +103,16 @@ function syncLayouts(configuration, model) {
|
||||
}, []);
|
||||
|
||||
let layout = {
|
||||
list: cleanList.length > 0 ? cleanList : createDefaultListLayout(model),
|
||||
list: cleanList.length > 0 ? cleanList : createDefaultListLayout(schema),
|
||||
editRelations:
|
||||
cleanEditRelations.length > 0
|
||||
? cleanEditRelations
|
||||
: createDefaultEditRelationsLayout(model),
|
||||
edit: cleanEdit.length > 0 ? cleanEdit : createDefaultEditLayout(model),
|
||||
: createDefaultEditRelationsLayout(schema),
|
||||
edit: cleanEdit.length > 0 ? cleanEdit : createDefaultEditLayout(schema),
|
||||
};
|
||||
|
||||
const newAttributes = _.difference(
|
||||
Object.keys(model.allAttributes),
|
||||
Object.keys(schema.attributes),
|
||||
Object.keys(configuration.metadatas)
|
||||
);
|
||||
|
||||
@ -125,26 +125,28 @@ function syncLayouts(configuration, model) {
|
||||
// only add valid listable attributes
|
||||
layout.list = _.uniq(
|
||||
layout.list
|
||||
.concat(newAttributes.filter(key => hasListableAttribute(model, key)))
|
||||
.concat(newAttributes.filter(key => isSortable(schema, key)))
|
||||
.slice(0, DEFAULT_LIST_LENGTH)
|
||||
);
|
||||
}
|
||||
|
||||
// add new relations to layout
|
||||
const newRelations = newAttributes.filter(key =>
|
||||
hasRelationAttribute(model, key)
|
||||
);
|
||||
if (schema.type !== 'group') {
|
||||
const newRelations = newAttributes.filter(key =>
|
||||
hasRelationAttribute(schema, key)
|
||||
);
|
||||
|
||||
layout.editRelations = _.uniq(layout.editRelations.concat(newRelations));
|
||||
layout.editRelations = _.uniq(layout.editRelations.concat(newRelations));
|
||||
}
|
||||
|
||||
// add new attributes to edit view
|
||||
const newEditAttributes = newAttributes.filter(
|
||||
key => hasEditableAttribute(model, key) && _.has(model.attributes, key)
|
||||
key => hasEditableAttribute(schema, key) && isVisible(schema, key)
|
||||
);
|
||||
|
||||
let currentRowIndex = Math.max(layout.edit.length - 1, 0);
|
||||
for (let key of newEditAttributes) {
|
||||
const attribute = model.attributes[key];
|
||||
const attribute = schema.attributes[key];
|
||||
const attributeSize = typeToSize(attribute.type);
|
||||
let currenRowSize = rowSize(layout.edit[currentRowIndex]);
|
||||
|
||||
@ -162,6 +164,31 @@ function syncLayouts(configuration, model) {
|
||||
return layout;
|
||||
}
|
||||
|
||||
const hasRelationAttribute = (schema, name) => {
|
||||
if (!_.has(schema.attributes, name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isRelation(schema.attributes[name]);
|
||||
};
|
||||
|
||||
const hasEditableAttribute = (schema, name) => {
|
||||
if (!_.has(schema.attributes, name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isVisible(schema, name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isRelation(schema.attributes[name])) {
|
||||
if (schema.modelType === 'group') return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
createDefaultLayouts,
|
||||
syncLayouts,
|
||||
|
||||
@ -2,13 +2,19 @@
|
||||
|
||||
const _ = require('lodash');
|
||||
const {
|
||||
isEditable,
|
||||
isSortable,
|
||||
hasListableAttribute,
|
||||
isSearchable,
|
||||
isVisible,
|
||||
isRelation,
|
||||
} = require('./attributes');
|
||||
const { formatContentTypeSchema } = require('../../ContentTypes');
|
||||
|
||||
function createDefaultMetadatas(model) {
|
||||
function createDefaultMetadatas(schema) {
|
||||
return {
|
||||
...Object.keys(schema.attributes).reduce((acc, name) => {
|
||||
acc[name] = createDefaultMetadata(schema, name);
|
||||
return acc;
|
||||
}, {}),
|
||||
id: {
|
||||
edit: {},
|
||||
list: {
|
||||
@ -17,31 +23,26 @@ function createDefaultMetadatas(model) {
|
||||
sortable: true,
|
||||
},
|
||||
},
|
||||
...Object.keys(model.allAttributes).reduce((acc, name) => {
|
||||
acc[name] = createDefaultMetadata(model, name);
|
||||
return acc;
|
||||
}, {}),
|
||||
};
|
||||
}
|
||||
|
||||
function createDefaultMetadata(model, name) {
|
||||
const attr = model.allAttributes[name];
|
||||
function createDefaultMetadata(schema, name) {
|
||||
const edit = {
|
||||
label: name,
|
||||
label: _.upperFirst(name),
|
||||
description: '',
|
||||
placeholder: '',
|
||||
visible: true,
|
||||
editable: isEditable(model, name),
|
||||
visible: isVisible(schema, name),
|
||||
editable: true,
|
||||
};
|
||||
|
||||
if (_.has(attr, 'model') || _.has(attr, 'collection')) {
|
||||
if (isRelation(schema.attributes[name])) {
|
||||
edit.mainField = 'id';
|
||||
}
|
||||
|
||||
const list = {
|
||||
label: name,
|
||||
searchable: true,
|
||||
sortable: isSortable(model, name),
|
||||
label: _.upperFirst(name),
|
||||
searchable: isSearchable(schema, name),
|
||||
sortable: isSortable(schema, name),
|
||||
};
|
||||
|
||||
return { edit, list };
|
||||
@ -49,39 +50,44 @@ function createDefaultMetadata(model, name) {
|
||||
|
||||
/** Synchronisation functions */
|
||||
|
||||
async function syncMetadatas(configuration, model) {
|
||||
async function syncMetadatas(configuration, schema) {
|
||||
// clear all keys that do not exist anymore
|
||||
if (_.isEmpty(configuration.metadatas)) return createDefaultMetadatas(model);
|
||||
if (_.isEmpty(configuration.metadatas)) return createDefaultMetadatas(schema);
|
||||
|
||||
// remove old keys
|
||||
const metasWithValidKeys = _.pick(
|
||||
configuration.metadatas,
|
||||
['id'].concat(Object.keys(model.allAttributes))
|
||||
Object.keys(schema.attributes)
|
||||
);
|
||||
|
||||
// add new keys and missing fields
|
||||
const metasWithDefaults = _.merge(
|
||||
{},
|
||||
createDefaultMetadatas(model),
|
||||
createDefaultMetadatas(schema),
|
||||
metasWithValidKeys
|
||||
);
|
||||
|
||||
// clear the invalid mainFields
|
||||
const updatedMetas = Object.keys(metasWithDefaults).reduce((acc, key) => {
|
||||
const meta = metasWithDefaults[key];
|
||||
const { edit, list } = meta;
|
||||
const { edit, list } = metasWithDefaults[key];
|
||||
const attr = schema.attributes[key];
|
||||
|
||||
let updatedMeta = { edit, list };
|
||||
// update sortable attr
|
||||
if (list.sortable && !isSortable(model, key)) {
|
||||
if (list.sortable && !isSortable(schema, key)) {
|
||||
_.set(updatedMeta, ['list', 'sortable'], false);
|
||||
_.set(acc, [key], updatedMeta);
|
||||
}
|
||||
|
||||
if (list.searchable && !isSearchable(schema, key)) {
|
||||
_.set(updatedMeta, ['list', 'searchable'], false);
|
||||
_.set(acc, [key], updatedMeta);
|
||||
}
|
||||
|
||||
if (!_.has(edit, 'mainField')) return acc;
|
||||
|
||||
// remove mainField if the attribute is not a relation anymore
|
||||
if (_.has(model.allAttributes[key], 'type')) {
|
||||
if (!isRelation(attr)) {
|
||||
_.set(updatedMeta, 'edit', _.omit(edit, ['mainField']));
|
||||
_.set(acc, [key], updatedMeta);
|
||||
return acc;
|
||||
@ -91,10 +97,11 @@ async function syncMetadatas(configuration, model) {
|
||||
if (edit.mainField === 'id') return acc;
|
||||
|
||||
// check the mainField in the targetModel
|
||||
const attr = model.allAttributes[key];
|
||||
const target = strapi.getModel(attr.model || attr.collection, attr.plugin);
|
||||
const targetSchema = getTargetSchema(attr.targetModel, attr.plugin);
|
||||
|
||||
if (!hasListableAttribute(target, meta.mainField)) {
|
||||
if (!targetSchema) return acc;
|
||||
|
||||
if (!isSortable(targetSchema, edit.mainField)) {
|
||||
_.set(updatedMeta, ['edit', 'mainField'], 'id');
|
||||
_.set(acc, [key], updatedMeta);
|
||||
return acc;
|
||||
@ -106,6 +113,13 @@ async function syncMetadatas(configuration, model) {
|
||||
return _.assign(metasWithDefaults, updatedMetas);
|
||||
}
|
||||
|
||||
const getTargetSchema = (name, plugin) => {
|
||||
const model = strapi.getModel(name, plugin);
|
||||
if (!model) return null;
|
||||
|
||||
return formatContentTypeSchema(model);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
createDefaultMetadatas,
|
||||
syncMetadatas,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const { hasListableAttribute } = require('./attributes');
|
||||
const { isSortable } = require('./attributes');
|
||||
|
||||
/**
|
||||
* Retunrs a configuration default settings
|
||||
@ -21,18 +21,16 @@ async function createDefaultSettings() {
|
||||
|
||||
/** Synchronisation functions */
|
||||
|
||||
async function syncSettings(configuration, model) {
|
||||
if (_.isEmpty(configuration.settings)) return createDefaultSettings(model);
|
||||
async function syncSettings(configuration, schema) {
|
||||
if (_.isEmpty(configuration.settings)) return createDefaultSettings(schema);
|
||||
|
||||
const { mainField = 'id', defaultSortBy = 'id' } =
|
||||
configuration.settings || {};
|
||||
|
||||
return {
|
||||
...configuration.settings,
|
||||
mainField: hasListableAttribute(model, mainField) ? mainField : 'id',
|
||||
defaultSortBy: hasListableAttribute(model, defaultSortBy)
|
||||
? defaultSortBy
|
||||
: 'id',
|
||||
mainField: isSortable(schema, mainField) ? mainField : 'id',
|
||||
defaultSortBy: isSortable(schema, defaultSortBy) ? defaultSortBy : 'id',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
5
packages/strapi/lib/core/bootstrap.js
vendored
5
packages/strapi/lib/core/bootstrap.js
vendored
@ -51,6 +51,7 @@ module.exports = function(strapi) {
|
||||
throw new Error(`Group ${key} is missing a collectionName attribute`);
|
||||
|
||||
return Object.assign(group, {
|
||||
modelType: 'group',
|
||||
globalId: group.globalId || _.upperFirst(_.camelCase(`group_${key}`)),
|
||||
});
|
||||
});
|
||||
@ -61,6 +62,7 @@ module.exports = function(strapi) {
|
||||
let model = strapi.api[key].models[index];
|
||||
|
||||
Object.assign(model, {
|
||||
modelType: 'contentType',
|
||||
apiName: key,
|
||||
globalId: model.globalId || _.upperFirst(_.camelCase(index)),
|
||||
collectionName: model.collectionName || `${index}`.toLocaleLowerCase(),
|
||||
@ -127,6 +129,7 @@ module.exports = function(strapi) {
|
||||
let model = strapi.admin.models[key];
|
||||
|
||||
Object.assign(model, {
|
||||
modelType: 'contentType',
|
||||
identity: model.identity || _.upperFirst(key),
|
||||
globalId: model.globalId || _.upperFirst(_.camelCase(`admin-${key}`)),
|
||||
connection:
|
||||
@ -155,6 +158,8 @@ module.exports = function(strapi) {
|
||||
let model = plugin.models[key];
|
||||
|
||||
Object.assign(model, {
|
||||
modelType: 'contentType',
|
||||
plugin: pluginName,
|
||||
collectionName:
|
||||
model.collectionName || `${pluginName}_${key}`.toLowerCase(),
|
||||
globalId:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user