Merge branch 'develop' into feat/shopify-app-store-install-flow
This commit is contained in:
@@ -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,
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -458,6 +458,9 @@
|
||||
"INSTAGRAM": {
|
||||
"PLACEHOLDER": "Add Instagram"
|
||||
},
|
||||
"TELEGRAM": {
|
||||
"PLACEHOLDER": "Add Telegram"
|
||||
},
|
||||
"TIKTOK": {
|
||||
"PLACEHOLDER": "Add TikTok"
|
||||
},
|
||||
|
||||
@@ -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 || '',
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
@@ -14,7 +14,7 @@ module MessageFilterHelpers
|
||||
end
|
||||
|
||||
def notifiable?
|
||||
incoming? || outgoing?
|
||||
(incoming? || outgoing?) && !private?
|
||||
end
|
||||
|
||||
def conversation_transcriptable?
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -142,7 +142,24 @@ describe NotificationListener do
|
||||
expect(first_agent.notifications.first.notification_type).to eq('conversation_mention')
|
||||
end
|
||||
|
||||
it 'will not create duplicate new message notifications for assignment & participation' do
|
||||
it 'will create a mention notification when a user is mentioned in a private note' do
|
||||
create(:inbox_member, user: first_agent, inbox: inbox)
|
||||
|
||||
message = build(
|
||||
:message,
|
||||
conversation: conversation,
|
||||
account: account,
|
||||
content: "hey [#{first_agent.name}](mention://user/#{first_agent.id}/#{first_agent.name})",
|
||||
private: true
|
||||
)
|
||||
event = Events::Base.new(event_name, Time.zone.now, message: message)
|
||||
listener.message_created(event)
|
||||
|
||||
expect(first_agent.notifications.count).to eq(1)
|
||||
expect(first_agent.notifications.first.notification_type).to eq('conversation_mention')
|
||||
end
|
||||
|
||||
it 'will not create new message notifications for private messages without mentions' do
|
||||
create(:inbox_member, user: first_agent, inbox: inbox)
|
||||
conversation.update(assignee: first_agent)
|
||||
# participants is created by async job. so creating it directly for testcase
|
||||
@@ -160,8 +177,7 @@ describe NotificationListener do
|
||||
listener.message_created(event)
|
||||
|
||||
expect(conversation.conversation_participants.map(&:user)).to include(first_agent)
|
||||
expect(first_agent.notifications.count).to eq(1)
|
||||
expect(first_agent.notifications.first.notification_type).to eq('assigned_conversation_new_message')
|
||||
expect(first_agent.notifications.count).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -2,11 +2,17 @@ require 'rails_helper'
|
||||
|
||||
describe Messages::NewMessageNotificationService do
|
||||
context 'when message is not notifiable' do
|
||||
it 'will not create any notifications' do
|
||||
it 'will not create any notifications for activity messages' do
|
||||
message = build(:message, message_type: :activity)
|
||||
expect(NotificationBuilder).not_to receive(:new)
|
||||
described_class.new(message: message).perform
|
||||
end
|
||||
|
||||
it 'will not create any notifications for private messages' do
|
||||
message = build(:message, message_type: :outgoing, private: true)
|
||||
expect(NotificationBuilder).not_to receive(:new)
|
||||
described_class.new(message: message).perform
|
||||
end
|
||||
end
|
||||
|
||||
context 'when message is notifiable' do
|
||||
|
||||
Reference in New Issue
Block a user