diff --git a/frappe/core/doctype/file/file.py b/frappe/core/doctype/file/file.py index 70288bed08..e16c687dc1 100644 --- a/frappe/core/doctype/file/file.py +++ b/frappe/core/doctype/file/file.py @@ -141,7 +141,7 @@ class File(NestedSet): def check_folder_is_empty(self): """Throw exception if folder is not empty""" - if frappe.get_all("File", {"folder": self.name}): + if self.is_folder and frappe.get_all("File", filters={"folder": self.name}): frappe.throw(_("Folder {0} is not empty").format(self.name)) def check_reference_doc_permission(self): diff --git a/frappe/core/doctype/file/file_list.js b/frappe/core/doctype/file/file_list.js index d424bb43d9..113548b7b1 100644 --- a/frappe/core/doctype/file/file_list.js +++ b/frappe/core/doctype/file/file_list.js @@ -31,7 +31,11 @@ frappe.listview_settings['File'] = { doclist.breadcrumb = $('') .insertBefore(doclist.filter_area); - doclist.page.add_menu_item(__("Create Folder"), function() { + doclist.listview.settings.setup_new_folder(doclist); + doclist.listview.settings.setup_dragdrop(doclist); + }, + setup_new_folder: function(doclist) { + doclist.page.add_menu_item(__("New Folder"), function() { var d = frappe.prompt(__("Name"), function(values) { if((values.value.indexOf("/") > -1)){ frappe.throw("Folder name should not include / !!!") @@ -39,17 +43,31 @@ frappe.listview_settings['File'] = { } var data = { "file_name": values.value, - "folder":doclist.current_folder + "folder": doclist.current_folder }; frappe.call({ - method:"frappe.core.doctype.file.file.create_new_folder", - args: data, - callback:function(r){ - } + method: "frappe.core.doctype.file.file.create_new_folder", + args: data, + callback: function(r) { } }) }, __('Enter folder name'), __("Create")); }); }, + setup_dragdrop: function(doclist) { + $(doclist.$page).on('dragenter dragover', false) + .on('drop', function (e) { + var dataTransfer = e.originalEvent.dataTransfer; + if (!(dataTransfer && dataTransfer.files && dataTransfer.files.length > 0)) { + return; + } + e.stopPropagation(); + e.preventDefault(); + frappe.upload.upload_file(dataTransfer.files[0], { + "folder": doclist.current_folder, + "from_form": 1 + }, {}); + }); + }, before_run: function(doclist) { var name_filter = doclist.filter_list.get_filter("file_name"); if(name_filter) { @@ -88,13 +106,18 @@ frappe.listview_settings['File'] = { frappe.utils.set_title(doclist.current_folder_name); }, set_primary_action:function(doclist){ - doclist.page.clear_primary_action(); doclist.page.set_primary_action(__("New"), function() { dialog = frappe.ui.get_upload_dialog({ - "data":{"folder": doclist.current_folder, "from_form": 1} - }) - + "args": { + "folder": doclist.current_folder, + "from_form": 1 + }, + callback: function() { + console.log('here') + doclist.refresh(); + } + }); }, "octicon octicon-plus"); }, post_render_item: function(list, row, data) { diff --git a/frappe/public/js/frappe/form/footer/attachments.js b/frappe/public/js/frappe/form/footer/attachments.js index de8c3e3356..480c45f8a0 100644 --- a/frappe/public/js/frappe/form/footer/attachments.js +++ b/frappe/public/js/frappe/form/footer/attachments.js @@ -146,10 +146,12 @@ frappe.ui.form.Attachments = Class.extend({ new_attachment: function(fieldname) { var me = this; if(!this.dialog){ - this.dialog = frappe.ui.get_upload_dialog({"data": me.get_args(), - "callback": me.attachment_uploaded, "curr": me, - "max_width": me.frm.cscript ? me.frm.cscript.attachment_max_width : null, - "max_height": me.frm.cscript ? me.frm.cscript.attachment_max_height : null}); + this.dialog = frappe.ui.get_upload_dialog({ + "args": me.get_args(), + "callback": me.attachment_uploaded, "curr": me, + "max_width": me.frm.cscript ? me.frm.cscript.attachment_max_width : null, + "max_height": me.frm.cscript ? me.frm.cscript.attachment_max_height : null + }); } }, get_args: function() { @@ -203,25 +205,29 @@ frappe.ui.get_upload_dialog = function(opts){ title: __('Upload Attachment'), }); + var btn = dialog.set_primary_action(__("Attach")); + btn.removeClass("btn-primary").addClass("btn-default"); + dialog.show(); $(dialog.body).empty(); frappe.upload.make({ parent: dialog.body, - args: opts.data, + args: opts.args, callback: function(attachment, r) { + dialog.hide(); if(opts.callback){ - opts.callback.call(opts.curr, attachment, r); - } - else{ - dialog.hide(); + opts.callback(attachment, r); } }, + on_select: function() { + btn.removeClass("btn-default").addClass("btn-primary"); + }, onerror: function() { dialog.hide(); }, - btn: dialog.set_primary_action(__("Attach")), + btn: btn, max_width: opts.max_width, max_height: opts.max_height, }); diff --git a/frappe/public/js/frappe/list/doclistview.js b/frappe/public/js/frappe/list/doclistview.js index 9919d9c939..d76826d718 100644 --- a/frappe/public/js/frappe/list/doclistview.js +++ b/frappe/public/js/frappe/list/doclistview.js @@ -48,13 +48,18 @@ $(document).on("save", function(event, doc) { frappe.views.set_list_as_dirty = function(doctype) { var list_page = "List/" + doctype; if(frappe.pages[list_page]) { - if(frappe.pages[list_page].doclistview) + if(frappe.pages[list_page].doclistview) { + if(frappe.pages[list_page].doclistview.dirty) { + // already refreshing... + return; + } frappe.pages[list_page].doclistview.dirty = true; + } } var route = frappe.get_route(); if(route[0]==="List" && route[1]===doctype) { setTimeout(function() { - frappe.pages[list_page].doclistview.run(); + frappe.pages[list_page].doclistview.refresh(); }, 100); } } @@ -158,7 +163,9 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ added = true; } }); - added && me.run(); + if(added) { + me.refresh(true); + } }); this.$page.find(".result-list").on("click", ".list-row-left", function(e) { // don't open in case of checkbox, star, filterable @@ -231,8 +238,11 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ this.refresh(); }, - refresh: function() { - var me = this; + refresh: function(dirty) { + if(window.ttt) throw "here"; + + + if(dirty!==undefined) this.dirty = dirty; this.init_stats(); if(this.listview.settings.refresh) { @@ -240,14 +250,14 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ } if(frappe.route_options) { - me.set_route_options(); - me.run(); - } else if(me.dirty) { - me.run(); + this.set_route_options(); + this.run(); + } else if(this.dirty) { + this.run(); } else { - if(new Date() - (me.last_updated_on || 0) > 30000) { + if(new Date() - (this.last_updated_on || 0) > 30000) { // older than 5 mins, refresh - me.run(); + this.run(); } } }, @@ -275,6 +285,12 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ run: function(more) { // set filter from route + var me = this; + + if(this.fresh && !more) { + return; + } + if(this.listview.settings.before_run) { this.listview.settings.before_run(this); } @@ -294,6 +310,20 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ this.last_updated_on = new Date(); this.dirty = false; + + // set a fresh so that multiple refreshes do not happen + // at the same time. This is true when deleting. + // AJAX response will try to refresh and list_update notification + // via async will also try to update. + // It is not possible to guess which will reach first + // (most probably async will) but this is a forced way + // to prevent instant refreshes on mutilple triggers + // in a loosly coupled way. + this.fresh = true; + setTimeout(function() { + me.fresh = false; + }, 1000); + this._super(more); if(this.listview.settings.post_render) { @@ -351,12 +381,14 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ this.$page.on("click", ".list-tag-preview", function() { me.toggle_tags(); }); this.page.set_secondary_action(__("Refresh"), function() { - me.run(); + me.dirty = true; + me.refresh(); }, "octicon octicon-sync"); this.page.btn_secondary.addClass("hidden-xs"); this.page.add_menu_item(__("Refresh"), function() { - me.run(); + me.dirty = true; + me.refresh(); }, "octicon octicon-sync").addClass("visible-xs"); if(frappe.model.can_import(this.doctype)) { @@ -541,7 +573,7 @@ frappe.views.DocListView = frappe.ui.Listing.extend({ callback: function(r) { if(!r.exc) { me.list_header.find(".list-select-all").prop("checked", false); - me.run(); + me.refresh(); } } }); diff --git a/frappe/public/js/frappe/upload.js b/frappe/public/js/frappe/upload.js index 97d115deff..0e65acf7cc 100644 --- a/frappe/public/js/frappe/upload.js +++ b/frappe/public/js/frappe/upload.js @@ -34,6 +34,10 @@ frappe.upload = { $file_input.trigger("change"); }); + if(opts.on_select) { + opts.on_select(); + } + } else { $upload.find(".uploaded-filename").addClass("hidden") $upload.find(".web-link-wrapper").removeClass("hidden");