diff --git a/frappe/__init__.py b/frappe/__init__.py index 3559c4b9e7..9e10d560c3 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -14,7 +14,7 @@ import os, sys, importlib, inspect, json from .exceptions import * from .utils.jinja import get_jenv, get_template, render_template, get_email_from_template -__version__ = '10.1.12' +__version__ = '10.1.13' __title__ = "Frappe Framework" local = Local() diff --git a/frappe/public/js/frappe/form/grid.js b/frappe/public/js/frappe/form/grid.js index caaa8036cc..587aab7340 100644 --- a/frappe/public/js/frappe/form/grid.js +++ b/frappe/public/js/frappe/form/grid.js @@ -166,66 +166,58 @@ frappe.ui.form.Grid = Class.extend({ if(this.display_status==="None") return; - if(!force && this.data_rows_are_same(data)) { - // soft refresh - this.header_row && this.header_row.refresh(); - for(var i in this.grid_rows) { - this.grid_rows[i].refresh(); - } - } else { - // redraw - var _scroll_y = $(document).scrollTop(); - this.make_head(); + // redraw + var _scroll_y = $(document).scrollTop(); + this.make_head(); - if(!this.grid_rows) { - this.grid_rows = []; - } - - this.truncate_rows(data); - this.grid_rows_by_docname = {}; - - for(var ri=0; ri < data.length; ri++) { - var d = data[ri]; - - if(d.idx===undefined) { - d.idx = ri + 1; - } - - if(this.grid_rows[ri]) { - var grid_row = this.grid_rows[ri]; - grid_row.doc = d; - grid_row.refresh(); - } else { - var grid_row = new frappe.ui.form.GridRow({ - parent: $rows, - parent_df: this.df, - docfields: this.docfields, - doc: d, - frm: this.frm, - grid: this - }); - this.grid_rows.push(grid_row); - } - - this.grid_rows_by_docname[d.name] = grid_row; - } - - this.wrapper.find(".grid-empty").toggleClass("hide", !!data.length); - - // toolbar - this.setup_toolbar(); - - // sortable - if(this.frm && this.is_sortable() && !this.sortable_setup_done) { - this.make_sortable($rows); - this.sortable_setup_done = true; - } - - this.last_display_status = this.display_status; - this.last_docname = this.frm && this.frm.docname; - frappe.utils.scroll_to(_scroll_y); + if(!this.grid_rows) { + this.grid_rows = []; } + this.truncate_rows(data); + this.grid_rows_by_docname = {}; + + for(var ri=0; ri < data.length; ri++) { + var d = data[ri]; + + if(d.idx===undefined) { + d.idx = ri + 1; + } + + if(this.grid_rows[ri]) { + var grid_row = this.grid_rows[ri]; + grid_row.doc = d; + grid_row.refresh(); + } else { + var grid_row = new frappe.ui.form.GridRow({ + parent: $rows, + parent_df: this.df, + docfields: this.docfields, + doc: d, + frm: this.frm, + grid: this + }); + this.grid_rows.push(grid_row); + } + + this.grid_rows_by_docname[d.name] = grid_row; + } + + this.wrapper.find(".grid-empty").toggleClass("hide", !!data.length); + + // toolbar + this.setup_toolbar(); + + // sortable + if(this.frm && this.is_sortable() && !this.sortable_setup_done) { + this.make_sortable($rows); + this.sortable_setup_done = true; + } + + this.last_display_status = this.display_status; + this.last_docname = this.frm && this.frm.docname; + frappe.utils.scroll_to(_scroll_y); + // red if mandatory this.form_grid.toggleClass('error', !!(this.df.reqd && !(data && data.length))); @@ -295,18 +287,6 @@ frappe.ui.form.Grid = Class.extend({ this.grid_rows_by_docname[docname] && this.grid_rows_by_docname[docname].refresh(); }, - data_rows_are_same: function(data) { - if(this.grid_rows) { - var same = data.length==this.grid_rows.length - && this.display_status==this.last_display_status - && (this.frm && this.frm.docname==this.last_docname) - && !$.map(this.grid_rows, function(g, i) { - return (g && g.doc && g.doc.name==data[i].name) ? null : true; - }).length; - - return same; - } - }, make_sortable: function($rows) { var me =this; if ('ontouchstart' in window) { diff --git a/frappe/public/js/frappe/form/save.js b/frappe/public/js/frappe/form/save.js index 16e925e182..01c8c4d648 100644 --- a/frappe/public/js/frappe/form/save.js +++ b/frappe/public/js/frappe/form/save.js @@ -26,7 +26,6 @@ frappe.ui.form.save = function (frm, action, callback, btn) { method: "frappe.desk.form.save.savedocs", args: { doc: frm.doc, action: action }, callback: function (r) { - frm.doc.__unsaved = false; $(document).trigger("save", [frm.doc]); callback(r); }, diff --git a/frappe/public/js/frappe/model/sync.js b/frappe/public/js/frappe/model/sync.js index 3d9bacaa2a..710be2cedb 100644 --- a/frappe/public/js/frappe/model/sync.js +++ b/frappe/public/js/frappe/model/sync.js @@ -102,6 +102,12 @@ $.extend(frappe.model, { update_in_locals: function(doc) { // update values in the existing local doc instead of replacing let local_doc = locals[doc.doctype][doc.name]; + let clear_keys = function(source, target) { + Object.keys(target).map(key => { + if (source[key] == undefined) delete target[key]; + }); + } + for (let fieldname in doc) { let df = frappe.meta.get_field(doc.doctype, fieldname); if (df && df.fieldtype === 'Table') { @@ -113,13 +119,25 @@ $.extend(frappe.model, { if (!(local_doc[fieldname] instanceof Array)) { local_doc[fieldname] = []; } - + // child table, override each row and append new rows if required for (let i=0; i < doc[fieldname].length; i++ ) { let d = doc[fieldname][i]; - if (local_doc[fieldname][i]) { + let local_d = local_doc[fieldname][i]; + if (local_d) { + // deleted and added again + if (!locals[d.doctype]) locals[d.doctype] = {}; + if (!d.name || !locals[d.doctype][d.name]) { + frappe.model.add_to_locals(d); + if (locals[d.doctype][local_d.name]) { + delete locals[d.doctype][local_d.name]; + } + } + // row exists, just copy the values - Object.assign(local_doc[fieldname][i], d); + Object.assign(local_d, d); + clear_keys(d, local_d); + } else { local_doc[fieldname].push(d); if (!d.parent) d.parent = doc.name; @@ -139,13 +157,15 @@ $.extend(frappe.model, { } local_doc[fieldname].length = doc[fieldname].length; - } } else { // literal local_doc[fieldname] = doc[fieldname]; } } + + // clear keys on parent + clear_keys(doc, local_doc); } }); diff --git a/frappe/public/js/legacy/client_script_helpers.js b/frappe/public/js/legacy/client_script_helpers.js index 930479c03e..1abac46bfa 100644 --- a/frappe/public/js/legacy/client_script_helpers.js +++ b/frappe/public/js/legacy/client_script_helpers.js @@ -509,3 +509,11 @@ _f.Frm.prototype.update_in_all_rows = function(table_fieldname, fieldname, value } refresh_field("items"); } + +_f.Frm.prototype.get_sum = function(table_fieldname, fieldname) { + let sum = 0; + for (let d of (this.doc[table_fieldname] || [])) { + sum += d[fieldname]; + } + return sum; +}; \ No newline at end of file