diff --git a/docs/3.x.x/guides/models.md b/docs/3.x.x/guides/models.md index fd9b43071e..955e662e46 100644 --- a/docs/3.x.x/guides/models.md +++ b/docs/3.x.x/guides/models.md @@ -27,6 +27,7 @@ The info key on the model-json states information about the model. This informat The options key on the model-json states. - `idAttribute`: This tells the model which attribute to expect as the unique identifier for each database row (typically an auto-incrementing primary key named 'id'). _Only valid for strapi-hook-bookshelf_ - `idAttributeType`: Data type of `idAttribute`, accepted list of value bellow. _Only valid for strapi-hook-bookshelf_ + - `timestamps`: This tells the model which attributes to use for timestamps. Accepts either `boolean` or `Array` of strings where frist element is create data and second elemtent is update date. Default value when set to `true` for Bookshelf is `["created_at", "updated_at"]` and for MongoDB is `["createdAt", "updatedAt"]`. ## Define the attributes diff --git a/packages/strapi-hook-bookshelf/lib/index.js b/packages/strapi-hook-bookshelf/lib/index.js index c4e6b7a533..abfaa347bb 100644 --- a/packages/strapi-hook-bookshelf/lib/index.js +++ b/packages/strapi-hook-bookshelf/lib/index.js @@ -89,7 +89,7 @@ module.exports = function(strapi) { // Register the final model for Bookshelf. const loadedModel = _.assign({ tableName: definition.collectionName, - hasTimestamps: _.get(definition, 'options.timestamps') === true, + hasTimestamps: _.get(definition, 'options.timestamps', false), idAttribute: _.get(definition, 'options.idAttribute', 'id'), associations: [], defaults: Object.keys(definition.attributes).reduce((acc, current) => { @@ -100,7 +100,14 @@ module.exports = function(strapi) { return acc; }, {}) }, definition.options); - + // Use default timestamp column names if value is `true` + if (_.get(loadedModel, 'hasTimestamps') === true) { + _.set(loadedModel, 'hasTimestamps', ['created_at', 'updated_at']); + } + // Use false for values other than `Boolean` or `Array` + if (!_.isArray(_.get(loadedModel, 'hasTimestamps')) && !_.isBoolean(_.get(loadedModel, 'hasTimestamps'))) { + _.set(loadedModel, 'hasTimestamps', false); + } if (_.isString(_.get(connection, 'options.pivot_prefix'))) { loadedModel.toJSON = function(options = {}) { const { shallow = false, omitPivot = false } = options; @@ -619,10 +626,10 @@ module.exports = function(strapi) { // Add created_at and updated_at field if timestamp option is true if (loadedModel.hasTimestamps) { - definition.attributes['created_at'] = { + definition.attributes[_.isString(loadedModel.hasTimestamps[0]) ? loadedModel.hasTimestamps[0] : 'created_at'] = { type: 'timestamp' }; - definition.attributes['updated_at'] = { + definition.attributes[_.isString(loadedModel.hasTimestamps[1]) ? loadedModel.hasTimestamps[1] : 'updated_at'] = { type: 'timestampUpdate' }; } @@ -701,8 +708,8 @@ module.exports = function(strapi) { // Remove from attributes (auto handled by bookshlef and not displayed on ctb) if (loadedModel.hasTimestamps) { - delete definition.attributes['created_at']; - delete definition.attributes['updated_at']; + delete definition.attributes[_.isString(loadedModel.hasTimestamps[0]) ? loadedModel.hasTimestamps[0] : 'created_at']; + delete definition.attributes[_.isString(loadedModel.hasTimestamps[1]) ? loadedModel.hasTimestamps[1] : 'updated_at']; } resolve(); diff --git a/packages/strapi-hook-mongoose/lib/index.js b/packages/strapi-hook-mongoose/lib/index.js index 025ea36247..80ab48fcaf 100644 --- a/packages/strapi-hook-mongoose/lib/index.js +++ b/packages/strapi-hook-mongoose/lib/index.js @@ -207,7 +207,16 @@ module.exports = function (strapi) { }); }); - collection.schema.set('timestamps', _.get(definition, 'options.timestamps') === true); + // Use provided timestamps if the elemnets in the array are string else use default. + if (_.isArray(_.get(definition, 'options.timestamps'))) { + const timestamps = { + createdAt: _.isString(_.get(definition, 'options.timestamps[0]')) ? _.get(definition, 'options.timestamps[0]') : 'createdAt', + updatedAt: _.isString(_.get(definition, 'options.timestamps[1]')) ? _.get(definition, 'options.timestamps[1]') : 'updatedAt' + }; + collection.schema.set('timestamps', timestamps); + } else { + collection.schema.set('timestamps', _.get(definition, 'options.timestamps') === true); + } collection.schema.set('minimize', _.get(definition, 'options.minimize', false) === true); collection.schema.options.toObject = collection.schema.options.toJSON = { diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/saga.js b/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/saga.js index 1c906ba375..cd94930713 100644 --- a/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/saga.js +++ b/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/saga.js @@ -77,15 +77,10 @@ export function* submit() { let shouldAddTranslationSuffix = false; // Remove the updated_at & created_at fields so it is updated correctly when using Postgres or MySQL db - if (record.updated_at) { - delete record.created_at; - delete record.updated_at; - } - - // Remove the updatedAt & createdAt fields so it is updated correctly when using MongoDB - if (record.updatedAt) { - delete record.createdAt; - delete record.updatedAt; + const timestamps = get(schema, ['models', currentModelName, 'options', 'timestamps'], null); + if (timestamps) { + delete record[timestamps[0]]; + delete record[timestamps[1]]; } try { diff --git a/packages/strapi-plugin-content-manager/config/functions/bootstrap.js b/packages/strapi-plugin-content-manager/config/functions/bootstrap.js index 19f95e9c33..3886c5b8cc 100644 --- a/packages/strapi-plugin-content-manager/config/functions/bootstrap.js +++ b/packages/strapi-plugin-content-manager/config/functions/bootstrap.js @@ -17,6 +17,7 @@ const pickData = (model) => _.pick(model, [ 'globalId', 'globalName', 'orm', + 'options.timestamps', 'loadedModel', 'primaryKey', 'associations' @@ -84,6 +85,7 @@ module.exports = async cb => { pageEntries: 10, defaultSort: model.primaryKey, sort: 'ASC', + options: model.options, editDisplay: { availableFields: {}, fields: [], @@ -330,8 +332,9 @@ module.exports = async cb => { // Here we just need to add the data from the current schema Object apisToAdd.map(apiPath => { const api = _.get(schema.models, apiPath); - const { search, filters, bulkActions, pageEntries } = _.get(prevSchema, 'generalSettings'); + const { search, filters, bulkActions, pageEntries, options } = _.get(prevSchema, 'generalSettings'); + _.set(api, 'options', options); _.set(api, 'filters', filters); _.set(api, 'search', search); _.set(api, 'bulkActions', bulkActions);