From a428dfc3f447665487cdc3e56d8554d6085177bf Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 11 Feb 2025 17:45:31 +0530 Subject: [PATCH 01/58] feat: handle mine event for incoming messages (#10867) Handle `mine` condition, missed in https://github.com/chatwoot/chatwoot/pull/10529 --- .../helper/AudioAlerts/DashboardAudioNotificationHelper.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/javascript/dashboard/helper/AudioAlerts/DashboardAudioNotificationHelper.js b/app/javascript/dashboard/helper/AudioAlerts/DashboardAudioNotificationHelper.js index 21cb0fc9f..9e79bb3a2 100644 --- a/app/javascript/dashboard/helper/AudioAlerts/DashboardAudioNotificationHelper.js +++ b/app/javascript/dashboard/helper/AudioAlerts/DashboardAudioNotificationHelper.js @@ -152,7 +152,10 @@ export class DashboardAudioNotificationHelper { const shouldPlayAudio = []; - if (audioAlertType.includes(EVENT_TYPES.ASSIGNED)) { + if ( + audioAlertType.includes(EVENT_TYPES.ASSIGNED) || + audioAlertType.includes('mine') + ) { shouldPlayAudio.push(assignedToMe); } if (audioAlertType.includes(EVENT_TYPES.UNASSIGNED)) { From 84822a013a01808829071a28f4f027130e45f58b Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 11 Feb 2025 17:45:59 +0530 Subject: [PATCH 02/58] fix: inconsistent reply box cc update (#10799) This PR target two issues ### CC & BCC not updated correctly When moving from one conversation to another, the store may not have the list of all the messages. A fetch is subsequently made to get the messages. However, this update does not trigger the `currentChat` watcher. This PR fixes it by adding a new watcher on `currentChat.messages`. We also update the `setCCAndToEmailsFromLastChat` method to reset the `cc`, `bcc` and `to` fields if the last email is not found. This ensures that the data is not carried forward from a previous email Fixes: https://github.com/chatwoot/chatwoot/issues/10477 ### To address are not added correctly to the `CC` If the `to` address of a previous email has multiple recipient, there was no case to add them to the CC. Fixes: https://github.com/chatwoot/chatwoot/issues/8925 --- Depends on: https://github.com/chatwoot/utils/pull/41 --- .../widgets/conversation/ReplyBox.vue | 57 +++++++------------ .../store/modules/conversations/getters.js | 18 ++---- package.json | 2 +- pnpm-lock.yaml | 28 ++++++--- 4 files changed, 48 insertions(+), 57 deletions(-) diff --git a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue index d3675dbac..7a876aaa6 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue @@ -30,7 +30,7 @@ import { import WhatsappTemplates from './WhatsappTemplates/Modal.vue'; import { MESSAGE_MAX_LENGTH } from 'shared/helpers/MessageTypeHelper'; import inboxMixin, { INBOX_FEATURES } from 'shared/mixins/inboxMixin'; -import { trimContent, debounce } from '@chatwoot/utils'; +import { trimContent, debounce, getRecipients } from '@chatwoot/utils'; import wootConstants from 'dashboard/constants/globals'; import { CONVERSATION_EVENTS } from '../../../helper/AnalyticsHelper/events'; import fileUploadMixin from 'dashboard/mixins/fileUploadMixin'; @@ -388,7 +388,6 @@ export default { watch: { currentChat(conversation) { const { can_reply: canReply } = conversation; - this.setCCAndToEmailsFromLastChat(); if (this.isOnPrivateNote) { @@ -403,6 +402,19 @@ export default { this.fetchAndSetReplyTo(); }, + // When moving from one conversation to another, the store may not have the + // list of all the messages. A fetch is subsequently made to get the messages. + // However, this update does not trigger the `currentChat` watcher. + // We can add a deep watcher to it, but then, that would be too broad of a net to cast + // And would impact performance too. So we watch the messages directly. + // The watcher here is `deep` too, because the messages array is mutated and + // not replaced. So, a shallow watcher would not catch the change. + 'currentChat.messages': { + handler() { + this.setCCAndToEmailsFromLastChat(); + }, + deep: true, + }, conversationIdByRoute(conversationId, oldConversationId) { if (conversationId !== oldConversationId) { this.setToDraft(oldConversationId, this.replyType); @@ -989,45 +1001,20 @@ export default { this.ccEmails = value.ccEmails; }, setCCAndToEmailsFromLastChat() { - if (!this.lastEmail) return; - - const { - content_attributes: { email: emailAttributes = {} }, - } = this.lastEmail; - - // Retrieve the email of the current conversation's sender const conversationContact = this.currentChat?.meta?.sender?.email || ''; - let cc = emailAttributes.cc ? [...emailAttributes.cc] : []; - let to = []; + const { email: inboxEmail, forward_to_email: forwardToEmail } = + this.inbox; - // there might be a situation where the current conversation will include a message from a third person, - // and the current conversation contact is in CC. - // This is an edge-case, reported here: CW-1511 [ONLY FOR INTERNAL REFERENCE] - // So we remove the current conversation contact's email from the CC list if present - if (cc.includes(conversationContact)) { - cc = cc.filter(email => email !== conversationContact); - } - - // If the last incoming message sender is different from the conversation contact, add them to the "to" - // and add the conversation contact to the CC - if (!emailAttributes.from.includes(conversationContact)) { - to.push(...emailAttributes.from); - cc.push(conversationContact); - } - - // Remove the conversation contact's email from the BCC list if present - let bcc = (emailAttributes.bcc || []).filter( - email => email !== conversationContact + const { cc, bcc, to } = getRecipients( + this.lastEmail, + conversationContact, + inboxEmail, + forwardToEmail ); - // Ensure only unique email addresses are in the CC list - bcc = [...new Set(bcc)]; - cc = [...new Set(cc)]; - to = [...new Set(to)]; - + this.toEmails = to.join(', '); this.ccEmails = cc.join(', '); this.bccEmails = bcc.join(', '); - this.toEmails = to.join(', '); }, fetchAndSetReplyTo() { const replyStorageKey = LOCAL_STORAGE_KEYS.MESSAGE_REPLY_TO; diff --git a/app/javascript/dashboard/store/modules/conversations/getters.js b/app/javascript/dashboard/store/modules/conversations/getters.js index 085766bfd..3695de6a1 100644 --- a/app/javascript/dashboard/store/modules/conversations/getters.js +++ b/app/javascript/dashboard/store/modules/conversations/getters.js @@ -27,18 +27,12 @@ const getters = { const selectedChat = _getters.getSelectedChat; const { messages = [] } = selectedChat; const lastEmail = [...messages].reverse().find(message => { - const { - content_attributes: contentAttributes = {}, - message_type: messageType, - } = message; - const { email = {} } = contentAttributes; - const isIncomingOrOutgoing = - messageType === MESSAGE_TYPE.OUTGOING || - messageType === MESSAGE_TYPE.INCOMING; - if (email.from && isIncomingOrOutgoing) { - return true; - } - return false; + const { message_type: messageType } = message; + if (message.private) return false; + + return [MESSAGE_TYPE.OUTGOING, MESSAGE_TYPE.INCOMING].includes( + messageType + ); }); return lastEmail; diff --git a/package.json b/package.json index b3fbda8f0..aefa5439d 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@breezystack/lamejs": "^1.2.7", "@chatwoot/ninja-keys": "1.2.3", "@chatwoot/prosemirror-schema": "1.1.1-next", - "@chatwoot/utils": "^0.0.35", + "@chatwoot/utils": "^0.0.38", "@formkit/core": "^1.6.7", "@formkit/vue": "^1.6.7", "@hcaptcha/vue3-hcaptcha": "^1.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 20142653e..6bbf22593 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,8 +23,8 @@ importers: specifier: 1.1.1-next version: 1.1.1-next '@chatwoot/utils': - specifier: ^0.0.35 - version: 0.0.35 + specifier: ^0.0.38 + version: 0.0.38 '@formkit/core': specifier: ^1.6.7 version: 1.6.7 @@ -376,6 +376,10 @@ packages: resolution: {integrity: sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==} engines: {node: '>=6.9.0'} + '@babel/runtime@7.26.7': + resolution: {integrity: sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==} + engines: {node: '>=6.9.0'} + '@babel/types@7.26.0': resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} engines: {node: '>=6.9.0'} @@ -393,8 +397,8 @@ packages: '@chatwoot/prosemirror-schema@1.1.1-next': resolution: {integrity: sha512-/M2qZ+ZF7GlQNt1riwVP499fvp3hxSqd5iy8hxyF9pkj9qQ+OKYn5JK+v3qwwqQY3IxhmNOn1Lp6tm7vstrd9Q==} - '@chatwoot/utils@0.0.35': - resolution: {integrity: sha512-uSRbd3pFp+IcEhsRtK1XGcFGFJc+X/YIwQnQrVDXsvsX3Mm7HEANj+Yz6J2clfHotajniwJwH2u5/y48+JrTyA==} + '@chatwoot/utils@0.0.38': + resolution: {integrity: sha512-6CTvuueBQLZJcm++pI2ZBY8Pp7OP3WzPCYyXoCagl8ZLpOfpjyVkLx9fc81falOoaVa/r+7EZ85Cv7vkT0ZyQw==} engines: {node: '>=10'} '@codemirror/commands@6.7.0': @@ -2372,8 +2376,8 @@ packages: resolution: {integrity: sha512-m1WR0xGiC6j6jNFAyW4Nvh4WxAi4JF4w9jRJwSI8nBmNcyZXPcP9VUQG+6gHQXAmqaGEKDKhOqAtENDC941UkA==} engines: {node: '>=0.11'} - date-fns@2.29.3: - resolution: {integrity: sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==} + date-fns@2.30.0: + resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} engines: {node: '>=0.11'} date-format-parse@0.2.7: @@ -5092,6 +5096,10 @@ snapshots: dependencies: regenerator-runtime: 0.14.1 + '@babel/runtime@7.26.7': + dependencies: + regenerator-runtime: 0.14.1 + '@babel/types@7.26.0': dependencies: '@babel/helper-string-parser': 7.25.9 @@ -5125,9 +5133,9 @@ snapshots: prosemirror-utils: 1.2.2(prosemirror-model@1.22.3)(prosemirror-state@1.4.3) prosemirror-view: 1.34.1 - '@chatwoot/utils@0.0.35': + '@chatwoot/utils@0.0.38': dependencies: - date-fns: 2.29.3 + date-fns: 2.30.0 '@codemirror/commands@6.7.0': dependencies: @@ -7380,7 +7388,9 @@ snapshots: date-fns@2.21.1: {} - date-fns@2.29.3: {} + date-fns@2.30.0: + dependencies: + '@babel/runtime': 7.26.7 date-format-parse@0.2.7: {} From cf025e0fa4302e496f4f27db6dcc92af195f4c31 Mon Sep 17 00:00:00 2001 From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Date: Tue, 11 Feb 2025 18:58:36 +0530 Subject: [PATCH 03/58] chore: Remove the background SVG from the help center (#10857) # Pull Request Template ## Description This PR will remove the hexagon background image from public portal. Fixes https://linear.app/chatwoot/issue/CW-4013/remove-the-background-from-the-help-center ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? **Screenshots** **Before** image image **After** image image ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules --- app/helpers/portal_helper.rb | 3 +-- spec/helpers/portal_helper_spec.rb | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/helpers/portal_helper.rb b/app/helpers/portal_helper.rb index 342bb62aa..2b1ab7b21 100644 --- a/app/helpers/portal_helper.rb +++ b/app/helpers/portal_helper.rb @@ -5,8 +5,7 @@ module PortalHelper end def generate_portal_bg(portal_color, theme) - bg_image = theme == 'dark' ? 'hexagon-dark.svg' : 'hexagon-light.svg' - "url(/assets/images/hc/#{bg_image}) #{generate_portal_bg_color(portal_color, theme)}" + generate_portal_bg_color(portal_color, theme) end def generate_gradient_to_bottom(theme) diff --git a/spec/helpers/portal_helper_spec.rb b/spec/helpers/portal_helper_spec.rb index 84ed4ba72..dfd37138a 100644 --- a/spec/helpers/portal_helper_spec.rb +++ b/spec/helpers/portal_helper_spec.rb @@ -33,26 +33,26 @@ describe PortalHelper do describe '#generate_portal_bg' do context 'when theme is dark' do it 'returns the correct background with dark grid image and color mix with black' do - expected_bg = 'url(/assets/images/hc/hexagon-dark.svg) color-mix(in srgb, #ff0000 20%, black)' + expected_bg = 'color-mix(in srgb, #ff0000 20%, black)' expect(helper.generate_portal_bg('#ff0000', 'dark')).to eq(expected_bg) end end context 'when theme is not dark' do it 'returns the correct background with light grid image and color mix with white' do - expected_bg = 'url(/assets/images/hc/hexagon-light.svg) color-mix(in srgb, #ff0000 20%, white)' + expected_bg = 'color-mix(in srgb, #ff0000 20%, white)' expect(helper.generate_portal_bg('#ff0000', 'light')).to eq(expected_bg) end end context 'when provided with various colors' do it 'adjusts the background appropriately for dark theme' do - expected_bg = 'url(/assets/images/hc/hexagon-dark.svg) color-mix(in srgb, #00ff00 20%, black)' + expected_bg = 'color-mix(in srgb, #00ff00 20%, black)' expect(helper.generate_portal_bg('#00ff00', 'dark')).to eq(expected_bg) end it 'adjusts the background appropriately for light theme' do - expected_bg = 'url(/assets/images/hc/hexagon-light.svg) color-mix(in srgb, #0000ff 20%, white)' + expected_bg = 'color-mix(in srgb, #0000ff 20%, white)' expect(helper.generate_portal_bg('#0000ff', 'light')).to eq(expected_bg) end end From a780de4b640da515939a8e0ead0bb889437a41ca Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 11 Feb 2025 19:15:46 +0530 Subject: [PATCH 04/58] refactor: show deprecation warnings in dev only (#10868) Fixes: https://github.com/chatwoot/chatwoot/issues/10734 --- app/javascript/dashboard/components/Modal.vue | 2 +- app/javascript/dashboard/components/buttons/Button.vue | 10 ++++++---- .../dashboard/components/widgets/forms/Input.vue | 10 ++++++---- app/javascript/v3/components/Button/SubmitButton.vue | 10 ++++++---- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/app/javascript/dashboard/components/Modal.vue b/app/javascript/dashboard/components/Modal.vue index a1f7ba5ed..653e6cde0 100644 --- a/app/javascript/dashboard/components/Modal.vue +++ b/app/javascript/dashboard/components/Modal.vue @@ -57,7 +57,7 @@ useEventListener(document.body, 'mouseup', onMouseUp); useEventListener(document, 'keydown', onKeydown); onMounted(() => { - if (onClose && typeof onClose === 'function') { + if (import.meta.env.DEV && onClose && typeof onClose === 'function') { // eslint-disable-next-line no-console console.warn( "[DEPRECATED] The 'onClose' prop is deprecated. Please use the 'close' event instead." diff --git a/app/javascript/dashboard/components/buttons/Button.vue b/app/javascript/dashboard/components/buttons/Button.vue index 1ec445890..64b5ecb9a 100644 --- a/app/javascript/dashboard/components/buttons/Button.vue +++ b/app/javascript/dashboard/components/buttons/Button.vue @@ -28,10 +28,12 @@ export default { }, }, created() { - // eslint-disable-next-line - console.warn( - '[DEPRECATED] This component has been deprecated and will be removed soon. Please use v3/components/Form/Button.vue instead' - ); + if (import.meta.env.DEV) { + // eslint-disable-next-line + console.warn( + '[DEPRECATED] This component has been deprecated and will be removed soon. Please use v3/components/Form/Button.vue instead' + ); + } }, }; diff --git a/app/javascript/dashboard/components/widgets/forms/Input.vue b/app/javascript/dashboard/components/widgets/forms/Input.vue index b34d81259..bd6d49470 100644 --- a/app/javascript/dashboard/components/widgets/forms/Input.vue +++ b/app/javascript/dashboard/components/widgets/forms/Input.vue @@ -40,10 +40,12 @@ export default { }, emits: ['update:modelValue', 'input', 'blur'], mounted() { - // eslint-disable-next-line - console.warn( - '[DEPRECATED] has be deprecated and will be removed soon. Please use v3/components/Form/Input.vue instead' - ); + if (import.meta.env.DEV) { + // eslint-disable-next-line no-console + console.warn( + '[DEPRECATED] has be deprecated and will be removed soon. Please use v3/components/Form/Input.vue instead' + ); + } }, methods: { onChange(e) { diff --git a/app/javascript/v3/components/Button/SubmitButton.vue b/app/javascript/v3/components/Button/SubmitButton.vue index 24c04acbb..88dad0799 100644 --- a/app/javascript/v3/components/Button/SubmitButton.vue +++ b/app/javascript/v3/components/Button/SubmitButton.vue @@ -40,10 +40,12 @@ export default { }, }, created() { - // eslint-disable-next-line - console.warn( - '[DEPRECATED] This component has been deprecated and will be removed soon. Please use v3/components/Form/Button.vue instead' - ); + if (import.meta.env.DEV) { + // eslint-disable-next-line + console.warn( + '[DEPRECATED] This component has been deprecated and will be removed soon. Please use v3/components/Form/Button.vue instead' + ); + } }, }; From 55d41b112b0558c3afa79718e1f3b8864b18893c Mon Sep 17 00:00:00 2001 From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Date: Tue, 11 Feb 2025 19:39:54 +0530 Subject: [PATCH 05/58] feat: Show shared contact's name in Telegram channel (#10856) # Pull Request Template ## Description This PR adds the ability to see the shared contact name in Telegram channels. ## Type of change - [x] New feature (non-breaking change which adds functionality) ## How Has This Been Tested? **Loom video** https://www.loom.com/share/cd318056ad4d44d4a1fc4b5d4ad38d60?sid=26d833ae-ded9-4cf0-9af7-81eecfa37f19 ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [x] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules --------- Co-authored-by: Shivam Mishra --- .../message/bubbles/BaseAttachment.vue | 4 ++ .../message/bubbles/Contact.vue | 15 +++-- app/models/attachment.rb | 4 +- .../telegram/incoming_message_service.rb | 6 +- .../20250207040150_add_meta_to_attachment.rb | 5 ++ db/schema.rb | 3 +- spec/models/attachment_spec.rb | 61 +++++++++++++++++++ 7 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 db/migrate/20250207040150_add_meta_to_attachment.rb diff --git a/app/javascript/dashboard/components-next/message/bubbles/BaseAttachment.vue b/app/javascript/dashboard/components-next/message/bubbles/BaseAttachment.vue index d494de908..8beceee26 100644 --- a/app/javascript/dashboard/components-next/message/bubbles/BaseAttachment.vue +++ b/app/javascript/dashboard/components-next/message/bubbles/BaseAttachment.vue @@ -10,6 +10,7 @@ defineProps({ iconBgColor: { type: String, default: 'bg-n-alpha-3' }, senderTranslationKey: { type: String, required: true }, content: { type: String, required: true }, + title: { type: String, default: '' }, // Title can be any name, description, etc action: { type: Object, required: true, @@ -48,6 +49,9 @@ const senderName = computed(() => { }} +
+ {{ title }} +
{{ content }}
diff --git a/app/javascript/dashboard/components-next/message/bubbles/Contact.vue b/app/javascript/dashboard/components-next/message/bubbles/Contact.vue index 7230a7e05..dda249559 100644 --- a/app/javascript/dashboard/components-next/message/bubbles/Contact.vue +++ b/app/javascript/dashboard/components-next/message/bubbles/Contact.vue @@ -11,7 +11,7 @@ import { ExceptionWithMessage, } from 'shared/helpers/CustomErrors'; -const { content, attachments } = useMessageContext(); +const { attachments } = useMessageContext(); const $store = useStore(); const { t } = useI18n(); @@ -24,6 +24,12 @@ const phoneNumber = computed(() => { return attachment.value.fallbackTitle; }); +const contactName = computed(() => { + const { meta } = attachment.value ?? {}; + const { firstName, lastName } = meta ?? {}; + return `${firstName ?? ''} ${lastName ?? ''}`.trim(); +}); + const formattedPhoneNumber = computed(() => { return phoneNumber.value.replace(/\s|-|[A-Za-z]/g, ''); }); @@ -32,13 +38,9 @@ const rawPhoneNumber = computed(() => { return phoneNumber.value.replace(/\D/g, ''); }); -const name = computed(() => { - return content.value; -}); - function getContactObject() { const contactItem = { - name: name.value, + name: contactName.value, phone_number: `+${rawPhoneNumber.value}`, }; return contactItem; @@ -99,6 +101,7 @@ const action = computed(() => ({ icon="i-teenyicons-user-circle-solid" icon-bg-color="bg-[#D6409F]" sender-translation-key="CONVERSATION.SHARED_ATTACHMENT.CONTACT" + :title="contactName" :content="phoneNumber" :action="formattedPhoneNumber ? action : null" /> diff --git a/app/models/attachment.rb b/app/models/attachment.rb index 65e56a21f..0bfd9a978 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -9,6 +9,7 @@ # external_url :string # fallback_title :string # file_type :integer default("image") +# meta :jsonb # created_at :datetime not null # updated_at :datetime not null # account_id :integer not null @@ -116,7 +117,8 @@ class Attachment < ApplicationRecord def contact_metadata { - fallback_title: fallback_title + fallback_title: fallback_title, + meta: meta || {} } end diff --git a/app/services/telegram/incoming_message_service.rb b/app/services/telegram/incoming_message_service.rb index d39005030..e337a03f6 100644 --- a/app/services/telegram/incoming_message_service.rb +++ b/app/services/telegram/incoming_message_service.rb @@ -143,7 +143,11 @@ class Telegram::IncomingMessageService @message.attachments.new( account_id: @message.account_id, file_type: :contact, - fallback_title: contact_card['phone_number'].to_s + fallback_title: contact_card['phone_number'].to_s, + meta: { + first_name: contact_card['first_name'], + last_name: contact_card['last_name'] + } ) end diff --git a/db/migrate/20250207040150_add_meta_to_attachment.rb b/db/migrate/20250207040150_add_meta_to_attachment.rb new file mode 100644 index 000000000..32188b4d7 --- /dev/null +++ b/db/migrate/20250207040150_add_meta_to_attachment.rb @@ -0,0 +1,5 @@ +class AddMetaToAttachment < ActiveRecord::Migration[7.0] + def change + add_column :attachments, :meta, :jsonb, default: {} + end +end diff --git a/db/schema.rb b/db/schema.rb index 17e5c46da..6bea44c8b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2025_01_16_061033) do +ActiveRecord::Schema[7.0].define(version: 2025_02_07_040150) do # These extensions should be enabled to support this database enable_extension "pg_stat_statements" enable_extension "pg_trgm" @@ -174,6 +174,7 @@ ActiveRecord::Schema[7.0].define(version: 2025_01_16_061033) do t.datetime "updated_at", precision: nil, null: false t.string "fallback_title" t.string "extension" + t.jsonb "meta", default: {} t.index ["account_id"], name: "index_attachments_on_account_id" t.index ["message_id"], name: "index_attachments_on_message_id" end diff --git a/spec/models/attachment_spec.rb b/spec/models/attachment_spec.rb index b1d19bd0e..241125538 100644 --- a/spec/models/attachment_spec.rb +++ b/spec/models/attachment_spec.rb @@ -67,4 +67,65 @@ RSpec.describe Attachment do expect(message.attachments.first.push_event_data[:data_url]).not_to eq message.attachments.first.external_url end end + + describe 'meta data handling' do + let(:message) { create(:message) } + + context 'when attachment is a contact type' do + let(:contact_attachment) do + message.attachments.create!( + account_id: message.account_id, + file_type: :contact, + fallback_title: '+1234567890', + meta: { + first_name: 'John', + last_name: 'Doe' + } + ) + end + + it 'stores and retrieves meta data correctly' do + expect(contact_attachment.meta['first_name']).to eq('John') + expect(contact_attachment.meta['last_name']).to eq('Doe') + end + + it 'includes meta data in push_event_data' do + event_data = contact_attachment.push_event_data + expect(event_data[:meta]).to eq({ + 'first_name' => 'John', + 'last_name' => 'Doe' + }) + end + + it 'returns empty hash for meta if not set' do + attachment = message.attachments.create!( + account_id: message.account_id, + file_type: :contact, + fallback_title: '+1234567890' + ) + expect(attachment.push_event_data[:meta]).to eq({}) + end + end + + context 'when meta is used with other file types' do + let(:image_attachment) do + attachment = message.attachments.new( + account_id: message.account_id, + file_type: :image, + meta: { description: 'Test image' } + ) + attachment.file.attach( + io: Rails.root.join('spec/assets/avatar.png').open, + filename: 'avatar.png', + content_type: 'image/png' + ) + attachment.save! + attachment + end + + it 'preserves meta data with file attachments' do + expect(image_attachment.meta['description']).to eq('Test image') + end + end + end end From c8387799323798a1a03f60cc53721872e1c02c81 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 12 Feb 2025 06:06:20 +0530 Subject: [PATCH 06/58] feat: Use feature flags across the routes (#10797) --- .../routes/dashboard/settings/agentBots/agentBot.routes.js | 4 ++++ .../routes/dashboard/settings/agents/agent.routes.js | 2 ++ .../dashboard/settings/attributes/attributes.routes.js | 2 ++ .../routes/dashboard/settings/auditlogs/audit.routes.js | 2 ++ .../dashboard/settings/automation/automation.routes.js | 2 ++ .../routes/dashboard/settings/canned/canned.routes.js | 2 ++ .../dashboard/settings/customRoles/customRole.routes.js | 2 ++ .../routes/dashboard/settings/inbox/inbox.routes.js | 7 +++++++ .../dashboard/settings/integrations/integrations.routes.js | 6 ++++++ .../routes/dashboard/settings/labels/labels.routes.js | 2 ++ .../routes/dashboard/settings/macros/macros.routes.js | 4 ++++ .../dashboard/routes/dashboard/settings/sla/sla.routes.js | 3 +++ .../routes/dashboard/settings/teams/teams.routes.js | 2 +- 13 files changed, 39 insertions(+), 1 deletion(-) diff --git a/app/javascript/dashboard/routes/dashboard/settings/agentBots/agentBot.routes.js b/app/javascript/dashboard/routes/dashboard/settings/agentBots/agentBot.routes.js index 5d93ea01d..b3942d0fe 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/agentBots/agentBot.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/agentBots/agentBot.routes.js @@ -1,3 +1,4 @@ +import { FEATURE_FLAGS } from '../../../../featureFlags'; import Bot from './Index.vue'; import CsmlEditBot from './csml/Edit.vue'; import CsmlNewBot from './csml/New.vue'; @@ -23,6 +24,7 @@ export default { name: 'agent_bots', component: Bot, meta: { + featureFlag: FEATURE_FLAGS.AGENT_BOTS, permissions: ['administrator'], }, }, @@ -31,6 +33,7 @@ export default { name: 'agent_bots_csml_new', component: CsmlNewBot, meta: { + featureFlag: FEATURE_FLAGS.AGENT_BOTS, permissions: ['administrator'], }, }, @@ -39,6 +42,7 @@ export default { name: 'agent_bots_csml_edit', component: CsmlEditBot, meta: { + featureFlag: FEATURE_FLAGS.AGENT_BOTS, permissions: ['administrator'], }, }, diff --git a/app/javascript/dashboard/routes/dashboard/settings/agents/agent.routes.js b/app/javascript/dashboard/routes/dashboard/settings/agents/agent.routes.js index 0e649fabe..e365d8e73 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/agents/agent.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/agents/agent.routes.js @@ -1,3 +1,4 @@ +import { FEATURE_FLAGS } from '../../../../featureFlags'; import { frontendURL } from '../../../../helper/URLHelper'; import SettingsWrapper from '../SettingsWrapper.vue'; import AgentHome from './Index.vue'; @@ -19,6 +20,7 @@ export default { name: 'agent_list', component: AgentHome, meta: { + featureFlag: FEATURE_FLAGS.AGENT_MANAGEMENT, permissions: ['administrator'], }, }, diff --git a/app/javascript/dashboard/routes/dashboard/settings/attributes/attributes.routes.js b/app/javascript/dashboard/routes/dashboard/settings/attributes/attributes.routes.js index f74727059..bd9183572 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/attributes/attributes.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/attributes/attributes.routes.js @@ -1,3 +1,4 @@ +import { FEATURE_FLAGS } from '../../../../featureFlags'; import { frontendURL } from '../../../../helper/URLHelper'; import SettingsWrapper from '../SettingsWrapper.vue'; import AttributesHome from './Index.vue'; @@ -19,6 +20,7 @@ export default { name: 'attributes_list', component: AttributesHome, meta: { + featureFlag: FEATURE_FLAGS.CUSTOM_ATTRIBUTES, permissions: ['administrator'], }, }, diff --git a/app/javascript/dashboard/routes/dashboard/settings/auditlogs/audit.routes.js b/app/javascript/dashboard/routes/dashboard/settings/auditlogs/audit.routes.js index 4d9e5d9ce..545c94eeb 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/auditlogs/audit.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/auditlogs/audit.routes.js @@ -1,3 +1,4 @@ +import { FEATURE_FLAGS } from '../../../../featureFlags'; import { frontendURL } from '../../../../helper/URLHelper'; import SettingsWrapper from '../SettingsWrapper.vue'; @@ -19,6 +20,7 @@ export default { path: 'list', name: 'auditlogs_list', meta: { + featureFlag: FEATURE_FLAGS.AUDIT_LOGS, permissions: ['administrator'], }, component: AuditLogsHome, diff --git a/app/javascript/dashboard/routes/dashboard/settings/automation/automation.routes.js b/app/javascript/dashboard/routes/dashboard/settings/automation/automation.routes.js index 302e476bb..81cfc6cc4 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/automation/automation.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/automation/automation.routes.js @@ -1,3 +1,4 @@ +import { FEATURE_FLAGS } from '../../../../featureFlags'; import { frontendURL } from '../../../../helper/URLHelper'; import SettingsWrapper from '../SettingsWrapper.vue'; import Automation from './Index.vue'; @@ -19,6 +20,7 @@ export default { name: 'automation_list', component: Automation, meta: { + featureFlag: FEATURE_FLAGS.AUTOMATIONS, permissions: ['administrator'], }, }, diff --git a/app/javascript/dashboard/routes/dashboard/settings/canned/canned.routes.js b/app/javascript/dashboard/routes/dashboard/settings/canned/canned.routes.js index 600d2664b..f9dbb6417 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/canned/canned.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/canned/canned.routes.js @@ -1,3 +1,4 @@ +import { FEATURE_FLAGS } from '../../../../featureFlags'; import { frontendURL } from '../../../../helper/URLHelper'; import { ROLES, @@ -22,6 +23,7 @@ export default { path: 'list', name: 'canned_list', meta: { + featureFlag: FEATURE_FLAGS.CANNED_RESPONSES, permissions: [...ROLES, ...CONVERSATION_PERMISSIONS], }, component: CannedHome, diff --git a/app/javascript/dashboard/routes/dashboard/settings/customRoles/customRole.routes.js b/app/javascript/dashboard/routes/dashboard/settings/customRoles/customRole.routes.js index af2fc43ae..361231e23 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/customRoles/customRole.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/customRoles/customRole.routes.js @@ -1,3 +1,4 @@ +import { FEATURE_FLAGS } from '../../../../featureFlags'; import { frontendURL } from 'dashboard/helper/URLHelper'; import SettingsWrapper from '../SettingsWrapper.vue'; @@ -17,6 +18,7 @@ export default { path: 'list', name: 'custom_roles_list', meta: { + featureFlag: FEATURE_FLAGS.CUSTOM_ROLES, permissions: ['administrator'], }, component: CustomRolesHome, diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/inbox.routes.js b/app/javascript/dashboard/routes/dashboard/settings/inbox/inbox.routes.js index aa1115a06..e837c68de 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/inbox.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/inbox.routes.js @@ -1,3 +1,4 @@ +import { FEATURE_FLAGS } from '../../../../featureFlags'; import { frontendURL } from '../../../../helper/URLHelper'; import ChannelFactory from './ChannelFactory.vue'; @@ -27,6 +28,7 @@ export default { name: 'settings_inbox_list', component: InboxHome, meta: { + featureFlag: FEATURE_FLAGS.INBOX_MANAGEMENT, permissions: ['administrator'], }, }, @@ -55,6 +57,7 @@ export default { name: 'settings_inbox_new', component: ChannelList, meta: { + featureFlag: FEATURE_FLAGS.INBOX_MANAGEMENT, permissions: ['administrator'], }, }, @@ -63,6 +66,7 @@ export default { name: 'settings_inbox_finish', component: FinishSetup, meta: { + featureFlag: FEATURE_FLAGS.INBOX_MANAGEMENT, permissions: ['administrator'], }, }, @@ -71,6 +75,7 @@ export default { name: 'settings_inboxes_page_channel', component: ChannelFactory, meta: { + featureFlag: FEATURE_FLAGS.INBOX_MANAGEMENT, permissions: ['administrator'], }, props: route => { @@ -81,6 +86,7 @@ export default { path: ':inbox_id/agents', name: 'settings_inboxes_add_agents', meta: { + featureFlag: FEATURE_FLAGS.INBOX_MANAGEMENT, permissions: ['administrator'], }, component: AddAgents, @@ -92,6 +98,7 @@ export default { name: 'settings_inbox_show', component: Settings, meta: { + featureFlag: FEATURE_FLAGS.INBOX_MANAGEMENT, permissions: ['administrator'], }, }, diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrations/integrations.routes.js b/app/javascript/dashboard/routes/dashboard/settings/integrations/integrations.routes.js index 3bb3e4708..a2ec06ae0 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/integrations/integrations.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/integrations/integrations.routes.js @@ -1,3 +1,4 @@ +import { FEATURE_FLAGS } from '../../../../featureFlags'; import { frontendURL } from '../../../../helper/URLHelper'; import SettingsWrapper from '../SettingsWrapper.vue'; import IntegrationHooks from './IntegrationHooks.vue'; @@ -19,6 +20,7 @@ export default { name: 'settings_applications', component: Index, meta: { + featureFlag: FEATURE_FLAGS.INTEGRATIONS, permissions: ['administrator'], }, }, @@ -27,6 +29,7 @@ export default { component: DashboardApps, name: 'settings_integrations_dashboard_apps', meta: { + featureFlag: FEATURE_FLAGS.INTEGRATIONS, permissions: ['administrator'], }, }, @@ -35,6 +38,7 @@ export default { component: Webhook, name: 'settings_integrations_webhook', meta: { + featureFlag: FEATURE_FLAGS.INTEGRATIONS, permissions: ['administrator'], }, }, @@ -62,6 +66,7 @@ export default { name: 'settings_integrations_slack', component: Slack, meta: { + featureFlag: FEATURE_FLAGS.INTEGRATIONS, permissions: ['administrator'], }, props: route => ({ code: route.query.code }), @@ -71,6 +76,7 @@ export default { name: 'settings_applications_integration', component: IntegrationHooks, meta: { + featureFlag: FEATURE_FLAGS.INTEGRATIONS, permissions: ['administrator'], }, props: route => ({ diff --git a/app/javascript/dashboard/routes/dashboard/settings/labels/labels.routes.js b/app/javascript/dashboard/routes/dashboard/settings/labels/labels.routes.js index ed5a504ab..2cd258902 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/labels/labels.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/labels/labels.routes.js @@ -1,3 +1,4 @@ +import { FEATURE_FLAGS } from '../../../../featureFlags'; import { frontendURL } from '../../../../helper/URLHelper'; import SettingsWrapper from '../SettingsWrapper.vue'; @@ -23,6 +24,7 @@ export default { path: 'list', name: 'labels_list', meta: { + featureFlag: FEATURE_FLAGS.LABELS, permissions: ['administrator'], }, component: Index, diff --git a/app/javascript/dashboard/routes/dashboard/settings/macros/macros.routes.js b/app/javascript/dashboard/routes/dashboard/settings/macros/macros.routes.js index e1d4729e6..c45775fe9 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/macros/macros.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/macros/macros.routes.js @@ -1,3 +1,4 @@ +import { FEATURE_FLAGS } from '../../../../featureFlags'; import { frontendURL } from 'dashboard/helper/URLHelper'; import { @@ -20,6 +21,7 @@ export default { name: 'macros_wrapper', component: Macros, meta: { + featureFlag: FEATURE_FLAGS.MACROS, permissions: [...ROLES, ...CONVERSATION_PERMISSIONS], }, }, @@ -41,6 +43,7 @@ export default { name: 'macros_edit', component: MacroEditor, meta: { + featureFlag: FEATURE_FLAGS.MACROS, permissions: [...ROLES, ...CONVERSATION_PERMISSIONS], }, }, @@ -49,6 +52,7 @@ export default { name: 'macros_new', component: MacroEditor, meta: { + featureFlag: FEATURE_FLAGS.MACROS, permissions: [...ROLES, ...CONVERSATION_PERMISSIONS], }, }, diff --git a/app/javascript/dashboard/routes/dashboard/settings/sla/sla.routes.js b/app/javascript/dashboard/routes/dashboard/settings/sla/sla.routes.js index 6955775b9..50ad28472 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/sla/sla.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/sla/sla.routes.js @@ -1,3 +1,4 @@ +import { FEATURE_FLAGS } from '../../../../featureFlags'; import { frontendURL } from '../../../../helper/URLHelper'; import SettingsWrapper from '../SettingsWrapper.vue'; @@ -14,6 +15,7 @@ export default { path: '', name: 'sla_wrapper', meta: { + featureFlag: FEATURE_FLAGS.SLA, permissions: ['administrator'], }, redirect: to => { @@ -24,6 +26,7 @@ export default { path: 'list', name: 'sla_list', meta: { + featureFlag: FEATURE_FLAGS.SLA, permissions: ['administrator'], }, component: Index, diff --git a/app/javascript/dashboard/routes/dashboard/settings/teams/teams.routes.js b/app/javascript/dashboard/routes/dashboard/settings/teams/teams.routes.js index d360573a5..39dc603cf 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/teams/teams.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/teams/teams.routes.js @@ -1,5 +1,5 @@ import { frontendURL } from '../../../../helper/URLHelper'; -import { FEATURE_FLAGS } from 'dashboard/featureFlags'; +import { FEATURE_FLAGS } from '../../../../featureFlags'; import TeamsIndex from './Index.vue'; import CreateStepWrap from './Create/Index.vue'; From b3f616da76e68fcdf90f017be4ee1e6e45f7224b Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 12 Feb 2025 11:52:01 +0530 Subject: [PATCH 07/58] feat: upgrade utils (#10884) --- package.json | 2 +- pnpm-lock.yaml | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index aefa5439d..5e026a488 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@breezystack/lamejs": "^1.2.7", "@chatwoot/ninja-keys": "1.2.3", "@chatwoot/prosemirror-schema": "1.1.1-next", - "@chatwoot/utils": "^0.0.38", + "@chatwoot/utils": "^0.0.39", "@formkit/core": "^1.6.7", "@formkit/vue": "^1.6.7", "@hcaptcha/vue3-hcaptcha": "^1.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6bbf22593..bb3403914 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,8 +23,8 @@ importers: specifier: 1.1.1-next version: 1.1.1-next '@chatwoot/utils': - specifier: ^0.0.38 - version: 0.0.38 + specifier: ^0.0.39 + version: 0.0.39 '@formkit/core': specifier: ^1.6.7 version: 1.6.7 @@ -397,8 +397,8 @@ packages: '@chatwoot/prosemirror-schema@1.1.1-next': resolution: {integrity: sha512-/M2qZ+ZF7GlQNt1riwVP499fvp3hxSqd5iy8hxyF9pkj9qQ+OKYn5JK+v3qwwqQY3IxhmNOn1Lp6tm7vstrd9Q==} - '@chatwoot/utils@0.0.38': - resolution: {integrity: sha512-6CTvuueBQLZJcm++pI2ZBY8Pp7OP3WzPCYyXoCagl8ZLpOfpjyVkLx9fc81falOoaVa/r+7EZ85Cv7vkT0ZyQw==} + '@chatwoot/utils@0.0.39': + resolution: {integrity: sha512-m/mt8WhhgEBj0kyfxCQjwyVLVj4Eyb1QRvs1cckL82b6xjyW69zicsVVpTIGd2DLTVdGPu1NzLPKKPaTOnIZgQ==} engines: {node: '>=10'} '@codemirror/commands@6.7.0': @@ -5133,7 +5133,7 @@ snapshots: prosemirror-utils: 1.2.2(prosemirror-model@1.22.3)(prosemirror-state@1.4.3) prosemirror-view: 1.34.1 - '@chatwoot/utils@0.0.38': + '@chatwoot/utils@0.0.39': dependencies: date-fns: 2.30.0 @@ -6599,7 +6599,7 @@ snapshots: '@videojs/http-streaming@2.13.1(video.js@7.18.1)': dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.7 '@videojs/vhs-utils': 3.0.4 aes-decrypter: 3.1.2 global: 4.4.0 @@ -6610,19 +6610,19 @@ snapshots: '@videojs/vhs-utils@3.0.4': dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.7 global: 4.4.0 url-toolkit: 2.2.5 '@videojs/vhs-utils@3.0.5': dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.7 global: 4.4.0 url-toolkit: 2.2.5 '@videojs/xhr@2.6.0': dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.7 global: 4.4.0 is-function: 1.0.2 @@ -6905,7 +6905,7 @@ snapshots: aes-decrypter@3.1.2: dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.7 '@videojs/vhs-utils': 3.0.5 global: 4.4.0 pkcs7: 1.0.4 @@ -8678,7 +8678,7 @@ snapshots: m3u8-parser@4.7.0: dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.7 '@videojs/vhs-utils': 3.0.5 global: 4.4.0 @@ -8813,7 +8813,7 @@ snapshots: mpd-parser@0.21.0: dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.7 '@videojs/vhs-utils': 3.0.5 '@xmldom/xmldom': 0.7.13 global: 4.4.0 @@ -8832,7 +8832,7 @@ snapshots: mux.js@6.0.1: dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.7 global: 4.4.0 mz@2.7.0: @@ -9066,7 +9066,7 @@ snapshots: pkcs7@1.0.4: dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.7 pkg-dir@7.0.0: dependencies: From cd80bd07ca9454ce3ff9e009e376c9ac13f50994 Mon Sep 17 00:00:00 2001 From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Date: Wed, 12 Feb 2025 12:31:54 +0530 Subject: [PATCH 08/58] fix: TypeError - Cannot read properties of null (reading 'name') (#10887) --- .../components-next/message/bubbles/BaseAttachment.vue | 2 +- .../dashboard/components-next/message/bubbles/Dyte.vue | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/javascript/dashboard/components-next/message/bubbles/BaseAttachment.vue b/app/javascript/dashboard/components-next/message/bubbles/BaseAttachment.vue index 8beceee26..e10d68d64 100644 --- a/app/javascript/dashboard/components-next/message/bubbles/BaseAttachment.vue +++ b/app/javascript/dashboard/components-next/message/bubbles/BaseAttachment.vue @@ -24,7 +24,7 @@ const { sender } = useMessageContext(); const { t } = useI18n(); const senderName = computed(() => { - return sender?.value.name; + return sender?.value?.name || ''; }); diff --git a/app/javascript/dashboard/components-next/message/bubbles/Dyte.vue b/app/javascript/dashboard/components-next/message/bubbles/Dyte.vue index d1fa326b4..61d3cf31d 100644 --- a/app/javascript/dashboard/components-next/message/bubbles/Dyte.vue +++ b/app/javascript/dashboard/components-next/message/bubbles/Dyte.vue @@ -9,7 +9,7 @@ import { useI18n } from 'vue-i18n'; import { useMessageContext } from '../provider.js'; import BaseAttachmentBubble from './BaseAttachment.vue'; -const { contentAttributes } = useMessageContext(); +const { content, sender, contentAttributes } = useMessageContext(); const { t } = useI18n(); @@ -53,6 +53,11 @@ const action = computed(() => ({ sender-translation-key="CONVERSATION.SHARED_ATTACHMENT.MEETING" :action="action" > +
+ + + {{ content }} +