contextual extension menu
This commit is contained in:
@@ -18,7 +18,6 @@ class Item {
|
||||
}
|
||||
|
||||
get contentObject() {
|
||||
// console.log("getting content object from content", this.content);
|
||||
if(!this.content) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -56,6 +56,12 @@ class Extension extends Item {
|
||||
})
|
||||
}
|
||||
|
||||
actionsWithContextForItem(item) {
|
||||
return this.actions.filter(function(action){
|
||||
return action.context == item.content_type || action.context == "Item";
|
||||
})
|
||||
}
|
||||
|
||||
mapContentToLocalProperties(contentObject) {
|
||||
super.mapContentToLocalProperties(contentObject)
|
||||
this.name = contentObject.name;
|
||||
|
||||
@@ -234,7 +234,7 @@ angular.module('app.frontend')
|
||||
return this.createRequestParamsForItem(item, options.additionalFields);
|
||||
}.bind(this));
|
||||
|
||||
console.log("syncing items", request.items);
|
||||
// console.log("syncing items", request.items);
|
||||
|
||||
if(this.syncToken) {
|
||||
request.sync_token = this.syncToken;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
class ContextualExtensionsMenu {
|
||||
|
||||
constructor() {
|
||||
this.restrict = "E";
|
||||
this.templateUrl = "frontend/directives/contextual-menu.html";
|
||||
this.scope = {
|
||||
item: "="
|
||||
};
|
||||
}
|
||||
|
||||
controller($scope, modelManager, extensionManager) {
|
||||
$scope.extensions = extensionManager.extensionsInContextOfItem($scope.item);
|
||||
|
||||
$scope.executeAction = function(action, extension) {
|
||||
action.running = true;
|
||||
extensionManager.executeAction(action, extension, $scope.item, function(response){
|
||||
action.running = false;
|
||||
})
|
||||
}
|
||||
|
||||
$scope.accessTypeForExtension = function(extension) {
|
||||
return extensionManager.extensionUsesEncryptedData(extension) ? "encrypted" : "decrypted";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
angular.module('app.frontend').directive('contextualExtensionsMenu', () => new ContextualExtensionsMenu);
|
||||
@@ -25,6 +25,12 @@ class ExtensionManager {
|
||||
return this.modelManager.extensions;
|
||||
}
|
||||
|
||||
extensionsInContextOfItem(item) {
|
||||
return this.extensions.filter(function(ext){
|
||||
return ext.actionsWithContextForItem(item).length > 0;
|
||||
})
|
||||
}
|
||||
|
||||
actionWithURL(url) {
|
||||
for (var extension of this.extensions) {
|
||||
return _.find(extension.actions, {url: url})
|
||||
@@ -115,14 +121,20 @@ class ExtensionManager {
|
||||
}
|
||||
|
||||
case "post": {
|
||||
var items;
|
||||
var params = {};
|
||||
|
||||
if(action.all) {
|
||||
items = this.modelManager.allItemsMatchingTypes(action.content_types);
|
||||
var items = this.modelManager.allItemsMatchingTypes(action.content_types);
|
||||
params.items = items.map(function(item){
|
||||
var params = this.outgoingParamsForItem(item, extension);
|
||||
return params;
|
||||
}.bind(this))
|
||||
|
||||
} else {
|
||||
items = [item];
|
||||
params.item = this.outgoingParamsForItem(item, extension);
|
||||
}
|
||||
|
||||
this.performPost(action, extension, items, function(items){
|
||||
this.performPost(action, extension, params, function(items){
|
||||
callback(items);
|
||||
});
|
||||
}
|
||||
@@ -149,7 +161,7 @@ class ExtensionManager {
|
||||
}
|
||||
|
||||
enableRepeatAction(action, extension) {
|
||||
console.log("Enabling repeat action", action);
|
||||
// console.log("Enabling repeat action", action);
|
||||
|
||||
if(!_.find(this.enabledRepeatActionUrls, action.url)) {
|
||||
this.enabledRepeatActionUrls.push(action.url);
|
||||
@@ -205,7 +217,12 @@ class ExtensionManager {
|
||||
action.lastExecuted = new Date();
|
||||
|
||||
if(action.verb == "post") {
|
||||
this.performPost(action, extension, changedItems, null);
|
||||
var params = {};
|
||||
params.items = changedItems.map(function(item){
|
||||
var params = this.outgoingParamsForItem(item, extension);
|
||||
return params;
|
||||
}.bind(this))
|
||||
this.performPost(action, extension, params, null);
|
||||
} else {
|
||||
// todo
|
||||
}
|
||||
@@ -215,12 +232,9 @@ class ExtensionManager {
|
||||
return this.apiController.paramsForExtension(item, this.extensionUsesEncryptedData(extension));
|
||||
}
|
||||
|
||||
performPost(action, extension, items, callback) {
|
||||
performPost(action, extension, params, callback) {
|
||||
var request = this.Restangular.oneUrl(action.url, action.url);
|
||||
request.items = items.map(function(item){
|
||||
var params = this.outgoingParamsForItem(item, extension);
|
||||
return params;
|
||||
}.bind(this))
|
||||
_.merge(request, params);
|
||||
|
||||
request.post().then(function(response){
|
||||
// console.log("watch action response", response);
|
||||
|
||||
@@ -140,7 +140,7 @@ class ModelManager {
|
||||
item.addItemAsRelationship(referencedItem);
|
||||
referencedItem.addItemAsRelationship(item);
|
||||
} else {
|
||||
console.log("Unable to find item:", reference.uuid);
|
||||
// console.log("Unable to find item:", reference.uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,7 +185,9 @@ class ModelManager {
|
||||
|
||||
setItemToBeDeleted(item) {
|
||||
item.deleted = true;
|
||||
item.setDirty(true);
|
||||
if(!item.dummy) {
|
||||
item.setDirty(true);
|
||||
}
|
||||
item.removeAllRelationships();
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
}
|
||||
|
||||
.nt-dropdown-menu.dark {
|
||||
background-color: $selection-color;
|
||||
background-color: white;
|
||||
color: $selected-text-color;
|
||||
|
||||
li {
|
||||
@@ -85,18 +85,27 @@
|
||||
bottom: 0px;
|
||||
background-color: #f1f1f1;
|
||||
color: $selected-text-color;
|
||||
// padding-top: 5px;
|
||||
height: 28px;
|
||||
cursor: default;
|
||||
|
||||
ol, ul {
|
||||
margin-top: 7px;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
&.dropdown-menu {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
li {
|
||||
text-align: left;
|
||||
|
||||
&.sep {
|
||||
margin: 6px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
a {
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
|
||||
64
app/assets/stylesheets/app/_directives.scss
Normal file
64
app/assets/stylesheets/app/_directives.scss
Normal file
@@ -0,0 +1,64 @@
|
||||
.dropdown-menu.contextual-menu {
|
||||
.extension {
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
|
||||
.ext-header {
|
||||
background-color: #ededed;
|
||||
border-bottom: 1px solid #d3d3d3;
|
||||
padding-top: 12px;
|
||||
padding-left: 10px;
|
||||
padding-bottom: 10px;
|
||||
|
||||
> .name {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
> .access {
|
||||
font-size: 12px;
|
||||
opacity: 0.5;
|
||||
font-weight: normal;
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
list-style:none;
|
||||
padding-left:0;
|
||||
|
||||
li {
|
||||
cursor: pointer;
|
||||
height: auto;
|
||||
|
||||
&.action {
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid rgba(black, 0.1);
|
||||
background-color: rgba(white, 0.9);
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(gray, 0.05);
|
||||
}
|
||||
|
||||
> .name {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
> .desc {
|
||||
font-weight: normal;
|
||||
opacity: 0.5;
|
||||
margin-top: 1px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ $dark-gray: #2e2e2e;
|
||||
@import "app/tags";
|
||||
@import "app/notes";
|
||||
@import "app/editor";
|
||||
@import "app/directives";
|
||||
|
||||
@font-face {
|
||||
font-family: 'icomoon';
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
%ul.dropdown-menu.dropdown-menu-left.nt-dropdown-menu.dark.contextual-menu
|
||||
.extension{"ng-repeat" => "extension in extensions"}
|
||||
.ext-header
|
||||
.name {{extension.name}}
|
||||
.access
|
||||
Can access your data
|
||||
%strong {{accessTypeForExtension(extension)}}
|
||||
%ul
|
||||
%li.action{"ng-repeat" => "action in extension.actionsWithContextForItem(item)", "ng-click" => "executeAction(action, extension)"}
|
||||
.name {{action.label}}
|
||||
.desc {{action.desc}}
|
||||
%span{"ng-if" => "action.running"}
|
||||
.spinner{"style" => "margin-top: 3px;"}
|
||||
@@ -9,7 +9,7 @@
|
||||
.section-menu
|
||||
%ul.nav.nav-pills
|
||||
%li.dropdown
|
||||
%a.dropdown-toggle{"ng-click" => "ctrl.clickedMenu()"}
|
||||
%a.dropdown-toggle{"ng-click" => "ctrl.clickedMenu(); ctrl.showExtensions = false"}
|
||||
File
|
||||
%span.caret{"ng-if" => "!ctrl.note.locked"}
|
||||
%span{"ng-if" => " ctrl.note.locked"}
|
||||
@@ -17,20 +17,28 @@
|
||||
%span.sr-only
|
||||
|
||||
%ul.dropdown-menu.dropdown-menu-left.nt-dropdown-menu.dark{"ng-if" => "ctrl.showMenu && !ctrl.note.locked"}
|
||||
%li
|
||||
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.toggleFullScreen()"} Toggle Fullscreen
|
||||
%li{"ng-click" => "ctrl.selectedMenuItem(); ctrl.toggleFullScreen()"}
|
||||
.text Toggle Fullscreen
|
||||
.shortcut Cmd + O
|
||||
%li
|
||||
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.toggleMarkdown()"} Toggle Markdown Preview
|
||||
%li{"ng-click" => "ctrl.selectedMenuItem(); ctrl.toggleMarkdown()"}
|
||||
.text Toggle Markdown Preview
|
||||
.shortcut Cmd + M
|
||||
%li{"ng-if" => "!ctrl.note.isSharedIndividually()"}
|
||||
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.shareNote()"} Share
|
||||
%li{"ng-if" => "ctrl.note.isSharedIndividually()"}
|
||||
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.editUrlPressed()"} Edit URL
|
||||
%li{"ng-if" => "ctrl.note.isSharedIndividually()"}
|
||||
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.unshareNote()"} Unshare
|
||||
%li
|
||||
%a.text{"ng-click" => "ctrl.deleteNote()"} Delete
|
||||
%li{"ng-if" => "!ctrl.note.isSharedIndividually()", "ng-click" => "ctrl.selectedMenuItem(); ctrl.shareNote()"}
|
||||
.text Share
|
||||
%li{"ng-if" => "ctrl.note.isSharedIndividually()", "ng-click" => "ctrl.selectedMenuItem(); ctrl.editUrlPressed()"}
|
||||
.text Edit URL
|
||||
%li{"ng-if" => "ctrl.note.isSharedIndividually()", "ng-click" => "ctrl.selectedMenuItem(); ctrl.unshareNote()"}
|
||||
.text Unshare
|
||||
%li{"ng-click" => "ctrl.deleteNote()"}
|
||||
.text Delete
|
||||
%li.sep
|
||||
%li.dropdown
|
||||
%a.dropdown-toggle{"ng-click" => "ctrl.showExtensions = !ctrl.showExtensions; ctrl.showMenu = false"}
|
||||
Extensions
|
||||
%span.caret
|
||||
%span.sr-only
|
||||
%contextual-extensions-menu{"ng-if" => "ctrl.showExtensions", "item" => "ctrl.note"}
|
||||
|
||||
.markdown.icon{"ng-if" => "ctrl.editorMode == 'preview'", "ng-click" => "ctrl.showMarkdown = !ctrl.showMarkdown"}
|
||||
.icon-markdown
|
||||
.panel.panel-default.info-panel{"ng-if" => "ctrl.showMarkdown"}
|
||||
|
||||
@@ -114,11 +114,11 @@
|
||||
.encryption-type
|
||||
%span {{action.encryptionModeString}}
|
||||
.execute
|
||||
%a{"ng-click" => "ctrl.selectedAction(action, extension)"}
|
||||
%span{"ng-if" => "action.repeat_mode"}
|
||||
%span{"ng-if" => "ctrl.extensionManager.isRepeatActionEnabled(action)", "ng-click" => "ctrl.extensionManager.disableRepeatAction(action, extension)"} Disable
|
||||
%span{"ng-if" => "!ctrl.extensionManager.isRepeatActionEnabled(action)", "ng-click" => "ctrl.extensionManager.enableRepeatAction(action, extension)"} Enable
|
||||
%span{"ng-if" => "!action.repeat_mode && !action.running"}
|
||||
%a{"ng-if" => "action.repeat_mode"}
|
||||
%span{"ng-if" => "ctrl.extensionManager.isRepeatActionEnabled(action)", "ng-click" => "ctrl.extensionManager.disableRepeatAction(action, extension)"} Disable
|
||||
%span{"ng-if" => "!ctrl.extensionManager.isRepeatActionEnabled(action)", "ng-click" => "ctrl.extensionManager.enableRepeatAction(action, extension)"} Enable
|
||||
%a{"ng-if" => "!action.repeat_mode", "ng-click" => "ctrl.selectedAction(action, extension)"}
|
||||
%span{"ng-if" => "!action.running"}
|
||||
Run
|
||||
%span{"ng-if" => "action.running"}
|
||||
.spinner{"style" => "margin-top: 3px;"}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
File
|
||||
%span.caret
|
||||
%span.sr-only
|
||||
|
||||
%ul.dropdown-menu.dropdown-menu-left.nt-dropdown-menu.dark{"ng-if" => "ctrl.showMenu"}
|
||||
%li{"ng-if" => "!ctrl.tag.isPublic()"}
|
||||
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.selectedTagShare($event)"} Share Tag
|
||||
@@ -20,6 +21,7 @@
|
||||
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.selectedTagUnshare()"} Unshare Tag
|
||||
%li{"ng-if" => "!ctrl.tag.all"}
|
||||
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.selectedTagDelete()"} Delete Tag
|
||||
|
||||
.menu-right-container
|
||||
.public-link{"ng-if" => "ctrl.tag.isPublic()"}
|
||||
%a.url{"ng-if" => "!ctrl.editingUrl", "href" => "{{ctrl.tag.presentationURL()}}", "target" => "_blank"}
|
||||
|
||||
88
vendor/assets/javascripts/transpiled.js
vendored
88
vendor/assets/javascripts/transpiled.js
vendored
@@ -1466,7 +1466,6 @@ var Item = function () {
|
||||
}, {
|
||||
key: 'contentObject',
|
||||
get: function get() {
|
||||
// console.log("getting content object from content", this.content);
|
||||
if (!this.content) {
|
||||
return {};
|
||||
}
|
||||
@@ -1584,6 +1583,13 @@ var Extension = function (_Item) {
|
||||
return action.context == "global";
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: 'actionsWithContextForItem',
|
||||
value: function actionsWithContextForItem(item) {
|
||||
return this.actions.filter(function (action) {
|
||||
return action.context == item.content_type || action.context == "Item";
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: 'mapContentToLocalProperties',
|
||||
value: function mapContentToLocalProperties(contentObject) {
|
||||
@@ -2091,7 +2097,7 @@ var User = function User(json_obj) {
|
||||
return this.createRequestParamsForItem(item, options.additionalFields);
|
||||
}.bind(this));
|
||||
|
||||
console.log("syncing items", request.items);
|
||||
// console.log("syncing items", request.items);
|
||||
|
||||
if (this.syncToken) {
|
||||
request.sync_token = this.syncToken;
|
||||
@@ -2447,6 +2453,42 @@ var User = function User(json_obj) {
|
||||
}
|
||||
};
|
||||
}]);
|
||||
;
|
||||
var ContextualExtensionsMenu = function () {
|
||||
function ContextualExtensionsMenu() {
|
||||
_classCallCheck(this, ContextualExtensionsMenu);
|
||||
|
||||
this.restrict = "E";
|
||||
this.templateUrl = "frontend/directives/contextual-menu.html";
|
||||
this.scope = {
|
||||
item: "="
|
||||
};
|
||||
}
|
||||
|
||||
_createClass(ContextualExtensionsMenu, [{
|
||||
key: 'controller',
|
||||
value: function controller($scope, modelManager, extensionManager) {
|
||||
$scope.extensions = extensionManager.extensionsInContextOfItem($scope.item);
|
||||
|
||||
$scope.executeAction = function (action, extension) {
|
||||
action.running = true;
|
||||
extensionManager.executeAction(action, extension, $scope.item, function (response) {
|
||||
action.running = false;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.accessTypeForExtension = function (extension) {
|
||||
return extensionManager.extensionUsesEncryptedData(extension) ? "encrypted" : "decrypted";
|
||||
};
|
||||
}
|
||||
}]);
|
||||
|
||||
return ContextualExtensionsMenu;
|
||||
}();
|
||||
|
||||
angular.module('app.frontend').directive('contextualExtensionsMenu', function () {
|
||||
return new ContextualExtensionsMenu();
|
||||
});
|
||||
;angular.module('app.frontend').directive('draggable', function () {
|
||||
return {
|
||||
scope: {
|
||||
@@ -2841,6 +2883,13 @@ var ExtensionManager = function () {
|
||||
}
|
||||
|
||||
_createClass(ExtensionManager, [{
|
||||
key: 'extensionsInContextOfItem',
|
||||
value: function extensionsInContextOfItem(item) {
|
||||
return this.extensions.filter(function (ext) {
|
||||
return ext.actionsWithContextForItem(item).length > 0;
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: 'actionWithURL',
|
||||
value: function actionWithURL(url) {
|
||||
var _iteratorNormalCompletion7 = true;
|
||||
@@ -3004,14 +3053,19 @@ var ExtensionManager = function () {
|
||||
|
||||
case "post":
|
||||
{
|
||||
var items;
|
||||
var params = {};
|
||||
|
||||
if (action.all) {
|
||||
items = this.modelManager.allItemsMatchingTypes(action.content_types);
|
||||
var items = this.modelManager.allItemsMatchingTypes(action.content_types);
|
||||
params.items = items.map(function (item) {
|
||||
var params = this.outgoingParamsForItem(item, extension);
|
||||
return params;
|
||||
}.bind(this));
|
||||
} else {
|
||||
items = [item];
|
||||
params.item = this.outgoingParamsForItem(item, extension);
|
||||
}
|
||||
|
||||
this.performPost(action, extension, items, function (items) {
|
||||
this.performPost(action, extension, params, function (items) {
|
||||
callback(items);
|
||||
});
|
||||
}
|
||||
@@ -3040,7 +3094,7 @@ var ExtensionManager = function () {
|
||||
}, {
|
||||
key: 'enableRepeatAction',
|
||||
value: function enableRepeatAction(action, extension) {
|
||||
console.log("Enabling repeat action", action);
|
||||
// console.log("Enabling repeat action", action);
|
||||
|
||||
if (!_.find(this.enabledRepeatActionUrls, action.url)) {
|
||||
this.enabledRepeatActionUrls.push(action.url);
|
||||
@@ -3097,7 +3151,12 @@ var ExtensionManager = function () {
|
||||
action.lastExecuted = new Date();
|
||||
|
||||
if (action.verb == "post") {
|
||||
this.performPost(action, extension, changedItems, null);
|
||||
var params = {};
|
||||
params.items = changedItems.map(function (item) {
|
||||
var params = this.outgoingParamsForItem(item, extension);
|
||||
return params;
|
||||
}.bind(this));
|
||||
this.performPost(action, extension, params, null);
|
||||
} else {
|
||||
// todo
|
||||
}
|
||||
@@ -3109,12 +3168,9 @@ var ExtensionManager = function () {
|
||||
}
|
||||
}, {
|
||||
key: 'performPost',
|
||||
value: function performPost(action, extension, items, callback) {
|
||||
value: function performPost(action, extension, params, callback) {
|
||||
var request = this.Restangular.oneUrl(action.url, action.url);
|
||||
request.items = items.map(function (item) {
|
||||
var params = this.outgoingParamsForItem(item, extension);
|
||||
return params;
|
||||
}.bind(this));
|
||||
_.merge(request, params);
|
||||
|
||||
request.post().then(function (response) {
|
||||
// console.log("watch action response", response);
|
||||
@@ -3389,7 +3445,7 @@ var ModelManager = function () {
|
||||
item.addItemAsRelationship(referencedItem);
|
||||
referencedItem.addItemAsRelationship(item);
|
||||
} else {
|
||||
console.log("Unable to find item:", reference.uuid);
|
||||
// console.log("Unable to find item:", reference.uuid);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -3454,7 +3510,9 @@ var ModelManager = function () {
|
||||
key: 'setItemToBeDeleted',
|
||||
value: function setItemToBeDeleted(item) {
|
||||
item.deleted = true;
|
||||
item.setDirty(true);
|
||||
if (!item.dummy) {
|
||||
item.setDirty(true);
|
||||
}
|
||||
item.removeAllRelationships();
|
||||
}
|
||||
}, {
|
||||
|
||||
2
vendor/assets/javascripts/transpiled.js.map
vendored
2
vendor/assets/javascripts/transpiled.js.map
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user