diff --git a/app/assets/javascripts/app/frontend/controllers/editor.js b/app/assets/javascripts/app/frontend/controllers/editor.js index 558172e8d..d560a0abf 100644 --- a/app/assets/javascripts/app/frontend/controllers/editor.js +++ b/app/assets/javascripts/app/frontend/controllers/editor.js @@ -93,17 +93,18 @@ angular.module('app.frontend') this.selectedEditor = function(editorComponent) { this.showEditorMenu = false; + + if(this.editorComponent && this.editorComponent !== editorComponent) { + // This disassociates the editor from the note, but the component itself still needs to be deactivated + this.disableComponentForCurrentItem(this.editorComponent); + // Now deactivate the component + componentManager.deactivateComponent(this.editorComponent); + } + if(editorComponent) { this.enableComponentForCurrentItem(editorComponent); - } else { - // Use plain system editor - if(this.editorComponent) { - // This disassociates the editor from the note, but the component itself still needs to be deactivated - this.disableComponentForCurrentItem(this.editorComponent); - // Now deactivate the component - componentManager.deactivateComponent(this.editorComponent); - } } + this.editorComponent = editorComponent; }.bind(this) diff --git a/app/assets/javascripts/app/frontend/controllers/home.js b/app/assets/javascripts/app/frontend/controllers/home.js index f72cedcfd..830479df3 100644 --- a/app/assets/javascripts/app/frontend/controllers/home.js +++ b/app/assets/javascripts/app/frontend/controllers/home.js @@ -1,6 +1,6 @@ angular.module('app.frontend') .controller('HomeCtrl', function ($scope, $location, $rootScope, $timeout, modelManager, - dbManager, syncManager, authManager, themeManager, passcodeManager, storageManager) { + dbManager, syncManager, authManager, themeManager, passcodeManager, storageManager, migrationManager) { storageManager.initialize(passcodeManager.hasPasscode(), authManager.isEphemeralSession()); diff --git a/app/assets/javascripts/app/services/componentManager.js b/app/assets/javascripts/app/services/componentManager.js index 330790d59..b1692592d 100644 --- a/app/assets/javascripts/app/services/componentManager.js +++ b/app/assets/javascripts/app/services/componentManager.js @@ -148,6 +148,12 @@ class ComponentManager { }) } + componentForUrl(url) { + return this.components.filter(function(component){ + return component.url === url; + })[0]; + } + componentForSessionKey(key) { return _.find(this.components, {sessionKey: key}); } @@ -493,18 +499,27 @@ class ComponentManager { } disassociateComponentWithItem(component, item) { + _.pull(component.associatedItemIds, item.uuid); + if(component.disassociatedItemIds.indexOf(item.uuid) !== -1) { return; } - _.pull(component.associatedItemIds, item.uuid); + component.disassociatedItemIds.push(item.uuid); + component.setDirty(true); this.syncManager.sync(); } associateComponentWithItem(component, item) { _.pull(component.disassociatedItemIds, item.uuid); + + if(component.associatedItemIds.includes(item.uuid)) { + return; + } + component.associatedItemIds.push(item.uuid); + component.setDirty(true); this.syncManager.sync(); } diff --git a/app/assets/javascripts/app/services/directives/views/globalExtensionsMenu.js b/app/assets/javascripts/app/services/directives/views/globalExtensionsMenu.js index fa29c8d4d..42bfa6f00 100644 --- a/app/assets/javascripts/app/services/directives/views/globalExtensionsMenu.js +++ b/app/assets/javascripts/app/services/directives/views/globalExtensionsMenu.js @@ -7,14 +7,13 @@ class GlobalExtensionsMenu { }; } - controller($scope, extensionManager, syncManager, modelManager, themeManager, editorManager, componentManager) { + controller($scope, extensionManager, syncManager, modelManager, themeManager, componentManager) { 'ngInject'; $scope.formData = {}; $scope.extensionManager = extensionManager; $scope.themeManager = themeManager; - $scope.editorManager = editorManager; $scope.componentManager = componentManager; $scope.serverExtensions = modelManager.itemsForContentType("SF|Extension"); @@ -120,23 +119,6 @@ class GlobalExtensionsMenu { } - // Editors - - $scope.deleteEditor = function(editor) { - if(confirm("Are you sure you want to delete this editor?")) { - editorManager.deleteEditor(editor); - } - } - - $scope.setDefaultEditor = function(editor) { - editorManager.setDefaultEditor(editor); - } - - $scope.removeDefaultEditor = function(editor) { - editorManager.removeDefaultEditor(editor); - } - - // Components $scope.revokePermissions = function(component) { @@ -219,11 +201,6 @@ class GlobalExtensionsMenu { } } - $scope.handleEditorLink = function(link, completion) { - editorManager.addNewEditorFromURL(link); - completion(); - } - } } diff --git a/app/assets/javascripts/app/services/editorManager.js b/app/assets/javascripts/app/services/editorManager.js deleted file mode 100644 index 1b9ee579b..000000000 --- a/app/assets/javascripts/app/services/editorManager.js +++ /dev/null @@ -1,100 +0,0 @@ -class EditorManager { - - constructor($rootScope, modelManager, syncManager) { - this.syncManager = syncManager; - this.modelManager = modelManager; - - this.editorType = "SN|Editor"; - this._systemEditor = { - systemEditor: true, - name: "Plain" - } - - $rootScope.$on("sync:completed", function(){ - // we want to wait for sync completion before creating a syncable system editor - // we need to sync the system editor so that we can assign note preferences to it - // that is, when a user selects Plain for a note, we need to remember that - if(this.systemEditor.uuid) { - return; - } - - var liveSysEditor = _.find(this.allEditors, {systemEditor: true}); - if(liveSysEditor) { - this._systemEditor = liveSysEditor; - } else { - this._systemEditor = modelManager.createItem({ - content_type: this.editorType, - systemEditor: true, - name: "Plain" - }) - modelManager.addItem(this._systemEditor); - this._systemEditor.setDirty(true); - syncManager.sync(); - } - }.bind(this)) - } - - get allEditors() { - return this.modelManager.itemsForContentType(this.editorType); - } - - get externalEditors() { - return this.allEditors.filter(function(editor){ - return !editor.systemEditor; - }) - } - - get systemEditors() { - return [this.systemEditor]; - } - - get systemEditor() { - return this._systemEditor; - } - - get defaultEditor() { - return _.find(this.externalEditors, {default: true}); - } - - editorForUrl(url) { - return this.externalEditors.filter(function(editor){return editor.url == url})[0]; - } - - setDefaultEditor(editor) { - var defaultEditor = this.defaultEditor; - if(defaultEditor) { - defaultEditor.default = false; - defaultEditor.setDirty(true); - } - editor.default = true; - editor.setDirty(true); - this.syncManager.sync(); - } - - removeDefaultEditor(editor) { - editor.default = false; - editor.setDirty(true); - this.syncManager.sync(); - } - - addNewEditorFromURL(url) { - var name = getParameterByName("name", url); - var editor = this.modelManager.createItem({ - content_type: this.editorType, - url: url, - name: name - }) - - this.modelManager.addItem(editor); - editor.setDirty(true); - this.syncManager.sync(); - } - - deleteEditor(editor) { - this.modelManager.setItemToBeDeleted(editor); - this.syncManager.sync(); - } - -} - -angular.module('app.frontend').service('editorManager', EditorManager); diff --git a/app/assets/javascripts/app/services/migrationManager.js b/app/assets/javascripts/app/services/migrationManager.js new file mode 100644 index 000000000..b7f252727 --- /dev/null +++ b/app/assets/javascripts/app/services/migrationManager.js @@ -0,0 +1,62 @@ +class MigrationManager { + + constructor($rootScope, modelManager, syncManager, componentManager) { + this.$rootScope = $rootScope; + this.modelManager = modelManager; + this.syncManager = syncManager; + 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); + } + } + }); + } + + /* + Migrate SN|Editor to SN|Component. Editors are deprecated as of November 2017. Editors using old APIs must + convert to using the new component API. + */ + + addEditorToComponentMigrator() { + this.migrators.push({ + content_type: "SN|Editor", + + handler: (editors) => { + // Convert editors to components + for(var editor of editors) { + // If there's already a component for this url, then skip this editor + if(editor.url && !this.componentManager.componentForUrl(editor.url)) { + var component = this.modelManager.createItem({ + content_type: "SN|Component", + url: editor.url, + name: editor.name, + area: "editor-editor" + }) + component.setAppDataItem("data", editor.data); + component.setDirty(true); + this.modelManager.addItem(component); + console.log("Created component", component, "From editor", editor); + } + } + + for(let editor of editors) { + editor.setItemToBeDeleted(); + } + + this.syncManager.sync(); + } + }) + } + + +} + +angular.module('app.frontend').service('migrationManager', MigrationManager); diff --git a/app/assets/templates/frontend/directives/global-extensions-menu.html.haml b/app/assets/templates/frontend/directives/global-extensions-menu.html.haml index 3a55fab07..4183d255b 100644 --- a/app/assets/templates/frontend/directives/global-extensions-menu.html.haml +++ b/app/assets/templates/frontend/directives/global-extensions-menu.html.haml @@ -4,7 +4,7 @@ .float-group.h20 %h1.tinted.pull-left Extensions %a.block.pull-right.dashboard-link{"href" => "https://dashboard.standardnotes.org", "target" => "_blank"} Open Dashboard - %div.clear{"ng-if" => "!extensionManager.extensions.length && !themeManager.themes.length && !editorManager.externalEditors.length"} + %div.clear{"ng-if" => "!extensionManager.extensions.length && !themeManager.themes.length && !componentManager.components.length"} %p Customize your experience with editors, themes, and actions. .tinted-box.mt-10 %h3 Available as part of the Extended subscription. @@ -34,25 +34,6 @@ %p.small.selectable.wrap{"ng-if" => "theme.showLink"} {{theme.url}} - %div{"ng-if" => "editorManager.externalEditors.length > 0"} - .header.container.section-margin - %h2 Editors - %p{"style" => "margin-top: 3px;"} Choose "Editor" in the note menu to use an editor for a specific note. - %ul - %li{"ng-repeat" => "editor in editorManager.externalEditors | orderBy: 'name'", "ng-click" => "clickedExtension(editor)"} - .container - %strong.red.medium{"ng-if" => "editor.conflict_of"} Conflicted copy - %h3 - %input.bold{"ng-if" => "editor.rename", "ng-model" => "editor.tempName", "ng-keyup" => "$event.keyCode == 13 && submitExtensionRename(editor);", "mb-autofocus" => "true", "should-focus" => "true"} - %span{"ng-if" => "!editor.rename"} {{editor.name}} - %div.mt-5{"ng-if" => "editor.showDetails"} - .link-group - %a{"ng-if" => "!editor.default", "ng-click" => "setDefaultEditor(editor); $event.stopPropagation();"} Make Default - %a.tinted{"ng-if" => "editor.default", "ng-click" => "removeDefaultEditor(editor); $event.stopPropagation();"} Remove as Default - %a{"ng-click" => "renameExtension(editor); $event.stopPropagation();"} Rename - %a{"ng-click" => "editor.showUrl = !editor.showUrl; $event.stopPropagation();"} Show Link - %a.red{ "ng-click" => "deleteEditor(editor); $event.stopPropagation();"} Delete - .wrap.mt-5.selectable{"ng-if" => "editor.showUrl"} {{editor.url}} %div{"ng-if" => "extensionManager.extensions.length"} .header.container.section-margin