From 3bc73a28c0299d8505b2901eb8cfe529d41f629b Mon Sep 17 00:00:00 2001 From: Alexandre Bodin Date: Mon, 15 Nov 2021 19:10:23 +0100 Subject: [PATCH] Add createdAt and updatedAt back into the CM layouts and metas --- .../components/DynamicTable/index.js | 1 - .../pages/ListView/FieldPicker/index.js | 1 - .../pages/ListViewLayoutManager/index.js | 1 - packages/core/content-manager/package.json | 3 +- .../server/services/data-mapper.js | 46 ++++++------------- .../utils/configuration/attributes.js | 6 +-- .../server/tests/index.test.e2e.js | 30 ------------ .../server/tests/single-type.test.e2e.js | 18 -------- .../utils/lib/__tests__/content-types.test.js | 6 +++ packages/core/utils/lib/content-types.js | 20 ++++++-- 10 files changed, 39 insertions(+), 93 deletions(-) diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicTable/index.js b/packages/core/admin/admin/src/content-manager/components/DynamicTable/index.js index 94871749cc..8f626d809b 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicTable/index.js +++ b/packages/core/admin/admin/src/content-manager/components/DynamicTable/index.js @@ -109,7 +109,6 @@ DynamicTable.propTypes = { contentType: PropTypes.shape({ attributes: PropTypes.object.isRequired, metadatas: PropTypes.object.isRequired, - info: PropTypes.shape({ label: PropTypes.string.isRequired }).isRequired, layouts: PropTypes.shape({ list: PropTypes.array.isRequired, editRelations: PropTypes.array, diff --git a/packages/core/admin/admin/src/content-manager/pages/ListView/FieldPicker/index.js b/packages/core/admin/admin/src/content-manager/pages/ListView/FieldPicker/index.js index 3fe7db35b3..3a160e256e 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListView/FieldPicker/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/ListView/FieldPicker/index.js @@ -74,7 +74,6 @@ FieldPicker.propTypes = { contentType: PropTypes.shape({ attributes: PropTypes.object.isRequired, metadatas: PropTypes.object.isRequired, - info: PropTypes.shape({ label: PropTypes.string.isRequired }).isRequired, layouts: PropTypes.shape({ list: PropTypes.array.isRequired, editRelations: PropTypes.array, diff --git a/packages/core/admin/admin/src/content-manager/pages/ListViewLayoutManager/index.js b/packages/core/admin/admin/src/content-manager/pages/ListViewLayoutManager/index.js index 28a322e3d5..78c6fc1c55 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListViewLayoutManager/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/ListViewLayoutManager/index.js @@ -43,7 +43,6 @@ ListViewLayout.propTypes = { contentType: PropTypes.shape({ attributes: PropTypes.object.isRequired, metadatas: PropTypes.object.isRequired, - info: PropTypes.shape({ label: PropTypes.string.isRequired }).isRequired, layouts: PropTypes.shape({ list: PropTypes.array.isRequired, editRelations: PropTypes.array, diff --git a/packages/core/content-manager/package.json b/packages/core/content-manager/package.json index d1bc1eab7e..a20c4fcb03 100644 --- a/packages/core/content-manager/package.json +++ b/packages/core/content-manager/package.json @@ -13,8 +13,7 @@ "dependencies": { "@sindresorhus/slugify": "1.1.0", "@strapi/utils": "3.6.8", - "lodash": "4.17.21", - "pluralize": "^8.0.0" + "lodash": "4.17.21" }, "author": { "name": "Strapi team", diff --git a/packages/core/content-manager/server/services/data-mapper.js b/packages/core/content-manager/server/services/data-mapper.js index 1f4f26a71c..57de799832 100644 --- a/packages/core/content-manager/server/services/data-mapper.js +++ b/packages/core/content-manager/server/services/data-mapper.js @@ -1,7 +1,6 @@ 'use strict'; -const { upperFirst, prop, pick, getOr } = require('lodash/fp'); -const pluralize = require('pluralize'); +const { pick, getOr } = require('lodash/fp'); const { contentTypes: contentTypesUtils } = require('@strapi/utils'); const dtoFields = [ @@ -21,16 +20,8 @@ module.exports = () => ({ toContentManagerModel(contentType) { return { ...contentType, - options: { - ...contentType.options, - timestamps: [], - }, apiID: contentType.modelName, isDisplayed: isVisible(contentType), - info: { - ...contentType.info, - label: formatContentTypeLabel(contentType), - }, attributes: { id: { type: 'integer', @@ -43,34 +34,23 @@ module.exports = () => ({ toDto: pick(dtoFields), }); -const formatContentTypeLabel = contentType => { - const name = prop('info.name', contentType) || contentType.modelName; - - try { - return contentTypesUtils.isSingleType(contentType) - ? upperFirst(name) - : upperFirst(pluralize(name)); - } catch (error) { - // in case pluralize throws cyrillic characters - return upperFirst(name); - } -}; - const formatAttributes = contentType => { - const { getVisibleAttributes } = contentTypesUtils; + const { getVisibleAttributes, getTimestamps } = contentTypesUtils; // only get attributes that can be seen in the auto generated Edit view or List view - return getVisibleAttributes(contentType).reduce((acc, key) => { - const attribute = contentType.attributes[key]; + return getVisibleAttributes(contentType) + .concat(getTimestamps(contentType)) + .reduce((acc, key) => { + const attribute = contentType.attributes[key]; - // ignore morph until they are handled in the front - if (attribute.type === 'relation' && attribute.relation.toLowerCase().includes('morph')) { + // ignore morph until they are handled in the front + if (attribute.type === 'relation' && attribute.relation.toLowerCase().includes('morph')) { + return acc; + } + + acc[key] = formatAttribute(key, attribute); return acc; - } - - acc[key] = formatAttribute(key, attribute); - return acc; - }, {}); + }, {}); }; // FIXME: not needed diff --git a/packages/core/content-manager/server/services/utils/configuration/attributes.js b/packages/core/content-manager/server/services/utils/configuration/attributes.js index 829be64ffd..1fcfcdfb8c 100644 --- a/packages/core/content-manager/server/services/utils/configuration/attributes.js +++ b/packages/core/content-manager/server/services/utils/configuration/attributes.js @@ -98,12 +98,12 @@ const isTimestamp = (schema, name) => { return false; } - const timestampsOpt = _.get(schema, ['options', 'timestamps']); - if (!timestampsOpt || !Array.isArray(timestampsOpt)) { + const timestamps = contentTypesUtils.getTimestamps(schema); + if (!timestamps || !Array.isArray(timestamps)) { return false; } - if (timestampsOpt.includes(name)) { + if (timestamps.includes(name)) { return true; } }; diff --git a/packages/core/content-manager/server/tests/index.test.e2e.js b/packages/core/content-manager/server/tests/index.test.e2e.js index 495a0e249b..2313ac2c9a 100644 --- a/packages/core/content-manager/server/tests/index.test.e2e.js +++ b/packages/core/content-manager/server/tests/index.test.e2e.js @@ -56,36 +56,6 @@ describe('Content Manager End to End', () => { await builder.cleanup(); }); - describe('Content Types api', () => { - test('Label is pluralized', async () => { - const res = await rq({ - url: `/content-manager/content-types`, - method: 'GET', - }); - - expect(res.statusCode).toBe(200); - expect(res.body.data).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - info: expect.objectContaining({ - label: 'Articles', - }), - }), - expect.objectContaining({ - info: expect.objectContaining({ - label: 'Tags', - }), - }), - expect.objectContaining({ - info: expect.objectContaining({ - label: 'Categories', - }), - }), - ]) - ); - }); - }); - describe('Test manyToMany relation (article - tag) with Content Manager', () => { beforeAll(async () => { data = { diff --git a/packages/core/content-manager/server/tests/single-type.test.e2e.js b/packages/core/content-manager/server/tests/single-type.test.e2e.js index 595dd7d499..f2e5279bfa 100644 --- a/packages/core/content-manager/server/tests/single-type.test.e2e.js +++ b/packages/core/content-manager/server/tests/single-type.test.e2e.js @@ -35,24 +35,6 @@ describe('Content Manager single types', () => { await builder.cleanup(); }); - test('Label is not pluralized', async () => { - const res = await rq({ - url: `/content-manager/content-types?kind=singleType`, - method: 'GET', - }); - - expect(res.statusCode).toBe(200); - expect(res.body.data).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - info: expect.objectContaining({ - label: 'Single-type-model', - }), - }), - ]) - ); - }); - test('find single type content returns 404 when not created', async () => { const res = await rq({ url: `/content-manager/single-types/${uid}`, diff --git a/packages/core/utils/lib/__tests__/content-types.test.js b/packages/core/utils/lib/__tests__/content-types.test.js index 61f5f38926..1f91ae3fc0 100644 --- a/packages/core/utils/lib/__tests__/content-types.test.js +++ b/packages/core/utils/lib/__tests__/content-types.test.js @@ -59,6 +59,12 @@ describe('Content types utils', () => { type: 'string', writable: false, }, + createdAt: { + type: 'datetime', + }, + updatedAt: { + type: 'datetime', + }, }, }); diff --git a/packages/core/utils/lib/content-types.js b/packages/core/utils/lib/content-types.js index 732dcb8e14..ebbd456fbd 100644 --- a/packages/core/utils/lib/content-types.js +++ b/packages/core/utils/lib/content-types.js @@ -1,6 +1,7 @@ 'use strict'; const _ = require('lodash'); +const { has } = require('lodash/fp'); const SINGLE_TYPE = 'singleType'; const COLLECTION_TYPE = 'collectionType'; @@ -31,8 +32,18 @@ const constants = { COLLECTION_TYPE, }; -const getTimestamps = () => { - return [CREATED_AT_ATTRIBUTE, UPDATED_AT_ATTRIBUTE]; +const getTimestamps = model => { + const attributes = []; + + if (has(CREATED_AT_ATTRIBUTE, model.attributes)) { + attributes.push(CREATED_AT_ATTRIBUTE); + } + + if (has(UPDATED_AT_ATTRIBUTE, model.attributes)) { + attributes.push(UPDATED_AT_ATTRIBUTE); + } + + return attributes; }; const getNonWritableAttributes = (model = {}) => { @@ -42,7 +53,7 @@ const getNonWritableAttributes = (model = {}) => { [] ); - return _.uniq([ID_ATTRIBUTE, ...getTimestamps(), ...nonWritableAttributes]); + return _.uniq([ID_ATTRIBUTE, ...getTimestamps(model), ...nonWritableAttributes]); }; const getWritableAttributes = (model = {}) => { @@ -60,7 +71,7 @@ const getNonVisibleAttributes = model => { [] ); - return _.uniq([ID_ATTRIBUTE, ...getTimestamps(), ...nonVisibleAttributes]); + return _.uniq([ID_ATTRIBUTE, ...getTimestamps(model), ...nonVisibleAttributes]); }; const getVisibleAttributes = model => { @@ -137,6 +148,7 @@ module.exports = { isWritableAttribute, getNonVisibleAttributes, getVisibleAttributes, + getTimestamps, isVisibleAttribute, hasDraftAndPublish, isDraft,