From dffb3d9efac406d0c1ac10e1004c47345c1c0760 Mon Sep 17 00:00:00 2001 From: garrettmills Date: Fri, 30 Oct 2020 21:59:42 -0500 Subject: [PATCH] Finish basic offline sync logic --- app/controllers/api/v1/File.controller.js | 7 + .../api/v1/FormDatabase.controller.js | 16 ++- app/controllers/api/v1/Offline.controller.js | 126 +++++++++++++++++- app/models/api/OfflineDataSync.model.js | 4 +- 4 files changed, 147 insertions(+), 6 deletions(-) diff --git a/app/controllers/api/v1/File.controller.js b/app/controllers/api/v1/File.controller.js index 9738b74..d66251d 100644 --- a/app/controllers/api/v1/File.controller.js +++ b/app/controllers/api/v1/File.controller.js @@ -32,6 +32,13 @@ class File extends Controller { FileIds: [], }) + if ( req.body.UUID ) { + const existingUUID = await FileGroup.findOne({ UUID: req.body.UUID }) + if ( !existingUUID ) { + group.UUID = req.body.UUID + } + } + await group.save() req.user.allow(`files:${group.UUID}`) await req.user.save() diff --git a/app/controllers/api/v1/FormDatabase.controller.js b/app/controllers/api/v1/FormDatabase.controller.js index ec97edc..490db3d 100644 --- a/app/controllers/api/v1/FormDatabase.controller.js +++ b/app/controllers/api/v1/FormDatabase.controller.js @@ -25,11 +25,18 @@ class FormDatabase extends Controller { if ( !node ) return res.status(404).message('Node not found with that ID.').api({}) const db = new Database({ - Name: req.body.name ? req.body.name : 'New Database', + Name: req.body.name || req.body.Name || 'New Database', NodeId: node.UUID, PageId: page.UUID, }) + if ( req.body.UUID ) { + const existingUUID = await Database.findOne({ UUID: req.body.UUID }) + if ( !existingUUID ) { + db.UUID = req.body.UUID + } + } + await db.save() req.user.allow(`database:${db.UUID}`); @@ -162,6 +169,13 @@ class FormDatabase extends Controller { additionalData: JSON.stringify(col.additionalData), }) + if ( col.UUID ) { + const existingUUID = await ColumnDef.findOne({ UUID: col.UUID }) + if ( !existingUUID ) { + new_col.UUID = col.UUID + } + } + await new_col.save() update_columns.push(new_col) } diff --git a/app/controllers/api/v1/Offline.controller.js b/app/controllers/api/v1/Offline.controller.js index de0c8f7..ffb5c8f 100644 --- a/app/controllers/api/v1/Offline.controller.js +++ b/app/controllers/api/v1/Offline.controller.js @@ -52,9 +52,6 @@ class OfflineController extends Controller { const OfflineDataSync = this.models.get('api:OfflineDataSync') const record = await OfflineDataSync.from_request(req) - - console.log('sync data', record) - const return_maps = {} // pages @@ -73,13 +70,136 @@ class OfflineController extends Controller { } // databases + if ( Array.isArray(record.databases) ) { + return_maps.databases = await this.do_sync_databases(req, record.databases) + } + // databaseColumns + if ( Array.isArray(record.databaseColumns) ) { + return_maps.databaseColumns = await this.do_sync_database_columns(req, record.databases, record.databaseColumns) + } + // databaseEntries + if ( Array.isArray(record.databaseEntries) ) { + return_maps.databaseEntries = await this.do_sync_database_entries(req, record.databases, record.databaseEntries) + } + // fileGroups + if ( Array.isArray(record.fileGroups) ) { + return_maps.fileGroups = await this.do_sync_file_groups(req, record.fileGroups) + } return res.api(return_maps) } + async do_sync_file_groups(req, file_recs) { + const FileController = this.controllers.get('api:v1:File') + const FileGroup = this.models.get('api:FileGroup') + + const uuid_mapping = {} + + for ( const rec of file_recs ) { + const existing_rec = await FileGroup.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, FilesId: rec.UUID } + fake_req.body = rec + + if ( existing_rec && rec.deleted ) { + await FileController.delete_group(fake_req, fake_req.response) + uuid_mapping[rec.UUID] = false + } else if ( !existing_rec ) { + await FileController.create_config(fake_req, fake_req.response) + uuid_mapping[rec.UUID] = fake_req.response?._api_data?.UUID + } + + // Currently, there's no reason to update a file group, since they have no internal metadata + } + + return uuid_mapping + } + + async do_sync_database_entries(req, database_recs, database_row_recs) { + const FormDatabaseController = this.controllers.get('api:v1:FormDatabase') + + const uuid_mapping = {} + + for ( const rec of database_recs ) { + const entries = database_row_recs.filter(x => !x.deleted && x.DatabaseId === rec.UUID) + + const fake_req = this.app.di().make(FakeRequest) + await fake_req.inflate(req) + fake_req.params = { PageId: rec.PageId, NodeId: rec.NodeId, DatabaseId: rec.UUID } + fake_req.body = entries.map(x => JSON.parse(x.RowDataJSON || '{}')) + + await FormDatabaseController.set_data(fake_req, fake_req.response) + + entries.forEach((rec, i) => { + uuid_mapping[rec.UUID] = fake_req.response?._api_data?.[i]?.UUID + }) + } + + return uuid_mapping + } + + async do_sync_database_columns(req, database_recs, database_col_recs) { + const FormDatabaseController = this.controllers.get('api:v1:FormDatabase') + + const uuid_mapping = {} + + for ( const rec of database_recs ) { + const col_recs = database_col_recs.filter(x => rec.ColumnIds.includes(x.UUID) && !x.deleted) + + const fake_req = this.app.di().make(FakeRequest) + await fake_req.inflate(req) + fake_req.params = { PageId: rec.PageId, NodeId: rec.NodeId, DatabaseId: rec.UUID } + fake_req.body = { columns: col_recs } + + await FormDatabaseController.set_columns(fake_req, fake_req.response) + + col_recs.forEach((rec, i) => { + uuid_mapping[rec.UUID] = fake_req.response?._api_data?.[i]?.UUID + }) + } + + return uuid_mapping + } + + async do_sync_databases(req, database_recs) { + const FormDatabaseController = this.controllers.get('api:v1:FormDatabase') + const Database = this.models.get('api:db:Database') + + const uuid_mapping = {} + + for ( const rec of database_recs ) { + const existing_db = await Database.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, DatabaseId: rec.UUID } + fake_req.body = rec + + if ( !existing_db && !rec.deleted ) { + // this was created on the client side + await FormDatabaseController.create_new(fake_req, fake_req.response) + uuid_mapping[rec.UUID] = fake_req.response?._api_data?.UUID + } else { + if ( rec.deleted ) { + // the database was deleted + await FormDatabaseController.drop_database(fake_req, fake_req.response) + uuid_mapping[rec.UUID] = false + } else { + // the database was updated + await FormDatabaseController.set_name(fake_req, fake_req.response) + uuid_mapping[rec.UUID] = fake_req.response?._api_data?.UUID + } + } + } + + return uuid_mapping + } + async do_sync_codiums(req, codium_recs) { const FormCodeController = this.controllers.get('api:v1:FormCode') const Codium = this.models.get('api:Codium') diff --git a/app/models/api/OfflineDataSync.model.js b/app/models/api/OfflineDataSync.model.js index 609fa1c..0227726 100644 --- a/app/models/api/OfflineDataSync.model.js +++ b/app/models/api/OfflineDataSync.model.js @@ -8,7 +8,7 @@ class OfflineDataSyncModel extends Model { sync_timestamp: { type: Date, default: () => new Date() }, UUID: { type: String, default: uuid }, codiums: [Object], - database: [Object], + databases: [Object], databaseColumns: [Object], databaseEntries: [Object], fileGroups: [Object], @@ -21,7 +21,7 @@ class OfflineDataSyncModel extends Model { const rec = new this({ user_id: req.user.id, codiums: req.body?.dirtyRecords.codiums, - database: req.body?.dirtyRecords.database, + databases: req.body?.dirtyRecords.databases, databaseColumns: req.body?.dirtyRecords.databaseColumns, databaseEntries: req.body?.dirtyRecords.databaseEntries, fileGroups: req.body?.dirtyRecords.fileGroups,