From 7ee70628433185407eb3558e5fbf8230aa372ae3 Mon Sep 17 00:00:00 2001
From: "Aswin Dev P.S"
Date: Tue, 11 Jan 2022 00:32:03 -0800
Subject: [PATCH] feat: Toggle to disallow users to send messages after a
conversation is resolved (#3605)
---
.../api/v1/accounts/inboxes_controller.rb | 2 +-
.../dashboard/i18n/locale/en/inboxMgmt.json | 8 ++++-
.../dashboard/settings/inbox/Settings.vue | 22 +++++++++++++
.../widget/components/ChatFooter.vue | 4 +--
app/models/inbox.rb | 33 ++++++++++---------
app/views/api/v1/models/_inbox.json.jbuilder | 1 +
app/views/widgets/show.html.erb | 3 +-
..._allow_messages_after_resolved_to_inbox.rb | 16 +++++++++
db/schema.rb | 3 +-
.../v1/accounts/inboxes_controller_spec.rb | 21 ++++++++++++
10 files changed, 91 insertions(+), 22 deletions(-)
create mode 100644 db/migrate/20211216110209_add_allow_messages_after_resolved_to_inbox.rb
diff --git a/app/controllers/api/v1/accounts/inboxes_controller.rb b/app/controllers/api/v1/accounts/inboxes_controller.rb
index 1720ee692..9f2cfba8c 100644
--- a/app/controllers/api/v1/accounts/inboxes_controller.rb
+++ b/app/controllers/api/v1/accounts/inboxes_controller.rb
@@ -118,7 +118,7 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
def permitted_params(channel_attributes = [])
params.permit(
: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]
)
end
diff --git a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json
index b64362027..fb1d5c35f 100644
--- a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json
+++ b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json
@@ -306,6 +306,10 @@
"ENABLED": "Enabled",
"DISABLED": "Disabled"
},
+ "ALLOW_MESSAGES_AFTER_RESOLVED": {
+ "ENABLED": "Enabled",
+ "DISABLED": "Disabled"
+ },
"ENABLE_HMAC": {
"LABEL": "Enable"
}
@@ -362,7 +366,9 @@
"INBOX_IDENTIFIER": "Inbox Identifier",
"INBOX_IDENTIFIER_SUB_TEXT": "Use the `inbox_identifier` token shown here to authentication your API clients.",
"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": {
"TITLE": "Reauthorize",
diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue
index cb61c2f97..79acdfef2 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue
@@ -215,6 +215,25 @@
+
+
@@ -420,6 +439,7 @@ export default {
emailCollectEnabled: false,
isAgentListUpdating: false,
csatSurveyEnabled: false,
+ allowMessagesAfterResolved: true,
selectedInboxName: '',
channelWebsiteUrl: '',
webhookUrl: '',
@@ -583,6 +603,7 @@ export default {
this.autoAssignment = this.inbox.enable_auto_assignment;
this.emailCollectEnabled = this.inbox.enable_email_collect;
this.csatSurveyEnabled = this.inbox.csat_survey_enabled;
+ this.allowMessagesAfterResolved = this.inbox.allow_messages_after_resolved;
this.channelWebsiteUrl = this.inbox.website_url;
this.channelWelcomeTitle = this.inbox.welcome_title;
this.channelWelcomeTagline = this.inbox.welcome_tagline;
@@ -625,6 +646,7 @@ export default {
enable_auto_assignment: this.autoAssignment,
enable_email_collect: this.emailCollectEnabled,
csat_survey_enabled: this.csatSurveyEnabled,
+ allow_messages_after_resolved: this.allowMessagesAfterResolved,
greeting_enabled: this.greetingEnabled,
greeting_message: this.greetingMessage || '',
channel: {
diff --git a/app/javascript/widget/components/ChatFooter.vue b/app/javascript/widget/components/ChatFooter.vue
index 58538d0c6..7561f1930 100755
--- a/app/javascript/widget/components/ChatFooter.vue
+++ b/app/javascript/widget/components/ChatFooter.vue
@@ -58,9 +58,9 @@ export default {
return getContrastingTextColor(this.widgetColor);
},
hideReplyBox() {
- const { csatSurveyEnabled } = window.chatwootWebChannel;
+ const { allowMessagesAfterResolved } = window.chatwootWebChannel;
const { status } = this.conversationAttributes;
- return csatSurveyEnabled && status === 'resolved';
+ return !allowMessagesAfterResolved && status === 'resolved';
},
showEmailTranscriptButton() {
return this.currentUser && this.currentUser.email;
diff --git a/app/models/inbox.rb b/app/models/inbox.rb
index f16a5ca92..774c66f9d 100644
--- a/app/models/inbox.rb
+++ b/app/models/inbox.rb
@@ -4,22 +4,23 @@
#
# Table name: inboxes
#
-# id :integer not null, primary key
-# channel_type :string
-# csat_survey_enabled :boolean default(FALSE)
-# email_address :string
-# enable_auto_assignment :boolean default(TRUE)
-# enable_email_collect :boolean default(TRUE)
-# greeting_enabled :boolean default(FALSE)
-# greeting_message :string
-# name :string not null
-# out_of_office_message :string
-# timezone :string default("UTC")
-# working_hours_enabled :boolean default(FALSE)
-# created_at :datetime not null
-# updated_at :datetime not null
-# account_id :integer not null
-# channel_id :integer not null
+# id :integer not null, primary key
+# allow_messages_after_resolved :boolean default(TRUE)
+# channel_type :string
+# csat_survey_enabled :boolean default(FALSE)
+# email_address :string
+# enable_auto_assignment :boolean default(TRUE)
+# enable_email_collect :boolean default(TRUE)
+# greeting_enabled :boolean default(FALSE)
+# greeting_message :string
+# name :string not null
+# out_of_office_message :string
+# timezone :string default("UTC")
+# working_hours_enabled :boolean default(FALSE)
+# created_at :datetime not null
+# updated_at :datetime not null
+# account_id :integer not null
+# channel_id :integer not null
#
# Indexes
#
diff --git a/app/views/api/v1/models/_inbox.json.jbuilder b/app/views/api/v1/models/_inbox.json.jbuilder
index f76b8566d..eca35c466 100644
--- a/app/views/api/v1/models/_inbox.json.jbuilder
+++ b/app/views/api/v1/models/_inbox.json.jbuilder
@@ -13,6 +13,7 @@ json.out_of_office_message resource.out_of_office_message
json.working_hours resource.weekly_schedule
json.timezone resource.timezone
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?
diff --git a/app/views/widgets/show.html.erb b/app/views/widgets/show.html.erb
index 0cd60c453..02361ce7b 100644
--- a/app/views/widgets/show.html.erb
+++ b/app/views/widgets/show.html.erb
@@ -23,7 +23,8 @@
csatSurveyEnabled: <%= @web_widget.inbox.csat_survey_enabled %>,
workingHours: <%= @web_widget.inbox.working_hours.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 = {
useInboxAvatarForBot: <%= ActiveModel::Type::Boolean.new.cast(ENV.fetch('USE_INBOX_AVATAR_FOR_BOT', false)) %>,
diff --git a/db/migrate/20211216110209_add_allow_messages_after_resolved_to_inbox.rb b/db/migrate/20211216110209_add_allow_messages_after_resolved_to_inbox.rb
new file mode 100644
index 000000000..4c44ac2bb
--- /dev/null
+++ b/db/migrate/20211216110209_add_allow_messages_after_resolved_to_inbox.rb
@@ -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
diff --git a/db/schema.rb b/db/schema.rb
index 14b64b78a..ad5bc66b0 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -461,6 +461,7 @@ ActiveRecord::Schema.define(version: 2021_12_21_125545) do
t.string "timezone", default: "UTC"
t.boolean "enable_email_collect", default: true
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"
end
@@ -829,4 +830,4 @@ ActiveRecord::Schema.define(version: 2021_12_21_125545) do
"NEW.display_id := nextval('camp_dpid_seq_' || NEW.account_id);"
end
-end
+end
\ No newline at end of file
diff --git a/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb b/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb
index ea28dcbd5..1c7082abc 100644
--- a/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb
@@ -308,6 +308,17 @@ RSpec.describe 'Inboxes API', type: :request do
expect(response.body).to include('Line Inbox')
expect(response.body).to include('callback_webhook_url')
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
@@ -467,6 +478,16 @@ RSpec.describe 'Inboxes API', type: :request do
inbox.reload
expect(inbox.reload.weekly_schedule.find { |schedule| schedule['day_of_week'] == 0 }['open_hour']).to eq 9
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