Start /api/v1/offline/sync endpoint
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
33ace4ed46
commit
55a22a4f4c
103
app/FakeRequest.js
Normal file
103
app/FakeRequest.js
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
const { Injectable } = require('flitter-di')
|
||||||
|
const FakeResponse = require('./FakeResponse')
|
||||||
|
|
||||||
|
class FakeRequest extends Injectable {
|
||||||
|
static get services() {
|
||||||
|
return [...super.services, 'models', 'app', 'configs']
|
||||||
|
}
|
||||||
|
|
||||||
|
response = new FakeResponse()
|
||||||
|
|
||||||
|
body = {}
|
||||||
|
session = {}
|
||||||
|
sessionID = undefined
|
||||||
|
user = undefined
|
||||||
|
is_auth = false
|
||||||
|
ip = undefined
|
||||||
|
headers = {}
|
||||||
|
connection = {
|
||||||
|
remoteAddress: undefined,
|
||||||
|
}
|
||||||
|
method = 'get'
|
||||||
|
originalUrl = undefined
|
||||||
|
path = undefined
|
||||||
|
params = {}
|
||||||
|
query = {}
|
||||||
|
xhr = false
|
||||||
|
|
||||||
|
async deflate() {
|
||||||
|
return {
|
||||||
|
body: {...this.body},
|
||||||
|
session_id: this.sessionID,
|
||||||
|
user_id: this.user?.id,
|
||||||
|
is_auth: this.is_auth,
|
||||||
|
ip: this.ip,
|
||||||
|
headers: {...this.headers},
|
||||||
|
remote_addr: this.connection?.remoteAddress,
|
||||||
|
method: this.method,
|
||||||
|
original_url: this.originalUrl,
|
||||||
|
path: this.path,
|
||||||
|
params: {...this.params},
|
||||||
|
query: {...this.query},
|
||||||
|
xhr: this.xhr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static serialize_request(req) {
|
||||||
|
return {
|
||||||
|
body: {...req.body},
|
||||||
|
session_id: req.sessionID,
|
||||||
|
user_id: req.user?.id,
|
||||||
|
is_auth: req.is_auth,
|
||||||
|
ip: req.ip,
|
||||||
|
headers: {...req.headers},
|
||||||
|
remote_addr: req.connection?.remoteAddress,
|
||||||
|
method: req.method,
|
||||||
|
original_url: req.originalUrl,
|
||||||
|
path: req.path,
|
||||||
|
params: {...req.params},
|
||||||
|
query: {...req.query},
|
||||||
|
xhr: req.xhr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async inflate(data) {
|
||||||
|
const User = this.models.get('auth:User')
|
||||||
|
const Session = require('./models/Session')
|
||||||
|
this.app.di().inject(Session)
|
||||||
|
|
||||||
|
this.body = data.body
|
||||||
|
|
||||||
|
this.sessionID = data.session_id || data.sessionID
|
||||||
|
if ( this.sessionID ) {
|
||||||
|
const session = await Session.findOne({ _id: this.sessionID })
|
||||||
|
if ( session ) {
|
||||||
|
this._session_instance = session
|
||||||
|
this.session = session.session
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.user_id = data.user_id || data.user?.id
|
||||||
|
if ( this.user_id ) {
|
||||||
|
const user = await User.findById(this.user_id)
|
||||||
|
if ( user ) {
|
||||||
|
this.user = user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.is_auth = data.is_auth
|
||||||
|
this.ip = data.ip
|
||||||
|
this.headers = {...(data.headers || {})}
|
||||||
|
this.connection = {
|
||||||
|
remoteAddress: data.remote_addr || data.connection?.remoteAddress,
|
||||||
|
}
|
||||||
|
this.method = data.method
|
||||||
|
this.originalUrl = data.original_url || data.originalUrl
|
||||||
|
this.path = data.path
|
||||||
|
this.params = {...(data.params || {})}
|
||||||
|
this.query = {...(data.query || {})}
|
||||||
|
this.xhr = data.xhr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = FakeRequest
|
52
app/FakeResponse.js
Normal file
52
app/FakeResponse.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
const { Injectable } = require('flitter-di')
|
||||||
|
|
||||||
|
class FakeResponse extends Injectable {
|
||||||
|
_message = 'OK'
|
||||||
|
_status = 200
|
||||||
|
_api_data = undefined
|
||||||
|
_send_data = undefined
|
||||||
|
_view = undefined
|
||||||
|
_view_data = undefined
|
||||||
|
|
||||||
|
status(set = undefined) {
|
||||||
|
if ( set ) {
|
||||||
|
this._status = set
|
||||||
|
return this
|
||||||
|
} else {
|
||||||
|
return this._status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message(set = undefined) {
|
||||||
|
if ( set ) {
|
||||||
|
this._message = set
|
||||||
|
return this
|
||||||
|
} else {
|
||||||
|
return this._message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
api(data = {}) {
|
||||||
|
this._api_data = data
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
send(data = '') {
|
||||||
|
this._send_data = ''
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
view(name, data = {}) {
|
||||||
|
this._view = name
|
||||||
|
this._view_data = data
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
page(name, data = {}) {
|
||||||
|
this._view = name
|
||||||
|
this._view_data = data
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = FakeResponse
|
@ -28,6 +28,21 @@ class FormCode extends Controller {
|
|||||||
code: '',
|
code: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if ( req.body.Language ) {
|
||||||
|
code.Language = req.body.Language
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( req.body.code ) {
|
||||||
|
code.code = req.body.code
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( req.body.UUID ) {
|
||||||
|
const existingUUID = await Codium.findOne({ UUID: req.body.UUID })
|
||||||
|
if ( !existingUUID ) {
|
||||||
|
code.UUID = req.body.UUID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await code.save()
|
await code.save()
|
||||||
return res.api(code)
|
return res.api(code)
|
||||||
}
|
}
|
||||||
|
223
app/controllers/api/v1/Offline.controller.js
Normal file
223
app/controllers/api/v1/Offline.controller.js
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
const { Controller } = require('libflitter')
|
||||||
|
const FakeRequest = require('../../../FakeRequest')
|
||||||
|
|
||||||
|
class OfflineController extends Controller {
|
||||||
|
static get services() {
|
||||||
|
return [...super.services, 'models', 'controllers', 'app']
|
||||||
|
}
|
||||||
|
|
||||||
|
async do_sync(req, res, next) {
|
||||||
|
// TODO account for modify date to not overwrite more recent data!!
|
||||||
|
|
||||||
|
const OfflineDataSync = this.models.get('api:OfflineDataSync')
|
||||||
|
const record = await OfflineDataSync.from_request(req)
|
||||||
|
|
||||||
|
console.log('sync data', record)
|
||||||
|
|
||||||
|
const return_maps = {}
|
||||||
|
|
||||||
|
// pages
|
||||||
|
if ( Array.isArray(record.pages) ) {
|
||||||
|
return_maps.pages = await this.do_sync_pages(req, record.pages)
|
||||||
|
}
|
||||||
|
|
||||||
|
// pageNodes
|
||||||
|
if ( Array.isArray(record.pageNodes) ) {
|
||||||
|
return_maps.pageNodes = await this.do_sync_page_nodes(req, record.pageNodes, record.pages)
|
||||||
|
}
|
||||||
|
|
||||||
|
// codiums
|
||||||
|
if ( Array.isArray(record.codiums) ) {
|
||||||
|
return_maps.codiums = await this.do_sync_codiums(req, record.codiums)
|
||||||
|
}
|
||||||
|
|
||||||
|
// databases
|
||||||
|
// databaseColumns
|
||||||
|
// databaseEntries
|
||||||
|
// fileGroups
|
||||||
|
|
||||||
|
return res.api(return_maps)
|
||||||
|
}
|
||||||
|
|
||||||
|
async do_sync_codiums(req, codium_recs) {
|
||||||
|
const FormCodeController = this.controllers.get('api:v1:FormCode')
|
||||||
|
const Codium = this.models.get('api:Codium')
|
||||||
|
|
||||||
|
const uuid_mapping = {}
|
||||||
|
|
||||||
|
for ( const rec of codium_recs ) {
|
||||||
|
const existing_code = await Codium.findOne({ UUID: rec.UUID })
|
||||||
|
|
||||||
|
const fake_req = this.app.di().make(FakeRequest)
|
||||||
|
await fake_req.inflate(req)
|
||||||
|
fake_req.params = { PageId: rec.PageId, NodeId: rec.NodeId, CodiumId: rec.UUID }
|
||||||
|
fake_req.body = rec
|
||||||
|
|
||||||
|
if ( !existing_code && !rec.deleted ) {
|
||||||
|
// This was created on the client side
|
||||||
|
await FormCodeController.create_new(fake_req, fake_req.response)
|
||||||
|
uuid_mapping[rec.UUID] = fake_req.response?._api_data?.UUID
|
||||||
|
} else {
|
||||||
|
if ( rec.deleted ) {
|
||||||
|
// The code was deleted
|
||||||
|
await FormCodeController.drop_code(fake_req, fake_req.response)
|
||||||
|
uuid_mapping[rec.UUID] = false
|
||||||
|
} else {
|
||||||
|
// The code was updated
|
||||||
|
await FormCodeController.set_values(fake_req, fake_req.response)
|
||||||
|
uuid_mapping[rec.UUID] = fake_req.response?._api_data?.UUID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return uuid_mapping
|
||||||
|
}
|
||||||
|
|
||||||
|
async do_sync_page_nodes(req, page_node_recs, page_recs) {
|
||||||
|
const PageController = this.controllers.get('api:v1:Page')
|
||||||
|
const PageModel = this.models.get('api:Page')
|
||||||
|
const NodeModel = this.models.get('api:Node')
|
||||||
|
|
||||||
|
const page_id_x_page = {}
|
||||||
|
for ( const page of page_recs ) {
|
||||||
|
page_id_x_page[page.UUID] = page
|
||||||
|
}
|
||||||
|
|
||||||
|
const uuid_mapping = {}
|
||||||
|
|
||||||
|
for ( const rec of page_node_recs ) {
|
||||||
|
rec.Value = rec.ValueJSON ? JSON.parse(rec.ValueJSON) : {}
|
||||||
|
|
||||||
|
const existing_node = await NodeModel.findOne({ UUID: rec.UUID })
|
||||||
|
const offline_page = page_id_x_page[rec.PageId]
|
||||||
|
let online_page = await PageModel.findOne({ UUID: rec.PageId })
|
||||||
|
|
||||||
|
if ( existing_node && rec.deleted ) {
|
||||||
|
// node that exists on the server was deleted
|
||||||
|
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 existing_node.delete()
|
||||||
|
uuid_mapping[rec.UUID] = false
|
||||||
|
} else if ( existing_node ) {
|
||||||
|
// if the node exists, we assume it's already in a page structure
|
||||||
|
// update the server-side record if the user can access it
|
||||||
|
if ( await online_page.is_accessible_by(req.user, 'edit') ) {
|
||||||
|
existing_node.Type = rec.Type
|
||||||
|
existing_node.Value = rec.Value
|
||||||
|
existing_node.UpdatedAt = new Date(rec.UpdatedAt)
|
||||||
|
existing_node.UpdateUserId = req.user.id
|
||||||
|
|
||||||
|
await existing_node.save()
|
||||||
|
uuid_mapping[rec.UUID] = existing_node.UUID
|
||||||
|
}
|
||||||
|
} else if ( !existing_node && online_page && !rec.deleted ) {
|
||||||
|
// the node was created offline
|
||||||
|
// first, save the node to the page
|
||||||
|
const fake_req = this.app.di().make(FakeRequest)
|
||||||
|
await fake_req.inflate(req)
|
||||||
|
fake_req.params = { PageId: online_page.UUID }
|
||||||
|
fake_req.body = { nodeData: {...rec} }
|
||||||
|
|
||||||
|
await PageController.save_node_to_page(fake_req, fake_req.response)
|
||||||
|
const new_uuid = uuid_mapping[rec.UUID] = fake_req.response?._api_data?.UUID
|
||||||
|
online_page = await PageModel.findOne({ UUID: rec.PageId }) // to refresh the model's data
|
||||||
|
|
||||||
|
// now, try to place the node in the correct spot
|
||||||
|
// if first in offline page, make first in online page
|
||||||
|
if ( Array.isArray(offline_page?.NodeIds) && offline_page.NodeIds[0] === rec.UUID ) {
|
||||||
|
online_page.NodeIds = [new_uuid, ...online_page.NodeIds.filter(x => x !== new_uuid && x !== rec.UUID)]
|
||||||
|
} else if ( Array.isArray(offline_page?.NodeIds) && offline_page.NodeIds.includes(rec.UUID) ) {
|
||||||
|
if ( offline_page.NodeIds.slice(-1)[0] !== rec.UUID ) {
|
||||||
|
// We're not first, and we're not last, so try to place in the correct spot
|
||||||
|
const index = offline_page.NodeIds.findIndex(x => x.UUID === rec.UUID)
|
||||||
|
let predecessor = undefined
|
||||||
|
let index_diff = 1
|
||||||
|
|
||||||
|
while ( !predecessor && (index - index_diff) >= 0 ) {
|
||||||
|
const maybe_predecessor = offline_page.NodeIds[index - index_diff]
|
||||||
|
if ( online_page.NodeIds.includes(maybe_predecessor) ) {
|
||||||
|
predecessor = maybe_predecessor
|
||||||
|
} else {
|
||||||
|
index_diff += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( predecessor ) {
|
||||||
|
// We found the predecessor to insert the child in the existing node
|
||||||
|
const newNodeIds = []
|
||||||
|
online_page.NodeIds.forEach(uuid => {
|
||||||
|
newNodeIds.push(uuid)
|
||||||
|
if ( uuid === predecessor ) {
|
||||||
|
newNodeIds.push(new_uuid)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
online_page.NodeIds = newNodeIds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await online_page.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
// assuming the pages were created first, we should never have a case
|
||||||
|
// where we have !existing_node && !online_page
|
||||||
|
}
|
||||||
|
|
||||||
|
return uuid_mapping
|
||||||
|
}
|
||||||
|
|
||||||
|
async do_sync_pages(req, page_recs) {
|
||||||
|
// TODO order pages by create date to prevent child-before-parent errors
|
||||||
|
const PageController = this.controllers.get('api:v1:Page')
|
||||||
|
const PageModel = this.models.get('api:Page')
|
||||||
|
|
||||||
|
const uuid_mapping = {}
|
||||||
|
|
||||||
|
for ( const rec of page_recs ) {
|
||||||
|
const UUID = rec.UUID
|
||||||
|
if ( !UUID ) continue;
|
||||||
|
|
||||||
|
const existing_page = await PageModel.findOne({ UUID })
|
||||||
|
const fake_req = this.app.di().make(FakeRequest)
|
||||||
|
await fake_req.inflate(req)
|
||||||
|
fake_req.body = {...rec}
|
||||||
|
|
||||||
|
if ( !existing_page && !rec.deleted ) {
|
||||||
|
// create the new page
|
||||||
|
if ( parseInt(rec.ParentId) === 0 ) {
|
||||||
|
// Create a new top-level page
|
||||||
|
fake_req.body.omit_starter = true
|
||||||
|
fake_req.body.name = rec.Name
|
||||||
|
await PageController.create_top_level(fake_req, fake_req.response)
|
||||||
|
} else {
|
||||||
|
// Create a new child page
|
||||||
|
fake_req.body.omit_starter = true
|
||||||
|
fake_req.body.name = rec.Name
|
||||||
|
fake_req.body.parentId = rec.ParentId
|
||||||
|
await PageController.create_child(fake_req, fake_req.response)
|
||||||
|
}
|
||||||
|
} else if ( existing_page ) {
|
||||||
|
fake_req.params = { PageId: rec.UUID }
|
||||||
|
|
||||||
|
if ( rec.deleted ) {
|
||||||
|
// The page was deleted on the client
|
||||||
|
await PageController.delete_page(fake_req, fake_req.response)
|
||||||
|
} else {
|
||||||
|
// update an existing page
|
||||||
|
await PageController.save_page(fake_req, fake_req.response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uuid_mapping[rec.UUID] = fake_req.response?._api_data?.UUID || false
|
||||||
|
}
|
||||||
|
|
||||||
|
return uuid_mapping
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = OfflineController
|
@ -28,7 +28,7 @@ class Page extends Controller {
|
|||||||
if ( PageId ) {
|
if ( PageId ) {
|
||||||
page = await PageModel.findOne({UUID: PageId})
|
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(req.user, 'update')) ) return req.security.deny()
|
if ( !(await page.is_accessible_by(req.user, 'update')) ) return res.security.deny()
|
||||||
} else {
|
} else {
|
||||||
page = new PageModel
|
page = new PageModel
|
||||||
page.CreatedUserId = req.user.id
|
page.CreatedUserId = req.user.id
|
||||||
@ -89,7 +89,7 @@ class Page extends Controller {
|
|||||||
|
|
||||||
const page = await PageModel.findOne({UUID: PageId})
|
const 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(req.user, 'update')) ) return req.security.deny()
|
if ( !(await page.is_accessible_by(req.user, 'update')) ) return res.security.deny()
|
||||||
|
|
||||||
const nodes = await Node.find({PageId: page.UUID})
|
const nodes = await Node.find({PageId: page.UUID})
|
||||||
const assoc_nodes = {}
|
const assoc_nodes = {}
|
||||||
@ -116,6 +116,14 @@ class Page extends Controller {
|
|||||||
CreatedUserId: req.user._id,
|
CreatedUserId: req.user._id,
|
||||||
UpdateUserId: req.user._id,
|
UpdateUserId: req.user._id,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if ( node.UUID ) {
|
||||||
|
const existingUUID = await Node.findOne({ UUID: node.UUID })
|
||||||
|
if ( !existingUUID ) {
|
||||||
|
node_obj.UUID = node.UUID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await node_obj.save()
|
await node_obj.save()
|
||||||
|
|
||||||
page.NodeIds.push(node_obj.UUID);
|
page.NodeIds.push(node_obj.UUID);
|
||||||
@ -208,6 +216,13 @@ class Page extends Controller {
|
|||||||
UpdateUserId: req.user.id
|
UpdateUserId: req.user.id
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if ( req.body.UUID ) {
|
||||||
|
const existingUUID = await PageModel.findOne({UUID: req.body.UUID})
|
||||||
|
if ( !existingUUID ) {
|
||||||
|
new_page.UUID = req.body.UUID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await new_page.save()
|
await new_page.save()
|
||||||
|
|
||||||
root_page.ChildPageIds.push(new_page.UUID)
|
root_page.ChildPageIds.push(new_page.UUID)
|
||||||
@ -216,19 +231,21 @@ class Page extends Controller {
|
|||||||
req.user.allow(`page:${new_page.UUID}`)
|
req.user.allow(`page:${new_page.UUID}`)
|
||||||
await req.user.save()
|
await req.user.save()
|
||||||
|
|
||||||
const starter_node = new Node({
|
if ( !req.body.omit_starter ) {
|
||||||
Type: 'paragraph',
|
const starter_node = new Node({
|
||||||
Value: {
|
Type: 'paragraph',
|
||||||
Value: 'Click to edit...',
|
Value: {
|
||||||
},
|
Value: 'Double-click to edit...',
|
||||||
PageId: new_page.UUID,
|
},
|
||||||
CreatedUserId: req.user.id,
|
PageId: new_page.UUID,
|
||||||
UpdateUserId: req.user.id
|
CreatedUserId: req.user.id,
|
||||||
})
|
UpdateUserId: req.user.id
|
||||||
|
})
|
||||||
|
|
||||||
await starter_node.save()
|
await starter_node.save()
|
||||||
new_page.NodeIds.push(starter_node.UUID)
|
new_page.NodeIds.push(starter_node.UUID)
|
||||||
await new_page.save()
|
await new_page.save()
|
||||||
|
}
|
||||||
|
|
||||||
return res.api(new_page)
|
return res.api(new_page)
|
||||||
}
|
}
|
||||||
@ -258,6 +275,13 @@ class Page extends Controller {
|
|||||||
UpdateUserId: req.user.id,
|
UpdateUserId: req.user.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if ( req.body.UUID ) {
|
||||||
|
const existingUUID = await PageModel.findOne({UUID: req.body.UUID})
|
||||||
|
if ( !existingUUID ) {
|
||||||
|
new_page.UUID = req.body.UUID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await new_page.save()
|
await new_page.save()
|
||||||
|
|
||||||
parent.ChildPageIds.push(new_page.UUID)
|
parent.ChildPageIds.push(new_page.UUID)
|
||||||
@ -266,19 +290,21 @@ class Page extends Controller {
|
|||||||
req.user.allow(`page:${new_page.UUID}`)
|
req.user.allow(`page:${new_page.UUID}`)
|
||||||
await req.user.save()
|
await req.user.save()
|
||||||
|
|
||||||
const starter_node = new Node({
|
if ( !req.body.omit_starter ) {
|
||||||
Type: 'paragraph',
|
const starter_node = new Node({
|
||||||
Value: {
|
Type: 'paragraph',
|
||||||
Value: 'Click to edit...',
|
Value: {
|
||||||
},
|
Value: 'Click to edit...',
|
||||||
PageId: new_page.UUID,
|
},
|
||||||
CreatedUserId: req.user.id,
|
PageId: new_page.UUID,
|
||||||
UpdateUserId: req.user.id
|
CreatedUserId: req.user.id,
|
||||||
})
|
UpdateUserId: req.user.id
|
||||||
|
})
|
||||||
|
|
||||||
await starter_node.save()
|
await starter_node.save()
|
||||||
new_page.NodeIds.push(starter_node.UUID)
|
new_page.NodeIds.push(starter_node.UUID)
|
||||||
await new_page.save()
|
await new_page.save()
|
||||||
|
}
|
||||||
|
|
||||||
return res.api(new_page)
|
return res.api(new_page)
|
||||||
}
|
}
|
||||||
|
13
app/models/Session.js
Normal file
13
app/models/Session.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
const { Model } = require('flitter-orm')
|
||||||
|
|
||||||
|
class SessionModel extends Model {
|
||||||
|
static collection = 'flitter_sessions'
|
||||||
|
static get schema() {
|
||||||
|
return {
|
||||||
|
expires: Date,
|
||||||
|
session: Object,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = SessionModel
|
37
app/models/api/OfflineDataSync.model.js
Normal file
37
app/models/api/OfflineDataSync.model.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
const { Model } = require('flitter-orm')
|
||||||
|
const uuid = require('uuid/v4')
|
||||||
|
|
||||||
|
class OfflineDataSyncModel extends Model {
|
||||||
|
static get schema() {
|
||||||
|
return {
|
||||||
|
user_id: String,
|
||||||
|
sync_timestamp: { type: Date, default: () => new Date() },
|
||||||
|
UUID: { type: String, default: uuid },
|
||||||
|
codiums: [Object],
|
||||||
|
database: [Object],
|
||||||
|
databaseColumns: [Object],
|
||||||
|
databaseEntries: [Object],
|
||||||
|
fileGroups: [Object],
|
||||||
|
pages: [Object],
|
||||||
|
pageNodes: [Object],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async from_request(req) {
|
||||||
|
const rec = new this({
|
||||||
|
user_id: req.user.id,
|
||||||
|
codiums: req.body?.dirtyRecords.codiums,
|
||||||
|
database: req.body?.dirtyRecords.database,
|
||||||
|
databaseColumns: req.body?.dirtyRecords.databaseColumns,
|
||||||
|
databaseEntries: req.body?.dirtyRecords.databaseEntries,
|
||||||
|
fileGroups: req.body?.dirtyRecords.fileGroups,
|
||||||
|
pages: req.body?.dirtyRecords.pages,
|
||||||
|
pageNodes: req.body?.dirtyRecords.pageNodes,
|
||||||
|
})
|
||||||
|
|
||||||
|
await rec.save()
|
||||||
|
return rec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = OfflineDataSyncModel
|
@ -99,6 +99,9 @@ const index = {
|
|||||||
|
|
||||||
// delete the specified code ref
|
// delete the specified code ref
|
||||||
'/code/:PageId/:NodeId/delete/:CodiumId': ['controller::api:v1:FormCode.drop_code'],
|
'/code/:PageId/:NodeId/delete/:CodiumId': ['controller::api:v1:FormCode.drop_code'],
|
||||||
|
|
||||||
|
// re-sync data when an offline client goes back online
|
||||||
|
'/offline/sync': ['controller::api:v1:Offline.do_sync'],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user