Merge branch 'develop' into heatmap-last-30-days
This commit is contained in:
+3
-2
@@ -77,7 +77,7 @@ const toggleMessageSignature = () => {
|
||||
setSignature();
|
||||
};
|
||||
|
||||
// Added this watch to dynamically set signature.
|
||||
// Added this watch to dynamically set signature on target inbox change.
|
||||
// Only targetInbox has value and is Advance Editor(used by isEmailOrWebWidgetInbox)
|
||||
// Set the signature only if the inbox based flag is true
|
||||
watch(
|
||||
@@ -86,7 +86,8 @@ watch(
|
||||
nextTick(() => {
|
||||
if (newValue && props.isEmailOrWebWidgetInbox) setSignature();
|
||||
});
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
const onClickInsertEmoji = emoji => {
|
||||
|
||||
@@ -15,18 +15,14 @@ import { useCamelCase } from 'dashboard/composables/useTransformKeys';
|
||||
* @property {Array} messages - Array of all messages [These are not in camelcase]
|
||||
*/
|
||||
const props = defineProps({
|
||||
readMessages: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
unReadMessages: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
currentUserId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
firstUnreadId: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
isAnEmailChannel: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
@@ -41,12 +37,8 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
const unread = computed(() => {
|
||||
return useCamelCase(props.unReadMessages, { deep: true });
|
||||
});
|
||||
|
||||
const read = computed(() => {
|
||||
return useCamelCase(props.readMessages, { deep: true });
|
||||
const allMessages = computed(() => {
|
||||
return useCamelCase(props.messages, { deep: true });
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -108,26 +100,18 @@ const getInReplyToMessage = parentMessage => {
|
||||
<template>
|
||||
<ul class="px-4 bg-n-background">
|
||||
<slot name="beforeAll" />
|
||||
<template v-for="(message, index) in read" :key="message.id">
|
||||
<Message
|
||||
v-bind="message"
|
||||
:is-email-inbox="isAnEmailChannel"
|
||||
:in-reply-to="getInReplyToMessage(message)"
|
||||
:group-with-next="shouldGroupWithNext(index, read)"
|
||||
:inbox-supports-reply-to="inboxSupportsReplyTo"
|
||||
:current-user-id="currentUserId"
|
||||
data-clarity-mask="True"
|
||||
<template v-for="(message, index) in allMessages" :key="message.id">
|
||||
<slot
|
||||
v-if="firstUnreadId && message.id === firstUnreadId"
|
||||
name="unreadBadge"
|
||||
/>
|
||||
</template>
|
||||
<slot name="beforeUnread" />
|
||||
<template v-for="(message, index) in unread" :key="message.id">
|
||||
<Message
|
||||
v-bind="message"
|
||||
:is-email-inbox="isAnEmailChannel"
|
||||
:in-reply-to="getInReplyToMessage(message)"
|
||||
:group-with-next="shouldGroupWithNext(index, unread)"
|
||||
:group-with-next="shouldGroupWithNext(index, allMessages)"
|
||||
:inbox-supports-reply-to="inboxSupportsReplyTo"
|
||||
:current-user-id="currentUserId"
|
||||
:is-email-inbox="isAnEmailChannel"
|
||||
data-clarity-mask="True"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -38,9 +38,10 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
const formatTime = time => {
|
||||
if (!time || Number.isNaN(time)) return '00:00';
|
||||
const minutes = Math.floor(time / 60);
|
||||
const seconds = Math.floor(time % 60);
|
||||
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
const toggleMute = () => {
|
||||
@@ -49,7 +50,7 @@ const toggleMute = () => {
|
||||
};
|
||||
|
||||
const onTimeUpdate = () => {
|
||||
currentTime.value = audioPlayer.value.currentTime;
|
||||
currentTime.value = audioPlayer.value?.currentTime;
|
||||
};
|
||||
|
||||
const seek = event => {
|
||||
|
||||
@@ -243,6 +243,15 @@ export default {
|
||||
unreadMessageCount() {
|
||||
return this.currentChat.unread_count || 0;
|
||||
},
|
||||
unreadMessageLabel() {
|
||||
const count =
|
||||
this.unreadMessageCount > 9 ? '9+' : this.unreadMessageCount;
|
||||
const label =
|
||||
this.unreadMessageCount > 1
|
||||
? 'CONVERSATION.UNREAD_MESSAGES'
|
||||
: 'CONVERSATION.UNREAD_MESSAGE';
|
||||
return `${count} ${this.$t(label)}`;
|
||||
},
|
||||
isInstagramDM() {
|
||||
return this.conversationType === 'instagram_direct_message';
|
||||
},
|
||||
@@ -492,12 +501,11 @@ export default {
|
||||
<NextMessageList
|
||||
v-if="showNextBubbles"
|
||||
class="conversation-panel"
|
||||
:read-messages="readMessages"
|
||||
:un-read-messages="unReadMessages"
|
||||
:current-user-id="currentUserId"
|
||||
:first-unread-id="unReadMessages[0]?.id"
|
||||
:is-an-email-channel="isAnEmailChannel"
|
||||
:inbox-supports-reply-to="inboxSupportsReplyTo"
|
||||
:messages="currentChat ? currentChat.messages : []"
|
||||
:messages="getMessages"
|
||||
>
|
||||
<template #beforeAll>
|
||||
<transition name="slide-up">
|
||||
@@ -507,15 +515,10 @@ export default {
|
||||
</li>
|
||||
</transition>
|
||||
</template>
|
||||
<template #beforeUnread>
|
||||
<template #unreadBadge>
|
||||
<li v-show="unreadMessageCount != 0" class="unread--toast">
|
||||
<span>
|
||||
{{ unreadMessageCount > 9 ? '9+' : unreadMessageCount }}
|
||||
{{
|
||||
unreadMessageCount > 1
|
||||
? $t('CONVERSATION.UNREAD_MESSAGES')
|
||||
: $t('CONVERSATION.UNREAD_MESSAGE')
|
||||
}}
|
||||
{{ unreadMessageLabel }}
|
||||
</span>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
@@ -99,6 +99,9 @@
|
||||
},
|
||||
"fallback": {
|
||||
"CONTENT": "has shared a url"
|
||||
},
|
||||
"contact": {
|
||||
"CONTENT": "Shared contact"
|
||||
}
|
||||
},
|
||||
"CHAT_SORT_BY_FILTER": {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"READ_MORE": "Read more",
|
||||
"WROTE": "wrote:",
|
||||
"FROM": "from",
|
||||
"EMAIL": "email"
|
||||
"EMAIL": "email",
|
||||
"EMAIL_SUBJECT": "subject"
|
||||
}
|
||||
}
|
||||
|
||||
+32
-14
@@ -35,6 +35,10 @@ const props = defineProps({
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
emailSubject: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
const navigateTo = computed(() => {
|
||||
@@ -49,6 +53,28 @@ const navigateTo = computed(() => {
|
||||
});
|
||||
|
||||
const createdAtTime = dynamicTime(props.createdAt);
|
||||
|
||||
const infoItems = computed(() => [
|
||||
{
|
||||
label: 'SEARCH.FROM',
|
||||
value: props.name,
|
||||
show: !!props.name,
|
||||
},
|
||||
{
|
||||
label: 'SEARCH.EMAIL',
|
||||
value: props.email,
|
||||
show: !!props.email,
|
||||
},
|
||||
{
|
||||
label: 'SEARCH.EMAIL_SUBJECT',
|
||||
value: props.emailSubject,
|
||||
show: !!props.emailSubject,
|
||||
},
|
||||
]);
|
||||
|
||||
const visibleInfoItems = computed(() =>
|
||||
infoItems.value.filter(item => item.show)
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -86,26 +112,18 @@ const createdAtTime = dynamicTime(props.createdAt);
|
||||
{{ createdAtTime }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<div class="flex flex-wrap gap-x-2 gap-y-1.5">
|
||||
<h5
|
||||
v-if="name"
|
||||
class="m-0 text-sm min-w-0 truncate text-n-slate-12 dark:text-n-slate-12"
|
||||
>
|
||||
<span class="text-xs font-norma text-n-slate-11 dark:text-n-slate-11">
|
||||
{{ $t('SEARCH.FROM') }}:
|
||||
</span>
|
||||
{{ name }}
|
||||
</h5>
|
||||
<h5
|
||||
v-if="email"
|
||||
class="m-0 overflow-hidden text-sm text-n-slate-12 dark:text-n-slate-12 truncate"
|
||||
v-for="item in visibleInfoItems"
|
||||
:key="item.label"
|
||||
class="m-0 text-sm min-w-0 text-n-slate-12 dark:text-n-slate-12 truncate"
|
||||
>
|
||||
<span
|
||||
class="text-xs font-normal text-n-slate-11 dark:text-n-slate-11"
|
||||
>
|
||||
{{ $t('SEARCH.EMAIL') }}:
|
||||
{{ $t(item.label) }}:
|
||||
</span>
|
||||
{{ email }}
|
||||
{{ item.value }}
|
||||
</h5>
|
||||
</div>
|
||||
<slot />
|
||||
|
||||
+14
-2
@@ -1,9 +1,10 @@
|
||||
<script setup>
|
||||
import { defineProps, computed } from 'vue';
|
||||
import { useMapGetter } from 'dashboard/composables/store.js';
|
||||
import SearchResultSection from './SearchResultSection.vue';
|
||||
import SearchResultConversationItem from './SearchResultConversationItem.vue';
|
||||
|
||||
defineProps({
|
||||
const props = defineProps({
|
||||
conversations: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
@@ -23,6 +24,13 @@ defineProps({
|
||||
});
|
||||
|
||||
const accountId = useMapGetter('getCurrentAccountId');
|
||||
|
||||
const conversationsWithSubject = computed(() => {
|
||||
return props.conversations.map(conversation => ({
|
||||
...conversation,
|
||||
mail_subject: conversation.additional_attributes?.mail_subject || '',
|
||||
}));
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -34,7 +42,10 @@ const accountId = useMapGetter('getCurrentAccountId');
|
||||
:is-fetching="isFetching"
|
||||
>
|
||||
<ul v-if="conversations.length" class="space-y-1.5 list-none">
|
||||
<li v-for="conversation in conversations" :key="conversation.id">
|
||||
<li
|
||||
v-for="conversation in conversationsWithSubject"
|
||||
:key="conversation.id"
|
||||
>
|
||||
<SearchResultConversationItem
|
||||
:id="conversation.id"
|
||||
:name="conversation.contact.name"
|
||||
@@ -42,6 +53,7 @@ const accountId = useMapGetter('getCurrentAccountId');
|
||||
:account-id="accountId"
|
||||
:inbox="conversation.inbox"
|
||||
:created-at="conversation.created_at"
|
||||
:email-subject="conversation.mail_subject"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user