From 5b167b5b5b9de36ee1afaec3748a43e5ba08537d Mon Sep 17 00:00:00 2001 From: Muhsin Keloth Date: Mon, 23 Feb 2026 19:26:45 +0400 Subject: [PATCH 1/2] fix(contacts): Show telegram id in contact details form (#13611) ## Summary This change fixes a mismatch in contact details where Telegram data could be shown in the contact profile/social icon area but was not available in the editable contact form. ### What changed - Added Telegram to the social links section of the next-gen contact form so agents can view and edit it alongside Facebook, Instagram, TikTok, Twitter, GitHub, and LinkedIn. - Added Telegram support to the legacy conversation contact edit form for parity between both contact editing experiences. - Mapped social_telegram_user_name into the editable socialProfiles payload when preparing contact form state, so Telegram usernames sourced from channel attributes are visible in the form. - Updated the conversation contact social profile merge logic so Telegram display prefers an explicitly saved social profile value and falls back to social_telegram_user_name when needed. - Added the missing English i18n placeholder: Add Telegram. ### Why Without this, users could see Telegram info in some contact views but could not reliably edit it in contact details, creating inconsistent behavior between display and edit states. --------- Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> --- .../Contacts/ContactsForm/ContactsForm.vue | 11 ++++++++++- app/javascript/dashboard/i18n/locale/en/contact.json | 3 +++ .../dashboard/conversation/contact/ContactForm.vue | 4 ++++ .../dashboard/conversation/contact/ContactInfo.vue | 8 ++++++-- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactsForm.vue b/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactsForm.vue index 3dc29738e..66296257f 100644 --- a/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactsForm.vue +++ b/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactsForm.vue @@ -44,6 +44,7 @@ const SOCIAL_CONFIG = { LINKEDIN: 'i-ri-linkedin-box-fill', FACEBOOK: 'i-ri-facebook-circle-fill', INSTAGRAM: 'i-ri-instagram-line', + TELEGRAM: 'i-ri-telegram-fill', TIKTOK: 'i-ri-tiktok-fill', TWITTER: 'i-ri-twitter-x-fill', GITHUB: 'i-ri-github-fill', @@ -66,6 +67,7 @@ const defaultState = { facebook: '', github: '', instagram: '', + telegram: '', tiktok: '', linkedin: '', twitter: '', @@ -103,9 +105,13 @@ const prepareStateBasedOnProps = () => { countryCode = '', country = '', city = '', + socialTelegramUserName = '', socialProfiles = {}, } = additionalAttributes || {}; + const telegramUsername = + socialProfiles?.telegram || socialTelegramUserName || ''; + Object.assign(state, { id, name, @@ -119,7 +125,10 @@ const prepareStateBasedOnProps = () => { countryCode, country, city, - socialProfiles, + socialProfiles: { + ...socialProfiles, + telegram: telegramUsername, + }, }, }); }; diff --git a/app/javascript/dashboard/i18n/locale/en/contact.json b/app/javascript/dashboard/i18n/locale/en/contact.json index fe04e5848..0d9f79984 100644 --- a/app/javascript/dashboard/i18n/locale/en/contact.json +++ b/app/javascript/dashboard/i18n/locale/en/contact.json @@ -458,6 +458,9 @@ "INSTAGRAM": { "PLACEHOLDER": "Add Instagram" }, + "TELEGRAM": { + "PLACEHOLDER": "Add Telegram" + }, "TIKTOK": { "PLACEHOLDER": "Add TikTok" }, diff --git a/app/javascript/dashboard/routes/dashboard/conversation/contact/ContactForm.vue b/app/javascript/dashboard/routes/dashboard/conversation/contact/ContactForm.vue index 77d4b9773..d8479c4f2 100644 --- a/app/javascript/dashboard/routes/dashboard/conversation/contact/ContactForm.vue +++ b/app/javascript/dashboard/routes/dashboard/conversation/contact/ContactForm.vue @@ -58,12 +58,14 @@ export default { twitter: '', linkedin: '', github: '', + telegram: '', }, socialProfileKeys: [ { key: 'facebook', prefixURL: 'https://facebook.com/' }, { key: 'twitter', prefixURL: 'https://twitter.com/' }, { key: 'linkedin', prefixURL: 'https://linkedin.com/' }, { key: 'github', prefixURL: 'https://github.com/' }, + { key: 'telegram', prefixURL: 'https://t.me/' }, { key: 'tiktok', prefixURL: 'https://tiktok.com/@' }, ], }; @@ -175,12 +177,14 @@ export default { const { social_profiles: socialProfiles = {}, screen_name: twitterScreenName, + social_telegram_user_name: telegramUserName, } = additionalAttributes; this.socialProfileUserNames = { twitter: socialProfiles.twitter || twitterScreenName || '', facebook: socialProfiles.facebook || '', linkedin: socialProfiles.linkedin || '', github: socialProfiles.github || '', + telegram: socialProfiles.telegram || telegramUserName || '', instagram: socialProfiles.instagram || '', tiktok: socialProfiles.tiktok || '', }; diff --git a/app/javascript/dashboard/routes/dashboard/conversation/contact/ContactInfo.vue b/app/javascript/dashboard/routes/dashboard/conversation/contact/ContactInfo.vue index 7392bea78..3899d1ddf 100644 --- a/app/javascript/dashboard/routes/dashboard/conversation/contact/ContactInfo.vue +++ b/app/javascript/dashboard/routes/dashboard/conversation/contact/ContactInfo.vue @@ -81,10 +81,14 @@ export default { screen_name: twitterScreenName, social_telegram_user_name: telegramUsername, } = this.additionalAttributes; + + const telegram = socialProfiles?.telegram || telegramUsername || ''; + const twitter = socialProfiles?.twitter || twitterScreenName || ''; + return { - twitter: twitterScreenName, - telegram: telegramUsername, ...(socialProfiles || {}), + twitter, + telegram, }; }, // Delete Modal From 2b85275e2693f7ec3b5f03cc7e2e3e5c1b75ba1b Mon Sep 17 00:00:00 2001 From: Tanmay Deep Sharma <32020192+tds-1@users.noreply.github.com> Date: Tue, 24 Feb 2026 13:32:54 +0530 Subject: [PATCH 2/2] feat: show assignment policy name in auto-assignment activity messages (#13598) --- .../concerns/activity_message_handler.rb | 22 +----------- .../assignee_activity_message_handler.rb | 35 +++++++++++++++++++ .../auto_assignment/assignment_service.rb | 4 +++ config/locales/en.yml | 3 ++ 4 files changed, 43 insertions(+), 21 deletions(-) create mode 100644 app/models/concerns/assignee_activity_message_handler.rb diff --git a/app/models/concerns/activity_message_handler.rb b/app/models/concerns/activity_message_handler.rb index c25aba47f..0300bd2d1 100644 --- a/app/models/concerns/activity_message_handler.rb +++ b/app/models/concerns/activity_message_handler.rb @@ -1,6 +1,7 @@ module ActivityMessageHandler extend ActiveSupport::Concern + include AssigneeActivityMessageHandler include PriorityActivityMessageHandler include LabelActivityMessageHandler include SlaActivityMessageHandler @@ -104,27 +105,6 @@ module ActivityMessageHandler content = I18n.t("conversations.activity.#{change_type}", user_name: Current.user.name) ::Conversations::ActivityMessageJob.perform_later(self, activity_message_params(content)) if content end - - def generate_assignee_change_activity_content(user_name) - params = { assignee_name: assignee&.name || '', user_name: user_name } - key = assignee_id ? 'assigned' : 'removed' - key = 'self_assigned' if self_assign? assignee_id - I18n.t("conversations.activity.assignee.#{key}", **params) - end - - def create_assignee_change_activity(user_name) - user_name = activity_message_owner(user_name) - - return unless user_name - - content = generate_assignee_change_activity_content(user_name) - ::Conversations::ActivityMessageJob.perform_later(self, activity_message_params(content)) if content - end - - def activity_message_owner(user_name) - user_name = I18n.t('automation.system_name') if !user_name && Current.executed_by.present? - user_name - end end ActivityMessageHandler.prepend_mod_with('ActivityMessageHandler') diff --git a/app/models/concerns/assignee_activity_message_handler.rb b/app/models/concerns/assignee_activity_message_handler.rb new file mode 100644 index 000000000..ff5516ec9 --- /dev/null +++ b/app/models/concerns/assignee_activity_message_handler.rb @@ -0,0 +1,35 @@ +module AssigneeActivityMessageHandler + extend ActiveSupport::Concern + + private + + def create_assignee_change_activity(user_name) + user_name = activity_message_owner(user_name) + + return unless user_name + + content = generate_assignee_change_activity_content(user_name) + ::Conversations::ActivityMessageJob.perform_later(self, activity_message_params(content)) if content + end + + def generate_assignee_change_activity_content(user_name) + params = { assignee_name: assignee&.name || '', user_name: user_name } + key = assignee_id ? 'assigned' : 'removed' + key = 'self_assigned' if self_assign? assignee_id + I18n.t("conversations.activity.assignee.#{key}", **params) + end + + def activity_message_owner(user_name) + if !user_name && Current.executed_by.present? + user_name = case Current.executed_by + when AssignmentPolicy + I18n.t('auto_assignment.policy_actor', policy_name: Current.executed_by.name) + when Inbox + I18n.t('auto_assignment.default_policy_name') + else + I18n.t('automation.system_name') + end + end + user_name + end +end diff --git a/app/services/auto_assignment/assignment_service.rb b/app/services/auto_assignment/assignment_service.rb index 89eff9d1c..e27f1e829 100644 --- a/app/services/auto_assignment/assignment_service.rb +++ b/app/services/auto_assignment/assignment_service.rb @@ -72,13 +72,17 @@ class AutoAssignment::AssignmentService end def assign_conversation(conversation, agent) + Current.executed_by = inbox.assignment_policy || inbox conversation.update!(assignee: agent) + Current.executed_by = nil rate_limiter = build_rate_limiter(agent) rate_limiter.track_assignment(conversation) dispatch_assignment_event(conversation, agent) true + ensure + Current.executed_by = nil end def dispatch_assignment_event(conversation, agent) diff --git a/config/locales/en.yml b/config/locales/en.yml index 05276009f..9cab941c2 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -438,6 +438,9 @@ en: seconds: one: '%{count} second' other: '%{count} seconds' + auto_assignment: + default_policy_name: 'Default Policy' + policy_actor: 'Automation System via %{policy_name}' automation: system_name: 'Automation System' crm: