diff --git a/app/assets/javascripts/app/controllers/home.js b/app/assets/javascripts/app/controllers/home.js index 6f626bd0d..4f84d647a 100644 --- a/app/assets/javascripts/app/controllers/home.js +++ b/app/assets/javascripts/app/controllers/home.js @@ -84,7 +84,7 @@ angular.module('app') } }); - syncManager.setEventHandler((syncEvent, data) => { + syncManager.addEventHandler((syncEvent, data) => { $rootScope.$broadcast(syncEvent, data || {}); }); diff --git a/app/assets/javascripts/app/directives/views/componentView.js b/app/assets/javascripts/app/directives/views/componentView.js index 61b8d98a2..b201c60a2 100644 --- a/app/assets/javascripts/app/directives/views/componentView.js +++ b/app/assets/javascripts/app/directives/views/componentView.js @@ -97,9 +97,9 @@ class ComponentView { offlineRestricted = component.offlineOnly && !isDesktopApplication(); urlError = - (!isDesktopApplication() && (!component.url && !component.hosted_url)) + (!isDesktopApplication() && (!component.hasValidHostedUrl())) || - (isDesktopApplication() && (!component.local_url && !component.url && !component.hosted_url)) + (isDesktopApplication() && (!component.local_url && !component.hasValidHostedUrl())) expired = component.valid_until && component.valid_until <= new Date(); @@ -129,7 +129,7 @@ class ComponentView { $scope.getUrl = function() { var url = componentManager.urlForComponent($scope.component); - $scope.component.runningLocally = (url !== $scope.component.url) && url !== ($scope.component.hosted_url); + $scope.component.runningLocally = (url == $scope.component.local_url); return url; } diff --git a/app/assets/javascripts/app/services/componentManager.js b/app/assets/javascripts/app/services/componentManager.js index 48531eb32..49adfa327 100644 --- a/app/assets/javascripts/app/services/componentManager.js +++ b/app/assets/javascripts/app/services/componentManager.js @@ -1,9 +1,10 @@ -/* This domain will be used to save context item client data */ -let ClientDataDomain = "org.standardnotes.sn.components"; class ComponentManager { constructor($rootScope, modelManager, syncManager, desktopManager, nativeExtManager, $timeout, $compile) { + /* This domain will be used to save context item client data */ + ComponentManager.ClientDataDomain = "org.standardnotes.sn.components"; + this.$compile = $compile; this.$rootScope = $rootScope; this.modelManager = modelManager; @@ -189,8 +190,7 @@ class ComponentManager { jsonForItem(item, component, source) { var params = {uuid: item.uuid, content_type: item.content_type, created_at: item.created_at, updated_at: item.updated_at, deleted: item.deleted}; params.content = item.createContentJSONFromProperties(); - /* Legacy is using component.url key, so if it's present, use it, otherwise use uuid */ - params.clientData = item.getDomainDataItem(component.url || component.uuid, ClientDataDomain) || {}; + params.clientData = item.getDomainDataItem(component.getClientDataKey(), ComponentManager.ClientDataDomain) || {}; /* This means the this function is being triggered through a remote Saving response, which should not update actual local content values. The reason is, Save responses may be delayed, and a user may have changed some values @@ -268,13 +268,13 @@ class ComponentManager { if(component.offlineOnly || (isDesktopApplication() && component.local_url)) { return component.local_url && component.local_url.replace("sn://", offlinePrefix + this.desktopManager.getApplicationDataPath() + "/"); } else { - return component.hosted_url || component.url; + return component.hosted_url || component.legacy_url; } } componentForUrl(url) { return this.components.filter(function(component){ - return component.url === url || component.hosted_url === url; + return component.hosted_url === url || component.legacy_url === url; })[0]; } @@ -474,7 +474,7 @@ class ComponentManager { var responseItem = _.find(responseItems, {uuid: item.uuid}); _.merge(item.content, responseItem.content); if(responseItem.clientData) { - item.setDomainDataItem(component.url || component.uuid, responseItem.clientData, ClientDataDomain); + item.setDomainDataItem(component.getClientDataKey(), responseItem.clientData, ComponentManager.ClientDataDomain); } item.setDirty(true); } @@ -505,7 +505,7 @@ class ComponentManager { for(let responseItem of responseItems) { var item = this.modelManager.createItem(responseItem); if(responseItem.clientData) { - item.setDomainDataItem(component.url || component.uuid, responseItem.clientData, ClientDataDomain); + item.setDomainDataItem(getClientDataKey(), responseItem.clientData, ComponentManager.ClientDataDomain); } this.modelManager.addItem(item); this.modelManager.resolveReferencesForItem(item, true); diff --git a/app/assets/javascripts/app/services/migrationManager.js b/app/assets/javascripts/app/services/migrationManager.js index d5a837bf4..6e67da829 100644 --- a/app/assets/javascripts/app/services/migrationManager.js +++ b/app/assets/javascripts/app/services/migrationManager.js @@ -1,23 +1,15 @@ -class MigrationManager { +class MigrationManager extends SFMigrationManager { - constructor($rootScope, modelManager, syncManager, componentManager) { - this.$rootScope = $rootScope; - this.modelManager = modelManager; - this.syncManager = syncManager; + constructor($rootScope, modelManager, syncManager, componentManager, storageManager) { + super(modelManager, syncManager, storageManager); this.componentManager = componentManager; + } - this.migrators = []; - - this.addEditorToComponentMigrator(); - - this.modelManager.addItemSyncObserver("migration-manager", "*", (allItems, validItems, deletedItems) => { - for(var migrator of this.migrators) { - var items = allItems.filter((item) => {return item.content_type == migrator.content_type}); - if(items.length > 0) { - migrator.handler(items); - } - } - }); + registeredMigrations() { + return [ + this.editorToComponentMigration(), + this.componentUrlToHostedUrl() + ]; } /* @@ -25,10 +17,10 @@ class MigrationManager { convert to using the new component API. */ - addEditorToComponentMigrator() { - this.migrators.push({ + editorToComponentMigration() { + return { + name: "editor-to-component", content_type: "SN|Editor", - handler: (editors) => { // Convert editors to components for(var editor of editors) { @@ -54,10 +46,36 @@ class MigrationManager { this.syncManager.sync(); } - }) + } } - + /* + Migrate component.url fields to component.hosted_url. This involves rewriting any note data that relied on the + component.url value to store clientData, such as the CodeEditor, which stores the programming language for the note + in the note's clientData[component.url]. We want to rewrite any matching items to transfer that clientData into + clientData[component.uuid]. + Created: July 6, 2018 + */ + componentUrlToHostedUrl() { + return { + name: "component-url-to-hosted-url", + content_type: "SN|Component", + handler: (components) => { + var notes = this.modelManager.validItemsForContentType("Note"); + for(var note of notes) { + for(var component of components) { + var clientData = note.getDomainDataItem(component.hosted_url, ComponentManager.ClientDataDomain); + if(clientData) { + note.setDomainDataItem(component.uuid, clientData, ComponentManager.ClientDataDomain); + note.setDomainDataItem(component.hosted_url, null, ComponentManager.ClientDataDomain); + note.setDirty(true); + } + } + } + this.syncManager.sync(); + } + } + } } angular.module('app').service('migrationManager', MigrationManager);