fix: show dropdown with reply as option and show reply to message on click
This commit is contained in:
parent
05a3493598
commit
7ed4d50309
@ -113,6 +113,7 @@
|
|||||||
<WhatsAppArea
|
<WhatsAppArea
|
||||||
class="px-10"
|
class="px-10"
|
||||||
v-model="whatsappMessages"
|
v-model="whatsappMessages"
|
||||||
|
v-model:reply="replyMessage"
|
||||||
:messages="whatsappMessages.data"
|
:messages="whatsappMessages.data"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -782,6 +783,7 @@
|
|||||||
ref="whatsappBox"
|
ref="whatsappBox"
|
||||||
v-if="title == 'WhatsApp'"
|
v-if="title == 'WhatsApp'"
|
||||||
v-model="doc"
|
v-model="doc"
|
||||||
|
v-model:reply="replyMessage"
|
||||||
v-model:whatsapp="whatsappMessages"
|
v-model:whatsapp="whatsappMessages"
|
||||||
:doctype="doctype"
|
:doctype="doctype"
|
||||||
@scroll="scroll"
|
@scroll="scroll"
|
||||||
|
|||||||
@ -3,86 +3,106 @@
|
|||||||
<div
|
<div
|
||||||
v-for="whatsapp in messages"
|
v-for="whatsapp in messages"
|
||||||
:key="whatsapp.name"
|
:key="whatsapp.name"
|
||||||
class="activity group mb-3 flex gap-2"
|
class="activity group flex gap-2"
|
||||||
:class="[whatsapp.type == 'Outgoing' ? 'flex-row-reverse' : '']"
|
:class="[
|
||||||
|
whatsapp.type == 'Outgoing' ? 'flex-row-reverse' : '',
|
||||||
|
whatsapp.reaction ? 'mb-7' : 'mb-3',
|
||||||
|
]"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
:id="whatsapp.name"
|
:id="whatsapp.name"
|
||||||
:class="[whatsapp.reaction ? 'mb-4' : '']"
|
class="group/message relative max-w-[90%] rounded-md bg-gray-50 p-1.5 pl-2 text-base shadow-sm"
|
||||||
class="relative inline-flex max-w-[90%] gap-2 rounded-md bg-gray-50 p-1.5 pl-2 text-base shadow-sm"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="absolute -bottom-5 flex gap-1 rounded-full border bg-white p-1 pb-[3px] shadow-sm"
|
v-if="whatsapp.reply_to_message_id"
|
||||||
v-if="whatsapp.reaction"
|
class="mb-1 cursor-pointer rounded-md border-0 border-l-4 border-green-500 bg-gray-200 px-2 py-4"
|
||||||
>
|
v-html="formatWhatsAppMessage(whatsapp.reply_to_message_id)"
|
||||||
<div class="flex size-4 items-center justify-center">
|
|
||||||
{{ whatsapp.reaction }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="whatsapp.content_type == 'text'"
|
|
||||||
v-html="formatWhatsAppMessage(whatsapp.message)"
|
|
||||||
/>
|
/>
|
||||||
<div v-else-if="whatsapp.content_type == 'image'">
|
<div class="inline-flex gap-2">
|
||||||
<img
|
|
||||||
:src="whatsapp.attach"
|
|
||||||
class="h-40 cursor-pointer rounded-md"
|
|
||||||
@click="() => openFileInAnotherTab(whatsapp.attach)"
|
|
||||||
/>
|
|
||||||
<div
|
<div
|
||||||
v-if="!whatsapp.message.startsWith('/files/')"
|
class="absolute -right-0.5 -top-0.5 flex cursor-pointer gap-1 rounded-full bg-white pb-2 pl-2 pr-1.5 pt-1.5 opacity-0 group-hover/message:opacity-100"
|
||||||
class="mt-1.5"
|
:style="{
|
||||||
v-html="formatWhatsAppMessage(whatsapp.message)"
|
background:
|
||||||
/>
|
'radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 1) 35%, rgba(238, 130, 238, 0) 100%)',
|
||||||
</div>
|
}"
|
||||||
<div
|
>
|
||||||
v-else-if="whatsapp.content_type == 'document'"
|
<Dropdown v-bind="{ open }" :options="messageOptions(whatsapp)">
|
||||||
class="flex items-center gap-2"
|
<FeatherIcon name="chevron-down" class="size-4 text-gray-600" />
|
||||||
>
|
</Dropdown>
|
||||||
<DocumentIcon
|
</div>
|
||||||
class="size-10 cursor-pointer rounded-md text-gray-500"
|
|
||||||
@click="() => openFileInAnotherTab(whatsapp.attach)"
|
|
||||||
/>
|
|
||||||
<div class="text-gray-600">Document</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-else-if="whatsapp.content_type == 'audio'"
|
|
||||||
class="flex items-center gap-2"
|
|
||||||
>
|
|
||||||
<audio :src="whatsapp.attach" controls class="cursor-pointer" />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-else-if="whatsapp.content_type == 'video'"
|
|
||||||
class="flex-col items-center gap-2"
|
|
||||||
>
|
|
||||||
<video
|
|
||||||
:src="whatsapp.attach"
|
|
||||||
controls
|
|
||||||
class="h-40 cursor-pointer rounded-md"
|
|
||||||
/>
|
|
||||||
<div
|
<div
|
||||||
v-if="!whatsapp.message.startsWith('/files/')"
|
class="absolute -bottom-5 flex gap-1 rounded-full border bg-white p-1 pb-[3px] shadow-sm"
|
||||||
class="mt-1.5"
|
v-if="whatsapp.reaction"
|
||||||
v-html="formatWhatsAppMessage(whatsapp.message)"
|
>
|
||||||
/>
|
<div class="flex size-4 items-center justify-center">
|
||||||
</div>
|
{{ whatsapp.reaction }}
|
||||||
<div class="-mb-1 flex shrink-0 items-end gap-1 text-gray-600">
|
|
||||||
<Tooltip :text="dateFormat(whatsapp.creation, 'ddd, MMM D, YYYY')">
|
|
||||||
<div class="text-2xs">
|
|
||||||
{{ dateFormat(whatsapp.creation, 'hh:mm a') }}
|
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</div>
|
||||||
<div v-if="whatsapp.type == 'Outgoing'">
|
<div
|
||||||
<CheckIcon
|
v-if="whatsapp.content_type == 'text'"
|
||||||
v-if="['sent', 'Success'].includes(whatsapp.status)"
|
v-html="formatWhatsAppMessage(whatsapp.message)"
|
||||||
class="size-4"
|
/>
|
||||||
|
<div v-else-if="whatsapp.content_type == 'image'">
|
||||||
|
<img
|
||||||
|
:src="whatsapp.attach"
|
||||||
|
class="h-40 cursor-pointer rounded-md"
|
||||||
|
@click="() => openFileInAnotherTab(whatsapp.attach)"
|
||||||
/>
|
/>
|
||||||
<DoubleCheckIcon
|
<div
|
||||||
v-else-if="['read', 'delivered'].includes(whatsapp.status)"
|
v-if="!whatsapp.message.startsWith('/files/')"
|
||||||
class="size-4"
|
class="mt-1.5"
|
||||||
:class="{ 'text-blue-500': whatsapp.status == 'read' }"
|
v-html="formatWhatsAppMessage(whatsapp.message)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="whatsapp.content_type == 'document'"
|
||||||
|
class="flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<DocumentIcon
|
||||||
|
class="size-10 cursor-pointer rounded-md text-gray-500"
|
||||||
|
@click="() => openFileInAnotherTab(whatsapp.attach)"
|
||||||
|
/>
|
||||||
|
<div class="text-gray-600">Document</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="whatsapp.content_type == 'audio'"
|
||||||
|
class="flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<audio :src="whatsapp.attach" controls class="cursor-pointer" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="whatsapp.content_type == 'video'"
|
||||||
|
class="flex-col items-center gap-2"
|
||||||
|
>
|
||||||
|
<video
|
||||||
|
:src="whatsapp.attach"
|
||||||
|
controls
|
||||||
|
class="h-40 cursor-pointer rounded-md"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-if="!whatsapp.message.startsWith('/files/')"
|
||||||
|
class="mt-1.5"
|
||||||
|
v-html="formatWhatsAppMessage(whatsapp.message)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="-mb-1 flex shrink-0 items-end gap-1 text-gray-600">
|
||||||
|
<Tooltip :text="dateFormat(whatsapp.creation, 'ddd, MMM D, YYYY')">
|
||||||
|
<div class="text-2xs">
|
||||||
|
{{ dateFormat(whatsapp.creation, 'hh:mm a') }}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
<div v-if="whatsapp.type == 'Outgoing'">
|
||||||
|
<CheckIcon
|
||||||
|
v-if="['sent', 'Success'].includes(whatsapp.status)"
|
||||||
|
class="size-4"
|
||||||
|
/>
|
||||||
|
<DoubleCheckIcon
|
||||||
|
v-else-if="['read', 'delivered'].includes(whatsapp.status)"
|
||||||
|
class="size-4"
|
||||||
|
:class="{ 'text-blue-500': whatsapp.status == 'read' }"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@ -113,8 +133,9 @@ import DoubleCheckIcon from '@/components/Icons/DoubleCheckIcon.vue'
|
|||||||
import DocumentIcon from '@/components/Icons/DocumentIcon.vue'
|
import DocumentIcon from '@/components/Icons/DocumentIcon.vue'
|
||||||
import ReactIcon from '@/components/Icons/ReactIcon.vue'
|
import ReactIcon from '@/components/Icons/ReactIcon.vue'
|
||||||
import { dateFormat } from '@/utils'
|
import { dateFormat } from '@/utils'
|
||||||
import { Tooltip, createResource } from 'frappe-ui'
|
import { Tooltip, Dropdown, createResource } from 'frappe-ui'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
import FeatherIcon from 'frappe-ui/src/components/FeatherIcon.vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
messages: Array,
|
messages: Array,
|
||||||
@ -165,4 +186,27 @@ function reactOnMessage(name, emoji) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const reply = defineModel('reply')
|
||||||
|
const replyMode = ref(false)
|
||||||
|
|
||||||
|
function messageOptions(message) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
label: 'Reply',
|
||||||
|
onClick: () => {
|
||||||
|
replyMode.value = true
|
||||||
|
reply.value = message
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// label: 'Forward',
|
||||||
|
// onClick: () => console.log('Forward'),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// label: 'Delete',
|
||||||
|
// onClick: () => console.log('Delete'),
|
||||||
|
// },
|
||||||
|
]
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,4 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<div v-if="reply?.message" class="flex justify-around items-center gap-2 px-10 pt-2">
|
||||||
|
<div
|
||||||
|
class="rounded-md flex-1 border-0 border-l-4 border-green-500 bg-gray-50 px-2 py-4 ml-13"
|
||||||
|
>
|
||||||
|
{{ reply.message }}
|
||||||
|
</div>
|
||||||
|
<Button class="mx-[11px]" variant="ghost" icon="x" @click="reply = {}" />
|
||||||
|
</div>
|
||||||
<div class="flex items-end gap-2 px-10 py-2.5">
|
<div class="flex items-end gap-2 px-10 py-2.5">
|
||||||
<div class="flex h-8 items-center gap-2">
|
<div class="flex h-8 items-center gap-2">
|
||||||
<FileUploader @success="(file) => uploadFile(file)">
|
<FileUploader @success="(file) => uploadFile(file)">
|
||||||
@ -28,7 +36,7 @@
|
|||||||
>
|
>
|
||||||
<SmileIcon
|
<SmileIcon
|
||||||
@click="togglePopover"
|
@click="togglePopover"
|
||||||
class="flex size-4.5 rounded-sm text-xl leading-none text-gray-500 cursor-pointer"
|
class="flex size-4.5 cursor-pointer rounded-sm text-xl leading-none text-gray-500"
|
||||||
/>
|
/>
|
||||||
</IconPicker>
|
</IconPicker>
|
||||||
</div>
|
</div>
|
||||||
@ -68,6 +76,7 @@ const props = defineProps({
|
|||||||
|
|
||||||
const doc = defineModel()
|
const doc = defineModel()
|
||||||
const whatsapp = defineModel('whatsapp')
|
const whatsapp = defineModel('whatsapp')
|
||||||
|
const reply = defineModel('reply')
|
||||||
const rows = ref(1)
|
const rows = ref(1)
|
||||||
const textarea = ref(null)
|
const textarea = ref(null)
|
||||||
const emoji = ref('')
|
const emoji = ref('')
|
||||||
@ -104,12 +113,14 @@ async function sendWhatsAppMessage() {
|
|||||||
message: content.value,
|
message: content.value,
|
||||||
to: doc.value.data.mobile_no,
|
to: doc.value.data.mobile_no,
|
||||||
attach: whatsapp.value.attach || '',
|
attach: whatsapp.value.attach || '',
|
||||||
|
reply_to: reply.value?.name || '',
|
||||||
content_type: whatsapp.value.content_type,
|
content_type: whatsapp.value.content_type,
|
||||||
}
|
}
|
||||||
content.value = ''
|
content.value = ''
|
||||||
fileType.value = ''
|
fileType.value = ''
|
||||||
whatsapp.value.attach = ''
|
whatsapp.value.attach = ''
|
||||||
whatsapp.value.content_type = 'text'
|
whatsapp.value.content_type = 'text'
|
||||||
|
reply.value = {}
|
||||||
createResource({
|
createResource({
|
||||||
url: 'crm.api.whatsapp.create_whatsapp_message',
|
url: 'crm.api.whatsapp.create_whatsapp_message',
|
||||||
params: args,
|
params: args,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user