chore: Add open conversation option (#11828)
Added conversation_status, assignee_id, team_id, and priority to the message_created event to allow users to build automations based on conversation details. Also introduced a new open_conversation action. --------- Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This commit is contained in:
@@ -126,6 +126,7 @@ const validateSingleAction = action => {
|
|||||||
'snooze_conversation',
|
'snooze_conversation',
|
||||||
'resolve_conversation',
|
'resolve_conversation',
|
||||||
'remove_assigned_team',
|
'remove_assigned_team',
|
||||||
|
'open_conversation',
|
||||||
];
|
];
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -147,7 +147,8 @@
|
|||||||
"SEND_ATTACHMENT": "Send Attachment",
|
"SEND_ATTACHMENT": "Send Attachment",
|
||||||
"SEND_MESSAGE": "Send a Message",
|
"SEND_MESSAGE": "Send a Message",
|
||||||
"CHANGE_PRIORITY": "Change Priority",
|
"CHANGE_PRIORITY": "Change Priority",
|
||||||
"ADD_SLA": "Add SLA"
|
"ADD_SLA": "Add SLA",
|
||||||
|
"OPEN_CONVERSATION": "Open conversation"
|
||||||
},
|
},
|
||||||
"ATTRIBUTES": {
|
"ATTRIBUTES": {
|
||||||
"MESSAGE_TYPE": "Message Type",
|
"MESSAGE_TYPE": "Message Type",
|
||||||
|
|||||||
@@ -32,6 +32,30 @@ export const AUTOMATIONS = {
|
|||||||
inputType: 'multi_select',
|
inputType: 'multi_select',
|
||||||
filterOperators: OPERATOR_TYPES_1,
|
filterOperators: OPERATOR_TYPES_1,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'status',
|
||||||
|
name: 'STATUS',
|
||||||
|
inputType: 'multi_select',
|
||||||
|
filterOperators: OPERATOR_TYPES_1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'assignee_id',
|
||||||
|
name: 'ASSIGNEE_NAME',
|
||||||
|
inputType: 'search_select',
|
||||||
|
filterOperators: OPERATOR_TYPES_3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'team_id',
|
||||||
|
name: 'TEAM_NAME',
|
||||||
|
inputType: 'search_select',
|
||||||
|
filterOperators: OPERATOR_TYPES_3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'priority',
|
||||||
|
name: 'PRIORITY',
|
||||||
|
inputType: 'multi_select',
|
||||||
|
filterOperators: OPERATOR_TYPES_1,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'conversation_language',
|
key: 'conversation_language',
|
||||||
name: 'CONVERSATION_LANGUAGE',
|
name: 'CONVERSATION_LANGUAGE',
|
||||||
@@ -82,7 +106,10 @@ export const AUTOMATIONS = {
|
|||||||
key: 'snooze_conversation',
|
key: 'snooze_conversation',
|
||||||
name: 'SNOOZE_CONVERSATION',
|
name: 'SNOOZE_CONVERSATION',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'open_conversation',
|
||||||
|
name: 'OPEN_CONVERSATION',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'resolve_conversation',
|
key: 'resolve_conversation',
|
||||||
name: 'RESOLVE_CONVERSATION',
|
name: 'RESOLVE_CONVERSATION',
|
||||||
@@ -508,6 +535,11 @@ export const AUTOMATION_ACTION_TYPES = [
|
|||||||
label: 'RESOLVE_CONVERSATION',
|
label: 'RESOLVE_CONVERSATION',
|
||||||
inputType: null,
|
inputType: null,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'open_conversation',
|
||||||
|
label: 'OPEN_CONVERSATION',
|
||||||
|
inputType: null,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'send_webhook_event',
|
key: 'send_webhook_event',
|
||||||
label: 'SEND_WEBHOOK_EVENT',
|
label: 'SEND_WEBHOOK_EVENT',
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class AutomationRule < ApplicationRecord
|
|||||||
|
|
||||||
def actions_attributes
|
def actions_attributes
|
||||||
%w[send_message add_label remove_label send_email_to_team assign_team assign_agent send_webhook_event mute_conversation
|
%w[send_message add_label remove_label send_email_to_team assign_team assign_agent send_webhook_event mute_conversation
|
||||||
send_attachment change_status resolve_conversation snooze_conversation change_priority send_email_transcript].freeze
|
send_attachment change_status resolve_conversation open_conversation snooze_conversation change_priority send_email_transcript].freeze
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_base_data
|
def file_base_data
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ class ActionService
|
|||||||
@conversation.resolved!
|
@conversation.resolved!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def open_conversation(_params)
|
||||||
|
@conversation.open!
|
||||||
|
end
|
||||||
|
|
||||||
def change_status(status)
|
def change_status(status)
|
||||||
@conversation.update!(status: status[0])
|
@conversation.update!(status: status[0])
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -171,6 +171,16 @@ describe AutomationRuleListener do
|
|||||||
listener.message_created(event)
|
listener.message_created(event)
|
||||||
expect(AutomationRules::ActionService).not_to have_received(:new).with(automation_rule, account, conversation)
|
expect(AutomationRules::ActionService).not_to have_received(:new).with(automation_rule, account, conversation)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'passes conversation attributes to conditions filter service' do
|
||||||
|
conversation.update!(status: :open, priority: :high)
|
||||||
|
listener.message_created(event)
|
||||||
|
expect(AutomationRules::ConditionsFilterService).to have_received(:new).with(
|
||||||
|
automation_rule,
|
||||||
|
conversation,
|
||||||
|
{ message: message, changed_attributes: { content: %w[nil Hi] } }
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -14,6 +14,17 @@ describe ActionService do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#open_conversation' do
|
||||||
|
let(:conversation) { create(:conversation, status: :resolved) }
|
||||||
|
let(:action_service) { described_class.new(conversation) }
|
||||||
|
|
||||||
|
it 'opens the conversation' do
|
||||||
|
expect(conversation.status).to eq('resolved')
|
||||||
|
action_service.open_conversation(nil)
|
||||||
|
expect(conversation.reload.status).to eq('open')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#change_priority' do
|
describe '#change_priority' do
|
||||||
let(:conversation) { create(:conversation) }
|
let(:conversation) { create(:conversation) }
|
||||||
let(:action_service) { described_class.new(conversation) }
|
let(:action_service) { described_class.new(conversation) }
|
||||||
|
|||||||
@@ -110,6 +110,29 @@ RSpec.describe AutomationRules::ConditionsFilterService do
|
|||||||
expect(described_class.new(rule, conversation, { message: message, changed_attributes: {} }).perform).to be(false)
|
expect(described_class.new(rule, conversation, { message: message, changed_attributes: {} }).perform).to be(false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when filtering messages based on conversation attributes' do
|
||||||
|
let(:conversation) { create(:conversation, account: account, status: :open, priority: :high) }
|
||||||
|
let(:message) do
|
||||||
|
create(:message, account: account, conversation: conversation, content: 'Test message',
|
||||||
|
inbox: conversation.inbox, message_type: :incoming)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'will return true when conversation status matches' do
|
||||||
|
rule.update(conditions: [{ 'values': ['open'], 'attribute_key': 'status', 'query_operator': nil, 'filter_operator': 'equal_to' }])
|
||||||
|
expect(described_class.new(rule, conversation, { message: message, changed_attributes: {} }).perform).to be(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'will return false when conversation status does not match' do
|
||||||
|
rule.update(conditions: [{ 'values': ['resolved'], 'attribute_key': 'status', 'query_operator': nil, 'filter_operator': 'equal_to' }])
|
||||||
|
expect(described_class.new(rule, conversation, { message: message, changed_attributes: {} }).perform).to be(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'will return true when conversation priority matches' do
|
||||||
|
rule.update(conditions: [{ 'values': ['high'], 'attribute_key': 'priority', 'query_operator': nil, 'filter_operator': 'equal_to' }])
|
||||||
|
expect(described_class.new(rule, conversation, { message: message, changed_attributes: {} }).perform).to be(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user