Add ability to retrieve specific page versions and nodes with ?version=XX param
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Garrett Mills 2020-11-02 20:04:10 -06:00
parent 14babd5b8b
commit 52382f6bf7
Signed by: garrettmills
GPG Key ID: D2BF5FBA8298F246
3 changed files with 112 additions and 8 deletions

View File

@ -12,13 +12,24 @@ class Page extends Controller {
const PageId = req.params.PageId const PageId = req.params.PageId
const user = req.user 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 ( !page ) return res.status(404).message('Page not found with that ID.').api({})
if ( !(await page.is_accessible_by(user)) ) return req.security.deny() 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) { async save_page(req, res) {
@ -35,7 +46,7 @@ class Page extends Controller {
page.OrgUserId = req.user._id 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({}) 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() 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 = {} const assoc_nodes = {}
nodes.forEach(node => { nodes.forEach(node => {
assoc_nodes[node.UUID] = node assoc_nodes[node.UUID] = node
}) })
const return_nodes = []; const return_nodes = []
for ( const uuid of page.NodeIds ) { for ( const uuid of page.NodeIds ) {
return_nodes.push(assoc_nodes[uuid]) return_nodes.push(assoc_nodes[uuid])
} }
return res.api(return_nodes); return res.api(return_nodes)
} }
async save_node_to_page(req, res) { async save_node_to_page(req, res) {

View File

@ -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) { async version_save(message = undefined, user_id = undefined) {
await this.new_version(message, user_id) await this.new_version(message, user_id)
return this.save() return this.save()
@ -44,6 +66,43 @@ class VersionedModel extends Model {
delete data.version_archive delete data.version_archive
return data 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 module.exports = exports = VersionedModel

View File

@ -115,8 +115,35 @@ class Page extends VersionedModel {
get nodes() { get nodes() {
const Node = this.models.get("api:Node") 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() { get childPages() {
const Page = this.models.get("api:Page") const Page = this.models.get("api:Page")
return this.has_many(Page, "ChildPageIds", "UUID") return this.has_many(Page, "ChildPageIds", "UUID")