From e089d6bafbad0dba1c2f31dfbf92e2ec71acbd88 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 13 Dec 2021 22:28:38 +0530 Subject: [PATCH 1/5] fix: adding a new child expands all childs The refresh method is causing deep reload of parent node. Doesn't seem like it's of any use here. ref: https://github.com/frappe/frappe/pull/4805 This fix had side effect of expanding all parent node recursively. --- frappe/public/js/frappe/ui/tree.js | 1 - frappe/public/js/frappe/views/treeview.js | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/ui/tree.js b/frappe/public/js/frappe/ui/tree.js index 4b11b092eb..c32d92aa32 100644 --- a/frappe/public/js/frappe/ui/tree.js +++ b/frappe/public/js/frappe/ui/tree.js @@ -299,7 +299,6 @@ frappe.ui.Tree = class { .appendTo($toolbar); $link.on('click', () => { obj.click(node); - this.refresh(); }); }); diff --git a/frappe/public/js/frappe/views/treeview.js b/frappe/public/js/frappe/views/treeview.js index 30da212f0a..44bbaaeeaf 100644 --- a/frappe/public/js/frappe/views/treeview.js +++ b/frappe/public/js/frappe/views/treeview.js @@ -242,6 +242,7 @@ frappe.views.TreeView = class TreeView { frappe.model.rename_doc(me.doctype, node.label, function(new_name) { node.$tree_link.find('a').text(new_name); node.label = new_name; + me.tree.refresh(); }); }, btnClass: "hidden-xs" From c33854010e74b82bb1c010572844681fc27dc0e4 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 13 Dec 2021 23:10:04 +0530 Subject: [PATCH 2/5] fix: while adding a new node only expand current node deep expand is pointless and clutters the screen. Only expand / refresh current node. --- frappe/public/js/frappe/views/treeview.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frappe/public/js/frappe/views/treeview.js b/frappe/public/js/frappe/views/treeview.js index 44bbaaeeaf..cc0a233003 100644 --- a/frappe/public/js/frappe/views/treeview.js +++ b/frappe/public/js/frappe/views/treeview.js @@ -318,10 +318,7 @@ frappe.views.TreeView = class TreeView { args: args, callback: function(r) { if(!r.exc) { - if(node.expanded) { - me.tree.toggle_node(node); - } - me.tree.load_children(node, true); + me.tree.load_children(node); } }, always: function() { From af67ecc11679b1f885df5f960d563ca541f1563d Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 13 Dec 2021 23:16:12 +0530 Subject: [PATCH 3/5] fix: dont refresh treeview on save / realtime treeview's refresh method loads the whole tree without keeping any state of what was expanded. So if triggered update via realtime the whole page reloads and you see expanded tree. --- frappe/public/js/frappe/list/list_view.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 3c9f1e39fb..e9727f889a 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -1910,12 +1910,6 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { if (!doctype) return; frappe.provide("frappe.views.trees"); - // refresh tree view - if (frappe.views.trees[doctype]) { - frappe.views.trees[doctype].tree.refresh(); - return; - } - // refresh list view const page_name = frappe.get_route_str(); const list_view = frappe.views.list_view[page_name]; From 7bd46a3e29b1ce39e3cff64f3541c22b7c5da44f Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Mon, 20 Dec 2021 13:21:07 +0530 Subject: [PATCH 4/5] fix: Escape matching pattern for substitution Tested on PY3.9.7 and PY3.9.9 --- frappe/patches/v14_0/remove_db_aggregation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/patches/v14_0/remove_db_aggregation.py b/frappe/patches/v14_0/remove_db_aggregation.py index 25a170f362..a8fa5b2ba1 100644 --- a/frappe/patches/v14_0/remove_db_aggregation.py +++ b/frappe/patches/v14_0/remove_db_aggregation.py @@ -27,6 +27,6 @@ def execute(): name, script = server_script["name"], server_script["script"] for agg in ["avg", "max", "min", "sum"]: - script = re.sub(f"frappe.db.{agg}(", f"frappe.qb.{agg}(", script) + script = re.sub(f"frappe.db.{agg}\(", f"frappe.qb.{agg}(", script) frappe.db.update("Server Script", name, "script", script) From 1d879f741b96d66a29bd9f14faaa4ba5ce1a534a Mon Sep 17 00:00:00 2001 From: phot0n Date: Thu, 16 Dec 2021 15:18:58 +0530 Subject: [PATCH 5/5] feat: before_uninstall and after_uninstall hooks --- frappe/__init__.py | 2 +- frappe/installer.py | 7 +++++++ frappe/utils/boilerplate.py | 6 ++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index defa6e3336..96aa2b1b5f 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -1203,7 +1203,7 @@ def read_file(path, raise_not_found=False): def get_attr(method_string): """Get python method object from its name.""" app_name = method_string.split(".")[0] - if not local.flags.in_install and app_name not in get_installed_apps(): + if not local.flags.in_uninstall and not local.flags.in_install and app_name not in get_installed_apps(): throw(_("App {0} is not installed").format(app_name), AppNotInstalledError) modulename = '.'.join(method_string.split('.')[:-1]) diff --git a/frappe/installer.py b/frappe/installer.py index cd6526c788..b50fa4a3b5 100755 --- a/frappe/installer.py +++ b/frappe/installer.py @@ -208,6 +208,7 @@ def remove_app(app_name, dry_run=False, yes=False, no_backup=False, force=False) import click site = frappe.local.site + app_hooks = frappe.get_hooks(app_name=app_name) # dont allow uninstall app if not installed unless forced if not force: @@ -233,6 +234,9 @@ def remove_app(app_name, dry_run=False, yes=False, no_backup=False, force=False) frappe.flags.in_uninstall = True + for before_uninstall in app_hooks.before_uninstall or []: + frappe.get_attr(before_uninstall)() + modules = frappe.get_all("Module Def", filters={"app_name": app_name}, pluck="name") drop_doctypes = _delete_modules(modules, dry_run=dry_run) @@ -243,6 +247,9 @@ def remove_app(app_name, dry_run=False, yes=False, no_backup=False, force=False) frappe.get_single('Installed Applications').update_versions() frappe.db.commit() + for after_uninstall in app_hooks.after_uninstall or []: + frappe.get_attr(after_uninstall)() + click.secho(f"Uninstalled App {app_name} from Site {site}", fg="green") frappe.flags.in_uninstall = False diff --git a/frappe/utils/boilerplate.py b/frappe/utils/boilerplate.py index 91f7dbb2f8..6c405ce467 100755 --- a/frappe/utils/boilerplate.py +++ b/frappe/utils/boilerplate.py @@ -203,6 +203,12 @@ app_license = "{app_license}" # before_install = "{app_name}.install.before_install" # after_install = "{app_name}.install.after_install" +# Uninstallation +# ------------ + +# before_uninstall = "{app_name}.uninstall.before_uninstall" +# after_uninstall = "{app_name}.uninstall.after_uninstall" + # Desk Notifications # ------------------ # See frappe.core.notifications.get_notification_config