fix: created call log in lead/deal calls tab
This commit is contained in:
parent
6277778b91
commit
f4a2fb15f8
@ -63,6 +63,77 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="title == 'Calls'">
|
||||
<div v-for="(call, i) in activities">
|
||||
<div class="grid grid-cols-[30px_minmax(auto,_1fr)] gap-4 px-5">
|
||||
<div
|
||||
class="relative flex justify-center after:absolute after:border-l after:border-gray-300 after:top-0 after:left-[50%] after:-z-10"
|
||||
:class="i != activities.length - 1 ? 'after:h-full' : 'after:h-4'"
|
||||
>
|
||||
<div
|
||||
class="flex items-center justify-center rounded-full outline outline-4 outline-white w-6 h-6 bg-gray-200 mt-[15px] z-10"
|
||||
>
|
||||
<FeatherIcon
|
||||
:name="
|
||||
call.type == 'Incoming' ? 'phone-incoming' : 'phone-outgoing'
|
||||
"
|
||||
class="w-3.5 h-3.5 text-gray-600"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-3 border rounded-lg p-4 mb-3 shadow-sm max-w-[60%]">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
{{ call.type == 'Incoming' ? 'Inbound' : 'Outbound' }} call
|
||||
</div>
|
||||
<div>
|
||||
<Tooltip
|
||||
class="text-gray-600 text-sm"
|
||||
:text="dateFormat(call.modified, dateTooltipFormat)"
|
||||
>
|
||||
{{ timeAgo(call.modified) }}
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-1">
|
||||
<DurationIcon class="w-4 h-4 text-gray-600" />
|
||||
<div class="text-sm text-gray-600">Duration</div>
|
||||
<div class="text-sm">{{ call.duration }}s</div>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center gap-1 cursor-pointer select-none"
|
||||
@click="call.show_recording = !call.show_recording"
|
||||
>
|
||||
<PlayIcon class="w-4 h-4 text-gray-600" />
|
||||
<div class="text-sm text-gray-600">
|
||||
{{
|
||||
call.show_recording ? 'Hide recording' : 'Listen to call'
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="call.show_recording"
|
||||
class="flex items-center justify-between border rounded"
|
||||
>
|
||||
<audio
|
||||
class="audio-control"
|
||||
controls
|
||||
:src="call.recording_url"
|
||||
></audio>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-1">
|
||||
<div class="text-sm">{{ call.from }}</div>
|
||||
<FeatherIcon name="arrow-right" class="w-4 h-4 text-gray-600" />
|
||||
<div class="text-sm">{{ call.to }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else v-for="(activity, i) in activities">
|
||||
<div class="grid grid-cols-[30px_minmax(auto,_1fr)] gap-4 px-5">
|
||||
<div
|
||||
@ -180,6 +251,8 @@ import UserAvatar from '@/components/UserAvatar.vue'
|
||||
import EmailIcon from '@/components/Icons/EmailIcon.vue'
|
||||
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
||||
import NoteIcon from '@/components/Icons/NoteIcon.vue'
|
||||
import DurationIcon from '@/components/Icons/DurationIcon.vue'
|
||||
import PlayIcon from '@/components/Icons/PlayIcon.vue'
|
||||
import { timeAgo, dateFormat, dateTooltipFormat } from '@/utils'
|
||||
import { usersStore } from '@/stores/users'
|
||||
import { Button, FeatherIcon, Tooltip, Dropdown, TextEditor } from 'frappe-ui'
|
||||
@ -201,6 +274,12 @@ const props = defineProps({
|
||||
const emit = defineEmits(['makeCall', 'makeNote', 'deleteNote'])
|
||||
|
||||
const activities = computed(() => {
|
||||
if (props.title == 'Calls') {
|
||||
props.activities.forEach((activity) => {
|
||||
activity.show_recording = false
|
||||
})
|
||||
return props.activities
|
||||
}
|
||||
props.activities.forEach((activity) => {
|
||||
activity.owner_name = getUser(activity.owner).full_name
|
||||
activity.icon = timelineIcon(activity.activity_type)
|
||||
@ -260,3 +339,18 @@ function timelineIcon(activity_type) {
|
||||
return 'edit'
|
||||
}
|
||||
</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>
|
||||
|
||||
24
frontend/src/components/Icons/DurationIcon.vue
Normal file
24
frontend/src/components/Icons/DurationIcon.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14 8C14 11.3137 11.3137 14 8 14C4.68629 14 2 11.3137 2 8C2 4.68629 4.68629 2 8 2C11.3137 2 14 4.68629 14 8Z"
|
||||
stroke="currentColor"
|
||||
stroke-miterlimit="10"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M8.00024 4.97693V8.00018L10.1666 10.1667"
|
||||
stroke="currentColor"
|
||||
stroke-miterlimit="10"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
19
frontend/src/components/Icons/MaximizeIcon.vue
Normal file
19
frontend/src/components/Icons/MaximizeIcon.vue
Normal file
@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="feather feather-maximize-2"
|
||||
>
|
||||
<polyline points="15 3 21 3 21 9" />
|
||||
<polyline points="9 21 3 21 3 15" />
|
||||
<line x1="21" y1="3" x2="14" y2="10" />
|
||||
<line x1="3" y1="21" x2="10" y2="14" />
|
||||
</svg>
|
||||
</template>
|
||||
@ -1,24 +1,19 @@
|
||||
<template>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="feather feather-minimize-2"
|
||||
>
|
||||
<path
|
||||
d="M2.66667 9.33331H6.66667V13.3333"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.33333"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M13.3333 6.66669H9.33333V2.66669"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.33333"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<polyline points="4 14 10 14 10 20" />
|
||||
<polyline points="20 10 14 10 14 4" />
|
||||
<line x1="14" y1="10" x2="21" y2="3" />
|
||||
<line x1="3" y1="21" x2="10" y2="14" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
18
frontend/src/components/Icons/PlayIcon.vue
Normal file
18
frontend/src/components/Icons/PlayIcon.vue
Normal file
@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M10 1C5.02944 1 1 5.02944 1 10C1 14.9706 5.02944 19 10 19C14.9706 19 19 14.9706 19 10C19 7.61305 18.0518 5.32387 16.364 3.63604C14.6761 1.94821 12.3869 1 10 1Z"
|
||||
fill="#DEEEFC"
|
||||
/>
|
||||
<path
|
||||
d="M13.2581 10.5593L9.02502 13.3556C8.7895 13.5169 8.48212 13.5452 8.21897 13.4297C7.95581 13.3143 7.77698 13.0728 7.75 12.7964V7.20365C7.77698 6.92722 7.95581 6.68568 8.21897 6.57025C8.48212 6.45482 8.7895 6.48309 9.02502 6.64438L13.2581 9.44073C13.4602 9.56041 13.5833 9.77207 13.5833 10C13.5833 10.2279 13.4602 10.4396 13.2581 10.5593Z"
|
||||
fill="#2D95F0"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@ -23,7 +23,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-3 pb-1 text-base font-medium mt-3">Call note</div>
|
||||
<div v-if="callNote.doc" class="flex flex-col p-3">
|
||||
<div v-if="callNote?.doc" class="flex flex-col p-3">
|
||||
<TextInput
|
||||
type="text"
|
||||
class="text-base bg-white border-none !pl-0 hover:bg-white focus:!shadow-none focus-visible:!ring-0"
|
||||
@ -67,6 +67,7 @@ const props = defineProps({
|
||||
const callLog = createDocumentResource({
|
||||
doctype: 'CRM Call Log',
|
||||
name: props.callLogId,
|
||||
setValue: {},
|
||||
})
|
||||
|
||||
const breadcrumbs = computed(() => [
|
||||
@ -120,6 +121,7 @@ const callNote = computed(() => {
|
||||
doctype: 'CRM Note',
|
||||
name: callLog.doc?.note,
|
||||
auto: true,
|
||||
setValue: {},
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -84,7 +84,7 @@
|
||||
v-model="deal"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col justify-between border-l w-[360px]">
|
||||
<div class="flex flex-col justify-between border-l w-[370px]">
|
||||
<div
|
||||
class="flex flex-col gap-3 pb-4 p-5 items-center justify-center border-b"
|
||||
>
|
||||
@ -388,9 +388,7 @@ const tabs = computed(() => {
|
||||
{
|
||||
label: 'Calls',
|
||||
icon: PhoneIcon,
|
||||
content: deal.data.activities.filter(
|
||||
(activity) => activity.activity_type === 'call'
|
||||
),
|
||||
content: calls.data,
|
||||
activityTitle: 'Calls',
|
||||
},
|
||||
// {
|
||||
@ -516,7 +514,7 @@ const notes = createListResource({
|
||||
fields: ['name', 'title', 'content', 'owner', 'modified'],
|
||||
filters: { lead: props.dealId },
|
||||
orderBy: 'modified desc',
|
||||
pageLength: 20,
|
||||
pageLength: 999,
|
||||
auto: true,
|
||||
})
|
||||
|
||||
@ -560,6 +558,29 @@ async function updateNote(note) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const calls = createListResource({
|
||||
type: 'list',
|
||||
doctype: 'CRM Call Log',
|
||||
cache: ['Call Logs', props.leadId],
|
||||
fields: [
|
||||
'name',
|
||||
'from',
|
||||
'to',
|
||||
'duration',
|
||||
'start_time',
|
||||
'end_time',
|
||||
'status',
|
||||
'type',
|
||||
'recording_url',
|
||||
'modified',
|
||||
'note',
|
||||
],
|
||||
filters: { lead: props.leadId },
|
||||
orderBy: 'modified desc',
|
||||
pageLength: 999,
|
||||
auto: true,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@ -87,7 +87,7 @@
|
||||
v-model="lead"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col justify-between border-l w-[360px]">
|
||||
<div class="flex flex-col justify-between border-l w-[370px]">
|
||||
<div
|
||||
class="flex flex-col gap-3 pb-4 p-5 items-center justify-center border-b"
|
||||
>
|
||||
@ -380,9 +380,7 @@ const tabs = computed(() => {
|
||||
{
|
||||
label: 'Calls',
|
||||
icon: PhoneIcon,
|
||||
content: lead.data.activities.filter(
|
||||
(activity) => activity.activity_type === 'call'
|
||||
),
|
||||
content: calls.data,
|
||||
activityTitle: 'Calls',
|
||||
},
|
||||
// {
|
||||
@ -549,7 +547,7 @@ const notes = createListResource({
|
||||
fields: ['name', 'title', 'content', 'owner', 'modified'],
|
||||
filters: { lead: props.leadId },
|
||||
orderBy: 'modified desc',
|
||||
pageLength: 20,
|
||||
pageLength: 999,
|
||||
auto: true,
|
||||
})
|
||||
|
||||
@ -593,6 +591,29 @@ async function updateNote(note) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const calls = createListResource({
|
||||
type: 'list',
|
||||
doctype: 'CRM Call Log',
|
||||
cache: ['Call Logs', props.leadId],
|
||||
fields: [
|
||||
'name',
|
||||
'from',
|
||||
'to',
|
||||
'duration',
|
||||
'start_time',
|
||||
'end_time',
|
||||
'status',
|
||||
'type',
|
||||
'recording_url',
|
||||
'modified',
|
||||
'note',
|
||||
],
|
||||
filters: { lead: props.leadId },
|
||||
orderBy: 'modified desc',
|
||||
pageLength: 999,
|
||||
auto: true,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user