From 3aab56b5acdfd3dbed47ac6993fc4c9dcb8a3f39 Mon Sep 17 00:00:00 2001 From: garrettmills Date: Mon, 2 Nov 2020 11:59:57 -0600 Subject: [PATCH] Add VersionedModel base and version page changes --- app/controllers/api/v1/Offline.controller.js | 4 +- app/controllers/api/v1/Page.controller.js | 43 ++++++++++-------- app/models/VersionedModel.js | 46 ++++++++++++++++++++ app/models/api/Page.model.js | 16 ++++--- 4 files changed, 82 insertions(+), 27 deletions(-) create mode 100644 app/models/VersionedModel.js diff --git a/app/controllers/api/v1/Offline.controller.js b/app/controllers/api/v1/Offline.controller.js index ffb5c8f..7a59a39 100644 --- a/app/controllers/api/v1/Offline.controller.js +++ b/app/controllers/api/v1/Offline.controller.js @@ -258,7 +258,7 @@ class OfflineController extends Controller { if ( online_page ) { // if it existed in the online page, delete it online_page.NodeIds = online_page.NodeIds.filter(x => x !== rec.UUID) - await online_page.save() + await online_page.version_save('Updated from offline sync') } await existing_node.delete() @@ -322,7 +322,7 @@ class OfflineController extends Controller { } } - await online_page.save() + await online_page.version_save('Updated page from online save') } // assuming the pages were created first, we should never have a case diff --git a/app/controllers/api/v1/Page.controller.js b/app/controllers/api/v1/Page.controller.js index e7fdf8c..c9dc064 100644 --- a/app/controllers/api/v1/Page.controller.js +++ b/app/controllers/api/v1/Page.controller.js @@ -35,14 +35,28 @@ class Page extends Controller { page.OrgUserId = req.user._id } + let save_message = 'Updated page metadata' + if ( !req.body.Name ) return res.status(400).message('Missing required: Name').api({}) - page.Name = req.body.Name + + if ( page.Name !== req.body.Name ) { + page.Name = req.body.Name + save_message = `Changed page name to ${page.Name}` + } if ( 'IsPublic' in req.body ) { + if ( Boolean(page.IsPublic) !== Boolean(req.body.IsPublic) ) { + save_message = `Made page ${req.body.IsPublic ? 'public' : 'private'}` + } + page.IsPublic = !!req.body.IsPublic } if ( 'IsVisibleInMenu' in req.body ) { + if ( Boolean(page.IsVisibleInMenu) !== Boolean(req.body.IsVisibleInMenu) ) { + save_message = `Made page ${req.body.IsVisibleInMenu ? 'visible' : 'hidden'} in menu` + } + page.IsVisibleInMenu = !!req.body.IsVisibleInMenu } @@ -56,8 +70,7 @@ class Page extends Controller { page.UpdatedAt = new Date page.UpdateUserId = req.user._id - - await page.save() + await page.version_save(save_message) return res.api(page) } @@ -127,7 +140,7 @@ class Page extends Controller { await node_obj.save() page.NodeIds.push(node_obj.UUID); - await page.save(); + await page.version_save(`Added ${node_obj.Type.split('_')[0]} node to page`); return res.api(node_obj) } } @@ -191,14 +204,8 @@ class Page extends Controller { } page.NodeIds = updated_nodes.map(x => x.UUID) - await page.save() - + await page.version_save('Bulk-updated nodes on page') res.api(updated_nodes) - - // Step 1: make sure the updated nodes are updated - // Make sure the deleted nodes are deleted - // Make sure the new nodes are created - // Make sure the order is correct } async create_top_level(req, res) { @@ -223,10 +230,10 @@ class Page extends Controller { } } - await new_page.save() + await new_page.version_save('Created new top-level page') root_page.ChildPageIds.push(new_page.UUID) - await root_page.save() + await root_page.version_save(`Added new top-level page "${new_page.Name}"`) req.user.allow(`page:${new_page.UUID}`) await req.user.save() @@ -244,7 +251,7 @@ class Page extends Controller { await starter_node.save() new_page.NodeIds.push(starter_node.UUID) - await new_page.save() + await new_page.version_save('Added paragraph node to page') } return res.api(new_page) @@ -282,10 +289,10 @@ class Page extends Controller { } } - await new_page.save() + await new_page.version_save(`Created new page as child of "${parent.Name}"`) parent.ChildPageIds.push(new_page.UUID) - await parent.save() + await parent.version_save(`Created new child page "${new_page.Name}"`) req.user.allow(`page:${new_page.UUID}`) await req.user.save() @@ -303,7 +310,7 @@ class Page extends Controller { await starter_node.save() new_page.NodeIds.push(starter_node.UUID) - await new_page.save() + await new_page.version_save('Added paragraph node to page') } return res.api(new_page) @@ -322,7 +329,7 @@ class Page extends Controller { page.Active = false page.DeletedAt = new Date - await page.save() + await page.version_save('Deleted page') return res.api({}) } } diff --git a/app/models/VersionedModel.js b/app/models/VersionedModel.js new file mode 100644 index 0000000..58f5640 --- /dev/null +++ b/app/models/VersionedModel.js @@ -0,0 +1,46 @@ +const Model = require('flitter-orm/src/model/Model'); +const uuid = require('uuid/v4'); + +class VersionedModel extends Model { + static get schema() { + return { + version_archive: [Object], + version_num: { type: Number, default: 1 }, + version_create_date: { type: Date, default: () => new Date }, + } + } + + async version_save(message = undefined) { + await this.new_version(message) + return this.save() + } + + async new_version(message = undefined) { + const version_data = await this.cast_to_version_data() + version_data.version_UUID = uuid() + version_data.version_message = message + + if ( !this.version_num ) this.version_num = 1 + if ( !this.version_archive ) this.version_archive = [] + + this.version_num += 1 + this.version_archive.push(version_data) + this.version_create_date = new Date() + } + + async cast_to_version_data() { + const schema = this.constructor.__schema + const shallow_object = {} + for ( const prop in schema.schema ) { + if ( prop in this ) { + shallow_object[prop] = this[prop] + } + } + + const data = await this.__scope_limit_save(schema.cast_to_schema(shallow_object)) + delete data.version_archive + return data + } +} + +module.exports = exports = VersionedModel diff --git a/app/models/api/Page.model.js b/app/models/api/Page.model.js index 5202d16..d04d095 100644 --- a/app/models/api/Page.model.js +++ b/app/models/api/Page.model.js @@ -1,6 +1,6 @@ -const Model = require("flitter-orm/src/model/Model"); -const { ObjectId } = require("mongodb"); -const uuid = require('uuid/v4'); +const VersionedModel = require('../VersionedModel') +const { ObjectId } = require('mongodb') +const uuid = require('uuid/v4') const ActiveScope = require('../scopes/Active.scope') @@ -9,13 +9,14 @@ const ActiveScope = require('../scopes/Active.scope') * ------------------------------------------------------------- * Put some description here! */ -class Page extends Model { +class Page extends VersionedModel { static get services() { - return [...super.services, "models"]; + return [...super.services, 'models']; } static get schema() { // Return a flitter-orm schema here. return { + ...super.schema, UUID: {type: String, default: () => uuid()}, Name: String, OrgUserId: ObjectId, @@ -201,7 +202,8 @@ class Page extends Model { // Add the user to the appropriate access list this[`shared_users_${level}`].push(user._id) - await this.save() + // TODO replace user.uid with name of user when we support that + await this.version_save(`Shared with ${user.uid} (${level} access)`) await user.save() } @@ -217,7 +219,7 @@ class Page extends Model { this.shared_users_update = this.shared_users_update.filter(x => String(x) !== user.id) this.shared_users_manage = this.shared_users_manage.filter(x => String(x) !== user.id) - await this.save() + await this.version_save(`Unshared with ${user.uid}`) await user.save() }