From 0fa048e23ca2b28c0bbd47df9ba68606b6410d69 Mon Sep 17 00:00:00 2001 From: Mo Bitar Date: Mon, 13 Feb 2017 11:42:27 -0600 Subject: [PATCH] preview action, click outside panel handle --- .../app/frontend/controllers/editor.js | 4 --- .../app/frontend/models/api/item.js | 1 + .../app/frontend/models/app/extension.js | 4 ++- .../javascripts/app/services/dbManager.js | 1 - .../directives/functional/click-outside.js | 27 +++++++++++++++++ .../views/contextualExtensionsMenu.js | 20 +++++++++++++ .../app/services/extensionManager.js | 28 +++++++++++++++--- .../javascripts/app/services/modelManager.js | 8 ++--- app/assets/stylesheets/app/_directives.scss | 29 +++++++++++++++++++ app/assets/stylesheets/app/_editor.scss | 11 ------- app/assets/stylesheets/app/_header.scss | 9 +++--- .../directives/contextual-menu.html.haml | 14 +++++++++ .../templates/frontend/editor.html.haml | 8 ++--- .../templates/frontend/header.html.haml | 4 +-- 14 files changed, 133 insertions(+), 35 deletions(-) create mode 100644 app/assets/javascripts/app/services/directives/functional/click-outside.js diff --git a/app/assets/javascripts/app/frontend/controllers/editor.js b/app/assets/javascripts/app/frontend/controllers/editor.js index 51ceee65f..8aee7ed7f 100644 --- a/app/assets/javascripts/app/frontend/controllers/editor.js +++ b/app/assets/javascripts/app/frontend/controllers/editor.js @@ -231,10 +231,6 @@ angular.module('app.frontend') } } - this.clickedMenu = function() { - this.showMenu = !this.showMenu; - } - this.deleteNote = function() { if(confirm("Are you sure you want to delete this note?")) { this.remove()(this.note); diff --git a/app/assets/javascripts/app/frontend/models/api/item.js b/app/assets/javascripts/app/frontend/models/api/item.js index f6129f5a0..d486f9739 100644 --- a/app/assets/javascripts/app/frontend/models/api/item.js +++ b/app/assets/javascripts/app/frontend/models/api/item.js @@ -37,6 +37,7 @@ class Item { updateFromJSON(json) { _.merge(this, json); + if(this.created_at) { this.created_at = new Date(this.created_at); this.updated_at = new Date(this.updated_at); diff --git a/app/assets/javascripts/app/frontend/models/app/extension.js b/app/assets/javascripts/app/frontend/models/app/extension.js index 97a2576f0..fd45b3444 100644 --- a/app/assets/javascripts/app/frontend/models/app/extension.js +++ b/app/assets/javascripts/app/frontend/models/app/extension.js @@ -79,6 +79,7 @@ class Extension extends Item { super.mapContentToLocalProperties(contentObject) this.name = contentObject.name; this.url = contentObject.url; + this.supported_types = contentObject.supported_types; this.actions = contentObject.actions.map(function(action){ return new Action(action); }) @@ -99,7 +100,8 @@ class Extension extends Item { var params = { name: this.name, url: this.url, - actions: this.actions + actions: this.actions, + supported_types: this.supported_types }; _.merge(params, super.structureParams()); diff --git a/app/assets/javascripts/app/services/dbManager.js b/app/assets/javascripts/app/services/dbManager.js index d7e3edabb..90d529ec3 100644 --- a/app/assets/javascripts/app/services/dbManager.js +++ b/app/assets/javascripts/app/services/dbManager.js @@ -102,7 +102,6 @@ class DBManager { this.openDatabase((db) => { var request = db.transaction("items", "readwrite").objectStore("items").delete(item.uuid); request.onsuccess = function(event) { - console.log("Successfully deleted item", item.uuid); if(callback) { callback(true); } diff --git a/app/assets/javascripts/app/services/directives/functional/click-outside.js b/app/assets/javascripts/app/services/directives/functional/click-outside.js new file mode 100644 index 000000000..10e40e1da --- /dev/null +++ b/app/assets/javascripts/app/services/directives/functional/click-outside.js @@ -0,0 +1,27 @@ +angular + .module('app.frontend') + .directive('clickOutside', ['$document', function($document) { + return { + restrict: 'A', + replace: false, + link : function($scope, $element, attrs) { + + var didApplyClickOutside = false; + + $element.bind('click', function(e) { + didApplyClickOutside = false; + if (attrs.isOpen) { + e.stopPropagation(); + } + }); + + $document.bind('click', function() { + if(!didApplyClickOutside) { + $scope.$apply(attrs.clickOutside); + didApplyClickOutside = true; + } + }) + + } + } + }]); diff --git a/app/assets/javascripts/app/services/directives/views/contextualExtensionsMenu.js b/app/assets/javascripts/app/services/directives/views/contextualExtensionsMenu.js index a0ed0e97d..f9a57b1b6 100644 --- a/app/assets/javascripts/app/services/directives/views/contextualExtensionsMenu.js +++ b/app/assets/javascripts/app/services/directives/views/contextualExtensionsMenu.js @@ -11,6 +11,8 @@ class ContextualExtensionsMenu { controller($scope, modelManager, extensionManager) { 'ngInject'; + $scope.renderData = {}; + $scope.extensions = _.map(extensionManager.extensionsInContextOfItem($scope.item), function(ext){ return _.cloneDeep(ext); }); @@ -27,12 +29,30 @@ class ContextualExtensionsMenu { } $scope.executeAction = function(action, extension) { + if(action.verb == "nested") { + action.showNestedActions = !action.showNestedActions; + return; + } action.running = true; extensionManager.executeAction(action, extension, $scope.item, function(response){ action.running = false; + $scope.handleActionResponse(action, response); }) } + $scope.handleActionResponse = function(action, response) { + switch (action.verb) { + case "render": { + var item = response.item; + if(item.content_type == "Note") { + $scope.renderData.title = item.title; + $scope.renderData.text = item.text; + $scope.renderData.showRenderModal = true; + } + } + } + } + $scope.accessTypeForExtension = function(extension) { return extensionManager.extensionUsesEncryptedData(extension) ? "encrypted" : "decrypted"; } diff --git a/app/assets/javascripts/app/services/extensionManager.js b/app/assets/javascripts/app/services/extensionManager.js index d9a0260f6..20b21de82 100644 --- a/app/assets/javascripts/app/services/extensionManager.js +++ b/app/assets/javascripts/app/services/extensionManager.js @@ -28,7 +28,7 @@ class ExtensionManager { extensionsInContextOfItem(item) { return this.extensions.filter(function(ext){ - return ext.actionsWithContextForItem(item).length > 0; + return _.includes(ext.supported_types, item.content_type) || ext.actionsWithContextForItem(item).length > 0; }) } @@ -152,9 +152,29 @@ class ExtensionManager { case "get": { this.Restangular.oneUrl(action.url, action.url).get().then(function(response){ action.error = false; - var items = response.items; - this.modelManager.mapResponseItemsToLocalModels(items); - customCallback(items); + var items = response.items || [response.item]; + EncryptionHelper.decryptMultipleItems(items, localStorage.getItem("mk")); + items = this.modelManager.mapResponseItemsToLocalModels(items); + for(var item of items) { + item.setDirty(true); + } + this.syncManager.sync(null); + customCallback({items: items}); + }.bind(this)) + .catch(function(response){ + action.error = true; + customCallback(null); + }) + + break; + } + + case "render": { + this.Restangular.oneUrl(action.url, action.url).get().then(function(response){ + action.error = false; + EncryptionHelper.decryptItem(response.item, localStorage.getItem("mk")); + var item = this.modelManager.createItem(response.item); + customCallback({item: item}); }.bind(this)) .catch(function(response){ action.error = true; diff --git a/app/assets/javascripts/app/services/modelManager.js b/app/assets/javascripts/app/services/modelManager.js index 8b23060dc..ab8ca7f44 100644 --- a/app/assets/javascripts/app/services/modelManager.js +++ b/app/assets/javascripts/app/services/modelManager.js @@ -64,10 +64,10 @@ class ModelManager { json_obj = _.omit(json_obj, omitFields || []) var item = this.findItem(json_obj["uuid"]); if(json_obj["deleted"] == true || !_.includes(this.acceptableContentTypes, json_obj["content_type"])) { - if(item) { - this.removeItemLocally(item) - } - continue; + if(item) { + this.removeItemLocally(item) + } + continue; } _.omit(json_obj, omitFields); diff --git a/app/assets/stylesheets/app/_directives.scss b/app/assets/stylesheets/app/_directives.scss index 39eb623dc..8d5f28cc5 100644 --- a/app/assets/stylesheets/app/_directives.scss +++ b/app/assets/stylesheets/app/_directives.scss @@ -1,4 +1,33 @@ +.extension-render-modal { + position: fixed; + margin-left: auto; + margin-right: auto; + left: 0; + right: 0; + top: 0; + bottom: 0; + z-index: 10000; + width: 100vw; + height: 100vh; + background-color: rgba(gray, 0.3); + + .content { + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-color: white; + width: 700px; + height: 500px; + margin: auto; + padding: 25px; + position: absolute; + top: 0; left: 0; bottom: 0; right: 0; + overflow-y: scroll; + } +} + .dropdown-menu.contextual-menu { + overflow-y: scroll; + max-height: 85vh; + .extension { &:not(:first-child) { diff --git a/app/assets/stylesheets/app/_editor.scss b/app/assets/stylesheets/app/_editor.scss index 6404713d5..3815f46a0 100644 --- a/app/assets/stylesheets/app/_editor.scss +++ b/app/assets/stylesheets/app/_editor.scss @@ -177,15 +177,6 @@ right: 0; } -.full-screen-button { - cursor: pointer; - position: absolute; - top: 25px; - right: 20px; - z-index: 100; -} - - ol { list-style-type: decimal; list-style-position: inside; @@ -196,8 +187,6 @@ ol { -webkit-padding-start: 0px; } - - .nav-tabs { a { color: black; diff --git a/app/assets/stylesheets/app/_header.scss b/app/assets/stylesheets/app/_header.scss index 5ba6cab79..1df8ef09a 100644 --- a/app/assets/stylesheets/app/_header.scss +++ b/app/assets/stylesheets/app/_header.scss @@ -150,6 +150,11 @@ } } +h2 { + margin-bottom: 0px; + margin-top: 0px; +} + .footer-bar { position: relative; width: 100%; @@ -194,10 +199,6 @@ display: block; } - h2 { - margin-bottom: 0px; - margin-top: 0px; - } h3 { font-size: 14px !important; diff --git a/app/assets/templates/frontend/directives/contextual-menu.html.haml b/app/assets/templates/frontend/directives/contextual-menu.html.haml index c30f5da5e..725b56474 100644 --- a/app/assets/templates/frontend/directives/contextual-menu.html.haml +++ b/app/assets/templates/frontend/directives/contextual-menu.html.haml @@ -10,5 +10,19 @@ %li.action{"ng-repeat" => "action in extension.actionsWithContextForItem(item)", "ng-click" => "executeAction(action, extension)"} .name {{action.label}} .desc {{action.desc}} + + %div{"ng-if" => "action.showNestedActions"} + %ul.mt-10 + %li.action.white-bg{"ng-repeat" => "subaction in action.subactions", "ng-click" => "executeAction(subaction, extension); $event.stopPropagation()", "style" => "margin-top: -1px;"} + .name {{subaction.label}} + .desc {{subaction.desc}} + %span{"ng-if" => "subaction.running"} + .spinner{"style" => "margin-top: 3px;"} + %span{"ng-if" => "action.running"} .spinner{"style" => "margin-top: 3px;"} + +.extension-render-modal{"ng-if" => "renderData.showRenderModal", "ng-click" => "renderData.showRenderModal = false"} + .content + %h2 {{renderData.title}} + %p.normal{"style" => "white-space: pre-wrap; font-family: monospace; font-size: 16px;"} {{renderData.text}} diff --git a/app/assets/templates/frontend/editor.html.haml b/app/assets/templates/frontend/editor.html.haml index af7635754..7b5242531 100644 --- a/app/assets/templates/frontend/editor.html.haml +++ b/app/assets/templates/frontend/editor.html.haml @@ -11,8 +11,8 @@ "ng-model" => "ctrl.tagsString", "placeholder" => "#tags", "ng-blur" => "ctrl.updateTagsFromTagsString($event, ctrl.tagsString)"} .section-menu %ul.nav.nav-pills - %li.dropdown - %a.dropdown-toggle{"ng-click" => "ctrl.clickedMenu(); ctrl.showExtensions = false"} + %li.dropdown{"click-outside" => "ctrl.showMenu = false;", "is-open" => "ctrl.showMenu"} + %a.dropdown-toggle{"ng-click" => "ctrl.showMenu = !ctrl.showMenu; ctrl.showExtensions = false;"} File %span.caret %span.sr-only @@ -27,8 +27,8 @@ %li{"ng-click" => "ctrl.deleteNote()"} .text Delete %li.sep - %li.dropdown{"ng-if" => "ctrl.hasAvailableExtensions()"} - %a.dropdown-toggle{"ng-click" => "ctrl.showExtensions = !ctrl.showExtensions; ctrl.showMenu = false"} + %li.dropdown{"ng-if" => "ctrl.hasAvailableExtensions()", "click-outside" => "ctrl.showExtensions = false;", "is-open" => "ctrl.showExtensions"} + %a.dropdown-toggle{"ng-click" => "ctrl.showExtensions = !ctrl.showExtensions; ctrl.showMenu = false;"} Extensions %span.caret %span.sr-only diff --git a/app/assets/templates/frontend/header.html.haml b/app/assets/templates/frontend/header.html.haml index f385f293c..972825eaf 100644 --- a/app/assets/templates/frontend/header.html.haml +++ b/app/assets/templates/frontend/header.html.haml @@ -1,10 +1,10 @@ .footer-bar .pull-left - .footer-bar-link + .footer-bar-link{"click-outside" => "ctrl.showAccountMenu = false;", "is-open" => "ctrl.showAccountMenu"} %a{"ng-click" => "ctrl.accountMenuPressed()", "ng-class" => "{red: ctrl.error}"} Account %account-menu{"ng-if" => "ctrl.showAccountMenu"} - .footer-bar-link + .footer-bar-link{"click-outside" => "ctrl.showExtensionsMenu = false;", "is-open" => "ctrl.showExtensionsMenu"} %a{"ng-click" => "ctrl.toggleExtensions()"} Extensions %global-extensions-menu{"ng-if" => "ctrl.showExtensionsMenu"}