Merge pull request #170 from shariquerik/calllog-modal
fix: Show call log details in modal
This commit is contained in:
commit
65f6692a12
@ -69,64 +69,14 @@ class CRMCallLog(Document):
|
||||
"duration",
|
||||
"from",
|
||||
"to",
|
||||
"note",
|
||||
"recording_url",
|
||||
"reference_doctype",
|
||||
"reference_docname",
|
||||
"creation",
|
||||
]
|
||||
return {'columns': columns, 'rows': rows}
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_call_log(name):
|
||||
doc = frappe.get_doc("CRM Call Log", name)
|
||||
doc = doc.as_dict()
|
||||
if doc.reference_docname and doc.reference_doctype == "CRM Lead":
|
||||
doc.lead = doc.reference_docname
|
||||
doc.lead_name = frappe.db.get_value("CRM Lead", doc.reference_docname, "lead_name")
|
||||
if doc.note:
|
||||
note = frappe.db.get_values("FCRM Note", doc.note, ["title", "content"])[0]
|
||||
doc.note_doc = {
|
||||
"name": doc.note,
|
||||
"title": note[0],
|
||||
"content": note[1]
|
||||
}
|
||||
|
||||
def get_contact(number):
|
||||
c = frappe.db.get_value("Contact", {"mobile_no": number}, ["full_name", "image"], as_dict=True)
|
||||
if c:
|
||||
return [c.full_name, c.image]
|
||||
return [None, None]
|
||||
|
||||
def get_lead_contact(number):
|
||||
l = frappe.db.get_value("CRM Lead", {"mobile_no": number, "converted": 0}, ["lead_name", "image"], as_dict=True)
|
||||
if l:
|
||||
return [l.lead_name, l.image]
|
||||
return [None, None]
|
||||
|
||||
def get_user(user):
|
||||
u = frappe.db.get_value("User", user, ["full_name", "user_image"], as_dict=True)
|
||||
if u:
|
||||
return [u.full_name, u.user_image]
|
||||
return [None, None]
|
||||
|
||||
if doc.type == "Incoming":
|
||||
doc.caller = {
|
||||
"label": get_contact(doc.get("from"))[0] or get_lead_contact(doc.get("from"))[0] or "Unknown",
|
||||
"image": get_contact(doc.get("from"))[1] or get_lead_contact(doc.get("from"))[1]
|
||||
}
|
||||
doc.receiver = {
|
||||
"label": get_user(doc.get("receiver"))[0],
|
||||
"image": get_user(doc.get("receiver"))[1]
|
||||
}
|
||||
else:
|
||||
doc.caller = {
|
||||
"label": get_user(doc.get("caller"))[0],
|
||||
"image": get_user(doc.get("caller"))[1]
|
||||
}
|
||||
doc.receiver = {
|
||||
"label": get_contact(doc.get("to"))[0] or get_lead_contact(doc.get("to"))[0] or "Unknown",
|
||||
"image": get_contact(doc.get("to"))[1] or get_lead_contact(doc.get("to"))[1]
|
||||
}
|
||||
|
||||
return doc
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_lead_from_call_log(call_log):
|
||||
lead = frappe.new_doc("CRM Lead")
|
||||
|
||||
23
frontend/src/components/Icons/CheckCircleIcon.vue
Normal file
23
frontend/src/components/Icons/CheckCircleIcon.vue
Normal file
@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g clip-path="url(#clip0_3668_69185)">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M14.25 8C14.25 11.4518 11.4518 14.25 8 14.25C4.54822 14.25 1.75 11.4518 1.75 8C1.75 4.54822 4.54822 1.75 8 1.75C11.4518 1.75 14.25 4.54822 14.25 8ZM15.25 8C15.25 12.0041 12.0041 15.25 8 15.25C3.99594 15.25 0.75 12.0041 0.75 8C0.75 3.99594 3.99594 0.75 8 0.75C12.0041 0.75 15.25 3.99594 15.25 8ZM11.2909 5.98482C11.4666 5.77175 11.4363 5.45663 11.2232 5.28096C11.0101 5.1053 10.695 5.13561 10.5193 5.34868L7.07001 9.53239L5.72845 7.79857C5.55946 7.58018 5.24543 7.54012 5.02703 7.70911C4.80863 7.8781 4.76858 8.19214 4.93756 8.41053L6.66217 10.6394C6.7552 10.7596 6.89788 10.831 7.04988 10.8334C7.20188 10.8357 7.3467 10.7688 7.4434 10.6515L11.2909 5.98482Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_3668_69185">
|
||||
<rect width="16" height="16" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</template>
|
||||
@ -3,10 +3,7 @@
|
||||
:columns="columns"
|
||||
:rows="rows"
|
||||
:options="{
|
||||
getRowRoute: (row) => ({
|
||||
name: 'Call Log',
|
||||
params: { callLogId: row.name },
|
||||
}),
|
||||
onRowClick: (row) => emit('showCallLog', row.name),
|
||||
selectable: options.selectable,
|
||||
showTooltip: options.showTooltip,
|
||||
resizeColumn: options.resizeColumn,
|
||||
|
||||
233
frontend/src/components/Modals/CallLogModal.vue
Normal file
233
frontend/src/components/Modals/CallLogModal.vue
Normal file
@ -0,0 +1,233 @@
|
||||
<template>
|
||||
<Dialog v-model="show">
|
||||
<template #body-title>
|
||||
<div class="flex items-center gap-3">
|
||||
<h3 class="text-2xl font-semibold leading-6 text-gray-900">
|
||||
{{ __('Call Details') }}
|
||||
</h3>
|
||||
</div>
|
||||
</template>
|
||||
<template #body-content>
|
||||
<div class="flex flex-col gap-3.5">
|
||||
<div
|
||||
v-for="field in detailFields"
|
||||
:key="field.name"
|
||||
class="flex gap-2 text-base text-gray-800"
|
||||
>
|
||||
<div class="grid size-7 place-content-center">
|
||||
<component :is="field.icon" />
|
||||
</div>
|
||||
<div class="flex min-h-7 w-full items-center gap-2">
|
||||
<div
|
||||
v-if="field.name == 'receiver'"
|
||||
class="flex items-center gap-1"
|
||||
>
|
||||
<Avatar
|
||||
:image="field.value.caller.image"
|
||||
:label="field.value.caller.label"
|
||||
size="sm"
|
||||
/>
|
||||
<div class="ml-1 flex flex-col gap-1">
|
||||
{{ field.value.caller.label }}
|
||||
</div>
|
||||
<FeatherIcon
|
||||
name="arrow-right"
|
||||
class="mx-1 h-4 w-4 text-gray-600"
|
||||
/>
|
||||
<Avatar
|
||||
:image="field.value.receiver.image"
|
||||
:label="field.value.receiver.label"
|
||||
size="sm"
|
||||
/>
|
||||
<div class="ml-1 flex flex-col gap-1">
|
||||
{{ field.value.receiver.label }}
|
||||
</div>
|
||||
</div>
|
||||
<Tooltip v-else-if="field.tooltip" :text="field.tooltip">
|
||||
{{ field.value }}
|
||||
</Tooltip>
|
||||
<div class="w-full" v-else-if="field.name == 'recording_url'">
|
||||
<audio
|
||||
class="audio-control w-full"
|
||||
controls
|
||||
:src="field.value"
|
||||
></audio>
|
||||
</div>
|
||||
<div
|
||||
class="max-h-30 min-h-16 w-full cursor-pointer overflow-hidden rounded border px-2 py-1.5 text-base text-gray-700"
|
||||
v-else-if="field.name == 'note'"
|
||||
@click="() => (showNoteModal = true)"
|
||||
>
|
||||
<div
|
||||
v-if="field.value?.title"
|
||||
:class="[field.value?.content ? 'mb-1 font-bold' : '']"
|
||||
v-html="field.value?.title"
|
||||
/>
|
||||
<div v-if="field.value?.content" v-html="field.value?.content" />
|
||||
</div>
|
||||
<div v-else :class="field.color ? `text-${field.color}-600` : ''">
|
||||
{{ field.value }}
|
||||
</div>
|
||||
<div v-if="field.link">
|
||||
<ArrowUpRightIcon
|
||||
class="h-4 w-4 shrink-0 cursor-pointer text-gray-600 hover:text-gray-800"
|
||||
@click="() => field.link()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template
|
||||
v-if="callLog.type.label == 'Incoming' && !callLog.reference_docname"
|
||||
#actions
|
||||
>
|
||||
<Button
|
||||
class="w-full"
|
||||
variant="solid"
|
||||
:label="__('Create lead')"
|
||||
@click="createLead"
|
||||
/>
|
||||
</template>
|
||||
</Dialog>
|
||||
<NoteModal v-model="showNoteModal" :note="callNoteDoc?.doc" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import ArrowUpRightIcon from '@/components/Icons/ArrowUpRightIcon.vue'
|
||||
import DurationIcon from '@/components/Icons/DurationIcon.vue'
|
||||
import ContactsIcon from '@/components/Icons/ContactsIcon.vue'
|
||||
import LeadsIcon from '@/components/Icons/LeadsIcon.vue'
|
||||
import Dealsicon from '@/components/Icons/DealsIcon.vue'
|
||||
import CalendarIcon from '@/components/Icons/CalendarIcon.vue'
|
||||
import NoteIcon from '@/components/Icons/NoteIcon.vue'
|
||||
import CheckCircleIcon from '@/components/Icons/CheckCircleIcon.vue'
|
||||
import NoteModal from '@/components/Modals/NoteModal.vue'
|
||||
import { FeatherIcon, Avatar, Tooltip, createDocumentResource, call } from 'frappe-ui'
|
||||
import { ref, computed, h, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const props = defineProps({
|
||||
callLog: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
})
|
||||
|
||||
const show = defineModel()
|
||||
const showNoteModal = ref(false)
|
||||
const router = useRouter()
|
||||
const callNoteDoc = ref(null)
|
||||
|
||||
const detailFields = computed(() => {
|
||||
let details = [
|
||||
{
|
||||
icon: h(FeatherIcon, {
|
||||
name: props.callLog.type.icon,
|
||||
class: 'h-3.5 w-3.5',
|
||||
}),
|
||||
name: 'type',
|
||||
value: props.callLog.type.label + ' Call',
|
||||
},
|
||||
{
|
||||
icon: ContactsIcon,
|
||||
name: 'receiver',
|
||||
value: {
|
||||
receiver: props.callLog.receiver,
|
||||
caller: props.callLog.caller,
|
||||
},
|
||||
},
|
||||
{
|
||||
icon:
|
||||
props.callLog.reference_doctype == 'CRM Lead' ? LeadsIcon : Dealsicon,
|
||||
name: 'reference_doctype',
|
||||
value: props.callLog.reference_doctype == 'CRM Lead' ? 'Lead' : 'Deal',
|
||||
link: () => {
|
||||
if (props.callLog.reference_doctype == 'CRM Lead') {
|
||||
router.push({
|
||||
name: 'Lead',
|
||||
params: { leadId: props.callLog.reference_docname },
|
||||
})
|
||||
} else {
|
||||
router.push({
|
||||
name: 'Deal',
|
||||
params: { dealId: props.callLog.reference_docname },
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: CalendarIcon,
|
||||
name: 'creation',
|
||||
value: props.callLog.creation.label,
|
||||
tooltip: props.callLog.creation.label,
|
||||
},
|
||||
{
|
||||
icon: DurationIcon,
|
||||
name: 'duration',
|
||||
value: props.callLog.duration.label,
|
||||
},
|
||||
{
|
||||
icon: CheckCircleIcon,
|
||||
name: 'status',
|
||||
value: props.callLog.status.label,
|
||||
color: props.callLog.status.color,
|
||||
},
|
||||
{
|
||||
icon: h(FeatherIcon, {
|
||||
name: 'play-circle',
|
||||
class: 'h-4 w-4 mt-2',
|
||||
}),
|
||||
name: 'recording_url',
|
||||
value: props.callLog.recording_url,
|
||||
},
|
||||
{
|
||||
icon: NoteIcon,
|
||||
name: 'note',
|
||||
value: callNoteDoc.value?.doc,
|
||||
},
|
||||
]
|
||||
|
||||
return details.filter((detail) => detail.value)
|
||||
})
|
||||
|
||||
function createLead() {
|
||||
call('crm.fcrm.doctype.crm_call_log.crm_call_log.create_lead_from_call_log', {
|
||||
call_log: props.callLog,
|
||||
}).then((d) => {
|
||||
if (d) {
|
||||
router.push({ name: 'Lead', params: { leadId: d } })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
watch(show, (val) => {
|
||||
if (val) {
|
||||
callNoteDoc.value = createDocumentResource({
|
||||
doctype: 'FCRM Note',
|
||||
name: props.callLog.note,
|
||||
fields: ['title', 'content'],
|
||||
cache: ['note', props.callLog.note],
|
||||
auto: true,
|
||||
})
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.audio-control {
|
||||
height: 36px;
|
||||
outline: none;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
background-color: rgb(237, 237, 237);
|
||||
}
|
||||
|
||||
audio::-webkit-media-controls-panel {
|
||||
background-color: rgb(237, 237, 237) !important;
|
||||
}
|
||||
|
||||
.audio-control::-webkit-media-controls-panel {
|
||||
background-color: white;
|
||||
}
|
||||
</style>
|
||||
@ -149,7 +149,7 @@ watch(
|
||||
nextTick(() => {
|
||||
title.value.el.focus()
|
||||
_note.value = { ...props.note }
|
||||
if (_note.value.title) {
|
||||
if (_note.value.title || _note.value.content) {
|
||||
editMode.value = true
|
||||
}
|
||||
})
|
||||
|
||||
@ -1,258 +0,0 @@
|
||||
<template>
|
||||
<LayoutHeader v-if="callLog.data">
|
||||
<template #left-header>
|
||||
<Breadcrumbs :items="breadcrumbs" />
|
||||
</template>
|
||||
<template #right-header>
|
||||
<Button
|
||||
v-if="callLog.data.type == 'Incoming' && !callLog.data.lead"
|
||||
variant="solid"
|
||||
:label="__('Create lead')"
|
||||
@click="createLead"
|
||||
>
|
||||
<template #prefix><FeatherIcon name="plus" class="h-4" /></template>
|
||||
</Button>
|
||||
</template>
|
||||
</LayoutHeader>
|
||||
<div v-if="callLog.data" class="max-w-lg p-6">
|
||||
<div class="pb-3 text-base font-medium">{{ __('Call details') }}</div>
|
||||
<div class="mb-3 flex flex-col gap-4 rounded-lg border p-4 shadow-sm">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<FeatherIcon
|
||||
:name="
|
||||
callLog.data.type == 'Incoming'
|
||||
? 'phone-incoming'
|
||||
: 'phone-outgoing'
|
||||
"
|
||||
class="h-4 w-4 text-gray-600"
|
||||
/>
|
||||
<div class="font-medium">
|
||||
{{
|
||||
callLog.data.type == 'Incoming'
|
||||
? __('Inbound Call')
|
||||
: __('Outbound Call')
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Badge
|
||||
:variant="'subtle'"
|
||||
:theme="statusColorMap[callLog.data.status]"
|
||||
size="md"
|
||||
:label="__(statusLabelMap[callLog.data.status])"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-1">
|
||||
<Avatar
|
||||
:image="callLog.data.caller.image"
|
||||
:label="callLog.data.caller.label"
|
||||
size="xl"
|
||||
/>
|
||||
<div class="ml-1 flex flex-col gap-1">
|
||||
<div class="text-base font-medium">
|
||||
{{ __(callLog.data.caller.label) }}
|
||||
</div>
|
||||
<div class="text-xs text-gray-600">
|
||||
{{ callLog.data.from }}
|
||||
</div>
|
||||
</div>
|
||||
<FeatherIcon name="arrow-right" class="mx-2 h-5 w-5 text-gray-600" />
|
||||
<Avatar
|
||||
:image="callLog.data.receiver.image"
|
||||
:label="callLog.data.receiver.label"
|
||||
size="xl"
|
||||
/>
|
||||
<div class="ml-1 flex flex-col gap-1">
|
||||
<div class="text-base font-medium">
|
||||
{{ __(callLog.data.receiver.label) }}
|
||||
</div>
|
||||
<div class="text-xs text-gray-600">
|
||||
{{ callLog.data.to }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-1">
|
||||
<DurationIcon class="h-4 w-4 text-gray-600" />
|
||||
<div class="text-sm text-gray-600">{{ __('Duration') }}</div>
|
||||
<div class="text-sm">{{ callLog.data.duration }}</div>
|
||||
</div>
|
||||
<Tooltip :text="dateFormat(callLog.data.creation, dateTooltipFormat)">
|
||||
<div class="text-sm text-gray-600">
|
||||
{{ __(timeAgo(callLog.data.creation)) }}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="callLog.data.recording_url" class="mt-6">
|
||||
<div class="mb-3 text-base font-medium">{{ __('Call recording') }}</div>
|
||||
<div class="flex items-center justify-between rounded border shadow-sm">
|
||||
<audio
|
||||
class="audio-control"
|
||||
controls
|
||||
:src="callLog.data.recording_url"
|
||||
></audio>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="callLog.data.note" class="mt-6">
|
||||
<div class="mb-3 text-base font-medium">{{ __('Call note') }}</div>
|
||||
<div
|
||||
class="flex h-56 cursor-pointer flex-col gap-3 rounded border p-4 shadow-sm"
|
||||
@click="showNoteModal = true"
|
||||
>
|
||||
<div class="truncate text-lg font-medium">
|
||||
{{ callLog.data.note_doc.title }}
|
||||
</div>
|
||||
<TextEditor
|
||||
v-if="callLog.data.note_doc.content"
|
||||
:content="callLog.data.note_doc.content"
|
||||
:editable="false"
|
||||
editor-class="!prose-sm max-w-none !text-sm text-gray-600 focus:outline-none"
|
||||
class="flex-1 overflow-hidden"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="callLog.data.lead" class="mt-6">
|
||||
<div class="mb-3 text-base font-medium">{{ __('Lead') }}</div>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
:route="{ name: 'Lead', params: { leadId: callLog.data.lead } }"
|
||||
:label="callLog.data.lead_name"
|
||||
class="p-4"
|
||||
>
|
||||
<template #prefix><Avatar :label="callLog.data.lead_name" /></template>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<NoteModal
|
||||
v-model="showNoteModal"
|
||||
:note="callLog.data?.note_doc"
|
||||
@after="updateNote"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import LayoutHeader from '@/components/LayoutHeader.vue'
|
||||
import DurationIcon from '@/components/Icons/DurationIcon.vue'
|
||||
import NoteModal from '@/components/Modals/NoteModal.vue'
|
||||
import {
|
||||
dateFormat,
|
||||
timeAgo,
|
||||
dateTooltipFormat,
|
||||
secondsToDuration,
|
||||
} from '@/utils'
|
||||
import {
|
||||
TextEditor,
|
||||
Avatar,
|
||||
call,
|
||||
Tooltip,
|
||||
createResource,
|
||||
Breadcrumbs,
|
||||
} from 'frappe-ui'
|
||||
import { computed, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const props = defineProps({
|
||||
callLogId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const showNoteModal = ref(false)
|
||||
|
||||
const callLog = createResource({
|
||||
url: 'crm.fcrm.doctype.crm_call_log.crm_call_log.get_call_log',
|
||||
auto: true,
|
||||
cache: ['callLog', props.callLogId],
|
||||
params: {
|
||||
name: props.callLogId,
|
||||
},
|
||||
transform: (doc) => {
|
||||
doc.duration = secondsToDuration(doc.duration)
|
||||
return doc
|
||||
},
|
||||
})
|
||||
|
||||
async function updateNote(_note) {
|
||||
if (_note.title || _note.content) {
|
||||
let d = await call('frappe.client.set_value', {
|
||||
doctype: 'FCRM Note',
|
||||
name: callLog.data?.note,
|
||||
fieldname: _note,
|
||||
})
|
||||
if (d.name) {
|
||||
callLog.reload()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createLead() {
|
||||
call('crm.fcrm.doctype.crm_call_log.crm_call_log.create_lead_from_call_log', {
|
||||
call_log: callLog.data,
|
||||
}).then((d) => {
|
||||
if (d) {
|
||||
callLog.reload()
|
||||
router.push({ name: 'Lead', params: { leadId: d } })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const breadcrumbs = computed(() => {
|
||||
let items = [{ label: __('Call Logs'), route: { name: 'Call Logs' } }]
|
||||
items.push({
|
||||
label: callLog.data?.caller.label,
|
||||
route: { name: 'Call Log', params: { callLogId: props.callLogId } },
|
||||
})
|
||||
return items
|
||||
})
|
||||
|
||||
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>
|
||||
|
||||
<style scoped>
|
||||
.audio-control {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
outline: none;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.audio-control::-webkit-media-controls-panel {
|
||||
background-color: white;
|
||||
}
|
||||
</style>
|
||||
@ -31,6 +31,7 @@
|
||||
rowCount: callLogs.data.row_count,
|
||||
totalCount: callLogs.data.total_count,
|
||||
}"
|
||||
@showCallLog="showCallLog"
|
||||
@loadMore="() => loadMore++"
|
||||
@columnWidthUpdated="() => triggerResize++"
|
||||
@updatePageCount="(count) => (updatedPageCount = count)"
|
||||
@ -47,6 +48,11 @@
|
||||
<span>{{ __('No Logs Found') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<CallLogModal
|
||||
v-model="showCallLogModal"
|
||||
v-model:reloadCallLogs="callLogs"
|
||||
:callLog="callLog"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@ -55,6 +61,7 @@ import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
||||
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,
|
||||
@ -139,6 +146,44 @@ const rows = computed(() => {
|
||||
})
|
||||
})
|
||||
|
||||
const showCallLogModal = ref(false)
|
||||
|
||||
const callLog = ref({
|
||||
name: '',
|
||||
caller: '',
|
||||
receiver: '',
|
||||
duration: '',
|
||||
type: '',
|
||||
status: '',
|
||||
from: '',
|
||||
to: '',
|
||||
note: '',
|
||||
recording_url: '',
|
||||
reference_doctype: '',
|
||||
reference_docname: '',
|
||||
creation: '',
|
||||
})
|
||||
|
||||
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,
|
||||
}
|
||||
showCallLogModal.value = true
|
||||
}
|
||||
|
||||
const statusLabelMap = {
|
||||
Completed: 'Completed',
|
||||
Initiated: 'Initiated',
|
||||
|
||||
@ -72,12 +72,6 @@ const routes = [
|
||||
component: () => import('@/pages/CallLogs.vue'),
|
||||
meta: { scrollPos: { top: 0, left: 0 } },
|
||||
},
|
||||
{
|
||||
path: '/call-logs/:callLogId',
|
||||
name: 'Call Log',
|
||||
component: () => import('@/pages/CallLog.vue'),
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: '/email-templates',
|
||||
name: 'Email Templates',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user