mockup/master: Merge pull request #773 from plone/theme-filemanager-searchi
GitHub <jenkins-z4DKO/[email protected]>
| Newsgroups | gmane.comp.web.zope.plone.cvs |
|---|---|
| Message-ID | <[email protected]> |
Repository: mockup Branch: refs/heads/master Date: 2017-07-14T00:11:39+03:00 Author: Asko Soukka (datakurre) <[email protected]> Commit: https://github.com/plone/mockup/commit/413bc2b66ef07d28d1a850cd61853397aacb5c22 Merge pull request #773 from plone/theme-filemanager-searching-feature Add search menu to search files by name and contents in filemanager pattern Files changed: A mockup/js/ui/templates/dropdown.xml A mockup/js/ui/views/anchor.js A mockup/js/ui/views/dropdown.js A mockup/patterns/filemanager/js/findfile.js A mockup/patterns/filemanager/js/findinfiles.js A mockup/patterns/filemanager/templates/popover.xml M .gitignore M CHANGES.rst M mockup/js/bundles/filemanager.js M mockup/patterns/filemanager/js/basepopover.js M mockup/patterns/filemanager/pattern.filemanager.less M mockup/patterns/filemanager/pattern.js M mockup/patterns/filemanager/templates/app.xml M mockup/patterns/thememapper/pattern.thememapper.less M mockup/patterns/tree/pattern.js diff --git a/.gitignore b/.gitignore index 687ae184..69d17555 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.orig *.egg-info *.py? .idea diff --git a/CHANGES.rst b/CHANGES.rst index acb27972..a5f16fbb 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -23,6 +23,17 @@ Bug fixes: New features: + - Improve the user experience for the theme editor + - Search for files and text within files and opening the file upon click. + - Add Bootstrap Dropdown menu to the UI views. + - Enable Drag and Drop inside of the theme editor file tree. + - Fixed the Drag and Drop files to root of the file tree. + - Fixed the autoscrolling issue when dragging a file in the file tree. + - Add Anchor (a) tag to the UI views. + - Upgrade JQTree to 1.4.1 + - Enable Drag and Drop inside of the theme editor file tree. + [b4oshany] + - Make thumb scale in folder contents listing adjustable/supressable. Replace meaningless paper clip icon (fontello) with mime type icons from mimetype registry. https://github.com/plone/Products.CMFPlone/issues/1734 diff --git a/mockup/js/bundles/filemanager.js b/mockup/js/bundles/filemanager.js index 18c3b196..84778497 100644 --- a/mockup/js/bundles/filemanager.js +++ b/mockup/js/bundles/filemanager.js @@ -1,6 +1,6 @@ define([ 'pat-registry', - 'mockup-patterns-filemanager' + 'mockup-patterns-filemanager', ], function(registry) { 'use strict'; // initialize only if we are in top frame diff --git a/mockup/js/ui/templates/dropdown.xml b/mockup/js/ui/templates/dropdown.xml new file mode 100644 index 00000000..34c20d25 --- /dev/null +++ b/mockup/js/ui/templates/dropdown.xml @@ -0,0 +1,10 @@ + +<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="dropdown-title"> + + </span> + <span class="caret"></span> +</a> +<ul class="dropdown-menu items dropdown-content" aria-labelledby="dropdown-menu-"> +</ul> diff --git a/mockup/js/ui/views/anchor.js b/mockup/js/ui/views/anchor.js new file mode 100644 index 00000000..9e0f8e4a --- /dev/null +++ b/mockup/js/ui/views/anchor.js @@ -0,0 +1,56 @@ +define([ + 'underscore', + 'mockup-ui-url/views/base', + 'mockup-patterns-tooltip' +], function(_, BaseView, Tooltip) { + 'use strict'; + + var AnchorView = BaseView.extend({ + tagName: 'a', + className: 'alink', + eventPrefix: 'button', + context: 'default', + idPrefix: 'alink-', + attributes: { + 'href': '#' + }, + extraClasses: [], + tooltip: null, + template: '<% if (icon) { %><span class="glyphicon glyphicon-<%= icon %>"></span><% } %> <%= title %>', + events: { + 'click': 'handleClick' + }, + initialize: function(options) { + if (!options.id) { + var title = options.title || ''; + options.id = title !== '' ? title.toLowerCase().replace(' ', '-') : this.cid; + } + BaseView.prototype.initialize.apply(this, [options]); + + this.on('render', function() { + this.$el.attr('title', this.options.title || ''); + this.$el.attr('aria-label', this.options.title || this.options.tooltip || ''); + _.each(this.extraClasses, function(klass) { + this.$el.addClass(klass); + }); + }, this); + }, + handleClick: function(e) { + e.preventDefault(); + if (!this.$el.prop('disabled')) { + this.uiEventTrigger('click', this, e); + } + }, + serializedModel: function() { + return _.extend({'icon': '', 'title': ''}, this.options); + }, + disable: function() { + this.$el.prop('disabled', true); + }, + enable: function() { + this.$el.prop('disabled', false); + } + }); + + return AnchorView; +}); diff --git a/mockup/js/ui/views/dropdown.js b/mockup/js/ui/views/dropdown.js new file mode 100644 index 00000000..90eb79f9 --- /dev/null +++ b/mockup/js/ui/views/dropdown.js @@ -0,0 +1,59 @@ +define([ + 'jquery', + 'underscore', + 'mockup-ui-url/views/buttongroup', + 'text!mockup-ui-url/templates/dropdown.xml', +], function($, _, ButtonGroup, DropdownTemplate) { + 'use strict'; + + var DropdownView = ButtonGroup.extend({ + idPrefix: 'btngroup-dropdown-', + template: DropdownTemplate, + className: 'btn-group-dropdown', + itemContainer: "ul.dropdown-content", + title: null, + + initialize: function(options) { + ButtonGroup.prototype.initialize.apply(this, [options]); + + this.on('render', function() { + this.renderTitle(); + }, this); + }, + + renderTitle: function() { + var title = this.options.title; + if(this.options.title === undefined) { + title = this.title; + if(this.title === null) { + title = "Menu Option"; + } + } + this.$('.dropdown-title').empty().append(title); + }, + + renderItems: function() { + var self = this; + var $container; + + if (this.itemContainer !== null) { + $container = $(this.itemContainer, this.$el); + if ($container.length === 0) { + throw 'Item Container element not found.'; + } + } else { + $container = this.$el; + } + + var $item = null; + _.each(this.items, function(view) { + $item = $("<li></li>"); + $item.append(view.render().$el.removeClass("btn")); + $container.append($item); + }, this); + }, + + }); + + return DropdownView; +}); diff --git a/mockup/patterns/filemanager/js/basepopover.js b/mockup/patterns/filemanager/js/basepopover.js index fee2ab53..301002b3 100644 --- a/mockup/patterns/filemanager/js/basepopover.js +++ b/mockup/patterns/filemanager/js/basepopover.js @@ -1,22 +1,53 @@ define([ + 'jquery', 'underscore', - 'mockup-ui-url/views/popover' -], function(_, PopoverView) { + 'mockup-ui-url/views/popover', + 'text!mockup-patterns-filemanager-url/templates/popover.xml', +], function($, _, PopoverView, PopoverTemplate) { 'use strict'; var FileManagerPopover = PopoverView.extend({ className: 'popover', title: _.template('nothing'), content: _.template('<div/>'), + template: PopoverTemplate, initialize: function(options) { this.app = options.app; PopoverView.prototype.initialize.apply(this, [options]); }, + afterRender: function () { + var self = this; + self.$el.find(".popover-close").click(function(e){ + self.hide(true); + }); + return self; + }, + getBodyClassName: function(){ + var name = 'popover-'; + if(this.options.id){ + name += this.options.id + '-'; + } + name += 'active'; + return name; + }, render: function() { var self = this; PopoverView.prototype.render.call(this); return self; }, + hide: function(closePopover) { + if(this.closeOnOutClick || closePopover == true){ + this.opened = false; + this.$el.removeClass('active'); + if (this.triggerView) { + this.triggerView.$el.removeClass('active'); + this.triggerView.$el.attr('aria-hidden', 'true'); + } + this.uiEventTrigger('hide', this); + this.$el.attr('aria-hidden', 'true'); + $('body').removeClass(this.getBodyClassName()); + } + }, toggle: function(button, e) { PopoverView.prototype.toggle.apply(this, [button, e]); var self = this; diff --git a/mockup/patterns/filemanager/js/findfile.js b/mockup/patterns/filemanager/js/findfile.js new file mode 100644 index 00000000..d4c0c3dd --- /dev/null +++ b/mockup/patterns/filemanager/js/findfile.js @@ -0,0 +1,101 @@ +define([ + 'jquery', + 'underscore', + 'mockup-patterns-filemanager-url/js/basepopover', + 'translate' +], function($, _, PopoverView, _t) { + 'use strict'; + + var FindFile = PopoverView.extend({ + className: 'popover filesearch', + closeOnOutClick: false, + backdropOptions: { + zIndex: '1009', + opacity: '0.4', + className: 'backdrop backdrop-popover', + classActiveName: 'backdrop-active', + closeOnEsc: false, + closeOnClick: false + }, + title: _.template('<%= _t("Find File") %>'), + content: _.template( + '<form>' + + '<div class="input-group">' + + '<input type="text" class="search form-control" ' + + 'id="file-search-field" placeholder="<%= _t("Find theme resource in plone") %>">' + + '</div>' + + '<div class="input-group">' + + '<input type="submit" class="btn btn-primary" value="<%= _t("Search") %>"/>' + + '</div>' + + '</form><br/>' + + '<ul class="results list-group">' + + '</ul>' + ), + appendToResults: function(item){ + var self = this; + var $item = $( + '<li class="list-group-item">' + + '<span class="badge"><a data-target="' + item.path + '" href=#">' + + _t(item.filename) + '</a></span>' + + '</li>'); + $('a', $item).click(function(e) { + e.preventDefault(); + self.findfile($(this).attr('data-target')); + }); + self.$results.append($item); + }, + filterFiles: function(patt, data){ + var self = this; + _.each(data, function(item) { + if(item.folder){ + self.filterFiles(patt, item.children); + }else{ + if(patt.test(item.filename)){ + self.appendToResults(item); + self.noMatches++; + } + } + }); + }, + render: function() { + var self = this; + PopoverView.prototype.render.call(this); + self.$form = self.$('form'); + self.$searchFor = self.$("input"); + self.$results = self.$('.results'); + self.$form.submit(function(e) { + e.preventDefault(); + $.ajax({ + url: self.app.options.actionUrl + '?action=dataTree', + dataType: 'json', + success: function(data) { + self.$results.empty(); + self.noMatches = 0; + var searchFor = self.$searchFor.val(); + var patt = new RegExp(searchFor, "g"); + self.filterFiles(patt, data); + if(self.noMatches == 0){ + self.$results.append("<span>No results found for " + searchFor + "</span>"); + } + } + }); + }); + return self; + }, + findfile: function(resource) { + var self = this; + self.app.doAction('getFile', { + data: { + path: resource + }, + dataType: 'json', + success: function(data) { + self.app.fileData[resource] = data; + self.app.openEditor(resource); + } + }); + } + }); + + return FindFile; +}); diff --git a/mockup/patterns/filemanager/js/findinfiles.js b/mockup/patterns/filemanager/js/findinfiles.js new file mode 100644 index 00000000..32b4dd80 --- /dev/null +++ b/mockup/patterns/filemanager/js/findinfiles.js @@ -0,0 +1,137 @@ +define([ + 'jquery', + 'underscore', + 'mockup-patterns-filemanager-url/js/basepopover', + 'translate' +], function($, _, PopoverView, _t) { + 'use strict'; + + var FindInFiles = PopoverView.extend({ + className: 'popover filesearch', + closeOnOutClick: false, + backdropOptions: { + zIndex: '1009', + opacity: '0.4', + className: 'backdrop backdrop-popover', + classActiveName: 'backdrop-active', + closeOnEsc: false, + closeOnClick: false + }, + title: _.template('<%= _t("File in File") %>'), + content: _.template( + '<form>' + + '<div class="input-group">' + + '<input type="text" class="search form-control" ' + + 'id="file-search-field" placeholder="<%= _t("Find text witin theme resource in plone") %>">' + + '</div>' + + '<div class="input-group">' + + '<input type="submit" class="btn btn-primary" value="<%= _t("Search") %>"/>' + + '</div>' + + '</form><br/>' + + '<ul style="max-height: 400px; overflow: auto;" class="results list-group">' + + '</ul>' + ), + appendToResults: function(item){ + var self = this, seen = null; + var file_item = + '<li class="list-group-item" data-id="' + item.file.label + '">' + + '<span class="badge">' + _t(item.file.filename) + '</span><ul>'; + for(var x in item.lines){ + seen = item.lines[x]; + file_item += '<li class="list-group-item" data-id="' + item.file.label + '">' + + '<span class="badge"><a class="ff-open-file" data-target="'+item.file.path+'" ' + + 'target-line="'+seen.line+'" href="#">Line ' + + '<span style="display: inline-block; width: 100px;">' + seen.line + + '</span><span>'+seen.text+'</span><a></span></li>'; + } + file_item += '</ul></li>'; + var $item = $(file_item); + $('a', $item).click(function(e) { + e.preventDefault(); + self.findinfiles( + $(this).attr("data-target"), + parseInt($(this).attr("target-line")) + ); + }); + self.$results.append($item); + }, + + filterFile: function(patt, item){ + var self = this; + $.ajax({ + url: self.app.options.actionUrl + '?action=getFile&path='+item.path.replace("/", "%2F"), + dataType: 'json', + success: function(data) { + var contents = data["contents"]; + if(contents == undefined){ + return; + } + var lines = contents.split("\n"); + var seen = [], line = ''; + var result = null; + for(var x in lines){ + line = lines[x]; + result = patt.exec(line); + if(result != null){ + seen.push({ + "line": parseInt(x) + 1, + "text": '<b>'+result[0]+'</b>'+line.substr(result["index"] + result[0].length, 20) + }); + } + } + if(seen.length > 0){ + self.appendToResults({file: item, lines: seen}); + self.noMatches += seen.length; + } + } + }); + }, + filterFiles: function(patt, data){ + var self = this; + _.each(data, function(item) { + if(item.folder){ + self.filterFiles(patt, item.children); + }else{ + self.filterFile(patt, item); + } + }); + }, + render: function() { + var self = this; + PopoverView.prototype.render.call(this); + self.$form = self.$('form'); + self.$searchFor = self.$("input"); + self.$results = self.$('.results'); + self.$form.submit(function(e) { + e.preventDefault(); + $.ajax({ + url: self.app.options.actionUrl + '?action=dataTree', + dataType: 'json', + success: function(data) { + self.$results.empty(); + self.noMatches = 0; + var searchFor = self.$searchFor.val(); + var patt = new RegExp(searchFor, "g"); + self.filterFiles(patt, data); + } + }); + }); + return self; + }, + findinfiles: function(resource, line) { + var self = this; + self.app.doAction('getFile', { + data: { + path: resource + }, + dataType: 'json', + success: function(data) { + self.app.fileData[resource] = data; + self.app.openEditor(resource, {goToLine: line}); + } + }); + } + }); + + return FindInFiles; +}); diff --git a/mockup/patterns/filemanager/pattern.filemanager.less b/mockup/patterns/filemanager/pattern.filemanager.less index b5fd4216..f2049f80 100644 --- a/mockup/patterns/filemanager/pattern.filemanager.less +++ b/mockup/patterns/filemanager/pattern.filemanager.less @@ -27,6 +27,11 @@ .popover:extend(.popover all){} .popover-title:extend(.popover-title all){} .popover-content:extend(.popover-content all){} + + .popover{ + max-width: 600px; + } + .arrow:extend(.arrow all){} .table:extend(.table all){} @@ -38,6 +43,11 @@ .btn-primary:extend(.btn-primary all){} .btn-group:extend(.btn-group all){} .btn-success:extend(.btn-success all){} + .btn-group-dropdown:extend(.btn-group all){ + display: inline-block; + margin: 0 !important; + vertical-align: initial !important; + } .input-group:extend(.input-group all){} .input-group-addon:extend(.input-group-addon all){} .input-group-btn:extend(.input-group-btn all){} @@ -112,6 +122,33 @@ margin-bottom: 0.5em; text-decoration: none; } + .btn-group > .btn-group-dropdown{ + float: none; + display: inline-block; + text-decoration: none; + + & > a.btn { + margin-bottom: 0.5em; + border-radius: 0; + float: none; + display: inline-block; + text-decoration: none; + padding: 5px 5px 8px 5px; + line-height: 10px; + font-size: 13px; + } + + &:last-child > a.btn{ + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; + } + + &:first-child > a.btn{ + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; + } + + } } .navbar-default { min-height: 250px diff --git a/mockup/patterns/filemanager/pattern.js b/mockup/patterns/filemanager/pattern.js index 24a14c54..d6a37f3c 100644 --- a/mockup/patterns/filemanager/pattern.js +++ b/mockup/patterns/filemanager/pattern.js @@ -40,17 +40,23 @@ define([ 'mockup-ui-url/views/toolbar', 'mockup-ui-url/views/button', 'mockup-ui-url/views/buttongroup', + 'mockup-ui-url/views/anchor', + 'mockup-ui-url/views/dropdown', 'mockup-patterns-filemanager-url/js/addnew', 'mockup-patterns-filemanager-url/js/newfolder', + 'mockup-patterns-filemanager-url/js/findfile', + 'mockup-patterns-filemanager-url/js/findinfiles', 'mockup-patterns-filemanager-url/js/delete', 'mockup-patterns-filemanager-url/js/customize', 'mockup-patterns-filemanager-url/js/rename', 'mockup-patterns-filemanager-url/js/upload', 'translate', 'mockup-utils', - 'text!mockup-ui-url/templates/popover.xml' + 'text!mockup-ui-url/templates/popover.xml', + 'text!mockup-ui-url/templates/dropdown.xml' ], function($, Base, _, Tree, TextEditor, AppTemplate, Toolbar, - ButtonView, ButtonGroup, AddNewView, NewFolderView, DeleteView, + ButtonView, ButtonGroup, AnchorView, DropdownView, + AddNewView, NewFolderView, FindFileView, FindInFilesView, DeleteView, CustomizeView, RenameView, UploadView, _t, utils) { 'use strict'; @@ -89,13 +95,21 @@ define([ self.options.treeConfig = $.extend(true, {}, self.treeConfig, { dataUrl: self.options.actionUrl + '?action=dataTree', + dragAndDrop: true, + useContextMenu: true, + onCanMoveTo: function(moved, target, position) { + /* if not using folder option, just allow, otherwise, only allow if folder */ + if (position === "inside") { + return target.folder === undefined || target.folder === true; + } + return true; + }, onCreateLi: function(node, li) { var imageTypes = ['png', 'jpg', 'jpeg', 'gif', 'ico']; var themeTypes = ['css', 'html', 'htm', 'txt', 'xml', 'js', 'cfg', 'less']; - $('span', li).addClass('glyphicon'); if (node.folder) { - $('span', li).addClass('glyphicon-folder-close'); + $('span', li).addClass('glyphicon-folder-close').addClass("droptarget"); } else if ($.inArray(node.fileType, imageTypes) >= 0) { $('span', li).addClass('glyphicon-picture'); } else if ($.inArray(node.fileType, themeTypes) >= 0) { @@ -114,51 +128,92 @@ define([ icon: 'floppy-disk', context: 'primary' }); - - var newFolderView = new NewFolderView({ - triggerView: new ButtonView({ + self.btns = { + "newfolder": new ButtonView({ id: 'newfolder', title: _t('New folder'), tooltip: _t('Add new folder to current directory'), icon: 'folder-open', context: 'default' }), - app: self - }); - var addNewView = new AddNewView({ - triggerView: new ButtonView({ + "newfile": new ButtonView({ id: 'addnew', title: _t('Add new file'), tooltip: _t('Add new file to current folder'), icon: 'file', context: 'default' }), - app: self - }); - var renameView = new RenameView({ - triggerView: new ButtonView({ + "findfile": new AnchorView({ + id: 'findfile', + title: _t('Find File'), + tooltip: _t('Find theme resource in plone'), + icon: 'file', + context: 'default' + }), + "findtextinfile": new AnchorView({ + id: 'findinfiles', + title: _t('Find in Files'), + tooltip: _t('Find text within theme resource in plone'), + icon: 'file', + context: 'default' + }), + "rename": new ButtonView({ id: 'rename', title: _t('Rename'), tooltip: _t('Rename currently selected resource'), icon: 'random', context: 'default' }), - app: self - }); - var deleteView = new DeleteView({ - triggerView: new ButtonView({ + "delete": new ButtonView({ id: 'delete', title: _t('Delete'), tooltip: _t('Delete currently selected resource'), icon: 'trash', context: 'danger' - }), + }) + }; + + var newFolderView = new NewFolderView({ + triggerView: self.btns["newfolder"], + app: self + }); + var addNewView = new AddNewView({ + triggerView: self.btns["newfile"], + app: self + }); + var findFileView = new FindFileView({ + triggerView: self.btns["findfile"], + app: self + }); + var findinFilesView = new FindInFilesView({ + triggerView: self.btns["findtextinfile"], + app: self + }); + var renameView = new RenameView({ + triggerView: self.btns["rename"], + app: self + }); + var deleteView = new DeleteView({ + triggerView: self.btns["delete"], app: self }); + var find_menu = new DropdownView({ + title: _t('Find'), + items: [ + findFileView.triggerView, + findinFilesView.triggerView + ], + id: 'find', + app: self, + disable: function() {} + }) + self.views = [ newFolderView, addNewView, + findFileView, + findinFilesView, renameView, deleteView ]; @@ -166,6 +221,7 @@ define([ self.saveBtn, newFolderView.triggerView, addNewView.triggerView, + find_menu, renameView.triggerView, deleteView.triggerView ]; @@ -299,6 +355,30 @@ define([ } }); + self.$tree.bind('tree.move', function(event) { + + var srcpath = event.move_info.moved_node.path; + var newpath = event.move_info.target_node.path; + if (event.move_info.position !== "inside" ){ + newpath = newpath.substring(newpath.indexOf('/'), newpath.lastIndexOf('/')); + } + + self.doAction('move', { + data: { + source: srcpath, + destination: newpath + }, + dataType: 'json', + success: function(data) { + console.log(data); + var jdata = JSON.parse(data); + if(jdata.error != ''){ + alert(jdata.error); + } + } + }); + }); + self.$tree.bind('tree.open', function(e) { var element = $(e.node.element).find(':first').find('.glyphicon'); $(element).addClass('glyphicon-folder-open'); @@ -525,12 +605,15 @@ define([ failure: options.failure || function() {} }); }, - openEditor: function(path) { + openEditor: function(path, options) { var self = this; if (path !== undefined) { self.updateTabs(path); } + if (options === undefined) { + options = {}; + } // first we need to save the current editor content if (self.currentPath) { @@ -567,6 +650,10 @@ define([ } self.resizeEditor(); + if(options.goToLine != undefined){ + self.ace.editor.gotoLine(options.goToLine, 0, true); + } + self.$el.trigger('fileChange'); self.ace.editor.on('change', function() { if (self.ace.editor.curOp && self.ace.editor.curOp.command.name) { diff --git a/mockup/patterns/filemanager/templates/app.xml b/mockup/patterns/filemanager/templates/app.xml index 11d594ff..e5194500 100644 --- a/mockup/patterns/filemanager/templates/app.xml +++ b/mockup/patterns/filemanager/templates/app.xml @@ -1,5 +1,7 @@ <div id="toolbar"> </div> +<div id="toolbar-action"> +</div> <div class="container"> <div class="tree"> </div> @@ -14,4 +16,4 @@ </div> </div> </nav> -</div> \ No newline at end of file +</div> diff --git a/mockup/patterns/filemanager/templates/popover.xml b/mockup/patterns/filemanager/templates/popover.xml new file mode 100644 index 00000000..a276f070 --- /dev/null +++ b/mockup/patterns/filemanager/templates/popover.xml @@ -0,0 +1,12 @@ +<div class="arrow"></div> +<div class="popover-label"> +<div style="position: relative;" class="popover-title"> +</div> +<a style="position: absolute; top: 5px; right: 3px; font-size: 16px; color: #999;" + href="#" class="popover-close"> + <span class="glyphicon glyphicon-remove"></span> +</a> +</div> +<div class="items popover-content"> +</div> + diff --git a/mockup/patterns/thememapper/pattern.thememapper.less b/mockup/patterns/thememapper/pattern.thememapper.less index 7666065a..4c58cce6 100644 --- a/mockup/patterns/thememapper/pattern.thememapper.less +++ b/mockup/patterns/thememapper/pattern.thememapper.less @@ -1,6 +1,6 @@ @import "@{mockuplessPath}/ui.less"; /* just be lazy here and include all of bootstrap... */ -@import "@{mockupPath}/filemanager/pattern.filemanager.less"; +@import "@{mockup-patterns-filemanager}"; body.plone-toolbar-left-default { padding-left: 0px; diff --git a/mockup/patterns/tree/pattern.js b/mockup/patterns/tree/pattern.js index 2be19804..3667140c 100644 --- a/mockup/patterns/tree/pattern.js +++ b/mockup/patterns/tree/pattern.js @@ -79,11 +79,14 @@ define([ } } - if (self.options.dragAndDrop && self.options.onCanMoveTo === undefined) { + if (self.options.onCanMoveTo === undefined) { self.options.onCanMoveTo = function(moved, target, position) { /* if not using folder option, just allow, otherwise, only allow if folder */ - return target.folder === undefined || target.folder === true; - }; + if (position === "inside") { + return target.folder === undefined || target.folder === true; + } + return true; + } } if (self.options.data && typeof(self.options.data) === 'string') { ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot