refactor: show call log detail in call log modal
This commit is contained in:
parent
e7ca90df51
commit
f5fa47bae0
@ -84,7 +84,9 @@
|
||||
</div>
|
||||
</template>
|
||||
<template
|
||||
v-if="callLog.type.label == 'Incoming' && !callLog.reference_docname"
|
||||
v-if="
|
||||
callLog.doc?.type.label == 'Incoming' && !callLog.doc?.reference_docname
|
||||
"
|
||||
#actions
|
||||
>
|
||||
<Button
|
||||
@ -116,11 +118,12 @@ import {
|
||||
createDocumentResource,
|
||||
call,
|
||||
} from 'frappe-ui'
|
||||
import { getCallLogDetail } from '@/utils/callLog'
|
||||
import { ref, computed, h, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const props = defineProps({
|
||||
callLog: {
|
||||
name: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
@ -130,60 +133,66 @@ const show = defineModel()
|
||||
const showNoteModal = ref(false)
|
||||
const router = useRouter()
|
||||
const callNoteDoc = ref(null)
|
||||
const callLog = ref({})
|
||||
|
||||
const detailFields = computed(() => {
|
||||
if (!callLog.value.doc) return []
|
||||
let details = [
|
||||
{
|
||||
icon: h(FeatherIcon, {
|
||||
name: props.callLog.type.icon,
|
||||
name: callLog.value.doc.type.icon,
|
||||
class: 'h-3.5 w-3.5',
|
||||
}),
|
||||
name: 'type',
|
||||
value: props.callLog.type.label + ' Call',
|
||||
value: callLog.value.doc.type.label + ' Call',
|
||||
},
|
||||
{
|
||||
icon: ContactsIcon,
|
||||
name: 'receiver',
|
||||
value: {
|
||||
receiver: props.callLog.receiver,
|
||||
caller: props.callLog.caller,
|
||||
receiver: callLog.value.doc.receiver,
|
||||
caller: callLog.value.doc.caller,
|
||||
},
|
||||
},
|
||||
{
|
||||
icon:
|
||||
props.callLog.reference_doctype == 'CRM Lead' ? LeadsIcon : Dealsicon,
|
||||
callLog.value.doc.reference_doctype == 'CRM Lead'
|
||||
? LeadsIcon
|
||||
: Dealsicon,
|
||||
name: 'reference_doctype',
|
||||
value: props.callLog.reference_doctype == 'CRM Lead' ? 'Lead' : 'Deal',
|
||||
value:
|
||||
callLog.value.doc.reference_doctype == 'CRM Lead' ? 'Lead' : 'Deal',
|
||||
link: () => {
|
||||
if (props.callLog.reference_doctype == 'CRM Lead') {
|
||||
if (callLog.value.doc.reference_doctype == 'CRM Lead') {
|
||||
router.push({
|
||||
name: 'Lead',
|
||||
params: { leadId: props.callLog.reference_docname },
|
||||
params: { leadId: callLog.value.doc.reference_docname },
|
||||
})
|
||||
} else {
|
||||
router.push({
|
||||
name: 'Deal',
|
||||
params: { dealId: props.callLog.reference_docname },
|
||||
params: { dealId: callLog.value.doc.reference_docname },
|
||||
})
|
||||
}
|
||||
},
|
||||
condition: () => callLog.value.doc.reference_docname,
|
||||
},
|
||||
{
|
||||
icon: CalendarIcon,
|
||||
name: 'creation',
|
||||
value: props.callLog.creation.label,
|
||||
tooltip: props.callLog.creation.label,
|
||||
value: callLog.value.doc.creation.label,
|
||||
tooltip: callLog.value.doc.creation.label,
|
||||
},
|
||||
{
|
||||
icon: DurationIcon,
|
||||
name: 'duration',
|
||||
value: props.callLog.duration.label,
|
||||
value: callLog.value.doc.duration.label,
|
||||
},
|
||||
{
|
||||
icon: CheckCircleIcon,
|
||||
name: 'status',
|
||||
value: props.callLog.status.label,
|
||||
color: props.callLog.status.color,
|
||||
value: callLog.value.doc.status.label,
|
||||
color: callLog.value.doc.status.color,
|
||||
},
|
||||
{
|
||||
icon: h(FeatherIcon, {
|
||||
@ -191,7 +200,7 @@ const detailFields = computed(() => {
|
||||
class: 'h-4 w-4 mt-2',
|
||||
}),
|
||||
name: 'recording_url',
|
||||
value: props.callLog.recording_url,
|
||||
value: callLog.value.doc.recording_url,
|
||||
},
|
||||
{
|
||||
icon: NoteIcon,
|
||||
@ -200,12 +209,14 @@ const detailFields = computed(() => {
|
||||
},
|
||||
]
|
||||
|
||||
return details.filter((detail) => detail.value)
|
||||
return details
|
||||
.filter((detail) => detail.value)
|
||||
.filter((detail) => (detail.condition ? detail.condition() : true))
|
||||
})
|
||||
|
||||
function createLead() {
|
||||
call('crm.fcrm.doctype.crm_call_log.crm_call_log.create_lead_from_call_log', {
|
||||
call_log: props.callLog,
|
||||
call_log: callLog.value.doc,
|
||||
}).then((d) => {
|
||||
if (d) {
|
||||
router.push({ name: 'Lead', params: { leadId: d } })
|
||||
@ -215,12 +226,45 @@ function createLead() {
|
||||
|
||||
watch(show, (val) => {
|
||||
if (val) {
|
||||
callNoteDoc.value = createDocumentResource({
|
||||
doctype: 'FCRM Note',
|
||||
name: props.callLog.note,
|
||||
fields: ['title', 'content'],
|
||||
cache: ['note', props.callLog.note],
|
||||
callLog.value = createDocumentResource({
|
||||
doctype: 'CRM Call Log',
|
||||
name: props.name,
|
||||
fields: [
|
||||
'name',
|
||||
'caller',
|
||||
'receiver',
|
||||
'duration',
|
||||
'type',
|
||||
'status',
|
||||
'from',
|
||||
'to',
|
||||
'note',
|
||||
'recording_url',
|
||||
'reference_doctype',
|
||||
'reference_docname',
|
||||
'creation',
|
||||
],
|
||||
cache: ['call_log', props.name],
|
||||
auto: true,
|
||||
transform: (doc) => {
|
||||
for (const key in doc) {
|
||||
doc[key] = getCallLogDetail(key, doc)
|
||||
}
|
||||
return doc
|
||||
},
|
||||
onSuccess: (doc) => {
|
||||
if (!doc.note) {
|
||||
callNoteDoc.value = null
|
||||
return
|
||||
}
|
||||
callNoteDoc.value = createDocumentResource({
|
||||
doctype: 'FCRM Note',
|
||||
name: doc.note,
|
||||
fields: ['title', 'content'],
|
||||
cache: ['note', doc.note],
|
||||
auto: true,
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
<CallLogModal
|
||||
v-model="showCallLogModal"
|
||||
v-model:reloadCallLogs="callLogs"
|
||||
:callLog="callLog"
|
||||
:name="selectedCallLog"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@ -64,20 +64,10 @@ import LayoutHeader from '@/components/LayoutHeader.vue'
|
||||
import ViewControls from '@/components/ViewControls.vue'
|
||||
import CallLogsListView from '@/components/ListViews/CallLogsListView.vue'
|
||||
import CallLogModal from '@/components/Modals/CallLogModal.vue'
|
||||
import {
|
||||
secondsToDuration,
|
||||
dateFormat,
|
||||
dateTooltipFormat,
|
||||
timeAgo,
|
||||
} from '@/utils'
|
||||
import { usersStore } from '@/stores/users'
|
||||
import { contactsStore } from '@/stores/contacts'
|
||||
import { getCallLogDetail } from '@/utils/callLog'
|
||||
import { Breadcrumbs } from 'frappe-ui'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
const { getUser } = usersStore()
|
||||
const { getContact, getLeadContact } = contactsStore()
|
||||
|
||||
const breadcrumbs = [{ label: __('Call Logs'), route: { name: 'Call Logs' } }]
|
||||
|
||||
const callLogsListView = ref(null)
|
||||
@ -94,119 +84,17 @@ const rows = computed(() => {
|
||||
return callLogs.value?.data.data.map((callLog) => {
|
||||
let _rows = {}
|
||||
callLogs.value?.data.rows.forEach((row) => {
|
||||
_rows[row] = callLog[row]
|
||||
|
||||
let incoming = callLog.type === 'Incoming'
|
||||
|
||||
if (row === 'caller') {
|
||||
_rows[row] = {
|
||||
label: incoming
|
||||
? getContact(callLog.from)?.full_name ||
|
||||
getLeadContact(callLog.from)?.full_name ||
|
||||
'Unknown'
|
||||
: getUser(callLog.caller).full_name,
|
||||
image: incoming
|
||||
? getContact(callLog.from)?.image ||
|
||||
getLeadContact(callLog.from)?.image
|
||||
: getUser(callLog.caller).user_image,
|
||||
}
|
||||
} else if (row === 'receiver') {
|
||||
_rows[row] = {
|
||||
label: incoming
|
||||
? getUser(callLog.receiver).full_name
|
||||
: getContact(callLog.to)?.full_name ||
|
||||
getLeadContact(callLog.to)?.full_name ||
|
||||
'Unknown',
|
||||
image: incoming
|
||||
? getUser(callLog.receiver).user_image
|
||||
: getContact(callLog.to)?.image ||
|
||||
getLeadContact(callLog.to)?.image,
|
||||
}
|
||||
} else if (row === 'duration') {
|
||||
_rows[row] = {
|
||||
label: secondsToDuration(callLog.duration),
|
||||
icon: 'clock',
|
||||
}
|
||||
} else if (row === 'type') {
|
||||
_rows[row] = {
|
||||
label: callLog.type,
|
||||
icon: incoming ? 'phone-incoming' : 'phone-outgoing',
|
||||
}
|
||||
} else if (row === 'status') {
|
||||
_rows[row] = {
|
||||
label: statusLabelMap[callLog.status],
|
||||
color: statusColorMap[callLog.status],
|
||||
}
|
||||
} else if (['modified', 'creation'].includes(row)) {
|
||||
_rows[row] = {
|
||||
label: dateFormat(callLog[row], dateTooltipFormat),
|
||||
timeAgo: __(timeAgo(callLog[row])),
|
||||
}
|
||||
}
|
||||
_rows[row] = getCallLogDetail(row, callLog)
|
||||
})
|
||||
return _rows
|
||||
})
|
||||
})
|
||||
|
||||
const showCallLogModal = ref(false)
|
||||
|
||||
const callLog = ref({
|
||||
name: '',
|
||||
caller: '',
|
||||
receiver: '',
|
||||
duration: '',
|
||||
type: '',
|
||||
status: '',
|
||||
from: '',
|
||||
to: '',
|
||||
note: '',
|
||||
recording_url: '',
|
||||
reference_doctype: '',
|
||||
reference_docname: '',
|
||||
creation: '',
|
||||
})
|
||||
const selectedCallLog = ref(null)
|
||||
|
||||
function showCallLog(name) {
|
||||
let d = rows.value?.find((row) => row.name === name)
|
||||
callLog.value = {
|
||||
name: d.name,
|
||||
caller: d.caller,
|
||||
receiver: d.receiver,
|
||||
duration: d.duration,
|
||||
type: d.type,
|
||||
status: d.status,
|
||||
from: d.from,
|
||||
to: d.to,
|
||||
note: d.note,
|
||||
recording_url: d.recording_url,
|
||||
reference_doctype: d.reference_doctype,
|
||||
reference_docname: d.reference_docname,
|
||||
creation: d.creation,
|
||||
}
|
||||
selectedCallLog.value = name
|
||||
showCallLogModal.value = true
|
||||
}
|
||||
|
||||
const statusLabelMap = {
|
||||
Completed: 'Completed',
|
||||
Initiated: 'Initiated',
|
||||
Busy: 'Declined',
|
||||
Failed: 'Failed',
|
||||
Queued: 'Queued',
|
||||
Cancelled: 'Cancelled',
|
||||
Ringing: 'Ringing',
|
||||
'No Answer': 'Missed Call',
|
||||
'In Progress': 'In Progress',
|
||||
}
|
||||
|
||||
const statusColorMap = {
|
||||
Completed: 'green',
|
||||
Busy: 'orange',
|
||||
Failed: 'red',
|
||||
Initiated: 'gray',
|
||||
Queued: 'gray',
|
||||
Cancelled: 'gray',
|
||||
Ringing: 'gray',
|
||||
'No Answer': 'red',
|
||||
'In Progress': 'blue',
|
||||
}
|
||||
</script>
|
||||
|
||||
84
frontend/src/utils/callLog.js
Normal file
84
frontend/src/utils/callLog.js
Normal file
@ -0,0 +1,84 @@
|
||||
import {
|
||||
secondsToDuration,
|
||||
dateFormat,
|
||||
dateTooltipFormat,
|
||||
timeAgo,
|
||||
} from '@/utils'
|
||||
import { usersStore } from '@/stores/users'
|
||||
import { contactsStore } from '@/stores/contacts'
|
||||
|
||||
const { getUser } = usersStore()
|
||||
const { getContact, getLeadContact } = contactsStore()
|
||||
|
||||
export function getCallLogDetail(row, log) {
|
||||
let incoming = log.type === 'Incoming'
|
||||
|
||||
if (row === 'caller') {
|
||||
return {
|
||||
label: incoming
|
||||
? getContact(log.from)?.full_name ||
|
||||
getLeadContact(log.from)?.full_name ||
|
||||
'Unknown'
|
||||
: getUser(log.caller).full_name,
|
||||
image: incoming
|
||||
? getContact(log.from)?.image || getLeadContact(log.from)?.image
|
||||
: getUser(log.caller).user_image,
|
||||
}
|
||||
} else if (row === 'receiver') {
|
||||
return {
|
||||
label: incoming
|
||||
? getUser(log.receiver).full_name
|
||||
: getContact(log.to)?.full_name ||
|
||||
getLeadContact(log.to)?.full_name ||
|
||||
'Unknown',
|
||||
image: incoming
|
||||
? getUser(log.receiver).user_image
|
||||
: getContact(log.to)?.image || getLeadContact(log.to)?.image,
|
||||
}
|
||||
} else if (row === 'duration') {
|
||||
return {
|
||||
label: secondsToDuration(log.duration),
|
||||
icon: 'clock',
|
||||
}
|
||||
} else if (row === 'type') {
|
||||
return {
|
||||
label: log.type,
|
||||
icon: incoming ? 'phone-incoming' : 'phone-outgoing',
|
||||
}
|
||||
} else if (row === 'status') {
|
||||
return {
|
||||
label: statusLabelMap[log.status],
|
||||
color: statusColorMap[log.status],
|
||||
}
|
||||
} else if (['modified', 'creation'].includes(row)) {
|
||||
return {
|
||||
label: dateFormat(log[row], dateTooltipFormat),
|
||||
timeAgo: __(timeAgo(log[row])),
|
||||
}
|
||||
}
|
||||
return log[row]
|
||||
}
|
||||
|
||||
export const statusLabelMap = {
|
||||
Completed: 'Completed',
|
||||
Initiated: 'Initiated',
|
||||
Busy: 'Declined',
|
||||
Failed: 'Failed',
|
||||
Queued: 'Queued',
|
||||
Cancelled: 'Cancelled',
|
||||
Ringing: 'Ringing',
|
||||
'No Answer': 'Missed Call',
|
||||
'In Progress': 'In Progress',
|
||||
}
|
||||
|
||||
export const statusColorMap = {
|
||||
Completed: 'green',
|
||||
Busy: 'orange',
|
||||
Failed: 'red',
|
||||
Initiated: 'gray',
|
||||
Queued: 'gray',
|
||||
Cancelled: 'gray',
|
||||
Ringing: 'gray',
|
||||
'No Answer': 'red',
|
||||
'In Progress': 'blue',
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user