feat: Toggle to disallow users to send messages after a conversation is resolved (#3605)

This commit is contained in:
Aswin Dev P.S
2022-01-11 00:32:03 -08:00
committed by GitHub
parent a0884310f4
commit 7ee7062843
10 changed files with 91 additions and 22 deletions

View File

@@ -118,7 +118,7 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
def permitted_params(channel_attributes = []) def permitted_params(channel_attributes = [])
params.permit( params.permit(
:name, :avatar, :greeting_enabled, :greeting_message, :enable_email_collect, :csat_survey_enabled, :name, :avatar, :greeting_enabled, :greeting_message, :enable_email_collect, :csat_survey_enabled,
:enable_auto_assignment, :working_hours_enabled, :out_of_office_message, :timezone, :enable_auto_assignment, :working_hours_enabled, :out_of_office_message, :timezone, :allow_messages_after_resolved,
channel: [:type, *channel_attributes] channel: [:type, *channel_attributes]
) )
end end

View File

@@ -306,6 +306,10 @@
"ENABLED": "Enabled", "ENABLED": "Enabled",
"DISABLED": "Disabled" "DISABLED": "Disabled"
}, },
"ALLOW_MESSAGES_AFTER_RESOLVED": {
"ENABLED": "Enabled",
"DISABLED": "Disabled"
},
"ENABLE_HMAC": { "ENABLE_HMAC": {
"LABEL": "Enable" "LABEL": "Enable"
} }
@@ -362,7 +366,9 @@
"INBOX_IDENTIFIER": "Inbox Identifier", "INBOX_IDENTIFIER": "Inbox Identifier",
"INBOX_IDENTIFIER_SUB_TEXT": "Use the `inbox_identifier` token shown here to authentication your API clients.", "INBOX_IDENTIFIER_SUB_TEXT": "Use the `inbox_identifier` token shown here to authentication your API clients.",
"FORWARD_EMAIL_TITLE": "Forward to Email", "FORWARD_EMAIL_TITLE": "Forward to Email",
"FORWARD_EMAIL_SUB_TEXT": "Start forwarding your emails to the following email address." "FORWARD_EMAIL_SUB_TEXT": "Start forwarding your emails to the following email address.",
"ALLOW_MESSAGES_AFTER_RESOLVED": "Allow messages after conversation resolved",
"ALLOW_MESSAGES_AFTER_RESOLVED_SUB_TEXT": "Allow the end-users to send messages even after the conversation is resolved."
}, },
"FACEBOOK_REAUTHORIZE": { "FACEBOOK_REAUTHORIZE": {
"TITLE": "Reauthorize", "TITLE": "Reauthorize",

View File

@@ -215,6 +215,25 @@
</p> </p>
</label> </label>
<label class="medium-9 columns">
{{ $t('INBOX_MGMT.SETTINGS_POPUP.ALLOW_MESSAGES_AFTER_RESOLVED') }}
<select v-model="allowMessagesAfterResolved">
<option :value="true">
{{ $t('INBOX_MGMT.EDIT.ALLOW_MESSAGES_AFTER_RESOLVED.ENABLED') }}
</option>
<option :value="false">
{{ $t('INBOX_MGMT.EDIT.ALLOW_MESSAGES_AFTER_RESOLVED.DISABLED') }}
</option>
</select>
<p class="help-text">
{{
$t(
'INBOX_MGMT.SETTINGS_POPUP.ALLOW_MESSAGES_AFTER_RESOLVED_SUB_TEXT'
)
}}
</p>
</label>
<label v-if="isAWebWidgetInbox"> <label v-if="isAWebWidgetInbox">
{{ $t('INBOX_MGMT.FEATURES.LABEL') }} {{ $t('INBOX_MGMT.FEATURES.LABEL') }}
</label> </label>
@@ -420,6 +439,7 @@ export default {
emailCollectEnabled: false, emailCollectEnabled: false,
isAgentListUpdating: false, isAgentListUpdating: false,
csatSurveyEnabled: false, csatSurveyEnabled: false,
allowMessagesAfterResolved: true,
selectedInboxName: '', selectedInboxName: '',
channelWebsiteUrl: '', channelWebsiteUrl: '',
webhookUrl: '', webhookUrl: '',
@@ -583,6 +603,7 @@ export default {
this.autoAssignment = this.inbox.enable_auto_assignment; this.autoAssignment = this.inbox.enable_auto_assignment;
this.emailCollectEnabled = this.inbox.enable_email_collect; this.emailCollectEnabled = this.inbox.enable_email_collect;
this.csatSurveyEnabled = this.inbox.csat_survey_enabled; this.csatSurveyEnabled = this.inbox.csat_survey_enabled;
this.allowMessagesAfterResolved = this.inbox.allow_messages_after_resolved;
this.channelWebsiteUrl = this.inbox.website_url; this.channelWebsiteUrl = this.inbox.website_url;
this.channelWelcomeTitle = this.inbox.welcome_title; this.channelWelcomeTitle = this.inbox.welcome_title;
this.channelWelcomeTagline = this.inbox.welcome_tagline; this.channelWelcomeTagline = this.inbox.welcome_tagline;
@@ -625,6 +646,7 @@ export default {
enable_auto_assignment: this.autoAssignment, enable_auto_assignment: this.autoAssignment,
enable_email_collect: this.emailCollectEnabled, enable_email_collect: this.emailCollectEnabled,
csat_survey_enabled: this.csatSurveyEnabled, csat_survey_enabled: this.csatSurveyEnabled,
allow_messages_after_resolved: this.allowMessagesAfterResolved,
greeting_enabled: this.greetingEnabled, greeting_enabled: this.greetingEnabled,
greeting_message: this.greetingMessage || '', greeting_message: this.greetingMessage || '',
channel: { channel: {

View File

@@ -58,9 +58,9 @@ export default {
return getContrastingTextColor(this.widgetColor); return getContrastingTextColor(this.widgetColor);
}, },
hideReplyBox() { hideReplyBox() {
const { csatSurveyEnabled } = window.chatwootWebChannel; const { allowMessagesAfterResolved } = window.chatwootWebChannel;
const { status } = this.conversationAttributes; const { status } = this.conversationAttributes;
return csatSurveyEnabled && status === 'resolved'; return !allowMessagesAfterResolved && status === 'resolved';
}, },
showEmailTranscriptButton() { showEmailTranscriptButton() {
return this.currentUser && this.currentUser.email; return this.currentUser && this.currentUser.email;

View File

@@ -4,22 +4,23 @@
# #
# Table name: inboxes # Table name: inboxes
# #
# id :integer not null, primary key # id :integer not null, primary key
# channel_type :string # allow_messages_after_resolved :boolean default(TRUE)
# csat_survey_enabled :boolean default(FALSE) # channel_type :string
# email_address :string # csat_survey_enabled :boolean default(FALSE)
# enable_auto_assignment :boolean default(TRUE) # email_address :string
# enable_email_collect :boolean default(TRUE) # enable_auto_assignment :boolean default(TRUE)
# greeting_enabled :boolean default(FALSE) # enable_email_collect :boolean default(TRUE)
# greeting_message :string # greeting_enabled :boolean default(FALSE)
# name :string not null # greeting_message :string
# out_of_office_message :string # name :string not null
# timezone :string default("UTC") # out_of_office_message :string
# working_hours_enabled :boolean default(FALSE) # timezone :string default("UTC")
# created_at :datetime not null # working_hours_enabled :boolean default(FALSE)
# updated_at :datetime not null # created_at :datetime not null
# account_id :integer not null # updated_at :datetime not null
# channel_id :integer not null # account_id :integer not null
# channel_id :integer not null
# #
# Indexes # Indexes
# #

View File

@@ -13,6 +13,7 @@ json.out_of_office_message resource.out_of_office_message
json.working_hours resource.weekly_schedule json.working_hours resource.weekly_schedule
json.timezone resource.timezone json.timezone resource.timezone
json.callback_webhook_url resource.callback_webhook_url json.callback_webhook_url resource.callback_webhook_url
json.allow_messages_after_resolved resource.allow_messages_after_resolved
json.tweets_enabled resource.channel.try(:tweets_enabled) if resource.twitter? json.tweets_enabled resource.channel.try(:tweets_enabled) if resource.twitter?

View File

@@ -23,7 +23,8 @@
csatSurveyEnabled: <%= @web_widget.inbox.csat_survey_enabled %>, csatSurveyEnabled: <%= @web_widget.inbox.csat_survey_enabled %>,
workingHours: <%= @web_widget.inbox.working_hours.to_json.html_safe %>, workingHours: <%= @web_widget.inbox.working_hours.to_json.html_safe %>,
outOfOfficeMessage: <%= @web_widget.inbox.out_of_office_message.to_json.html_safe %>, outOfOfficeMessage: <%= @web_widget.inbox.out_of_office_message.to_json.html_safe %>,
utcOffset: '<%= ActiveSupport::TimeZone[@web_widget.inbox.timezone].now.formatted_offset %>' utcOffset: '<%= ActiveSupport::TimeZone[@web_widget.inbox.timezone].now.formatted_offset %>',
allowMessagesAfterResolved: <%= @web_widget.inbox.allow_messages_after_resolved %>
} }
window.chatwootWidgetDefaults = { window.chatwootWidgetDefaults = {
useInboxAvatarForBot: <%= ActiveModel::Type::Boolean.new.cast(ENV.fetch('USE_INBOX_AVATAR_FOR_BOT', false)) %>, useInboxAvatarForBot: <%= ActiveModel::Type::Boolean.new.cast(ENV.fetch('USE_INBOX_AVATAR_FOR_BOT', false)) %>,

View File

@@ -0,0 +1,16 @@
class AddAllowMessagesAfterResolvedToInbox < ActiveRecord::Migration[6.1]
def change
add_column :inboxes, :allow_messages_after_resolved, :boolean, default: true
update_csat_enabled_inboxes
end
def update_csat_enabled_inboxes
::Inbox.where(channel_type: 'Channel::WebWidget', csat_survey_enabled: true).find_in_batches do |inboxes_batch|
inboxes_batch.each do |inbox|
inbox.allow_messages_after_resolved = false
inbox.save!
end
end
end
end

View File

@@ -461,6 +461,7 @@ ActiveRecord::Schema.define(version: 2021_12_21_125545) do
t.string "timezone", default: "UTC" t.string "timezone", default: "UTC"
t.boolean "enable_email_collect", default: true t.boolean "enable_email_collect", default: true
t.boolean "csat_survey_enabled", default: false t.boolean "csat_survey_enabled", default: false
t.boolean 'allow_messages_after_resolved', default: true
t.index ["account_id"], name: "index_inboxes_on_account_id" t.index ["account_id"], name: "index_inboxes_on_account_id"
end end
@@ -829,4 +830,4 @@ ActiveRecord::Schema.define(version: 2021_12_21_125545) do
"NEW.display_id := nextval('camp_dpid_seq_' || NEW.account_id);" "NEW.display_id := nextval('camp_dpid_seq_' || NEW.account_id);"
end end
end end

View File

@@ -308,6 +308,17 @@ RSpec.describe 'Inboxes API', type: :request do
expect(response.body).to include('Line Inbox') expect(response.body).to include('Line Inbox')
expect(response.body).to include('callback_webhook_url') expect(response.body).to include('callback_webhook_url')
end end
it 'creates the webwidget inbox that allow messages after conversation is resolved' do
post "/api/v1/accounts/#{account.id}/inboxes",
headers: admin.create_new_auth_token,
params: valid_params,
as: :json
expect(response).to have_http_status(:success)
json_response = JSON.parse(response.body)
expect(json_response['allow_messages_after_resolved']).to be true
end
end end
end end
@@ -467,6 +478,16 @@ RSpec.describe 'Inboxes API', type: :request do
inbox.reload inbox.reload
expect(inbox.reload.weekly_schedule.find { |schedule| schedule['day_of_week'] == 0 }['open_hour']).to eq 9 expect(inbox.reload.weekly_schedule.find { |schedule| schedule['day_of_week'] == 0 }['open_hour']).to eq 9
end end
it 'updates the webwidget inbox to disallow the messages after conversation is resolved' do
patch "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}",
headers: admin.create_new_auth_token,
params: valid_params.merge({ allow_messages_after_resolved: false }),
as: :json
expect(response).to have_http_status(:success)
expect(inbox.reload.allow_messages_after_resolved).to be_falsey
end
end end
end end