@@ -19,18 +22,18 @@
-
- {{ contact.data.salutation + '. ' }}
+
+ {{ contact.doc.salutation + '. ' }}
- {{ contact.data.full_name }}
+ {{ contact.doc.full_name }}
+ />
@@ -132,7 +129,7 @@
@@ -169,13 +166,14 @@ import DealsIcon from '@/components/Icons/DealsIcon.vue'
import DealsListView from '@/components/ListViews/DealsListView.vue'
import { formatDate, timeAgo, validateIsImageFile } from '@/utils'
import { getView } from '@/utils/view'
-import { showAddressModal, addressProps } from '@/composables/modals'
+import { useDocument } from '@/data/document'
import { getSettings } from '@/stores/settings'
import { getMeta } from '@/stores/meta'
import { globalStore } from '@/stores/global.js'
import { usersStore } from '@/stores/users.js'
import { organizationsStore } from '@/stores/organizations.js'
import { statusesStore } from '@/stores/statuses'
+import { showAddressModal, addressProps } from '@/composables/modals'
import { callEnabled } from '@/composables/settings'
import {
Breadcrumbs,
@@ -211,23 +209,7 @@ const props = defineProps({
const route = useRoute()
const router = useRouter()
-const _contact = ref({})
-
-const contact = createResource({
- url: 'crm.api.contact.get_contact',
- cache: ['contact', props.contactId],
- params: {
- name: props.contactId,
- },
- auto: true,
- transform: (data) => {
- return {
- ...data,
- actual_mobile_no: data.mobile_no,
- mobile_no: data.mobile_no,
- }
- },
-})
+const { document: contact } = useDocument('Contact', props.contactId)
const breadcrumbs = computed(() => {
let items = [{ label: __('Contacts'), route: { name: 'Contacts' } }]
@@ -256,7 +238,7 @@ const breadcrumbs = computed(() => {
const title = computed(() => {
let t = doctypeMeta['Contact']?.title_field || 'name'
- return contact.data?.[t] || props.contactId
+ return contact.doc?.[t] || props.contactId
})
usePageMeta(() => {
@@ -266,14 +248,13 @@ usePageMeta(() => {
}
})
-async function changeContactImage(file) {
- await call('frappe.client.set_value', {
- doctype: 'Contact',
- name: props.contactId,
- fieldname: 'image',
- value: file?.file_url || '',
+function changeContactImage(file) {
+ contact.doc.image = file?.file_url || ''
+ contact.save.submit(null, {
+ onSuccess: () => {
+ toast.success(__('Contact image updated'))
+ },
})
- contact.reload()
}
async function deleteContact() {
@@ -343,22 +324,18 @@ function getParsedSections(_sections) {
...field,
type: 'dropdown',
options:
- contact.data?.email_ids?.map((email) => {
+ contact.doc?.email_ids?.map((email) => {
return {
name: email.name,
value: email.email_id,
- selected: email.email_id === contact.data.email_id,
+ selected: email.email_id === contact.doc.email_id,
placeholder: 'john@doe.com',
onClick: () => {
- _contact.value.email_id = email.email_id
setAsPrimary('email', email.email_id)
},
onSave: (option, isNew) => {
if (isNew) {
createNew('email', option.value)
- if (contact.data.email_ids.length === 1) {
- _contact.value.email_id = option.value
- }
} else {
editOption(
'Contact Email',
@@ -369,24 +346,15 @@ function getParsedSections(_sections) {
}
},
onDelete: async (option, isNew) => {
- contact.data.email_ids = contact.data.email_ids.filter(
+ contact.doc.email_ids = contact.doc.email_ids.filter(
(email) => email.name !== option.name,
)
!isNew && (await deleteOption('Contact Email', option.name))
- if (_contact.value.email_id === option.value) {
- if (contact.data.email_ids.length === 0) {
- _contact.value.email_id = ''
- } else {
- _contact.value.email_id = contact.data.email_ids.find(
- (email) => email.is_primary,
- )?.email_id
- }
- }
},
}
}) || [],
create: () => {
- contact.data?.email_ids?.push({
+ contact.doc?.email_ids?.push({
name: 'new-1',
value: '',
selected: false,
@@ -400,22 +368,17 @@ function getParsedSections(_sections) {
read_only: false,
fieldtype: 'dropdown',
options:
- contact.data?.phone_nos?.map((phone) => {
+ contact.doc?.phone_nos?.map((phone) => {
return {
name: phone.name,
value: phone.phone,
- selected: phone.phone === contact.data.actual_mobile_no,
+ selected: phone.phone === contact.doc.mobile_no,
onClick: () => {
- _contact.value.actual_mobile_no = phone.phone
- _contact.value.mobile_no = phone.phone
setAsPrimary('mobile_no', phone.phone)
},
onSave: (option, isNew) => {
if (isNew) {
createNew('phone', option.value)
- if (contact.data.phone_nos.length === 1) {
- _contact.value.actual_mobile_no = option.value
- }
} else {
editOption(
'Contact Phone',
@@ -426,25 +389,15 @@ function getParsedSections(_sections) {
}
},
onDelete: async (option, isNew) => {
- contact.data.phone_nos = contact.data.phone_nos.filter(
+ contact.doc.phone_nos = contact.doc.phone_nos.filter(
(phone) => phone.name !== option.name,
)
!isNew && (await deleteOption('Contact Phone', option.name))
- if (_contact.value.actual_mobile_no === option.value) {
- if (contact.data.phone_nos.length === 0) {
- _contact.value.actual_mobile_no = ''
- } else {
- _contact.value.actual_mobile_no =
- contact.data.phone_nos.find(
- (phone) => phone.is_primary_mobile_no,
- )?.phone
- }
- }
},
}
}) || [],
create: () => {
- contact.data?.phone_nos?.push({
+ contact.doc?.phone_nos?.push({
name: 'new-1',
value: '',
selected: false,
@@ -456,7 +409,6 @@ function getParsedSections(_sections) {
return {
...field,
create: (value, close) => {
- _contact.value.address = value
openAddressModal()
close()
},
@@ -474,7 +426,7 @@ function getParsedSections(_sections) {
async function setAsPrimary(field, value) {
let d = await call('crm.api.contact.set_as_primary', {
- contact: contact.data.name,
+ contact: contact.doc.name,
field,
value,
})
@@ -487,7 +439,7 @@ async function setAsPrimary(field, value) {
async function createNew(field, value) {
if (!value) return
let d = await call('crm.api.contact.create_new', {
- contact: contact.data.name,
+ contact: contact.doc.name,
field,
value,
})
diff --git a/frontend/src/pages/MobileOrganization.vue b/frontend/src/pages/MobileOrganization.vue
index 5ed074af..ce4dd57b 100644
--- a/frontend/src/pages/MobileOrganization.vue
+++ b/frontend/src/pages/MobileOrganization.vue
@@ -158,6 +158,7 @@ import CameraIcon from '@/components/Icons/CameraIcon.vue'
import DealsIcon from '@/components/Icons/DealsIcon.vue'
import ContactsIcon from '@/components/Icons/ContactsIcon.vue'
import { showAddressModal, addressProps } from '@/composables/modals'
+import { useDocument } from '@/data/document'
import { getSettings } from '@/stores/settings'
import { getMeta } from '@/stores/meta'
import { globalStore } from '@/stores/global'
@@ -175,7 +176,6 @@ import {
TabPanel,
call,
createListResource,
- createDocumentResource,
usePageMeta,
createResource,
toast,
@@ -199,13 +199,10 @@ const { doctypeMeta } = getMeta('CRM Organization')
const route = useRoute()
const router = useRouter()
-const organization = createDocumentResource({
- doctype: 'CRM Organization',
- name: props.organizationId,
- cache: ['organization', props.organizationId],
- fields: ['*'],
- auto: true,
-})
+const { document: organization } = useDocument(
+ 'CRM Organization',
+ props.organizationId,
+)
const breadcrumbs = computed(() => {
let items = [{ label: __('Organizations'), route: { name: 'Organizations' } }]
@@ -288,8 +285,6 @@ function openWebsite() {
else window.open(organization.doc.website, '_blank')
}
-const _organization = ref({})
-
const sections = createResource({
url: 'crm.fcrm.doctype.crm_fields_layout.crm_fields_layout.get_sidepanel_sections',
cache: ['sidePanelSections', 'CRM Organization'],
@@ -306,7 +301,6 @@ function getParsedSections(_sections) {
return {
...field,
create: (value, close) => {
- _organization.value.address = value
openAddressModal()
close()
},
diff --git a/frontend/src/pages/Organization.vue b/frontend/src/pages/Organization.vue
index 769d345f..ac08cb01 100644
--- a/frontend/src/pages/Organization.vue
+++ b/frontend/src/pages/Organization.vue
@@ -186,9 +186,9 @@ import CameraIcon from '@/components/Icons/CameraIcon.vue'
import DealsIcon from '@/components/Icons/DealsIcon.vue'
import ContactsIcon from '@/components/Icons/ContactsIcon.vue'
import { showAddressModal, addressProps } from '@/composables/modals'
+import { useDocument } from '@/data/document'
import { getSettings } from '@/stores/settings'
import { getMeta } from '@/stores/meta'
-import { globalStore } from '@/stores/global'
import { usersStore } from '@/stores/users'
import { statusesStore } from '@/stores/statuses'
import { getView } from '@/utils/view'
@@ -202,13 +202,12 @@ import {
Tabs,
call,
createListResource,
- createDocumentResource,
usePageMeta,
createResource,
toast,
} from 'frappe-ui'
import { h, computed, ref } from 'vue'
-import { useRoute, useRouter } from 'vue-router'
+import { useRoute } from 'vue-router'
import DeleteLinkedDocModal from '@/components/DeleteLinkedDocModal.vue'
const props = defineProps({
@@ -220,37 +219,20 @@ const props = defineProps({
const { brand } = getSettings()
const { getUser } = usersStore()
-const { $dialog } = globalStore()
const { getDealStatus } = statusesStore()
const { doctypeMeta } = getMeta('CRM Organization')
const route = useRoute()
-const router = useRouter()
const errorTitle = ref('')
const errorMessage = ref('')
const showDeleteLinkedDocModal = ref(false)
-const organization = createDocumentResource({
- doctype: 'CRM Organization',
- name: props.organizationId,
- cache: ['organization', props.organizationId],
- fields: ['*'],
- auto: true,
- onSuccess: () => {
- errorTitle.value = ''
- errorMessage.value = ''
- },
- onError: (err) => {
- if (err.messages?.[0]) {
- errorTitle.value = __('Not permitted')
- errorMessage.value = __(err.messages?.[0])
- } else {
- router.push({ name: 'Organizations' })
- }
- },
-})
+const { document: organization } = useDocument(
+ 'CRM Organization',
+ props.organizationId,
+)
const breadcrumbs = computed(() => {
let items = [{ label: __('Organizations'), route: { name: 'Organizations' } }]
@@ -319,8 +301,6 @@ function openWebsite() {
else window.open(organization.doc.website, '_blank')
}
-const _organization = ref({})
-
const sections = createResource({
url: 'crm.fcrm.doctype.crm_fields_layout.crm_fields_layout.get_sidepanel_sections',
cache: ['sidePanelSections', 'CRM Organization'],
@@ -337,7 +317,6 @@ function getParsedSections(_sections) {
return {
...field,
create: (value, close) => {
- _organization.value.address = value
openAddressModal()
close()
},