From 00e97d19e331c3a1a8bc0c303aacdd06d7319c63 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Tue, 28 Nov 2023 14:26:26 +0530 Subject: [PATCH] fix: added filter, sort & list view settings in contact list --- crm/hooks.py | 6 +- crm/overrides/contact.py | 58 +++++++++++++ frontend/src/pages/Contacts.vue | 144 +++++++++++++++++++------------- frontend/src/pages/Leads.vue | 1 - 4 files changed, 147 insertions(+), 62 deletions(-) create mode 100644 crm/overrides/contact.py diff --git a/crm/hooks.py b/crm/hooks.py index fdaef00f..abfc9d0e 100644 --- a/crm/hooks.py +++ b/crm/hooks.py @@ -117,9 +117,9 @@ website_route_rules = [ # --------------- # Override standard doctype classes -# override_doctype_class = { -# "ToDo": "custom_app.overrides.CustomToDo" -# } +override_doctype_class = { + "Contact": "crm.overrides.contact.CustomContact" +} # Document Events # --------------- diff --git a/crm/overrides/contact.py b/crm/overrides/contact.py new file mode 100644 index 00000000..0cf250a0 --- /dev/null +++ b/crm/overrides/contact.py @@ -0,0 +1,58 @@ +# import frappe +from frappe import _ +from frappe.contacts.doctype.contact.contact import Contact + + +class CustomContact(Contact): + @staticmethod + def sort_options(): + return [ + { "label": 'Created', "value": 'creation' }, + { "label": 'Modified', "value": 'modified' }, + { "label": 'Organization', "value": 'company_name' }, + { "label": 'Full Name', "value": 'full_name' }, + { "label": 'First Name', "value": 'first_name' }, + { "label": 'Last Name', "value": 'last_name' }, + { "label": 'Email', "value": 'email' }, + { "label": 'Mobile no', "value": 'mobile_no' }, + ] + + @staticmethod + def default_list_data(): + columns = [ + { + 'label': 'Name', + 'key': 'full_name', + 'width': '17rem', + }, + { + 'label': 'Email', + 'key': 'email_id', + 'width': '12rem', + }, + { + 'label': 'Phone', + 'key': 'mobile_no', + 'width': '12rem', + }, + { + 'label': 'Organization', + 'key': 'company_name', + 'width': '12rem', + }, + { + 'label': 'Last modified', + 'key': 'modified', + 'width': '8rem', + }, + ] + rows = [ + "name", + "full_name", + "company_name", + "email_id", + "mobile_no", + "modified", + "image", + ] + return {'columns': columns, 'rows': rows} diff --git a/frontend/src/pages/Contacts.vue b/frontend/src/pages/Contacts.vue index f94464f1..fae545dc 100644 --- a/frontend/src/pages/Contacts.vue +++ b/frontend/src/pages/Contacts.vue @@ -30,10 +30,14 @@
-
- + @@ -43,21 +47,25 @@ import ContactModal from '@/components/Modals/ContactModal.vue' import ContactsListView from '@/components/ListViews/ContactsListView.vue' import SortBy from '@/components/SortBy.vue' import Filter from '@/components/Filter.vue' -import { FeatherIcon, Breadcrumbs, Dropdown } from 'frappe-ui' -import { contactsStore } from '@/stores/contacts.js' +import ViewSettings from '@/components/ViewSettings.vue' +import { FeatherIcon, Breadcrumbs, Dropdown, createResource } from 'frappe-ui' import { organizationsStore } from '@/stores/organizations.js' +import { useOrderBy } from '@/composables/orderby' +import { useFilter } from '@/composables/filter' import { dateFormat, dateTooltipFormat, timeAgo } from '@/utils' -import { ref, computed, onMounted } from 'vue' +import { useDebounceFn } from '@vueuse/core' +import { ref, computed, watch } from 'vue' import { useRoute } from 'vue-router' -const { contacts } = contactsStore() const { getOrganization } = organizationsStore() +const { get: getOrderBy } = useOrderBy() +const { getArgs, storage } = useFilter() const route = useRoute() const showContactModal = ref(false) const currentContact = computed(() => { - return contacts.data.find( + return contacts.data?.data?.find( (contact) => contact.name === route.params.contactId ) }) @@ -80,6 +88,77 @@ const currentView = ref({ icon: 'list', }) +function getParams() { + const filters = getArgs() || {} + const order_by = getOrderBy() || 'modified desc' + + return { + doctype: 'Contact', + filters: filters, + order_by: order_by, + } +} + +const contacts = createResource({ + url: 'crm.api.doc.get_list_data', + params: getParams(), + auto: true, +}) + +watch( + () => getOrderBy(), + (value, old_value) => { + if (!value && !old_value) return + contacts.params = getParams() + contacts.reload() + }, + { immediate: true } +) + +watch( + storage, + useDebounceFn((value, old_value) => { + if (JSON.stringify([...value]) === JSON.stringify([...old_value])) return + contacts.params = getParams() + contacts.reload() + }, 300), + { deep: true } +) + +const rows = computed(() => { + if (!contacts.data?.data) return [] + return contacts.data.data.map((contact) => { + let _rows = {} + contacts.data.rows.forEach((row) => { + _rows[row] = contact[row] + + if (row == 'full_name') { + _rows[row] = { + label: contact.full_name, + image_label: contact.full_name, + image: contact.image, + } + } else if (row == 'company_name') { + _rows[row] = { + label: contact.company_name, + logo: getOrganization(contact.company_name)?.organization_logo, + } + } else if (row == 'modified') { + _rows[row] = { + label: dateFormat(contact.modified, dateTooltipFormat), + timeAgo: timeAgo(contact.modified), + } + } else if (row == 'creation') { + _rows[row] = { + label: dateFormat(contact.creation, dateTooltipFormat), + timeAgo: timeAgo(contact.creation), + } + } + }) + return _rows + }) +}) + const viewsDropdownOptions = [ { label: 'List', @@ -122,55 +201,4 @@ const viewsDropdownOptions = [ }, }, ] - -const rows = computed(() => { - return contacts.data.map((contact) => { - return { - name: contact.name, - full_name: { - label: contact.full_name, - image_label: contact.full_name, - image: contact.image, - }, - email: contact.email_id, - mobile_no: contact.mobile_no, - company_name: { - label: contact.company_name, - logo: getOrganization(contact.company_name)?.organization_logo, - }, - modified: { - label: dateFormat(contact.modified, dateTooltipFormat), - timeAgo: timeAgo(contact.modified), - }, - } - }) -}) - -const columns = [ - { - label: 'Name', - key: 'full_name', - width: '17rem', - }, - { - label: 'Email', - key: 'email', - width: '12rem', - }, - { - label: 'Phone', - key: 'mobile_no', - width: '12rem', - }, - { - label: 'Organization', - key: 'company_name', - width: '12rem', - }, - { - label: 'Last modified', - key: 'modified', - width: '8rem', - }, -] diff --git a/frontend/src/pages/Leads.vue b/frontend/src/pages/Leads.vue index a721e964..96308b71 100644 --- a/frontend/src/pages/Leads.vue +++ b/frontend/src/pages/Leads.vue @@ -137,7 +137,6 @@ const rows = computed(() => { if (!leads.data?.data) return [] return leads.data.data.map((lead) => { let _rows = {} - leads.data.rows.forEach((row) => { _rows[row] = lead[row]