diff --git a/core/lexicon/en/file.inc.php b/core/lexicon/en/file.inc.php index 762dd752194..5c0627cefd1 100644 --- a/core/lexicon/en/file.inc.php +++ b/core/lexicon/en/file.inc.php @@ -61,6 +61,7 @@ $_lang['file_folder_parent_desc'] = 'Relative to the basePath of the media source'; $_lang['file_folder_remove'] = 'Delete Directory'; $_lang['file_folder_remove_confirm'] = 'Are you sure you want to delete the directory: "[[+directory]]"?
This could potentially break your website.'; +$_lang['file_folder_move_confirm'] = 'Are you sure you want to move "[[+item]]" to "[[+destination]]"? This could break your site if done accidentally.'; $_lang['file_folder_rename'] = 'Rename Directory'; $_lang['file_last_accessed'] = 'Last Accessed'; $_lang['file_last_modified'] = 'Last Modified'; diff --git a/manager/assets/modext/widgets/system/modx.tree.directory.js b/manager/assets/modext/widgets/system/modx.tree.directory.js index 77a154bfc24..f3757c3c692 100644 --- a/manager/assets/modext/widgets/system/modx.tree.directory.js +++ b/manager/assets/modext/widgets/system/modx.tree.directory.js @@ -342,34 +342,55 @@ Ext.extend(MODx.tree.Directory,MODx.tree.Tree,{ destSource = dropEvent.tree.source; } - MODx.Ajax.request({ - url: this.config.url - ,params: { - source: orgSource - ,from: from - ,destSource: destSource - ,to: to - ,action: this.config.sortAction || 'Browser/Directory/Sort' - ,point: dropEvent.point - } - ,listeners: { - 'success': {fn:function(r) { - var el = dropEvent.dropNode.getUI().getTextEl(); - if (el) {Ext.get(el).frame();} - this.fireEvent('afterSort',{event:dropEvent,result:r}); - },scope:this} - ,'failure': {fn:function(r) { - MODx.form.Handler.errorJSON(r); - this.refresh(); - if (r.message != '') { - MODx.msg.alert(_('error'), r.message); - } else if (r.data && r.data[0]) { - MODx.msg.alert(r.data[0]['id'], r.data[0]['msg']); - } - return false; - },scope:this} + const dropNode = dropEvent.dropNode; + const targetNode = dropEvent.target; + // append → drop into target; above/below → sibling insert under parent folder + const destNode = (dropEvent.point === 'append' || !targetNode.parentNode) + ? targetNode + : targetNode.parentNode; + const stripHtml = function(value) { + return String(value || '').replace(/(<([^>]+)>)/ig, ''); + }; + const itemLabel = Ext.util.Format.htmlEncode(stripHtml(dropNode.attributes.text || dropNode.text)); + const destLabel = Ext.util.Format.htmlEncode(stripHtml(destNode.attributes.text || destNode.text)); + + Ext.Msg.confirm(_('warning'), _('file_folder_move_confirm', { + item: itemLabel, + destination: destLabel + }), function(btn) { + if (btn !== 'yes') { + this.refresh(); + return; } - }); + MODx.Ajax.request({ + url: this.config.url + ,params: { + source: orgSource + ,from: from + ,destSource: destSource + ,to: to + ,action: this.config.sortAction || 'Browser/Directory/Sort' + ,point: dropEvent.point + } + ,listeners: { + 'success': {fn: function(r) { + const el = dropEvent.dropNode.getUI().getTextEl(); + if (el) { Ext.get(el).frame(); } + this.fireEvent('afterSort', {event: dropEvent, result: r}); + }, scope: this} + ,'failure': {fn: function(r) { + MODx.form.Handler.errorJSON(r); + this.refresh(); + if (r.message !== '') { + MODx.msg.alert(_('error'), r.message); + } else if (r.data && r.data[0]) { + MODx.msg.alert(r.data[0]['id'], r.data[0]['msg']); + } + return false; + }, scope: this} + } + }); + }, this); } ,getPath: function(node) {