diff --git a/crm/fcrm/doctype/crm_fields_layout/crm_fields_layout.py b/crm/fcrm/doctype/crm_fields_layout/crm_fields_layout.py index d51dd465f..514e2ad58 100644 --- a/crm/fcrm/doctype/crm_fields_layout/crm_fields_layout.py +++ b/crm/fcrm/doctype/crm_fields_layout/crm_fields_layout.py @@ -14,7 +14,7 @@ class CRMFieldsLayout(Document): @frappe.whitelist() -def get_fields_layout(doctype: str, type: str): +def get_fields_layout(doctype: str, type: str, no_reactivity=False): tabs = [] layout = None @@ -30,7 +30,7 @@ def get_fields_layout(doctype: str, type: str): has_tabs = tabs[0].get("sections") if tabs and tabs[0] else False if not has_tabs: - tabs = [{"sections": tabs}] + tabs = [{"name": "first_tab", "sections": tabs}] allowed_fields = [] for tab in tabs: @@ -60,6 +60,10 @@ def get_fields_layout(doctype: str, type: str): "read_only": field.read_only, "placeholder": field.get("placeholder"), "filters": field.get("link_filters"), + "depends_on": "" if no_reactivity else field.get("depends_on"), + "mandatory_depends_on": "" + if no_reactivity + else field.get("mandatory_depends_on"), } column["fields"][column.get("fields").index(field["name"])] = field diff --git a/frontend/src/components/FieldLayout.vue b/frontend/src/components/FieldLayout.vue index 38c303392..0ac58d674 100644 --- a/frontend/src/components/FieldLayout.vue +++ b/frontend/src/components/FieldLayout.vue @@ -263,7 +263,7 @@ import Link from '@/components/Controls/Link.vue' import Grid from '@/components/Controls/Grid.vue' import { getMeta } from '@/stores/meta' import { usersStore } from '@/stores/users' -import { getFormat } from '@/utils' +import { getFormat, evaluateDependsOnValue } from '@/utils' import { flt } from '@/utils/numberFormat.js' import { Tabs, Tooltip, DatePicker, DateTimePicker } from 'frappe-ui' import { ref, computed } from 'vue' @@ -300,7 +300,17 @@ const _tabs = computed(() => { if (field.type == 'Link' && field.options == 'User') { field.type = 'User' } - return field + return { + ...field, + display_via_depends_on: evaluateDependsOnValue( + field.depends_on, + props.data, + ), + mandatory_via_depends_on: evaluateDependsOnValue( + field.mandatory_depends_on, + props.data, + ), + } }) .filter((field) => { return ( diff --git a/frontend/src/components/FieldLayoutEditor.vue b/frontend/src/components/FieldLayoutEditor.vue index c30a15b43..926d81e5b 100644 --- a/frontend/src/components/FieldLayoutEditor.vue +++ b/frontend/src/components/FieldLayoutEditor.vue @@ -201,8 +201,9 @@ @click=" tabs[tabIndex].sections.push({ label: __('New Section'), + name: 'section_' + getRandom(), opened: true, - columns: [{ fields: [] }], + columns: [{ name: 'column_' + getRandom(), fields: [] }], }) " > @@ -218,6 +219,7 @@ import Autocomplete from '@/components/frappe-ui/Autocomplete.vue' import DragVerticalIcon from '@/components/Icons/DragVerticalIcon.vue' import Draggable from 'vuedraggable' +import { getRandom } from '@/utils' import { Dropdown, createResource } from 'frappe-ui' import { ref, computed, watch } from 'vue' @@ -293,16 +295,31 @@ function addTab() { return } - props.tabs.push({ label: __('New Tab'), sections: [] }) + props.tabs.push({ + label: __('New Tab'), + name: 'tab_' + getRandom(), + sections: [], + }) tabIndex.value = props.tabs.length ? props.tabs.length - 1 : 0 } function addField(column, field) { if (!field) return + if (field.fieldtype === 'Select') { + field.options = field.options.split('\n') + field.options = field.options.map((option) => { + return { label: option, value: option } + }) + if (field.options[0].value !== '') { + field.options.unshift({ label: '', value: '' }) + } + } let newFieldObj = { ...field, name: field.fieldname, type: field.fieldtype, + depends_on: '', + mandatory_depends_on: '', } column.fields.push(newFieldObj) } @@ -420,7 +437,11 @@ function getSectionOptions(i, section, tab) { label: __('Add column'), icon: 'columns', onClick: () => { - section.columns.push({ label: '', fields: [] }) + section.columns.push({ + label: '', + name: 'column_' + getRandom(), + fields: [], + }) }, condition: () => section.columns.length < 4, }, diff --git a/frontend/src/components/Modals/DataFieldsModal.vue b/frontend/src/components/Modals/DataFieldsModal.vue index e512d4261..8278fbeca 100644 --- a/frontend/src/components/Modals/DataFieldsModal.vue +++ b/frontend/src/components/Modals/DataFieldsModal.vue @@ -66,7 +66,7 @@ const dirty = ref(false) const preview = ref(false) function getParams() { - return { doctype: _doctype.value, type: 'Data Fields' } + return { doctype: _doctype.value, type: 'Data Fields', no_reactivity: 1 } } const tabs = createResource({ diff --git a/frontend/src/components/SidePanelLayout.vue b/frontend/src/components/SidePanelLayout.vue index bf085ec60..7c306bfb9 100644 --- a/frontend/src/components/SidePanelLayout.vue +++ b/frontend/src/components/SidePanelLayout.vue @@ -232,7 +232,7 @@ import Link from '@/components/Controls/Link.vue' import UserAvatar from '@/components/UserAvatar.vue' import { getMeta } from '@/stores/meta' import { usersStore } from '@/stores/users' -import { getFormat } from '@/utils' +import { getFormat, evaluateDependsOnValue } from '@/utils' import { flt } from '@/utils/numberFormat.js' import { Tooltip, DateTimePicker, DatePicker } from 'frappe-ui' import { computed } from 'vue' @@ -263,7 +263,9 @@ const _fields = computed(() => { let all_fields = [] props.fields?.forEach((field) => { let df = field?.all_properties - if (df?.depends_on) evaluate_depends_on(df.depends_on, field) + if (df?.depends_on && !evaluateDependsOnValue(df.depends_on, data.value)) { + field.hidden = true + } all_fields.push({ ...field, filters: df?.link_filters && JSON.parse(df.link_filters), @@ -273,32 +275,6 @@ const _fields = computed(() => { return all_fields }) -function evaluate_depends_on(expression, field) { - if (expression.substr(0, 5) == 'eval:') { - try { - let out = evaluate(expression.substr(5), { doc: data.value }) - if (!out) { - field.hidden = true - } - } catch (e) { - console.error(e) - } - } -} - -function evaluate(code, context = {}) { - let variable_names = Object.keys(context) - let variables = Object.values(context) - code = `let out = ${code}; return out` - try { - let expression_function = new Function(...variable_names, code) - return expression_function(...variables) - } catch (error) { - console.log('Error evaluating the following expression:') - console.error(code) - throw error - } -}