From 52382f6bf76d13abd982f3010bd94a6cd03e33aa Mon Sep 17 00:00:00 2001 From: garrettmills Date: Mon, 2 Nov 2020 20:04:10 -0600 Subject: [PATCH] Add ability to retrieve specific page versions and nodes with ?version=XX param --- app/controllers/api/v1/Page.controller.js | 32 +++++++++--- app/models/VersionedModel.js | 59 +++++++++++++++++++++++ app/models/api/Page.model.js | 29 ++++++++++- 3 files changed, 112 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/v1/Page.controller.js b/app/controllers/api/v1/Page.controller.js index 4fc0709..4d9a393 100644 --- a/app/controllers/api/v1/Page.controller.js +++ b/app/controllers/api/v1/Page.controller.js @@ -12,13 +12,24 @@ class Page extends Controller { const PageId = req.params.PageId const user = req.user - const page = await PageModel.findOne({UUID: PageId}) + let page = await PageModel.findOne({UUID: PageId}) if ( !page ) return res.status(404).message('Page not found with that ID.').api({}) if ( !(await page.is_accessible_by(user)) ) return req.security.deny() - page.level = await page.access_level_for(req.user) + const level = await page.access_level_for(req.user) - return res.api(page) + const version_num = req.body.version || req.query.version + if ( version_num ) { + if ( page.has_version(version_num) ) { + page = await page.as_version(version_num) + } + } + + const data = page.toJSON() + delete data.version_archive + data.level = level + data._id = page.id + return res.api(data) } async save_page(req, res) { @@ -35,7 +46,7 @@ class Page extends Controller { page.OrgUserId = req.user._id } - let save_message = 'Updated page metadata' + let save_message = 'Page contents saved' if ( !req.body.Name ) return res.status(400).message('Missing required: Name').api({}) @@ -84,17 +95,24 @@ class Page extends Controller { if ( !(await page.is_accessible_by(req.user)) ) return req.security.deny() } - const nodes = await Node.find({PageId: page.UUID}); + const version_num = req.body.version || req.query.version + if ( version_num ) { + if ( page.has_version(version_num) ) { + page = await page.as_version(version_num) + } + } + + const nodes = await page.nodes const assoc_nodes = {} nodes.forEach(node => { assoc_nodes[node.UUID] = node }) - const return_nodes = []; + const return_nodes = [] for ( const uuid of page.NodeIds ) { return_nodes.push(assoc_nodes[uuid]) } - return res.api(return_nodes); + return res.api(return_nodes) } async save_node_to_page(req, res) { diff --git a/app/models/VersionedModel.js b/app/models/VersionedModel.js index a9839e1..911773a 100644 --- a/app/models/VersionedModel.js +++ b/app/models/VersionedModel.js @@ -11,6 +11,28 @@ class VersionedModel extends Model { } } + __is_version_instantation = false + __version_base = undefined + __version_data = undefined + + is_a_version() { + return this.__is_version_instantation + } + + version_base() { + return this.__version_base + } + + raw_version_data() { + return this.__version_data + } + + __initialize_version(base, data = {}) { + this.__is_version_instantation = true + this.__version_base = base + this.__version_data = data + } + async version_save(message = undefined, user_id = undefined) { await this.new_version(message, user_id) return this.save() @@ -44,6 +66,43 @@ class VersionedModel extends Model { delete data.version_archive return data } + + async get_version_data(version_num = undefined) { + if ( typeof version_num === 'undefined' ) { + return await this.cast_to_version_data() + } else { + return this.version_archive.find(data => Number(data.version_num) === Number(version_num)) + } + } + + has_version(version_num = undefined) { + return !!this.version_archive.find(data => { + return Number(data.version_num) === Number(version_num) + }) + } + + toJSON() { + const data = {...this} + delete data.__version_data + delete data.__version_base + delete data.__is_version_instantation + delete data.version_archive + + if ( this.is_a_version() ) { + data.version_message = this.__version_data.version_message + data.version_user_id = this.__version_data.version_user_id + } + + return data + } + + async as_version(version_num = undefined) { + const data = await this.get_version_data(version_num) + console.log('as version data', data, version_num) + const inst = new this.constructor(data) + inst.__initialize_version(this, data) + return inst + } } module.exports = exports = VersionedModel diff --git a/app/models/api/Page.model.js b/app/models/api/Page.model.js index 0aac9d2..521d5e3 100644 --- a/app/models/api/Page.model.js +++ b/app/models/api/Page.model.js @@ -115,8 +115,35 @@ class Page extends VersionedModel { get nodes() { const Node = this.models.get("api:Node") - return this.has_many(Node, "NodeIds", "UUID") + const node_promise = this.has_many(Node, "NodeIds", "UUID") + if ( this.is_a_version() ) { + // return the nodes for this version! + return (async () => { + const nodes = await node_promise + const version_data = this.raw_version_data() + const return_nodes = [] + if ( version_data?.node_version_nums ) { + const node_x_version_num = {} + for ( const item of version_data.node_version_nums ) { + node_x_version_num[item.NodeId] = item.version_num + } + + for ( const node of nodes ) { + if ( node_x_version_num[node.UUID] ) { + return_nodes.push(await node.as_version(node_x_version_num[node.UUID])) + } else { + return_nodes.push(node) + } + } + } + + return return_nodes + })() + } else { + return node_promise + } } + get childPages() { const Page = this.models.get("api:Page") return this.has_many(Page, "ChildPageIds", "UUID")