chore: Change the conversation bot status to pending (#2677)

fixes: #2649
This commit is contained in:
Sojan Jose 2021-07-21 22:02:43 +05:30 committed by GitHub
parent a0886d37bc
commit a7ca55c080
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 87 additions and 54 deletions

View file

@ -49,7 +49,8 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
def toggle_status
if params[:status]
@conversation.status = params[:status]
status = params[:status] == 'bot' ? 'pending' : params[:status]
@conversation.status = status
@status = @conversation.save
else
@status = @conversation.toggle_status
@ -106,6 +107,9 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
def conversation_params
additional_attributes = params[:additional_attributes]&.permit! || {}
status = params[:status].present? ? { status: params[:status] } : {}
# TODO: temporary fallback for the old bot status in conversation, we will remove after couple of releases
status = { status: 'pending' } if status[:status] == 'bot'
{
account_id: Current.account.id,
inbox_id: @contact_inbox.inbox_id,

View file

@ -24,7 +24,7 @@
{{ this.$t('CONVERSATION.HEADER.REOPEN_ACTION') }}
</woot-button>
<woot-button
v-else-if="isBot"
v-else-if="isPending"
class-names="resolve"
color-scheme="primary"
icon="ion-person"
@ -48,12 +48,12 @@
class="dropdown-pane dropdown-pane--open"
>
<woot-dropdown-menu>
<woot-dropdown-item v-if="!isBot">
<woot-dropdown-item v-if="!isPending">
<woot-button
variant="clear"
@click="() => toggleStatus(STATUS_TYPE.BOT)"
@click="() => toggleStatus(STATUS_TYPE.PENDING)"
>
{{ this.$t('CONVERSATION.RESOLVE_DROPDOWN.OPEN_BOT') }}
{{ this.$t('CONVERSATION.RESOLVE_DROPDOWN.MARK_PENDING') }}
</woot-button>
</woot-dropdown-item>
</woot-dropdown-menu>
@ -91,20 +91,20 @@ export default {
isOpen() {
return this.currentChat.status === wootConstants.STATUS_TYPE.OPEN;
},
isBot() {
return this.currentChat.status === wootConstants.STATUS_TYPE.BOT;
isPending() {
return this.currentChat.status === wootConstants.STATUS_TYPE.PENDING;
},
isResolved() {
return this.currentChat.status === wootConstants.STATUS_TYPE.RESOLVED;
},
buttonClass() {
if (this.isBot) return 'primary';
if (this.isPending) return 'primary';
if (this.isOpen) return 'success';
if (this.isResolved) return 'warning';
return '';
},
showDropDown() {
return !this.isBot;
return !this.isPending;
},
},
methods: {

View file

@ -8,7 +8,7 @@ export default {
STATUS_TYPE: {
OPEN: 'open',
RESOLVED: 'resolved',
BOT: 'bot',
PENDING: 'pending',
},
};
export const DEFAULT_REDIRECT_URL = '/app/';

View file

@ -47,8 +47,8 @@
"VALUE": "resolved"
},
{
"TEXT": "Bot",
"VALUE": "bot"
"TEXT": "Pending",
"VALUE": "pending"
}
],
"ATTACHMENTS": {

View file

@ -41,7 +41,7 @@
"DETAILS": "details"
},
"RESOLVE_DROPDOWN": {
"OPEN_BOT": "Open with bot"
"MARK_PENDING": "Mark as pending"
},
"FOOTER": {
"MSG_INPUT": "Shift + enter for new line. Start with '/' to select a Canned Response.",

View file

@ -7,10 +7,10 @@ jest.mock('widget/helpers/axios');
describe('#actions', () => {
describe('#get attributes', () => {
it('sends mutation if api is success', async () => {
API.get.mockResolvedValue({ data: { id: 1, status: 'bot' } });
API.get.mockResolvedValue({ data: { id: 1, status: 'pending' } });
await actions.getAttributes({ commit });
expect(commit.mock.calls).toEqual([
['SET_CONVERSATION_ATTRIBUTES', { id: 1, status: 'bot' }],
['SET_CONVERSATION_ATTRIBUTES', { id: 1, status: 'pending' }],
['conversation/setMetaUserLastSeenAt', undefined, { root: true }],
]);
});
@ -23,10 +23,10 @@ describe('#actions', () => {
describe('#update attributes', () => {
it('sends correct mutations', () => {
actions.update({ commit }, { id: 1, status: 'bot' });
actions.update({ commit }, { id: 1, status: 'pending' });
expect(commit).toBeCalledWith('UPDATE_CONVERSATION_ATTRIBUTES', {
id: 1,
status: 'bot',
status: 'pending',
});
});
});

View file

@ -4,11 +4,11 @@ describe('#getters', () => {
it('getConversationParams', () => {
const state = {
id: 1,
status: 'bot',
status: 'pending',
};
expect(getters.getConversationParams(state)).toEqual({
id: 1,
status: 'bot',
status: 'pending',
});
});
});

View file

@ -14,7 +14,7 @@ describe('#mutations', () => {
describe('#UPDATE_CONVERSATION_ATTRIBUTES', () => {
it('update status if it is same conversation', () => {
const state = { id: 1, status: 'bot' };
const state = { id: 1, status: 'pending' };
mutations.UPDATE_CONVERSATION_ATTRIBUTES(state, {
id: 1,
status: 'open',
@ -22,12 +22,12 @@ describe('#mutations', () => {
expect(state).toEqual({ id: 1, status: 'open' });
});
it('doesnot update status if it is not the same conversation', () => {
const state = { id: 1, status: 'bot' };
const state = { id: 1, status: 'pending' };
mutations.UPDATE_CONVERSATION_ATTRIBUTES(state, {
id: 2,
status: 'open',
});
expect(state).toEqual({ id: 1, status: 'bot' });
expect(state).toEqual({ id: 1, status: 'pending' });
});
});

View file

@ -1,7 +1,7 @@
class NotificationListener < BaseListener
def conversation_created(event)
conversation, account = extract_conversation_and_account(event)
return if conversation.bot?
return if conversation.pending?
conversation.inbox.members.each do |agent|
NotificationBuilder.new(
@ -17,7 +17,7 @@ class NotificationListener < BaseListener
conversation, account = extract_conversation_and_account(event)
assignee = conversation.assignee
return unless conversation.notifiable_assignee_change?
return if conversation.bot?
return if conversation.pending?
NotificationBuilder.new(
notification_type: 'conversation_assignment',

View file

@ -45,7 +45,7 @@ class Conversation < ApplicationRecord
validates :inbox_id, presence: true
before_validation :validate_additional_attributes
enum status: { open: 0, resolved: 1, bot: 2 }
enum status: { open: 0, resolved: 1, pending: 2 }
scope :latest, -> { order(last_activity_at: :desc) }
scope :unassigned, -> { where(assignee_id: nil) }
@ -64,7 +64,7 @@ class Conversation < ApplicationRecord
has_one :csat_survey_response, dependent: :destroy
has_many :notifications, as: :primary_actor, dependent: :destroy
before_create :set_bot_conversation
before_create :mark_conversation_pending_if_bot
# wanted to change this to after_update commit. But it ended up creating a loop
# reinvestigate in future and identity the implications
@ -91,7 +91,7 @@ class Conversation < ApplicationRecord
def toggle_status
# FIXME: implement state machine with aasm
self.status = open? ? :resolved : :open
self.status = :open if bot?
self.status = :open if pending?
save
end
@ -144,8 +144,9 @@ class Conversation < ApplicationRecord
self.additional_attributes = {} unless additional_attributes.is_a?(Hash)
end
def set_bot_conversation
self.status = :bot if inbox.agent_bot_inbox&.active? || inbox.hooks.pluck(:app_id).include?('dialogflow')
def mark_conversation_pending_if_bot
# TODO: make this an inbox config instead of assuming bot conversations should start as pending
self.status = :pending if inbox.agent_bot_inbox&.active? || inbox.hooks.pluck(:app_id).include?('dialogflow')
end
def notify_conversation_creation

View file

@ -63,7 +63,7 @@ en:
status:
resolved: "Conversation was marked resolved by %{user_name}"
open: "Conversation was reopened by %{user_name}"
bot: "Conversation was transferred to bot by %{user_name}"
pending: "Conversation was marked as pending by %{user_name}"
auto_resolved: "Conversation was marked resolved by system due to %{duration} days of inactivity"
assignee:
self_assigned: "%{user_name} self-assigned this conversation"

View file

@ -5,7 +5,7 @@ class Integrations::Dialogflow::ProcessorService
message = event_data[:message]
return if message.private?
return unless processable_message?(message)
return unless message.conversation.bot?
return unless message.conversation.pending?
response = get_dialogflow_response(message.conversation.contact_inbox.source_id, message_content(message))
process_response(message, response)

View file

@ -32,7 +32,7 @@ RSpec.describe 'API Base', type: :request do
describe 'request with api_access_token for bot' do
let!(:agent_bot) { create(:agent_bot) }
let!(:inbox) { create(:inbox, account: account) }
let!(:conversation) { create(:conversation, account: account, inbox: inbox, assignee: user, status: 'bot') }
let!(:conversation) { create(:conversation, account: account, inbox: inbox, assignee: user, status: 'pending') }
context 'when it is an unauthorized url' do
it 'returns unauthorized' do

View file

@ -200,6 +200,20 @@ RSpec.describe 'Conversations API', type: :request do
end
it 'creates a conversation in specificed status' do
allow(Rails.configuration.dispatcher).to receive(:dispatch)
post "/api/v1/accounts/#{account.id}/conversations",
headers: agent.create_new_auth_token,
params: { source_id: contact_inbox.source_id, status: 'pending' },
as: :json
expect(response).to have_http_status(:success)
response_data = JSON.parse(response.body, symbolize_names: true)
expect(response_data[:status]).to eq('pending')
end
# TODO: remove this spec when we remove the condition check in controller
# Added for backwards compatibility for bot status
it 'creates a conversation as pending if status is specified as bot' do
allow(Rails.configuration.dispatcher).to receive(:dispatch)
post "/api/v1/accounts/#{account.id}/conversations",
headers: agent.create_new_auth_token,
@ -208,7 +222,7 @@ RSpec.describe 'Conversations API', type: :request do
expect(response).to have_http_status(:success)
response_data = JSON.parse(response.body, symbolize_names: true)
expect(response_data[:status]).to eq('bot')
expect(response_data[:status]).to eq('pending')
end
it 'creates a new conversation with message when message is passed' do
@ -269,8 +283,8 @@ RSpec.describe 'Conversations API', type: :request do
expect(conversation.reload.status).to eq('resolved')
end
it 'toggles the conversation status to open from bot' do
conversation.update!(status: 'bot')
it 'toggles the conversation status to open from pending' do
conversation.update!(status: 'pending')
post "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/toggle_status",
headers: agent.create_new_auth_token,
@ -283,13 +297,27 @@ RSpec.describe 'Conversations API', type: :request do
it 'toggles the conversation status to specific status when parameter is passed' do
expect(conversation.status).to eq('open')
post "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/toggle_status",
headers: agent.create_new_auth_token,
params: { status: 'pending' },
as: :json
expect(response).to have_http_status(:success)
expect(conversation.reload.status).to eq('pending')
end
# TODO: remove this spec when we remove the condition check in controller
# Added for backwards compatibility for bot status
it 'toggles the conversation status to pending status when parameter bot is passed' do
expect(conversation.status).to eq('open')
post "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/toggle_status",
headers: agent.create_new_auth_token,
params: { status: 'bot' },
as: :json
expect(response).to have_http_status(:success)
expect(conversation.reload.status).to eq('bot')
expect(conversation.reload.status).to eq('pending')
end
end
end

View file

@ -3,7 +3,7 @@ require 'rails_helper'
describe Integrations::Dialogflow::ProcessorService do
let(:account) { create(:account) }
let(:hook) { create(:integrations_hook, :dialogflow, account: account) }
let(:conversation) { create(:conversation, account: account, status: :bot) }
let(:conversation) { create(:conversation, account: account, status: :pending) }
let(:message) { create(:message, account: account, conversation: conversation) }
let(:event_name) { 'message.created' }
let(:event_data) { { message: message } }

View file

@ -40,7 +40,7 @@ shared_examples_for 'round_robin_handler' do
account: account,
contact: create(:contact, account: account),
inbox: inbox,
status: 'bot',
status: 'pending',
assignee: nil
)

View file

@ -345,8 +345,8 @@ RSpec.describe Conversation, type: :model do
let!(:bot_inbox) { create(:agent_bot_inbox) }
let(:conversation) { create(:conversation, inbox: bot_inbox.inbox) }
it 'returns conversation status as bot' do
expect(conversation.status).to eq('bot')
it 'returns conversation status as pending' do
expect(conversation.status).to eq('pending')
end
end
@ -354,8 +354,8 @@ RSpec.describe Conversation, type: :model do
let(:hook) { create(:integrations_hook, :dialogflow) }
let(:conversation) { create(:conversation, inbox: hook.inbox) }
it 'returns conversation status as bot' do
expect(conversation.status).to eq('bot')
it 'returns conversation status as pending' do
expect(conversation.status).to eq('pending')
end
end

View file

@ -13,7 +13,7 @@ properties:
description: ID of the inbox
status:
type: string
enum: ['open', 'resolved', 'bot']
enum: ['open', 'resolved', 'pending']
description: The status of the conversation
timestamp:
type: string

View file

@ -14,7 +14,7 @@ get:
- name: status
in: query
type: string
enum: ['open', 'resolved', 'bot']
enum: ['open', 'resolved', 'pending']
required: true
- name: page
in: query

View file

@ -15,7 +15,7 @@ get:
- name: status
in: query
type: string
enum: ['open', 'resolved', 'bot']
enum: ['open', 'resolved', 'pending']
- name: page
in: query
type: integer
@ -71,8 +71,8 @@ post:
description: Lets you specify attributes like browser information
status:
type: string
enum: ['open', 'resolved', 'bot']
description: Specify the conversation whether it's bot, open, closed
enum: ['open', 'resolved', 'pending']
description: Specify the conversation whether it's pending, open, closed
responses:
200:

View file

@ -15,7 +15,7 @@ parameters:
properties:
status:
type: string
enum: ["open", "resolved", "bot"]
enum: ["open", "resolved", "pending"]
required: true
description: The status of the conversation
responses:

View file

@ -1417,7 +1417,7 @@
"enum": [
"open",
"resolved",
"bot"
"pending"
]
},
{
@ -1508,9 +1508,9 @@
"enum": [
"open",
"resolved",
"bot"
"pending"
],
"description": "Specify the conversation whether it's bot, open, closed"
"description": "Specify the conversation whether it's pending, open, closed"
}
}
}
@ -1574,7 +1574,7 @@
"enum": [
"open",
"resolved",
"bot"
"pending"
],
"required": true
},
@ -1688,7 +1688,7 @@
"enum": [
"open",
"resolved",
"bot"
"pending"
],
"required": true,
"description": "The status of the conversation"
@ -2850,7 +2850,7 @@
"enum": [
"open",
"resolved",
"bot"
"pending"
],
"description": "The status of the conversation"
},