From 9bfc97a823328163d7c632072528c163e66c9e23 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Tue, 23 Feb 2021 18:53:24 +0530 Subject: [PATCH 1/4] fix: 'Not Saved' even after saving/submitting a doctype --- frappe/core/doctype/user_permission/user_permission.js | 2 +- frappe/public/js/frappe/form/form.js | 4 ++-- frappe/public/js/frappe/model/model.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frappe/core/doctype/user_permission/user_permission.js b/frappe/core/doctype/user_permission/user_permission.js index 4c3f5b4eb8..6c6b74c5df 100644 --- a/frappe/core/doctype/user_permission/user_permission.js +++ b/frappe/core/doctype/user_permission/user_permission.js @@ -45,7 +45,7 @@ frappe.ui.form.on('User Permission', { set_applicable_for_constraint: frm => { frm.toggle_reqd('applicable_for', !frm.doc.apply_to_all_doctypes); if (frm.doc.apply_to_all_doctypes) { - frm.set_value('applicable_for', null); + frm.set_value('applicable_for', null, null, true); } }, diff --git a/frappe/public/js/frappe/form/form.js b/frappe/public/js/frappe/form/form.js index 8d96054d16..a0f546b42c 100644 --- a/frappe/public/js/frappe/form/form.js +++ b/frappe/public/js/frappe/form/form.js @@ -1320,7 +1320,7 @@ frappe.ui.form.Form = class FrappeForm { return doc; } - set_value(field, value, if_missing) { + set_value(field, value, if_missing, avoid_dirty=false) { var me = this; var _set = function(f, v) { var fieldobj = me.fields_dict[f]; @@ -1340,7 +1340,7 @@ frappe.ui.form.Form = class FrappeForm { me.refresh_field(f); return Promise.resolve(); } else { - return frappe.model.set_value(me.doctype, me.doc.name, f, v); + return frappe.model.set_value(me.doctype, me.doc.name, f, v, me.fieldtype, avoid_dirty); } } } else { diff --git a/frappe/public/js/frappe/model/model.js b/frappe/public/js/frappe/model/model.js index 9ec7b0e931..f93f712740 100644 --- a/frappe/public/js/frappe/model/model.js +++ b/frappe/public/js/frappe/model/model.js @@ -401,7 +401,7 @@ $.extend(frappe.model, { } }, - set_value: function(doctype, docname, fieldname, value, fieldtype) { + set_value: function(doctype, docname, fieldname, value, fieldtype, avoid_dirty=false) { /* help: Set a value locally (if changed) and execute triggers */ var doc; @@ -427,7 +427,7 @@ $.extend(frappe.model, { } doc[key] = value; - tasks.push(() => frappe.model.trigger(key, value, doc)); + if (!avoid_dirty) tasks.push(() => frappe.model.trigger(key, value, doc)); } else { // execute link triggers (want to reselect to execute triggers) if(in_list(["Link", "Dynamic Link"], fieldtype) && doc) { From c4be72c2d404f337ba10d747e27525feb66aa9b7 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 18 Mar 2022 12:18:15 +0530 Subject: [PATCH 2/4] fix: Pass skip_dirty_trigger flag to the set_value and model trigger Also, renamed avoid_dirty to skip_dirty_trigger to be more explicit --- frappe/public/js/frappe/model/model.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frappe/public/js/frappe/model/model.js b/frappe/public/js/frappe/model/model.js index d0b1c729c6..3b95a4b3f1 100644 --- a/frappe/public/js/frappe/model/model.js +++ b/frappe/public/js/frappe/model/model.js @@ -412,7 +412,7 @@ $.extend(frappe.model, { } }, - set_value: function(doctype, docname, fieldname, value, fieldtype, avoid_dirty=false) { + set_value: function(doctype, docname, fieldname, value, fieldtype, skip_dirty_trigger=false) { /* help: Set a value locally (if changed) and execute triggers */ var doc; @@ -438,11 +438,11 @@ $.extend(frappe.model, { } doc[key] = value; - if (!avoid_dirty) tasks.push(() => frappe.model.trigger(key, value, doc)); + tasks.push(() => frappe.model.trigger(key, value, doc, skip_dirty_trigger)); } else { // execute link triggers (want to reselect to execute triggers) if(in_list(["Link", "Dynamic Link"], fieldtype) && doc) { - tasks.push(() => frappe.model.trigger(key, value, doc)); + tasks.push(() => frappe.model.trigger(key, value, doc, skip_dirty_trigger)); } } }); @@ -467,7 +467,7 @@ $.extend(frappe.model, { frappe.model.events[doctype][fieldname].push(fn); }, - trigger: function(fieldname, value, doc) { + trigger: function(fieldname, value, doc, skip_dirty_trigger=false) { const tasks = []; function enqueue_events(events) { @@ -477,7 +477,7 @@ $.extend(frappe.model, { if (!fn) continue; tasks.push(() => { - const return_value = fn(fieldname, value, doc); + const return_value = fn(fieldname, value, doc, skip_dirty_trigger); // if the trigger returns a promise, return it, // or use the default promise frappe.after_ajax From adb989fff2458cc92678ef6b6f5c224904be1864 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 18 Mar 2022 12:19:36 +0530 Subject: [PATCH 3/4] feat: Option to set form dirty even if form save is disabled --- frappe/public/js/frappe/form/form.js | 14 +++++++++----- frappe/public/js/frappe/form/toolbar.js | 6 +++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/frappe/public/js/frappe/form/form.js b/frappe/public/js/frappe/form/form.js index 494e3af705..7ec6677c7f 100644 --- a/frappe/public/js/frappe/form/form.js +++ b/frappe/public/js/frappe/form/form.js @@ -246,10 +246,12 @@ frappe.ui.form.Form = class FrappeForm { var me = this; // on main doc - frappe.model.on(me.doctype, "*", function(fieldname, value, doc) { + frappe.model.on(me.doctype, "*", function(fieldname, value, doc, skip_dirty_trigger=false) { // set input if (cstr(doc.name) === me.docname) { - me.dirty(); + if (!skip_dirty_trigger) { + me.dirty(); + } let field = me.fields_dict[fieldname]; field && field.refresh(fieldname); @@ -953,10 +955,12 @@ frappe.ui.form.Form = class FrappeForm { this.toolbar.set_primary_action(); } - disable_save() { + disable_save(set_dirty=false) { // IMPORTANT: this function should be called in refresh event this.save_disabled = true; this.toolbar.current_status = null; + // field changes should make form dirty + this.set_dirty = set_dirty; this.page.clear_primary_action(); } @@ -1447,7 +1451,7 @@ frappe.ui.form.Form = class FrappeForm { return doc; } - set_value(field, value, if_missing, avoid_dirty=false) { + set_value(field, value, if_missing, skip_dirty_trigger=false) { var me = this; var _set = function(f, v) { var fieldobj = me.fields_dict[f]; @@ -1467,7 +1471,7 @@ frappe.ui.form.Form = class FrappeForm { me.refresh_field(f); return Promise.resolve(); } else { - return frappe.model.set_value(me.doctype, me.doc.name, f, v, me.fieldtype, avoid_dirty); + return frappe.model.set_value(me.doctype, me.doc.name, f, v, me.fieldtype, skip_dirty_trigger); } } } else { diff --git a/frappe/public/js/frappe/form/toolbar.js b/frappe/public/js/frappe/form/toolbar.js index 016390a4e1..e55eb9fdeb 100644 --- a/frappe/public/js/frappe/form/toolbar.js +++ b/frappe/public/js/frappe/form/toolbar.js @@ -534,14 +534,14 @@ frappe.ui.form.Toolbar = class Toolbar { }); } show_title_as_dirty() { - if(this.frm.save_disabled) + if (this.frm.save_disabled && !this.frm.set_dirty) return; - if(this.frm.doc.__unsaved) { + if (this.frm.is_dirty()) { this.page.set_indicator(__("Not Saved"), "orange"); } - $(this.frm.wrapper).attr("data-state", this.frm.doc.__unsaved ? "dirty" : "clean"); + $(this.frm.wrapper).attr("data-state", this.frm.is_dirty() ? "dirty" : "clean"); } show_jump_to_field_dialog() { From fedcf48ada2bd17ce01f2238af9749b68a837437 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 18 Mar 2022 12:20:51 +0530 Subject: [PATCH 4/4] fix: Customize form issue where it remains "Not Saved" even after update fixes: https://github.com/frappe/frappe/issues/16068 --- frappe/custom/doctype/customize_form/customize_form.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/frappe/custom/doctype/customize_form/customize_form.js b/frappe/custom/doctype/customize_form/customize_form.js index 4862185b99..9cfe315e44 100644 --- a/frappe/custom/doctype/customize_form/customize_form.js +++ b/frappe/custom/doctype/customize_form/customize_form.js @@ -14,7 +14,6 @@ frappe.ui.form.on("Customize Form", { }, onload: function(frm) { - frm.disable_save(); frm.set_query("doc_type", function() { return { translate_values: false, @@ -110,7 +109,7 @@ frappe.ui.form.on("Customize Form", { }, refresh: function(frm) { - frm.disable_save(); + frm.disable_save(true); frm.page.clear_icons(); if (frm.doc.doc_type) { @@ -169,7 +168,7 @@ frappe.ui.form.on("Customize Form", { doc_type = localStorage.getItem("customize_doctype"); } if (doc_type) { - setTimeout(() => frm.set_value("doc_type", doc_type), 1000); + setTimeout(() => frm.set_value("doc_type", doc_type, false, true), 1000); } }, @@ -341,11 +340,11 @@ frappe.customize_form.confirm = function(msg, frm) { } frappe.customize_form.clear_locals_and_refresh = function(frm) { + delete frm.doc.__unsaved; // clear doctype from locals frappe.model.clear_doc("DocType", frm.doc.doc_type); delete frappe.meta.docfield_copy[frm.doc.doc_type]; - frm.refresh(); -} +}; extend_cscript(cur_frm.cscript, new frappe.model.DocTypeController({frm: cur_frm}));