diff --git a/frappe/desk/page/form_builder/form_builder.js b/frappe/desk/page/form_builder/form_builder.js index 01542570c2..bd17a216c5 100644 --- a/frappe/desk/page/form_builder/form_builder.js +++ b/frappe/desk/page/form_builder/form_builder.js @@ -20,8 +20,10 @@ function load_form_builder(wrapper) { let route = frappe.get_route(); if (route.length > 1) { let doctype = frappe.router.routes[route[1]].doctype; + let is_customize_form = route[2] === "customize"; if (frappe.form_builder?.doctype == doctype) { + frappe.form_builder.store.is_customize_form = is_customize_form; frappe.form_builder.store.fetch(); return; } @@ -34,6 +36,7 @@ function load_form_builder(wrapper) { wrapper: $parent, page: wrapper.page, doctype: doctype, + customize: is_customize_form, }); }); } diff --git a/frappe/public/js/form_builder/components/FieldProperties.vue b/frappe/public/js/form_builder/components/FieldProperties.vue index e26df967a9..f92dbd4d53 100644 --- a/frappe/public/js/form_builder/components/FieldProperties.vue +++ b/frappe/public/js/form_builder/components/FieldProperties.vue @@ -9,14 +9,14 @@ let store = useStore(); let search_text = ref(""); let docfield_df = computed(() => { - let fields = store.docfields.filter(df => { + let fields = store.get_docfields.filter(df => { if ( in_list(["Tab Break", "Section Break", "Column Break", "Fold"], df.fieldtype) || !df.label ) { return false; } - if (df.depends_on && !evaluate_depends_on_value(df.depends_on, store.selected_field)) { + if (df.depends_on && !df.depends_on.includes("cur_frm") && !evaluate_depends_on_value(df.depends_on, store.selected_field)) { return false; } diff --git a/frappe/public/js/form_builder/form_builder.bundle.js b/frappe/public/js/form_builder/form_builder.bundle.js index 71e4bfd06a..b6e891138d 100644 --- a/frappe/public/js/form_builder/form_builder.bundle.js +++ b/frappe/public/js/form_builder/form_builder.bundle.js @@ -4,10 +4,11 @@ import { useStore } from "./store"; import FormBuilderComponent from "./components/FormBuilder.vue"; class FormBuilder { - constructor({ wrapper, page, doctype }) { + constructor({ wrapper, page, doctype, customize }) { this.$wrapper = $(wrapper); this.page = page; this.doctype = doctype; + this.customize = customize; // clear actions this.page.clear_actions(); @@ -39,6 +40,7 @@ class FormBuilder { // create a store this.store = useStore(); this.store.doctype = this.doctype; + this.store.is_customize_form = this.customize; // mount the app this.$form_builder = app.mount(this.$wrapper.get(0)); diff --git a/frappe/public/js/form_builder/store.js b/frappe/public/js/form_builder/store.js index 11b4cd9c51..88a92fbb2d 100644 --- a/frappe/public/js/form_builder/store.js +++ b/frappe/public/js/form_builder/store.js @@ -7,22 +7,29 @@ export const useStore = defineStore("store", { doctype: "", doc: null, docfields: [], + custom_docfields: [], layout: {}, active_tab: "", selected_field: null, dirty: false, + is_customize_form: false, }), getters: { selected: (state) => { return (name) => state.selected_field?.name == name; }, - get_df() { + get_docfields: (state) => { + return state.is_customize_form ? state.custom_docfields : state.docfields; + }, + get_df: (state) => { return (fieldtype, fieldname = "", label = "") => { - let df = frappe.model.get_new_doc("DocField"); + let docfield = state.is_customize_form ? "Customize Form Field" : "DocField"; + let df = frappe.model.get_new_doc(docfield); df.name = frappe.utils.get_random(8); df.fieldtype = fieldtype; df.fieldname = fieldname; df.label = label; + state.is_customize_form && (df.is_custom_field = 1); return df; }; }, @@ -31,14 +38,30 @@ export const useStore = defineStore("store", { async fetch() { await frappe.model.clear_doc("DocType", this.doctype); await frappe.model.with_doctype(this.doctype); - this.doc = frappe.get_doc("DocType", this.doctype); - if (!this.docfields.length) { - await frappe.model.with_doctype("DocField"); - this.docfields = frappe.get_meta("DocField").fields; + if (this.is_customize_form) { + await frappe.model.with_doc("Customize Form"); + let doc = frappe.get_doc("Customize Form"); + doc.doc_type = this.doctype; + let r = await frappe.call({ method: "fetch_to_customize", doc }); + this.doc = r.docs[0]; + } else { + this.doc = await frappe.db.get_doc("DocType", this.doctype); + } + + if (!this.get_docfields.length) { + let docfield = this.is_customize_form ? "Customize Form Field" : "DocField"; + await frappe.model.with_doctype(docfield); + let df = frappe.get_meta(docfield).fields; + if (this.is_customize_form) { + this.custom_docfields = df; + } else { + this.docfields = df; + } } this.layout = this.get_layout(); + this.active_tab = this.layout.tabs[0].df.name; nextTick(() => (this.dirty = false)); }, async reset_changes() { @@ -47,7 +70,7 @@ export const useStore = defineStore("store", { this.active_tab = first_tab.df.name; this.selected_field = null; }, - save_changes() { + async save_changes() { if (!this.dirty) { frappe.show_alert({ message: __("No changes to save"), indicator: "orange" }); return; @@ -55,6 +78,23 @@ export const useStore = defineStore("store", { frappe.dom.freeze(__("Saving...")); + try { + if (this.is_customize_form) { + let doc = frappe.get_doc("Customize Form"); + doc.doc_type = this.doctype; + doc.fields = this.get_updated_fields(); + await frappe.call({ method: "save_customization", doc }); + } else { + this.doc.fields = this.get_updated_fields(); + await frappe.call("frappe.client.save", { doc: this.doc }); + frappe.toast("Fields Table Updated"); + } + this.fetch(); + } finally { + frappe.dom.unfreeze(); + } + }, + get_updated_fields() { let fields = []; let idx = 0; @@ -94,18 +134,7 @@ export const useStore = defineStore("store", { }); }); - // update fields table with latest changes - this.doc.fields = fields; - - frappe - .call("frappe.client.save", { - doc: this.doc, - }) - .then(() => { - this.fetch(); - frappe.toast("Fields Table Updated"); - }) - .always(() => frappe.dom.unfreeze()); + return fields; }, get_layout() { return create_layout(this.doc.fields, this.get_df);