Migrate editors to components, disable previous editor when selecting new one

This commit is contained in:
Mo Bitar
2017-11-09 17:20:13 -06:00
parent 8767f1c5ec
commit 4e39a5e1b9
7 changed files with 90 additions and 154 deletions

View File

@@ -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)

View File

@@ -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());

View File

@@ -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();
}

View File

@@ -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();
}
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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