diff --git a/app/assets/javascripts/app/frontend/controllers/editor.js b/app/assets/javascripts/app/frontend/controllers/editor.js index a53a5cb98..0b2d02b9a 100644 --- a/app/assets/javascripts/app/frontend/controllers/editor.js +++ b/app/assets/javascripts/app/frontend/controllers/editor.js @@ -37,7 +37,7 @@ angular.module('app.frontend') } } }) - .controller('EditorCtrl', function ($scope, $sce, $timeout, authManager, $rootScope, extensionManager, syncManager, modelManager, editorManager, themeManager, componentManager) { + .controller('EditorCtrl', function ($sce, $timeout, authManager, $rootScope, extensionManager, syncManager, modelManager, editorManager, themeManager, componentManager) { this.componentManager = componentManager; this.componentStack = []; diff --git a/app/assets/javascripts/app/frontend/models/api/item.js b/app/assets/javascripts/app/frontend/models/api/item.js index d2658c3b5..2b333748b 100644 --- a/app/assets/javascripts/app/frontend/models/api/item.js +++ b/app/assets/javascripts/app/frontend/models/api/item.js @@ -113,7 +113,7 @@ class Item { this.setDirty(true); } - locallyClearAllReferences() { + removeReferencesNotPresentIn(references) { } diff --git a/app/assets/javascripts/app/frontend/models/app/editor.js b/app/assets/javascripts/app/frontend/models/app/editor.js index 0a38c20bc..39a152147 100644 --- a/app/assets/javascripts/app/frontend/models/app/editor.js +++ b/app/assets/javascripts/app/frontend/models/app/editor.js @@ -61,9 +61,15 @@ class Editor extends Item { this.notes = []; } - locallyClearAllReferences() { - super.locallyClearAllReferences(); - this.notes = []; + removeReferencesNotPresentIn(references) { + super.removeReferencesNotPresentIn(references); + + var uuids = references.map(function(ref){return ref.uuid}); + this.notes.forEach(function(note){ + if(!uuids.includes(note.uuid)) { + _.pull(this.notes, note); + } + }.bind(this)) } potentialItemOfInterestHasChangedItsUUID(newItem, oldUUID, newUUID) { diff --git a/app/assets/javascripts/app/frontend/models/app/note.js b/app/assets/javascripts/app/frontend/models/app/note.js index 4e0da8d2c..db8f69a9c 100644 --- a/app/assets/javascripts/app/frontend/models/app/note.js +++ b/app/assets/javascripts/app/frontend/models/app/note.js @@ -56,12 +56,16 @@ class Note extends Item { this.tags = []; } - locallyClearAllReferences() { - super.locallyClearAllReferences(); + removeReferencesNotPresentIn(references) { + super.removeReferencesNotPresentIn(references); + + var uuids = references.map(function(ref){return ref.uuid}); this.tags.forEach(function(tag){ - _.pull(tag.notes, this); + if(!uuids.includes(tag.uuid)) { + _.pull(tag.notes, this); + _.pull(this.tags, tag); + } }.bind(this)) - this.tags = []; } isBeingRemovedLocally() { diff --git a/app/assets/javascripts/app/frontend/models/app/tag.js b/app/assets/javascripts/app/frontend/models/app/tag.js index 85b84c739..11cdcf6a0 100644 --- a/app/assets/javascripts/app/frontend/models/app/tag.js +++ b/app/assets/javascripts/app/frontend/models/app/tag.js @@ -55,13 +55,14 @@ class Tag extends Item { this.notes = []; } - locallyClearAllReferences() { - super.locallyClearAllReferences(); + removeReferencesNotPresentIn(references) { + var uuids = references.map(function(ref){return ref.uuid}); this.notes.forEach(function(note){ - _.pull(note.tags, this); + if(!uuids.includes(note.uuid)) { + _.pull(note.tags, this); + _.pull(this.notes, note); + } }.bind(this)) - - this.notes = []; } isBeingRemovedLocally() { diff --git a/app/assets/javascripts/app/services/modelManager.js b/app/assets/javascripts/app/services/modelManager.js index 6ddc1ac4f..c13272d64 100644 --- a/app/assets/javascripts/app/services/modelManager.js +++ b/app/assets/javascripts/app/services/modelManager.js @@ -198,20 +198,24 @@ class ModelManager { } resolveReferencesForItem(item) { - item.locallyClearAllReferences(); + var contentObject = item.contentObject; + + // If another client removes an item's references, this client won't pick up the removal unless + // we remove everything not present in the current list of references + item.removeReferencesNotPresentIn(contentObject.references); + if(!contentObject.references) { return; } - for(var reference of contentObject.references) { var referencedItem = this.findItem(reference.uuid); if(referencedItem) { item.addItemAsRelationship(referencedItem); referencedItem.addItemAsRelationship(item); } else { - // console.log("Unable to find item:", reference.uuid); + // console.log("Unable to find reference:", reference.uuid, "for item:", item); } } } diff --git a/app/assets/javascripts/app/services/syncManager.js b/app/assets/javascripts/app/services/syncManager.js index 01636771a..396a06825 100644 --- a/app/assets/javascripts/app/services/syncManager.js +++ b/app/assets/javascripts/app/services/syncManager.js @@ -187,6 +187,13 @@ class SyncManager { this.syncStatus.current = 0; } + // when doing a sync request that returns items greater than the limit, and thus subsequent syncs are required, + // we want to keep track of all retreived items, then save to local storage only once all items have been retrieved, + // so that relationships remain intact + if(!this.allRetreivedItems) { + this.allRetreivedItems = []; + } + var params = {}; params.limit = 150; params.items = _.map(subItems, function(item){ @@ -209,6 +216,7 @@ class SyncManager { this.$rootScope.$broadcast("sync:updated_token", this.syncToken); var retrieved = this.handleItemsResponse(response.retrieved_items, null); + this.allRetreivedItems = this.allRetreivedItems.concat(retrieved); // merge only metadata for saved items // we write saved items to disk now because it clears their dirty status then saves @@ -218,7 +226,6 @@ class SyncManager { this.handleUnsavedItemsResponse(response.unsaved) this.writeItemsToLocalStorage(saved, false, null); - this.writeItemsToLocalStorage(retrieved, false, null); this.syncStatus.syncOpInProgress = false; this.syncStatus.current += subItems.length; @@ -239,6 +246,9 @@ class SyncManager { this.sync(callback, options); }.bind(this), 10); // wait 10ms to allow UI to update } else { + this.writeItemsToLocalStorage(this.allRetreivedItems, false, null); + this.allRetreivedItems = []; + this.callQueuedCallbacksAndCurrent(callback, response); this.$rootScope.$broadcast("sync:completed"); }