From ccd138dc213bf60b8f4f3a9659f22ae041bc5cab Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Tue, 21 Nov 2023 15:47:08 +0530 Subject: [PATCH 1/8] feat: load custom fields in lead page --- crm/fcrm/doctype/crm_lead/api.py | 135 +++++++++++++++++++++-- crm/fcrm/doctype/crm_lead/crm_lead.json | 78 ++++++-------- frontend/src/pages/Lead.vue | 137 +++++++----------------- 3 files changed, 192 insertions(+), 158 deletions(-) diff --git a/crm/fcrm/doctype/crm_lead/api.py b/crm/fcrm/doctype/crm_lead/api.py index 4abd959a3..0407d890f 100644 --- a/crm/fcrm/doctype/crm_lead/api.py +++ b/crm/fcrm/doctype/crm_lead/api.py @@ -1,20 +1,13 @@ -import json - import frappe from frappe import _ -from frappe.desk.form.load import get_docinfo +from pypika import Criterion @frappe.whitelist() def get_lead(name): Lead = frappe.qb.DocType("CRM Lead") - query = ( - frappe.qb.from_(Lead) - .select("*") - .where(Lead.name == name) - .limit(1) - ) + query = frappe.qb.from_(Lead).select("*").where(Lead.name == name).limit(1) lead = query.run(as_dict=True) if not len(lead): @@ -22,3 +15,127 @@ def get_lead(name): lead = lead.pop() return lead + +@frappe.whitelist() +def get_lead_fields(): + DocField = frappe.qb.DocType("DocField") + CustomField = frappe.qb.DocType("Custom Field") + not_allowed_fieldtypes = [ + "Section Break", + "Column Break", + ] + restricted_fieldnames = [ + "converted", + "lead_owner", + "status", + "image", + "naming_series" + ] + + fields = ( + frappe.qb.from_(DocField) + .select( + DocField.fieldname, + DocField.fieldtype, + DocField.label, + DocField.name, + DocField.options, + DocField.read_only, + DocField.idx, + ) + .where(DocField.parent == "CRM Lead") + .where(DocField.hidden == False) + .where(Criterion.notin(DocField.fieldtype, not_allowed_fieldtypes)) + .where(Criterion.notin(DocField.fieldname, restricted_fieldnames)) + .orderby(DocField.idx) + .run(as_dict=True) + ) + + custom_fields = ( + frappe.qb.from_(CustomField) + .select( + CustomField.fieldname, + CustomField.fieldtype, + CustomField.label, + CustomField.name, + CustomField.options, + CustomField.read_only, + CustomField.idx, + CustomField.insert_after, + ) + .where(CustomField.dt == "CRM Lead") + .where(CustomField.hidden == False) + .where(Criterion.notin(CustomField.fieldtype, not_allowed_fieldtypes)) + .orderby(CustomField.idx) + .run(as_dict=True) + ) + + all_fields = [] + all_fields.extend(fields) + + # Add custom fields based on insert_after + for custom_field in custom_fields: + if custom_field.insert_after: + for i, field in enumerate(all_fields): + if field.fieldname == custom_field.insert_after: + all_fields.insert(i + 1, custom_field) + break + else: + all_fields.prepend(custom_field) + + sections = {} + section_fields = [] + last_section = None + + for field in all_fields: + if field.fieldtype == "Tab Break" and last_section: + sections[last_section]["fields"] = section_fields + last_section = None + if field.read_only: + section_fields = [] + continue + if field.fieldtype == "Tab Break": + section_fields = [] + last_section = field.fieldname + sections[field.fieldname] = { + "label": field.label, + "opened": True, + "fields": [], + } + else: + section_fields.append(get_field_obj(field)) + + lead_fields = [] + for section in sections: + lead_fields.append(sections[section]) + + return lead_fields + +def get_field_obj(field): + obj = { + "label": field.label, + "type": get_type(field), + "name": field.fieldname, + } + + obj["placeholder"] = "Add " + field.label.lower() + "..." + + if field.fieldtype == "Link": + obj["placeholder"] = "Select " + field.label.lower() + "..." + obj["doctype"] = field.options + elif field.fieldtype == "Select": + obj["options"] = [{"label": option, "value": option} for option in field.options.split("\n")] + + if field.read_only: + obj["tooltip"] = "This field is read only and cannot be edited." + + return obj + +def get_type(field): + if field.fieldtype == "Data" and field.options == "Phone": + return "phone" + elif field.fieldtype == "Data" and field.options == "Email": + return "email" + elif field.read_only: + return "read_only" + return field.fieldtype.lower() \ No newline at end of file diff --git a/crm/fcrm/doctype/crm_lead/crm_lead.json b/crm/fcrm/doctype/crm_lead/crm_lead.json index 3aaa2ad60..d75ba940d 100644 --- a/crm/fcrm/doctype/crm_lead/crm_lead.json +++ b/crm/fcrm/doctype/crm_lead/crm_lead.json @@ -8,36 +8,32 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ + "details", + "organization", + "website", + "industry", + "job_title", "naming_series", + "source", + "person_tab", "salutation", "first_name", - "middle_name", "last_name", - "column_break_izjs", + "email", + "mobile_no", + "organization_tab", + "section_break_uixv", "lead_name", + "middle_name", "gender", - "image", - "column_break_lcuv", - "lead_owner", + "phone", + "column_break_dbsv", "status", - "job_title", - "source", - "converted", - "organization_tab", - "section_break_uixv", - "organization", + "lead_owner", "no_of_employees", - "column_break_dbsv", - "website", "annual_revenue", - "industry", - "contact_tab", - "section_break_ymew", - "email", - "column_break_sijm", - "mobile_no", - "column_break_sjtw", - "phone" + "image", + "converted" ], "fields": [ { @@ -67,20 +63,12 @@ "fieldtype": "Data", "label": "Last Name" }, - { - "fieldname": "column_break_lcuv", - "fieldtype": "Column Break" - }, { "fieldname": "gender", "fieldtype": "Link", "label": "Gender", "options": "Gender" }, - { - "fieldname": "column_break_izjs", - "fieldtype": "Column Break" - }, { "default": "Open", "fieldname": "status", @@ -91,10 +79,6 @@ "reqd": 1, "search_index": 1 }, - { - "fieldname": "section_break_ymew", - "fieldtype": "Section Break" - }, { "fieldname": "email", "fieldtype": "Data", @@ -110,20 +94,12 @@ "options": "URL", "read_only": 1 }, - { - "fieldname": "column_break_sijm", - "fieldtype": "Column Break" - }, { "fieldname": "mobile_no", "fieldtype": "Data", "label": "Mobile No", "options": "Phone" }, - { - "fieldname": "column_break_sjtw", - "fieldtype": "Column Break" - }, { "fieldname": "phone", "fieldtype": "Data", @@ -192,12 +168,8 @@ { "fieldname": "organization_tab", "fieldtype": "Tab Break", - "label": "Organization" - }, - { - "fieldname": "contact_tab", - "fieldtype": "Tab Break", - "label": "Contact" + "label": "Others", + "read_only": 1 }, { "fieldname": "organization", @@ -212,12 +184,22 @@ "in_list_view": 1, "in_standard_filter": 1, "label": "Converted" + }, + { + "fieldname": "person_tab", + "fieldtype": "Tab Break", + "label": "Person" + }, + { + "fieldname": "details", + "fieldtype": "Tab Break", + "label": "Details" } ], "image_field": "image", "index_web_pages_for_search": 1, "links": [], - "modified": "2023-11-13 13:35:35.783003", + "modified": "2023-11-21 13:02:11.680600", "modified_by": "Administrator", "module": "FCRM", "name": "CRM Lead", diff --git a/frontend/src/pages/Lead.vue b/frontend/src/pages/Lead.vue index 7e25019b9..c6c0fe76c 100644 --- a/frontend/src/pages/Lead.vue +++ b/frontend/src/pages/Lead.vue @@ -135,7 +135,7 @@
@@ -173,6 +173,7 @@
- - + /> - {{ field.value }} + {{ field.value || lead.data[field.name] }} { - return [ - { - label: 'Details', - opened: true, - fields: [ - { - label: 'Organization', - type: 'link', - name: 'organization', - placeholder: 'Select organization', - doctype: 'CRM Organization', - change: (data) => data && updateField('organization', data), - create: (value, close) => { - _organization.value.organization_name = value - showOrganizationModal.value = true - close() - }, - link: () => - router.push({ - name: 'Organization', - params: { organizationId: lead.data.organization }, - }), - }, - { - label: 'Website', - type: 'read_only', - name: 'website', - value: organization.value?.website, - tooltip: - 'It is a read only field, value is fetched from organization', - }, - { - label: 'Industry', - type: 'read_only', - name: 'industry', - value: organization.value?.industry, - tooltip: - 'It is a read only field, value is fetched from organization', - }, - { - label: 'Job title', - type: 'data', - name: 'job_title', - }, - { - label: 'Source', - type: 'link', - name: 'source', - placeholder: 'Select source...', - doctype: 'CRM Lead Source', - change: (data) => updateField('source', data), - }, - ], - }, - { - label: 'Person', - opened: true, - fields: [ - { - label: 'Salutation', - type: 'link', - name: 'salutation', - placeholder: 'Mr./Mrs./Ms...', - doctype: 'Salutation', - change: (data) => updateField('salutation', data), - }, - { - label: 'First name', - type: 'data', - name: 'first_name', - }, - { - label: 'Last name', - type: 'data', - name: 'last_name', - }, - { - label: 'Email', - type: 'email', - name: 'email', - }, - { - label: 'Mobile no.', - type: 'phone', - name: 'mobile_no', - }, - ], - }, - ] +const detailSections = createResource({ + url: 'crm.fcrm.doctype.crm_lead.api.get_lead_fields', + cache: 'leadFields', + auto: true, + transform: (data) => { + return getParsedFields(data) + }, }) +function getParsedFields(sections) { + sections.forEach((section) => { + section.fields.forEach((field) => { + if (['website', 'industry'].includes(field.name)) { + field.value = organization.value?.[field.name] + } else if (field.name == 'organization') { + field.create = (value, close) => { + _organization.value.organization_name = value + showOrganizationModal.value = true + close() + } + field.link = () => + router.push({ + name: 'Organization', + params: { organizationId: lead.data.organization }, + }) + } + }) + }) + + return sections +} + const organization = computed(() => { return getOrganization(lead.data.organization) }) From 037b468e0063ab94b5bdf3c4cd3ee41ddf0a4cb7 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 22 Nov 2023 13:23:35 +0530 Subject: [PATCH 2/8] fix: moved get_doctype_fields logic to crm/api/doc.py --- crm/api/doc.py | 119 ++++++++++++++++++++++ crm/fcrm/doctype/crm_lead/api.py | 127 +----------------------- crm/fcrm/doctype/crm_lead/crm_lead.json | 4 +- frontend/src/pages/Lead.vue | 5 +- 4 files changed, 126 insertions(+), 129 deletions(-) diff --git a/crm/api/doc.py b/crm/api/doc.py index 6ff2788e2..9a2299ed0 100644 --- a/crm/api/doc.py +++ b/crm/api/doc.py @@ -45,3 +45,122 @@ def get_filterable_fields(doctype: str): res = [] res.extend(from_doc_fields) return res + +@frappe.whitelist() +def get_doctype_fields(doctype): + DocField = frappe.qb.DocType("DocField") + CustomField = frappe.qb.DocType("Custom Field") + not_allowed_fieldtypes = [ + "Section Break", + "Column Break", + ] + + fields = ( + frappe.qb.from_(DocField) + .select( + DocField.fieldname, + DocField.fieldtype, + DocField.label, + DocField.name, + DocField.options, + DocField.read_only, + DocField.idx, + ) + .where(DocField.parent == doctype) + .where(DocField.hidden == False) + .where(Criterion.notin(DocField.fieldtype, not_allowed_fieldtypes)) + .orderby(DocField.idx) + .run(as_dict=True) + ) + + custom_fields = ( + frappe.qb.from_(CustomField) + .select( + CustomField.fieldname, + CustomField.fieldtype, + CustomField.label, + CustomField.name, + CustomField.options, + CustomField.read_only, + CustomField.idx, + CustomField.insert_after, + ) + .where(CustomField.dt == doctype) + .where(CustomField.hidden == False) + .where(Criterion.notin(CustomField.fieldtype, not_allowed_fieldtypes)) + .orderby(CustomField.idx) + .run(as_dict=True) + ) + + all_fields = [] + all_fields.extend(fields) + + # Add custom fields based on insert_after + for custom_field in custom_fields: + if custom_field.insert_after: + for i, field in enumerate(all_fields): + if field.fieldname == custom_field.insert_after: + all_fields.insert(i + 1, custom_field) + break + else: + all_fields.prepend(custom_field) + + sections = {} + section_fields = [] + last_section = None + + for field in all_fields: + if field.fieldtype == "Tab Break" and last_section: + sections[last_section]["fields"] = section_fields + last_section = None + if field.read_only: + section_fields = [] + continue + if field.fieldtype == "Tab Break": + if field.read_only: + section_fields = [] + continue + section_fields = [] + last_section = field.fieldname + sections[field.fieldname] = { + "label": field.label, + "opened": True, + "fields": [], + } + else: + section_fields.append(get_field_obj(field)) + + deal_fields = [] + for section in sections: + deal_fields.append(sections[section]) + + return deal_fields + +def get_field_obj(field): + obj = { + "label": field.label, + "type": get_type(field), + "name": field.fieldname, + } + + obj["placeholder"] = "Add " + field.label.lower() + "..." + + if field.fieldtype == "Link": + obj["placeholder"] = "Select " + field.label.lower() + "..." + obj["doctype"] = field.options + elif field.fieldtype == "Select": + obj["options"] = [{"label": option, "value": option} for option in field.options.split("\n")] + + if field.read_only: + obj["tooltip"] = "This field is read only and cannot be edited." + + return obj + +def get_type(field): + if field.fieldtype == "Data" and field.options == "Phone": + return "phone" + elif field.fieldtype == "Data" and field.options == "Email": + return "email" + elif field.read_only: + return "read_only" + return field.fieldtype.lower() \ No newline at end of file diff --git a/crm/fcrm/doctype/crm_lead/api.py b/crm/fcrm/doctype/crm_lead/api.py index 0407d890f..f51be6fa6 100644 --- a/crm/fcrm/doctype/crm_lead/api.py +++ b/crm/fcrm/doctype/crm_lead/api.py @@ -1,6 +1,5 @@ import frappe from frappe import _ -from pypika import Criterion @frappe.whitelist() @@ -14,128 +13,4 @@ def get_lead(name): frappe.throw(_("Lead not found"), frappe.DoesNotExistError) lead = lead.pop() - return lead - -@frappe.whitelist() -def get_lead_fields(): - DocField = frappe.qb.DocType("DocField") - CustomField = frappe.qb.DocType("Custom Field") - not_allowed_fieldtypes = [ - "Section Break", - "Column Break", - ] - restricted_fieldnames = [ - "converted", - "lead_owner", - "status", - "image", - "naming_series" - ] - - fields = ( - frappe.qb.from_(DocField) - .select( - DocField.fieldname, - DocField.fieldtype, - DocField.label, - DocField.name, - DocField.options, - DocField.read_only, - DocField.idx, - ) - .where(DocField.parent == "CRM Lead") - .where(DocField.hidden == False) - .where(Criterion.notin(DocField.fieldtype, not_allowed_fieldtypes)) - .where(Criterion.notin(DocField.fieldname, restricted_fieldnames)) - .orderby(DocField.idx) - .run(as_dict=True) - ) - - custom_fields = ( - frappe.qb.from_(CustomField) - .select( - CustomField.fieldname, - CustomField.fieldtype, - CustomField.label, - CustomField.name, - CustomField.options, - CustomField.read_only, - CustomField.idx, - CustomField.insert_after, - ) - .where(CustomField.dt == "CRM Lead") - .where(CustomField.hidden == False) - .where(Criterion.notin(CustomField.fieldtype, not_allowed_fieldtypes)) - .orderby(CustomField.idx) - .run(as_dict=True) - ) - - all_fields = [] - all_fields.extend(fields) - - # Add custom fields based on insert_after - for custom_field in custom_fields: - if custom_field.insert_after: - for i, field in enumerate(all_fields): - if field.fieldname == custom_field.insert_after: - all_fields.insert(i + 1, custom_field) - break - else: - all_fields.prepend(custom_field) - - sections = {} - section_fields = [] - last_section = None - - for field in all_fields: - if field.fieldtype == "Tab Break" and last_section: - sections[last_section]["fields"] = section_fields - last_section = None - if field.read_only: - section_fields = [] - continue - if field.fieldtype == "Tab Break": - section_fields = [] - last_section = field.fieldname - sections[field.fieldname] = { - "label": field.label, - "opened": True, - "fields": [], - } - else: - section_fields.append(get_field_obj(field)) - - lead_fields = [] - for section in sections: - lead_fields.append(sections[section]) - - return lead_fields - -def get_field_obj(field): - obj = { - "label": field.label, - "type": get_type(field), - "name": field.fieldname, - } - - obj["placeholder"] = "Add " + field.label.lower() + "..." - - if field.fieldtype == "Link": - obj["placeholder"] = "Select " + field.label.lower() + "..." - obj["doctype"] = field.options - elif field.fieldtype == "Select": - obj["options"] = [{"label": option, "value": option} for option in field.options.split("\n")] - - if field.read_only: - obj["tooltip"] = "This field is read only and cannot be edited." - - return obj - -def get_type(field): - if field.fieldtype == "Data" and field.options == "Phone": - return "phone" - elif field.fieldtype == "Data" and field.options == "Email": - return "email" - elif field.read_only: - return "read_only" - return field.fieldtype.lower() \ No newline at end of file + return lead \ No newline at end of file diff --git a/crm/fcrm/doctype/crm_lead/crm_lead.json b/crm/fcrm/doctype/crm_lead/crm_lead.json index d75ba940d..c885e4a78 100644 --- a/crm/fcrm/doctype/crm_lead/crm_lead.json +++ b/crm/fcrm/doctype/crm_lead/crm_lead.json @@ -13,7 +13,6 @@ "website", "industry", "job_title", - "naming_series", "source", "person_tab", "salutation", @@ -23,6 +22,7 @@ "mobile_no", "organization_tab", "section_break_uixv", + "naming_series", "lead_name", "middle_name", "gender", @@ -199,7 +199,7 @@ "image_field": "image", "index_web_pages_for_search": 1, "links": [], - "modified": "2023-11-21 13:02:11.680600", + "modified": "2023-11-22 13:03:02.261001", "modified_by": "Administrator", "module": "FCRM", "name": "CRM Lead", diff --git a/frontend/src/pages/Lead.vue b/frontend/src/pages/Lead.vue index c6c0fe76c..743fe8b2f 100644 --- a/frontend/src/pages/Lead.vue +++ b/frontend/src/pages/Lead.vue @@ -423,7 +423,8 @@ function validateFile(file) { } const detailSections = createResource({ - url: 'crm.fcrm.doctype.crm_lead.api.get_lead_fields', + url: 'crm.api.doc.get_doctype_fields', + params: { doctype: 'CRM Lead' }, cache: 'leadFields', auto: true, transform: (data) => { @@ -436,6 +437,8 @@ function getParsedFields(sections) { section.fields.forEach((field) => { if (['website', 'industry'].includes(field.name)) { field.value = organization.value?.[field.name] + field.tooltip = + 'This field is read-only and is fetched from the organization' } else if (field.name == 'organization') { field.create = (value, close) => { _organization.value.organization_name = value From e9cbc6067523e988eb007f634bb2f7d7c9039009 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 22 Nov 2023 13:30:09 +0530 Subject: [PATCH 3/8] feat: load custom fields in deal page --- crm/fcrm/doctype/crm_deal/crm_deal.json | 43 +++++---- frontend/src/pages/Deal.vue | 122 ++++++++++-------------- 2 files changed, 76 insertions(+), 89 deletions(-) diff --git a/crm/fcrm/doctype/crm_deal/crm_deal.json b/crm/fcrm/doctype/crm_deal/crm_deal.json index 1363f8099..1cc608fc5 100644 --- a/crm/fcrm/doctype/crm_deal/crm_deal.json +++ b/crm/fcrm/doctype/crm_deal/crm_deal.json @@ -6,23 +6,24 @@ "doctype": "DocType", "engine": "InnoDB", "field_order": [ - "naming_series", + "organization_tab", "organization", "website", "annual_revenue", - "column_break_afce", - "deal_owner", "close_date", - "status", "probability", "next_step", - "section_break_eepu", - "lead", - "column_break_bqvs", "contacts_tab", "email", "mobile_no", - "contacts" + "contacts", + "others_tab", + "naming_series", + "status", + "deal_owner", + "section_break_eepu", + "lead", + "column_break_bqvs" ], "fields": [ { @@ -40,18 +41,16 @@ "fetch_from": "organization.annual_revenue", "fieldname": "annual_revenue", "fieldtype": "Int", - "label": "Annual Revenue" - }, - { - "fieldname": "column_break_afce", - "fieldtype": "Column Break" + "label": "Amount", + "read_only": 1 }, { "fetch_from": "organization.website", "fieldname": "website", "fieldtype": "Data", "label": "Website", - "options": "URL" + "options": "URL", + "read_only": 1 }, { "fieldname": "close_date", @@ -92,7 +91,8 @@ { "fieldname": "contacts_tab", "fieldtype": "Tab Break", - "label": "Contacts" + "label": "Contacts", + "read_only": 1 }, { "fieldname": "email", @@ -121,11 +121,22 @@ "fieldtype": "Table", "label": "Contacts", "options": "CRM Contacts" + }, + { + "fieldname": "others_tab", + "fieldtype": "Tab Break", + "label": "Others", + "read_only": 1 + }, + { + "fieldname": "organization_tab", + "fieldtype": "Tab Break", + "label": "Organization" } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2023-11-09 19:58:15.620483", + "modified": "2023-11-22 13:26:52.401192", "modified_by": "Administrator", "module": "FCRM", "name": "CRM Deal", diff --git a/frontend/src/pages/Deal.vue b/frontend/src/pages/Deal.vue index 42dd6ffaa..55150d0ea 100644 --- a/frontend/src/pages/Deal.vue +++ b/frontend/src/pages/Deal.vue @@ -96,10 +96,10 @@
@@ -191,13 +191,14 @@
{ - return [ - { - label: 'Organization', - opened: true, - fields: [ - { - label: 'Organization', - type: 'link', - name: 'organization', - placeholder: 'Select organization', - doctype: 'CRM Organization', - change: (data) => updateField('organization', data), - create: (value, close) => { - _organization.value.organization_name = value - showOrganizationModal.value = true - close() - }, - link: () => { - router.push({ - name: 'Organization', - params: { organizationId: organization.value.name }, - }) - }, - }, - { - label: 'Website', - type: 'read_only', - name: 'website', - value: organization.value?.website, - tooltip: - 'It is a read only field, value is fetched from organization', - }, - { - label: 'Amount', - type: 'read_only', - name: 'annual_revenue', - value: organization.value?.annual_revenue, - tooltip: - 'It is a read only field, value is fetched from organization', - }, - { - label: 'Close date', - type: 'date', - name: 'close_date', - }, - { - label: 'Probability', - type: 'data', - name: 'probability', - }, - { - label: 'Next step', - type: 'data', - name: 'next_step', - }, - ], - }, - { - label: 'Contacts', - opened: true, - contacts: deal.data.contacts.map((contact) => { - return { - name: contact.contact, - is_primary: contact.is_primary, - opened: false, - } - }), - }, - ] +const detailSections = createResource({ + url: 'crm.api.doc.get_doctype_fields', + params: { doctype: 'CRM Deal' }, + cache: 'dealFields', + auto: true, + transform: (data) => { + return getParsedFields(data) + }, }) +function getParsedFields(sections) { + sections.forEach((section) => { + section.fields.forEach((field) => { + if (['website', 'annual_revenue'].includes(field.name)) { + field.value = organization.value?.[field.name] + field.tooltip = + 'This field is read-only and is fetched from the organization' + } else if (field.name == 'organization') { + field.create = (value, close) => { + _organization.value.organization_name = value + showOrganizationModal.value = true + close() + } + field.link = () => + router.push({ + name: 'Organization', + params: { organizationId: deal.data.organization }, + }) + } + }) + }) + + let contactSection = { + label: 'Contacts', + opened: true, + contacts: deal.data.contacts.map((contact) => { + return { + name: contact.contact, + is_primary: contact.is_primary, + opened: false, + } + }), + } + + return [...sections, contactSection] +} + const showContactModal = ref(false) const _contact = ref({}) From 36455b8faf1fa769a700488ed07ff895dce74976 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 22 Nov 2023 13:54:41 +0530 Subject: [PATCH 4/8] fix: moved section fields in separate component --- frontend/src/components/SectionFields.vue | 86 +++++++++++++++++ frontend/src/pages/Deal.vue | 63 ++----------- frontend/src/pages/Lead.vue | 110 ++-------------------- 3 files changed, 98 insertions(+), 161 deletions(-) create mode 100644 frontend/src/components/SectionFields.vue diff --git a/frontend/src/components/SectionFields.vue b/frontend/src/components/SectionFields.vue new file mode 100644 index 000000000..a90922743 --- /dev/null +++ b/frontend/src/components/SectionFields.vue @@ -0,0 +1,86 @@ + + + diff --git a/frontend/src/pages/Deal.vue b/frontend/src/pages/Deal.vue index 55150d0ea..cf0c07ef3 100644 --- a/frontend/src/pages/Deal.vue +++ b/frontend/src/pages/Deal.vue @@ -153,64 +153,12 @@ leave-to-class="max-h-0 overflow-hidden" >
-
-
- {{ field.label }} -
-
- - - - {{ field.value }} - - -
- -
+ :fields="section.fields" + v-model="deal.data" + @update="updateField" + />
-
-
- {{ field.label }} -
-
- - - - - - - - - {{ field.value || lead.data[field.name] }} - - -
- -
+
@@ -293,13 +196,12 @@ import NoteIcon from '@/components/Icons/NoteIcon.vue' import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue' import CameraIcon from '@/components/Icons/CameraIcon.vue' import LinkIcon from '@/components/Icons/LinkIcon.vue' -import ExternalLinkIcon from '@/components/Icons/ExternalLinkIcon.vue' import LayoutHeader from '@/components/LayoutHeader.vue' import Toggler from '@/components/Toggler.vue' import Activities from '@/components/Activities.vue' import UserAvatar from '@/components/UserAvatar.vue' import OrganizationModal from '@/components/Modals/OrganizationModal.vue' -import Link from '@/components/Controls/Link.vue' +import SectionFields from '@/components/SectionFields.vue' import { leadStatuses, statusDropdownOptions, From b157f255f8a1fd95e4d036a018557e94bd56cf8c Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 22 Nov 2023 14:34:58 +0530 Subject: [PATCH 5/8] fix: created Section Component using Toggler component and used in lead/deal --- frontend/src/components/Section.vue | 56 ++++++ frontend/src/components/SectionFields.vue | 128 ++++++------- frontend/src/components/Toggler.vue | 24 --- frontend/src/pages/Deal.vue | 217 +++++++++------------- frontend/src/pages/Lead.vue | 47 ++--- 5 files changed, 223 insertions(+), 249 deletions(-) create mode 100644 frontend/src/components/Section.vue delete mode 100644 frontend/src/components/Toggler.vue diff --git a/frontend/src/components/Section.vue b/frontend/src/components/Section.vue new file mode 100644 index 000000000..20e4573e8 --- /dev/null +++ b/frontend/src/components/Section.vue @@ -0,0 +1,56 @@ + + diff --git a/frontend/src/components/SectionFields.vue b/frontend/src/components/SectionFields.vue index a90922743..d0c2ec27d 100644 --- a/frontend/src/components/SectionFields.vue +++ b/frontend/src/components/SectionFields.vue @@ -1,69 +1,71 @@ diff --git a/frontend/src/components/Toggler.vue b/frontend/src/components/Toggler.vue deleted file mode 100644 index 010608753..000000000 --- a/frontend/src/components/Toggler.vue +++ /dev/null @@ -1,24 +0,0 @@ - - diff --git a/frontend/src/pages/Deal.vue b/frontend/src/pages/Deal.vue index cf0c07ef3..4a04d8899 100644 --- a/frontend/src/pages/Deal.vue +++ b/frontend/src/pages/Deal.vue @@ -101,19 +101,8 @@ class="flex flex-col p-3" :class="{ 'border-b': i !== detailSections.data.length - 1 }" > - -
-
- - {{ section.label }} -
+
+