mockup/contextual-menu: Closes #787, Dragging the same file back and forth gives err

Oshane Bailey <jenkins-z4DKO/[email protected]>
Newsgroups gmane.comp.web.zope.plone.cvs
Message-ID <[email protected]>
Repository: mockup
Branch: refs/heads/contextual-menu
Date: 2017-07-23T18:33:16Z
Author: Oshane Bailey (b4oshany) <[email protected]>
Commit: https://github.com/plone/mockup/commit/3a414c24b69e0c4573591d421cb88e320a519aa0

Closes #787, Dragging the same file back and forth gives error on file manager pattern

Files changed:
M bower.json
M mockup/js/config.js
M mockup/js/ui/templates/dropdown.xml
M mockup/js/ui/views/anchor.js
M mockup/patterns/filemanager/pattern.filemanager.less
M mockup/patterns/filemanager/pattern.js
M mockup/patterns/thememapper/pattern.js

diff --git a/bower.json b/bower.json
index 55232710..13cba75a 100644
--- a/bower.json
+++ b/bower.json
@@ -23,7 +23,9 @@
     "requirejs-text": "2.0.15",
     "select2": "3.5.4",
     "selectivizr": "1.0.2",
-    "tinymce-builded": "4.5.6"
+    "tinymce-builded": "4.5.6",
+    "js-shortcuts": "^1.0.1"
+    "cs-jqtree-contextmenu": "^0.1.0",
   },
   "devDependencies": {
     "expect": "0.3.1",
diff --git a/mockup/js/config.js b/mockup/js/config.js
index db006c03..7c49ed42 100644
--- a/mockup/js/config.js
+++ b/mockup/js/config.js
@@ -46,6 +46,7 @@
       'jquery.tools.dateinput': 'bower_components/jquery.recurrenceinput.js/lib/jquery.tools.dateinput',
       'jquery.tools.overlay': 'bower_components/jquery.recurrenceinput.js/lib/jquery.tools.overlay',
       'jquery.tmpl': 'bower_components/jquery.recurrenceinput.js/lib/jquery.tmpl',
+      'js-shortcuts': 'bower_components/js-shortcuts/js-shortcuts.js',
       'translate': 'js/i18n-wrapper',
       'marked': 'bower_components/marked/lib/marked',
       'mockup-bundles-docs': 'js/bundles/docs',
@@ -140,6 +141,7 @@
       'expect': { exports: 'window.expect' },
       'jqtree': { deps: ['jquery'] },
       'jqtree-contextmenu': { deps: ['jqtree'] },
+      'js-shortcuts': { deps: ['jquery'] },
       'select2': { deps: ["jquery"] },
       'jquery.cookie': { deps: ['jquery'] },
       'jquery.event.drag': { deps: ['jquery'] },
diff --git a/mockup/js/ui/templates/dropdown.xml b/mockup/js/ui/templates/dropdown.xml
index 34c20d25..82c130e7 100644
--- a/mockup/js/ui/templates/dropdown.xml
+++ b/mockup/js/ui/templates/dropdown.xml
@@ -1,6 +1,6 @@
 
 <a href="#" class="btn btn-default dropdown-toggle" type="button" id="dropdown-menu-" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
-  <span class="glyphicon glyphicon-search"></span>
+  <span class="glyphicon glyphicon-<%= icon %>"></span>
   <span class="dropdown-title">
 
   </span>
diff --git a/mockup/js/ui/views/anchor.js b/mockup/js/ui/views/anchor.js
index 9e0f8e4a..3d373ee2 100644
--- a/mockup/js/ui/views/anchor.js
+++ b/mockup/js/ui/views/anchor.js
@@ -11,12 +11,13 @@ define([
     eventPrefix: 'button',
     context: 'default',
     idPrefix: 'alink-',
+    shortcut: '',
     attributes: {
       'href': '#'
     },
     extraClasses: [],
     tooltip: null,
-    template: '<% if (icon) { %><span class="glyphicon glyphicon-<%= icon %>"></span><% } %> <%= title %>',
+    template: '<% if (icon) { %><span class="glyphicon glyphicon-<%= icon %>"></span><% } %> <%= title %> <span class="shortcut"><%= shortcut %></span>',
     events: {
       'click': 'handleClick'
     },
@@ -28,7 +29,7 @@ define([
       BaseView.prototype.initialize.apply(this, [options]);
 
       this.on('render', function() {
-        this.$el.attr('title', this.options.title || '');
+        this.$el.attr('title', this.options.tooltip || this.options.title || '');
         this.$el.attr('aria-label', this.options.title || this.options.tooltip || '');
         _.each(this.extraClasses, function(klass) {
           this.$el.addClass(klass);
@@ -42,7 +43,7 @@ define([
       }
     },
     serializedModel: function() {
-      return _.extend({'icon': '', 'title': ''}, this.options);
+      return _.extend({'icon': '', 'title': '', 'shortcut': ''}, this.options);
     },
     disable: function() {
       this.$el.prop('disabled', true);
diff --git a/mockup/patterns/filemanager/pattern.filemanager.less b/mockup/patterns/filemanager/pattern.filemanager.less
index f2049f80..ed7c07a3 100644
--- a/mockup/patterns/filemanager/pattern.filemanager.less
+++ b/mockup/patterns/filemanager/pattern.filemanager.less
@@ -47,6 +47,15 @@
         display: inline-block;
         margin: 0 !important;
         vertical-align: initial !important;
+        
+        span.shortcut {
+            display: inline-block;
+            float: right;
+        }
+
+        ul.dropdown-menu.items.dropdown-content {
+            min-width: 250px;
+        }
     }
     .input-group:extend(.input-group all){}
     .input-group-addon:extend(.input-group-addon all){}
diff --git a/mockup/patterns/filemanager/pattern.js b/mockup/patterns/filemanager/pattern.js
index f4e194ad..58fd9b47 100644
--- a/mockup/patterns/filemanager/pattern.js
+++ b/mockup/patterns/filemanager/pattern.js
@@ -53,12 +53,13 @@ define([
   'mockup-patterns-filemanager-url/js/upload',
   'translate',
   'mockup-utils',
+  'js-shortcuts',
   'text!mockup-ui-url/templates/popover.xml',
   'text!mockup-ui-url/templates/dropdown.xml'
 ], function($, Base, _, ContextMenu, Tree, TextEditor, AppTemplate, Toolbar,
   ButtonView, ButtonGroup, AnchorView, DropdownView,
   AddNewView, NewFolderView, FindFileView, FindInFilesView, DeleteView,
-  CustomizeView, RenameView, UploadView, _t, utils) {
+  CustomizeView, RenameView, UploadView, _t, utils, jsShortcuts) {
   'use strict';
 
   var FileManager = Base.extend({
@@ -127,58 +128,56 @@ define([
         id: 'save',
         title: _t('Save'),
         icon: 'floppy-disk',
-        context: 'primary'
+        context: 'primary',
+        shortcut: 'Ctrl-S'
       });
       self.btns = {
-        "newfolder": new ButtonView({
+        "newfolder": new AnchorView({
           id: 'newfolder',
           title: _t('New folder'),
           tooltip: _t('Add new folder to current directory'),
           icon: 'folder-open',
-          context: 'default'
+          context: 'default',
+          shortcut: 'Alt-Shift-N'
         }),
-        "newfile": new ButtonView({
+        "newfile": new AnchorView({
           id: 'addnew',
-          title: _t('Add new file'),
+          title: _t('New file'),
           tooltip: _t('Add new file to current folder'),
           icon: 'file',
-          context: 'default'
+          context: 'default',
+          shortcut: 'Alt-N'
         }),
         "findfile": new AnchorView({
           id: 'findfile',
           title: _t('Find File'),
           tooltip: _t('Find theme resource in plone'),
-          icon: 'file',
-          context: 'default'
+          icon: 'search',
+          context: 'default',
+          shortcut: 'Ctrl-F'
         }),
         "findtextinfile": new AnchorView({
           id: 'findinfiles',
           title: _t('Find in Files'),
           tooltip: _t('Find text within theme resource in plone'),
-          icon: 'file',
-          context: 'default'
+          icon: 'search',
+          context: 'default',
+          shortcut: 'Ctrl-E'
         }),
-        "rename": new ButtonView({
+        "rename": new AnchorView({
           id: 'rename',
           title: _t('Rename'),
           tooltip: _t('Rename currently selected resource'),
           icon: 'random',
           context: 'default'
         }),
-        "delete": new ButtonView({
+        "delete": new AnchorView({
           id: 'delete',
           title: _t('Delete'),
           tooltip: _t('Delete currently selected resource'),
           icon: 'trash',
           context: 'danger'
         }),
-        "upload": new ButtonView({
-            id: 'upload',
-            title: _t('Upload'),
-            tooltip: _t('Upload file to current directory'),
-            icon: 'upload',
-            context: 'default'
-        })
       };
 
       var newFolderView = new NewFolderView({
@@ -206,35 +205,71 @@ define([
         app: self
       });
 
+      var file_menu = new DropdownView({
+        title: _t('File'),
+        items: [
+          addNewView.triggerView,
+          newFolderView.triggerView
+        ],
+        id: 'file_menu',
+        app: self,
+        icon: 'file',
+        disable: function() {}
+      });
+
+      var edit_menu = new DropdownView({
+        title: _t('Edit'),
+        items: [
+          renameView.triggerView,
+          deleteView.triggerView
+        ],
+        id: 'edit_menu',
+        app: self,
+        icon: 'file',
+        disable: function() {}
+      });
+
       var find_menu = new DropdownView({
         title: _t('Find'),
         items: [
           findFileView.triggerView,
           findinFilesView.triggerView
         ],
-        id: 'find',
+        id: 'find_menu',
+        icon: 'search',
         app: self,
         disable: function() {}
       });
 
-      self.views = [
-        newFolderView,
-        addNewView,
-        findFileView,
-        findinFilesView,
-        renameView,
-        deleteView
-      ];
+      var views = {
+        "file_menu": [
+          newFolderView,
+          addNewView
+        ],
+        "edit_menu": [
+          renameView,
+          deleteView,
+        ],
+        "find_menu": [
+          findFileView,
+          findinFilesView
+        ],
+      };
       var mainButtons = [
         self.saveBtn,
-        newFolderView.triggerView,
-        addNewView.triggerView,
+        file_menu,
+        edit_menu,
         find_menu,
-        renameView.triggerView,
-        deleteView.triggerView
       ];
 
       if (self.options.uploadUrl && utils.featureSupport.dragAndDrop() && utils.featureSupport.fileApi()) {
+        self.btns["upload"] = new AnchorView({
+            id: 'upload',
+            title: _t('Upload Local Files...'),
+            tooltip: _t('Upload file to current directory'),
+            icon: 'upload',
+            context: 'default'
+        });
         var uploadView = new UploadView({
           triggerView: self.btns["upload"],
           app: self,
@@ -247,22 +282,28 @@ define([
 
           }
         });
-        self.views.push(uploadView);
-        mainButtons.push(uploadView.triggerView);
+        
+        views.file_menu.push(uploadView);
+        file_menu.items.push(uploadView.triggerView);
       }
       if (self.options.resourceSearchUrl) {
+        self.btns["customize"] = new AnchorView({
+          id: 'customize',
+          title: _t('Add new override'),
+          tooltip: _t('Find resource in plone to override'),
+          context: 'default'
+        });
         var customizeView = new CustomizeView({
-          triggerView: new ButtonView({
-            id: 'customize',
-            title: _t('Add new override'),
-            tooltip: _t('Find resource in plone to override'),
-            context: 'default'
-          }),
+          triggerView: self.btns["customize"],
           app: self
         });
-        self.views.push(customizeView);
-        mainButtons.push(customizeView.triggerView);
+        views["edit_menu"].push(customizeView);
+        edit_menu.items.push(customizeView.triggerView);
       }
+      console.log(mainButtons);
+      console.log(views);
+      self.views = [];
+      self.views = self.views.concat(views.file_menu).concat(views.edit_menu).concat(views.find_menu);
 
       self.toolbar = new Toolbar({
         items: [
@@ -301,7 +342,29 @@ define([
         self._save();
       });
       self.render();
+      self.shortcuts();
+      
     },
+    
+    shortcuts: function(){
+      var self = this;
+      shortcut.add("Alt+N", function () {
+        self.btns.newfile.$el.click();
+      });
+      shortcut.add("Alt+Shift+N", function () {
+        self.btns.newfolder.$el.click();
+      });
+      shortcut.add("Ctrl+S", function () {
+        self.saveBtn.$el.click();
+      });
+      shortcut.add("Ctrl+F", function () {
+        self.btns.findfile.$el.click();
+      });
+      shortcut.add("Ctrl+E", function () {
+        self.btns.findtextinfile.$el.click();
+      });
+    },
+    
     $: function(selector) {
       return this.$el.find(selector);
     },
@@ -372,8 +435,9 @@ define([
 
       self.$tree.bind('tree.move', function(event) {
         
+        var target_node = event.move_info.target_node;
         var srcpath = event.move_info.moved_node.path;
-        var newpath = event.move_info.target_node.path;
+        var newpath = target_node.path;
         if (event.move_info.position !== "inside" ){
           newpath = newpath.substring(newpath.indexOf('/'), newpath.lastIndexOf('/'));
         }
@@ -386,6 +450,9 @@ define([
           dataType: 'json',
           success: function(data) {
             console.log(data);
+            self.$tree.tree('reload', function() {
+              self.$tree.tree('selectNode', target_node);
+            });
             var jdata = JSON.parse(data);
             if(jdata.error != ''){
               alert(jdata.error);
diff --git a/mockup/patterns/thememapper/pattern.js b/mockup/patterns/thememapper/pattern.js
index b8c21767..ef016f7b 100644
--- a/mockup/patterns/thememapper/pattern.js
+++ b/mockup/patterns/thememapper/pattern.js
@@ -39,8 +39,12 @@ define([
   'mockup-patterns-thememapper-url/js/cacheview',
   'mockup-ui-url/views/button',
   'mockup-ui-url/views/buttongroup',
+  'mockup-ui-url/views/anchor',
+  'mockup-ui-url/views/dropdown',
   'mockup-utils'
-], function($, Base, _, _t, InspectorTemplate, FileManager, RuleBuilder, RuleBuilderView, LessBuilderView, CacheView, ButtonView, ButtonGroup, utils) {
+], function($, Base, _, _t, InspectorTemplate, FileManager, RuleBuilder, RuleBuilderView,
+            LessBuilderView, CacheView, ButtonView, ButtonGroup,
+            AnchorView, DropdownView, utils) {
   'use strict';
 
   var inspectorTemplate = _.template(InspectorTemplate);
@@ -317,6 +321,8 @@ define([
       self.fileManager = new FileManager(self.$fileManager, self.options.filemanagerConfig);
       self.fileManager.setUploadUrl();
 
+      self.btns = {};
+      self.menus = {};
       self.setupButtons();
 
       self.ruleBuilder = new RuleBuilder(self, self.ruleBuilderCallback);
@@ -337,7 +343,7 @@ define([
         ruleBuilder: self.ruleBuilder,
         url: self.options.unthemedUrl,
       });
-      self.buildLessButton.disable();
+      self.btns.buildLessButton.disable();
 
       if(!self.options.editable) {
         if(self.fileManager.toolbar) {
@@ -382,10 +388,10 @@ define([
       var self = this;
 
       if(node.fileType === 'less'){
-        self.buildLessButton.enable();
+        self.btns.buildLessButton.enable();
       }
       else {
-        self.buildLessButton.disable();
+        self.btns.buildLessButton.disable();
       }
 
       if (node.path !== '') {
@@ -469,8 +475,8 @@ define([
       var $parent = self.$mockupInspector.parent();
       $parent.slideDown();
       self.hidden = false;
-      self.showInspectorsButton.options.title = 'Hide inspectors';
-      self.showInspectorsButton.applyTemplate();
+      self.btns.showInspectorsButton.options.title = 'Hide inspectors';
+      self.btns.showInspectorsButton.applyTemplate();
       $('html, body').animate({
         scrollTop: $parent.offset().top - 50
       }, 500);
@@ -480,41 +486,41 @@ define([
       var $parent = self.$mockupInspector.parent();
       $parent.slideUp();
       self.hidden = true;
-      self.showInspectorsButton.options.title = 'Show inspectors';
-      self.showInspectorsButton.applyTemplate();
+      self.btns.showInspectorsButton.options.title = 'Show inspectors';
+      self.btns.showInspectorsButton.applyTemplate();
     },
     setupButtons: function(){
       var self = this;
-      self.showInspectorsButton = new ButtonView({
+      self.btns.showInspectorsButton = new ButtonView({
         id: 'showinspectors',
         title: _t('Show inspectors'),
         icon: 'search',
         tooltip: _t('Show inspector panels'),
         context: 'default'
       });
-      self.showInspectorsButton.on('button:click', function(){
+      self.btns.showInspectorsButton.on('button:click', function(){
         if (self.hidden) {
           self.showInspectors();
         } else {
           self.hideInspectors();
         }
       });
-
-      self.buildRuleButton = new ButtonView({
+      
+      self.btns.buildRuleButton = new AnchorView({
         id: 'buildrule',
         title: _t('Build rule'),
         icon: 'wrench',
         tooltip: _t('rule building wizard'),
         context: 'default'
       });
-      self.fullscreenButton = new ButtonView({
+      self.btns.fullscreenButton = new ButtonView({
         id: 'fullscreenEditor',
         title: _t('Fullscreen'),
         icon: 'fullscreen',
         tooltip: _t('view the editor in fullscreen'),
         context: 'default'
       });
-      self.fullscreenButton.on('button:click', function() {
+      self.btns.fullscreenButton.on('button:click', function() {
         var btn = $('<a href="#">'+
             '<span class="btn btn-danger closeeditor">' + _t('Close Fullscreen') + '</span>'+
             '</a>').prependTo($('.tree'));
@@ -536,62 +542,75 @@ define([
       self.previewThemeButton.on('button:click', function(){
         window.open(self.options.previewUrl);
       });
-      self.buildLessButton = new ButtonView({
+      self.btns.buildLessButton = new AnchorView({
         id: 'buildless',
         title: _t('Build CSS'),
         icon: 'cog',
         tooltip: _t('Compile LESS file'),
         context: 'default'
       });
-      self.refreshButton = new ButtonView({
+      self.btns.refreshButton = new ButtonView({
         id: 'refreshButton ',
         title: _t('Refresh'),
         icon: 'refresh',
         tooltip: _t('Reload the current file'),
         context: 'default'
       });
-      self.refreshButton.on('button:click', function() {
+      self.btns.refreshButton.on('button:click', function() {
         self.fileManager.refreshFile();
       });
-      self.cacheButton = new ButtonView({
+      self.btns.cacheButton = new ButtonView({
         id: 'cachebutton',
         title: _t('Clear cache'),
         icon: 'floppy-remove',
         tooltip: _t('Clear site\'s theme cache'),
         context: 'default'
       });
-      self.helpButton = new ButtonView({
+      self.btns.helpButton = new ButtonView({
         id: 'helpbutton',
         title: _t('Help'),
         icon: 'question-sign',
         tooltip: _t('Show help'),
         context: 'default'
       });
-      self.helpButton.on('button:click', function(){
+      self.btns.helpButton.on('button:click', function(){
         window.open(self.options.helpUrl);
       });
       self.rulebuilderView = new RuleBuilderView({
-        triggerView: self.buildRuleButton,
+        triggerView: self.btns.buildRuleButton,
         app: self
       });
       self.cacheView = new CacheView({
-        triggerView: self.cacheButton,
+        triggerView: self.btns.cacheButton,
         app: self
       });
       self.lessbuilderView = new LessBuilderView({
-        triggerView: self.buildLessButton,
+        triggerView: self.btns.buildLessButton,
         app: self
       });
+      
+
+      self.menus.tools = new DropdownView({
+        title: _t('Tools'),
+        items: [
+          self.btns.buildRuleButton,
+          self.btns.buildLessButton,
+        ],
+        id: 'file_menu',
+        app: self,
+        icon: 'file',
+        disable: function() {}
+      });
+      
       self.buttonGroup = new ButtonGroup({
         items: [
-          self.showInspectorsButton,
-          self.buildRuleButton,
+          self.menus.tools,
+          self.btns.showInspectorsButton,
           self.previewThemeButton,
-          self.fullscreenButton,
-          self.buildLessButton,
-          self.refreshButton,
-          self.cacheButton,
-          self.helpButton
+          self.btns.fullscreenButton,
+          self.btns.refreshButton,
+          self.btns.cacheButton,
+          self.btns.helpButton
         ],
         id: 'mapper'
       });



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.