diff --git a/frappe/public/js/frappe/form/quick_entry.js b/frappe/public/js/frappe/form/quick_entry.js index 1a535ce666..3cfb3aa530 100644 --- a/frappe/public/js/frappe/form/quick_entry.js +++ b/frappe/public/js/frappe/form/quick_entry.js @@ -25,13 +25,15 @@ frappe.ui.form.make_quick_entry = (doctype, after_insert, init_callback, doc, fo return frappe.quick_entry.setup(); }; -frappe.ui.form.QuickEntryForm = class QuickEntryForm { +frappe.ui.form.QuickEntryForm = class QuickEntryForm extends frappe.ui.Dialog { constructor(doctype, after_insert, init_callback, doc, force) { + super({ auto_make: false }); this.doctype = doctype; this.after_insert = after_insert; this.init_callback = init_callback; this.doc = doc; this.force = force ? force : false; + this.dialog = this; // for backward compatibility } setup() { @@ -132,29 +134,39 @@ frappe.ui.form.QuickEntryForm = class QuickEntryForm { this.script_manager.setup(); } + get mandatory() { + // Backwards compatibility + console.warn("QuickEntryForm: .mandatory is deprecated, use .docfields instead"); + return this.docfields; + } + + set mandatory(value) { + // Backwards compatibility + console.warn("QuickEntryForm: .mandatory is deprecated, use .docfields instead"); + this.docfields = value; + } + render_dialog() { var me = this; - this.dialog = new frappe.ui.Dialog({ - title: this.get_title(), - fields: this.docfields, - doc: this.doc, - }); + this.fields = this.docfields; + this.title = this.get_title(); + super.make(); this.register_primary_action(); this.render_edit_in_full_page_link(); this.setup_cmd_enter_for_save(); - this.dialog.onhide = () => (frappe.quick_entry = null); - this.dialog.show(); + this.onhide = () => (frappe.quick_entry = null); + this.show(); - this.dialog.refresh_dependency(); + this.refresh_dependency(); this.set_defaults(); this.script_manager.trigger("refresh"); if (this.init_callback) { - this.init_callback(this.dialog); + this.init_callback(this); } } @@ -170,7 +182,7 @@ frappe.ui.form.QuickEntryForm = class QuickEntryForm { register_primary_action() { var me = this; - this.dialog.set_primary_action(__("Save"), function () { + this.set_primary_action(__("Save"), function () { if (me.dialog.working) { return; } @@ -247,14 +259,14 @@ frappe.ui.form.QuickEntryForm = class QuickEntryForm { process_after_insert(r) { // delete the old doc - frappe.model.clear_doc(this.dialog.doc.doctype, this.dialog.doc.name); - this.dialog.doc = r.message; + frappe.model.clear_doc(this.doc.doctype, this.doc.name); + this.doc = r.message; if (this.script_manager.has_handler("after_save")) { return this.script_manager.trigger("after_save"); } else if (frappe._from_link) { - frappe.ui.form.update_calling_link(this.dialog.doc); + frappe.ui.form.update_calling_link(this.doc); } else if (this.after_insert) { - this.after_insert(this.dialog.doc); + this.after_insert(this.doc); } else { this.open_form_if_not_list(); } @@ -263,7 +275,7 @@ frappe.ui.form.QuickEntryForm = class QuickEntryForm { setup_cmd_enter_for_save() { var me = this; // ctrl+enter to save - this.dialog.wrapper.keydown(function (e) { + this.wrapper.keydown(function (e) { if ((e.ctrlKey || e.metaKey) && e.which == 13) { if (!frappe.request.ajax_count) { // not already working -- double entry @@ -278,7 +290,7 @@ frappe.ui.form.QuickEntryForm = class QuickEntryForm { open_form_if_not_list() { if (this.meta.issingle) return; let route = frappe.get_route(); - let doc = this.dialog.doc; + let doc = this.doc; if (route && !(route[0] === "List" && route[1] === doc.doctype)) { frappe.run_serially([() => frappe.set_route("Form", doc.doctype, doc.name)]); } @@ -286,17 +298,17 @@ frappe.ui.form.QuickEntryForm = class QuickEntryForm { update_doc() { var me = this; - var data = this.dialog.get_values(true); + var data = this.get_values(true); $.each(data, function (key, value) { if (!is_null(value)) { me.dialog.doc[key] = value; } }); - return this.dialog.doc; + return this.doc; } open_doc(set_hooks) { - this.dialog.hide(); + this.hide(); this.update_doc(); if (set_hooks && this.after_insert) { frappe.route_options = frappe.route_options || {}; @@ -309,13 +321,13 @@ frappe.ui.form.QuickEntryForm = class QuickEntryForm { render_edit_in_full_page_link() { if (this.force || this.hide_full_form_button) return; - this.dialog.add_custom_action(__("Edit Full Form"), () => this.open_doc(true)); + this.add_custom_action(__("Edit Full Form"), () => this.open_doc(true)); } set_defaults() { var me = this; // set defaults - $.each(this.dialog.fields_dict, function (fieldname, field) { + $.each(this.fields_dict, function (fieldname, field) { field.doctype = me.doc.doctype; field.docname = me.doc.name; diff --git a/frappe/public/js/frappe/form/script_manager.js b/frappe/public/js/frappe/form/script_manager.js index badce4460f..3ff3fb92cb 100644 --- a/frappe/public/js/frappe/form/script_manager.js +++ b/frappe/public/js/frappe/form/script_manager.js @@ -245,6 +245,7 @@ frappe.ui.form.ScriptManager = class ScriptManager { this.trigger("setup"); } + log_error(caller, e) { frappe.show_alert({ message: __("Error in Client Script."), indicator: "error" }); console.group && console.group(); diff --git a/frappe/public/js/frappe/ui/dialog.js b/frappe/public/js/frappe/ui/dialog.js index eea34bb65e..da288621b8 100644 --- a/frappe/public/js/frappe/ui/dialog.js +++ b/frappe/public/js/frappe/ui/dialog.js @@ -13,8 +13,10 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup { this.display = false; this.is_dialog = true; - $.extend(this, { animate: true, size: null }, opts); - this.make(); + $.extend(this, { animate: true, size: null, auto_make: true }, opts); + if (this.auto_make) { + this.make(); + } } make() { @@ -127,10 +129,6 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup { }); } - get $backdrop() { - return $(this.$wrapper.data("bs.modal")?._backdrop); - } - set_modal_size() { if (!this.fields) { this.size = ""; @@ -259,7 +257,7 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup { this.$wrapper.removeClass("modal-minimize"); if (this.minimizable && this.is_minimized) { - this.$backdrop.show(); + $(".modal-backdrop").toggle(); this.is_minimized = false; } @@ -272,10 +270,6 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup { } hide() { - if (this.animate && this.animation_speed === "slow") { - this.$wrapper.addClass("slow"); - this.$backdrop.addClass("slow"); - } this.$wrapper.modal("hide"); this.is_visible = false; } @@ -297,7 +291,7 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup { } toggle_minimize() { - this.$backdrop.toggle(); + $(".modal-backdrop").toggle(); let modal = this.$wrapper.closest(".modal").toggleClass("modal-minimize"); modal.attr("tabindex") ? modal.removeAttr("tabindex") : modal.attr("tabindex", -1); this.is_minimized = !this.is_minimized; @@ -323,6 +317,8 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup { action && action_button.click(action); } + + add_custom_button() {} }; frappe.ui.hide_open_dialog = () => { diff --git a/frappe/public/js/frappe/ui/field_group.js b/frappe/public/js/frappe/ui/field_group.js index 27fe08439c..4a1022ec9f 100644 --- a/frappe/public/js/frappe/ui/field_group.js +++ b/frappe/public/js/frappe/ui/field_group.js @@ -6,6 +6,8 @@ frappe.ui.FieldGroup = class FieldGroup extends frappe.ui.form.Layout { constructor(opts) { super(opts); this.dirty = false; + this.fetch_dict = {}; + $.each(this.fields || [], function (i, f) { if (!f.fieldname && f.label) { f.fieldname = f.label.replace(/ /g, "_").toLowerCase(); @@ -197,4 +199,43 @@ frappe.ui.FieldGroup = class FieldGroup extends frappe.ui.form.Layout { field.df[prop] = value; field.refresh(); } + + set_query(fieldname, opt1, opt2) { + if (opt2) { + // on child table + // set_query(fieldname, parent fieldname, query) + if (this.fields_dict[opt1]) + this.fields_dict[opt1].grid.get_field(fieldname).get_query = opt2; + } else { + // on parent table + // set_query(fieldname, query) + if (this.fields_dict[fieldname]) { + this.fields_dict[fieldname].get_query = opt1; + } + } + } + + // UTILITIES + add_fetch(link_field, source_field, target_field, target_doctype) { + /* + Example fetch dict to get sender_email from email_id field in sender: + { + "Notification": { + "sender": { + "sender_email": "email_id" + } + } + } + */ + + if (!target_doctype) target_doctype = "*"; + + // Target field kept as key because source field could be non-unique + this.fetch_dict.setDefault(target_doctype, {}).setDefault(link_field, {})[target_field] = + source_field; + } + + is_new() { + return this.doc.__islocal; + } };