mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-03 12:37:56 +00:00
feat: Toggle to disallow users to send messages after a conversation is resolved (#3605)
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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: {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -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?
|
||||||
|
|
||||||
|
|||||||
@@ -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)) %>,
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user