diff --git a/app/javascript/dashboard/components-next/message/bubbles/Contact.vue b/app/javascript/dashboard/components-next/message/bubbles/Contact.vue
index ce16e1b1e..7230a7e05 100644
--- a/app/javascript/dashboard/components-next/message/bubbles/Contact.vue
+++ b/app/javascript/dashboard/components-next/message/bubbles/Contact.vue
@@ -3,6 +3,7 @@ import { computed } from 'vue';
import { useAlert } from 'dashboard/composables';
import { useStore } from 'dashboard/composables/store';
import { useI18n } from 'vue-i18n';
+import { useMessageContext } from '../provider.js';
import BaseAttachmentBubble from './BaseAttachment.vue';
import {
@@ -10,45 +11,13 @@ import {
ExceptionWithMessage,
} from 'shared/helpers/CustomErrors';
-/**
- * @typedef {Object} Attachment
- * @property {number} id - Unique identifier for the attachment
- * @property {number} messageId - ID of the associated message
- * @property {'image'|'audio'|'video'|'file'|'location'|'fallback'|'share'|'story_mention'|'contact'|'ig_reel'} fileType - Type of the attachment (file or image)
- * @property {number} accountId - ID of the associated account
- * @property {string|null} extension - File extension
- * @property {string} dataUrl - URL to access the full attachment data
- * @property {string} thumbUrl - URL to access the thumbnail version
- * @property {number} fileSize - Size of the file in bytes
- * @property {number|null} width - Width of the image if applicable
- * @property {number|null} height - Height of the image if applicable
- */
-
-/**
- * @typedef {Object} Props
- * @property {Attachment[]} [attachments=[]] - The attachments associated with the message
- */
-
-const props = defineProps({
- content: {
- type: String,
- required: true,
- },
- attachments: {
- type: Array,
- required: true,
- },
- sender: {
- type: Object,
- default: () => ({}),
- },
-});
+const { content, attachments } = useMessageContext();
const $store = useStore();
const { t } = useI18n();
const attachment = computed(() => {
- return props.attachments[0];
+ return attachments.value[0];
});
const phoneNumber = computed(() => {
@@ -64,7 +33,7 @@ const rawPhoneNumber = computed(() => {
});
const name = computed(() => {
- return props.content;
+ return content.value;
});
function getContactObject() {
@@ -129,7 +98,6 @@ const action = computed(() => ({
({}),
- },
-});
+const { contentAttributes } = useMessageContext();
const { t } = useI18n();
const meetingData = computed(() => {
- return useCamelCase(props.contentAttributes.data);
+ return useCamelCase(contentAttributes.value.data);
});
const isLoading = ref(false);
@@ -57,7 +50,6 @@ const action = computed(() => ({
diff --git a/app/javascript/dashboard/components-next/message/bubbles/Email/EmailMeta.vue b/app/javascript/dashboard/components-next/message/bubbles/Email/EmailMeta.vue
index 0549a806d..d0378d67b 100644
--- a/app/javascript/dashboard/components-next/message/bubbles/Email/EmailMeta.vue
+++ b/app/javascript/dashboard/components-next/message/bubbles/Email/EmailMeta.vue
@@ -1,57 +1,44 @@
-
+ ({}),
- },
-});
+const { attachments } = useMessageContext();
const { t } = useI18n();
const url = computed(() => {
- return props.attachments[0].dataUrl;
+ return attachments.value[0].dataUrl;
});
const fileName = computed(() => {
@@ -58,7 +31,6 @@ const fileType = computed(() => {
-
+
{{ $t('COMPONENTS.MEDIA.IMAGE_UNAVAILABLE') }}
-
+
{
@click="downloadAttachment"
/>
-
+
[],
- },
-});
-
const emit = defineEmits(['error']);
+const { variant, content, attachments } = useMessageContext();
const attachment = computed(() => {
- return props.attachments[0];
+ return attachments.value[0];
});
-const { variant } = useMessageContext();
const hasImgStoryError = ref(false);
const hasVideoStoryError = ref(false);
const formattedContent = computed(() => {
if (variant.value === MESSAGE_VARIANTS.ACTIVITY) {
- return props.content;
+ return content.value;
}
- return new MessageFormatter(props.content).formattedMessage;
+ return new MessageFormatter(content.value).formattedMessage;
});
const onImageLoadError = () => {
diff --git a/app/javascript/dashboard/components-next/message/bubbles/Location.vue b/app/javascript/dashboard/components-next/message/bubbles/Location.vue
index 5266f3a81..eb669eb41 100644
--- a/app/javascript/dashboard/components-next/message/bubbles/Location.vue
+++ b/app/javascript/dashboard/components-next/message/bubbles/Location.vue
@@ -1,43 +1,14 @@
-
-
-
-
+ />
-
-
diff --git a/app/javascript/dashboard/components-next/message/bubbles/Text/Index.vue b/app/javascript/dashboard/components-next/message/bubbles/Text/Index.vue
index dc573760e..93020b6be 100644
--- a/app/javascript/dashboard/components-next/message/bubbles/Text/Index.vue
+++ b/app/javascript/dashboard/components-next/message/bubbles/Text/Index.vue
@@ -4,47 +4,25 @@ import BaseBubble from 'next/message/bubbles/Base.vue';
import FormattedContent from './FormattedContent.vue';
import AttachmentChips from 'next/message/chips/AttachmentChips.vue';
import { MESSAGE_TYPES } from '../../constants';
+import { useMessageContext } from '../../provider.js';
-/**
- * @typedef {Object} Attachment
- * @property {number} id - Unique identifier for the attachment
- * @property {number} messageId - ID of the associated message
- * @property {'image'|'audio'|'video'|'file'|'location'|'fallback'|'share'|'story_mention'|'contact'|'ig_reel'} fileType - Type of the attachment (file or image)
- * @property {number} accountId - ID of the associated account
- * @property {string|null} extension - File extension
- * @property {string} dataUrl - URL to access the full attachment data
- * @property {string} thumbUrl - URL to access the thumbnail version
- * @property {number} fileSize - Size of the file in bytes
- * @property {number|null} width - Width of the image if applicable
- * @property {number|null} height - Height of the image if applicable
- */
-const props = defineProps({
- content: {
- type: String,
- required: true,
- },
- attachments: {
- type: Array,
- default: () => [],
- },
- contentAttributes: {
- type: Object,
- default: () => ({}),
- },
- messageType: {
- type: Number,
- required: true,
- validator: value => Object.values(MESSAGE_TYPES).includes(value),
- },
-});
+const { content, attachments, contentAttributes, messageType } =
+ useMessageContext();
const isTemplate = computed(() => {
- return props.messageType === MESSAGE_TYPES.TEMPLATE;
+ return messageType.value === MESSAGE_TYPES.TEMPLATE;
+});
+
+const isEmpty = computed(() => {
+ return !content.value && !attachments.value.length;
});
+
+ {{ $t('CONVERSATION.NO_CONTENT') }}
+
diff --git a/app/javascript/dashboard/components-next/message/bubbles/Video.vue b/app/javascript/dashboard/components-next/message/bubbles/Video.vue
index 2d8586111..2ccecd4db 100644
--- a/app/javascript/dashboard/components-next/message/bubbles/Video.vue
+++ b/app/javascript/dashboard/components-next/message/bubbles/Video.vue
@@ -3,39 +3,14 @@ import { ref, computed } from 'vue';
import BaseBubble from './Base.vue';
import Icon from 'next/icon/Icon.vue';
import { useSnakeCase } from 'dashboard/composables/useTransformKeys';
-import { useMessageContext } from 'next/message/provider.js';
+import { useMessageContext } from '../provider.js';
import GalleryView from 'dashboard/components/widgets/conversation/components/GalleryView.vue';
import { ATTACHMENT_TYPES } from '../constants';
-/**
- * @typedef {Object} Attachment
- * @property {number} id - Unique identifier for the attachment
- * @property {number} messageId - ID of the associated message
- * @property {'image'|'audio'|'video'|'file'|'location'|'fallback'|'share'|'story_mention'|'contact'|'ig_reel'} fileType - Type of the attachment (file or image)
- * @property {number} accountId - ID of the associated account
- * @property {string|null} extension - File extension
- * @property {string} dataUrl - URL to access the full attachment data
- * @property {string} thumbUrl - URL to access the thumbnail version
- * @property {number} fileSize - Size of the file in bytes
- * @property {number|null} width - Width of the image if applicable
- * @property {number|null} height - Height of the image if applicable
- */
-
-/**
- * @typedef {Object} Props
- * @property {Attachment[]} [attachments=[]] - The attachments associated with the message
- */
-
-const props = defineProps({
- attachments: {
- type: Array,
- required: true,
- },
-});
const emit = defineEmits(['error']);
const hasError = ref(false);
const showGallery = ref(false);
-const { filteredCurrentChatAttachments } = useMessageContext();
+const { filteredCurrentChatAttachments, attachments } = useMessageContext();
const handleError = () => {
hasError.value = true;
@@ -43,7 +18,7 @@ const handleError = () => {
};
const attachment = computed(() => {
- return props.attachments[0];
+ return attachments.value[0];
});
const isReel = computed(() => {
@@ -53,25 +28,28 @@ const isReel = computed(() => {
-
-
+
+
+
+
+
-
{
diff --git a/app/javascript/dashboard/components-next/message/provider.js b/app/javascript/dashboard/components-next/message/provider.js
index cf35c6c40..f4c501845 100644
--- a/app/javascript/dashboard/components-next/message/provider.js
+++ b/app/javascript/dashboard/components-next/message/provider.js
@@ -5,6 +5,112 @@ import { ATTACHMENT_TYPES } from './constants';
const MessageControl = Symbol('MessageControl');
+/**
+ * @typedef {Object} Attachment
+ * @property {number} id - Unique identifier for the attachment
+ * @property {number} messageId - ID of the associated message
+ * @property {'image'|'audio'|'video'|'file'|'location'|'fallback'|'share'|'story_mention'|'contact'|'ig_reel'} fileType - Type of the attachment (file or image)
+ * @property {number} accountId - ID of the associated account
+ * @property {string|null} extension - File extension
+ * @property {string} dataUrl - URL to access the full attachment data
+ * @property {string} thumbUrl - URL to access the thumbnail version
+ * @property {number} fileSize - Size of the file in bytes
+ * @property {number|null} width - Width of the image if applicable
+ * @property {number|null} height - Height of the image if applicable
+ */
+
+/**
+ * @typedef {Object} Sender
+ * @property {Object} additional_attributes - Additional attributes of the sender
+ * @property {Object} custom_attributes - Custom attributes of the sender
+ * @property {string} email - Email of the sender
+ * @property {number} id - ID of the sender
+ * @property {string|null} identifier - Identifier of the sender
+ * @property {string} name - Name of the sender
+ * @property {string|null} phone_number - Phone number of the sender
+ * @property {string} thumbnail - Thumbnail URL of the sender
+ * @property {string} type - Type of sender
+ */
+
+/**
+ * @typedef {Object} EmailContent
+ * @property {string[]|null} bcc - BCC recipients
+ * @property {string[]|null} cc - CC recipients
+ * @property {string} contentType - Content type of the email
+ * @property {string} date - Date the email was sent
+ * @property {string[]} from - From email address
+ * @property {Object} htmlContent - HTML content of the email
+ * @property {string} htmlContent.full - Full HTML content
+ * @property {string} htmlContent.reply - Reply HTML content
+ * @property {string} htmlContent.quoted - Quoted HTML content
+ * @property {string|null} inReplyTo - Message ID being replied to
+ * @property {string} messageId - Unique message identifier
+ * @property {boolean} multipart - Whether the email is multipart
+ * @property {number} numberOfAttachments - Number of attachments
+ * @property {string} subject - Email subject line
+ * @property {Object} textContent - Text content of the email
+ * @property {string} textContent.full - Full text content
+ * @property {string} textContent.reply - Reply text content
+ * @property {string} textContent.quoted - Quoted text content
+ * @property {string[]} to - To email addresses
+ */
+
+/**
+ * @typedef {Object} ContentAttributes
+ * @property {string} externalError - an error message to be shown if the message failed to send
+ * @property {Object} [data] - Optional data object containing roomName and messageId
+ * @property {string} data.roomName - Name of the room
+ * @property {string} data.messageId - ID of the message
+ * @property {'story_mention'} [imageType] - Flag to indicate this is a story mention
+ * @property {'dyte'} [type] - Flag to indicate this is a dyte call
+ * @property {EmailContent} [email] - Email content and metadata
+ * @property {string|null} [ccEmail] - CC email addresses
+ * @property {string|null} [bccEmail] - BCC email addresses
+ */
+
+/**
+ * @typedef {'sent'|'delivered'|'read'|'failed'|'progress'} MessageStatus
+ * @typedef {'text'|'input_text'|'input_textarea'|'input_email'|'input_select'|'cards'|'form'|'article'|'incoming_email'|'input_csat'|'integrations'|'sticker'} MessageContentType
+ * @typedef {0|1|2|3} MessageType
+ * @typedef {'contact'|'user'|'Contact'|'User'} SenderType
+ * @typedef {'user'|'agent'|'activity'|'private'|'bot'|'error'|'template'|'email'|'unsupported'} MessageVariant
+ * @typedef {'left'|'center'|'right'} MessageOrientation
+
+ * @typedef {Object} MessageContext
+ * @property {import('vue').Ref} content - The message content
+ * @property {import('vue').Ref} conversationId - The ID of the conversation to which the message belongs
+ * @property {import('vue').Ref} createdAt - Timestamp when the message was created
+ * @property {import('vue').Ref} currentUserId - The ID of the current user
+ * @property {import('vue').Ref} id - The unique identifier for the message
+ * @property {import('vue').Ref} inboxId - The ID of the inbox to which the message belongs
+ * @property {import('vue').Ref} [groupWithNext=false] - Whether the message should be grouped with the next message
+ * @property {import('vue').Ref} [isEmailInbox=false] - Whether the message is from an email inbox
+ * @property {import('vue').Ref} [private=false] - Whether the message is private
+ * @property {import('vue').Ref} [senderId=null] - The ID of the sender
+ * @property {import('vue').Ref} [error=null] - Error message if the message failed to send
+ * @property {import('vue').Ref} [attachments=[]] - The attachments associated with the message
+ * @property {import('vue').Ref} [contentAttributes={}] - Additional attributes of the message content
+ * @property {import('vue').Ref} contentType - Content type of the message
+ * @property {import('vue').Ref} status - The delivery status of the message
+ * @property {import('vue').Ref} messageType - The type of message (must be one of MESSAGE_TYPES)
+ * @property {import('vue').Ref