Skip to content

Commit

Permalink
feat: Add an option to disable endConversation button (#4352)
Browse files Browse the repository at this point in the history
  • Loading branch information
pranavrajs committed Apr 6, 2022
1 parent 821b953 commit 0b03e4b
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 10 deletions.
5 changes: 4 additions & 1 deletion app/controllers/api/v1/widget/conversations_controller.rb
Expand Up @@ -45,7 +45,10 @@ def toggle_typing
end

def toggle_status
head :not_found && return if conversation.nil?
return head :not_found if conversation.nil?

return head :forbidden unless @web_widget.end_conversation?

unless conversation.resolved?
conversation.status = :resolved
conversation.save
Expand Down
3 changes: 2 additions & 1 deletion app/javascript/dashboard/i18n/locale/en/inboxMgmt.json
Expand Up @@ -395,7 +395,8 @@
"FEATURES": {
"LABEL": "Features",
"DISPLAY_FILE_PICKER": "Display file picker on the widget",
"DISPLAY_EMOJI_PICKER": "Display emoji picker on the widget"
"DISPLAY_EMOJI_PICKER": "Display emoji picker on the widget",
"ALLOW_END_CONVERSATION": "Allow users to end conversation from the widget"
},
"SETTINGS_POPUP": {
"MESSENGER_HEADING": "Messenger Script",
Expand Down
Expand Up @@ -285,6 +285,17 @@
{{ $t('INBOX_MGMT.FEATURES.DISPLAY_EMOJI_PICKER') }}
</label>
</div>
<div v-if="isAWebWidgetInbox" class="settings-item settings-item">
<input
v-model="selectedFeatureFlags"
type="checkbox"
value="end_conversation"
@input="handleFeatureFlag"
/>
<label for="end_conversation">
{{ $t('INBOX_MGMT.FEATURES.ALLOW_END_CONVERSATION') }}
</label>
</div>

<woot-submit-button
v-if="isAPIInbox"
Expand Down
7 changes: 4 additions & 3 deletions app/javascript/widget/components/HeaderActions.vue
@@ -1,7 +1,7 @@
<template>
<div v-if="showHeaderActions" class="actions flex items-center">
<button
v-if="conversationStatus === 'open'"
v-if="conversationStatus === 'open' && hasEndConversationEnabled"
class="button transparent compact"
:title="$t('END_CONVERSATION')"
@click="resolveConversation"
Expand Down Expand Up @@ -43,12 +43,13 @@ import { mapGetters } from 'vuex';
import { IFrameHelper, RNHelper } from 'widget/helpers/utils';
import { popoutChatWindow } from '../helpers/popoutHelper';
import FluentIcon from 'shared/components/FluentIcon/Index.vue';
import darkModeMixin from 'widget/mixins/darkModeMixin.js';
import darkModeMixin from 'widget/mixins/darkModeMixin';
import configMixin from 'widget/mixins/configMixin';
export default {
name: 'HeaderActions',
components: { FluentIcon },
mixins: [darkModeMixin],
mixins: [configMixin, darkModeMixin],
props: {
showPopoutButton: {
type: Boolean,
Expand Down
3 changes: 3 additions & 0 deletions app/javascript/widget/mixins/configMixin.js
Expand Up @@ -18,6 +18,9 @@ export default {
hasAttachmentsEnabled() {
return this.channelConfig.enabledFeatures.includes('attachments');
},
hasEndConversationEnabled() {
return this.channelConfig.enabledFeatures.includes('end_conversation');
},
preChatFormEnabled() {
return window.chatwootWebChannel.preChatFormEnabled;
},
Expand Down
5 changes: 3 additions & 2 deletions app/javascript/widget/mixins/specs/configMixin.spec.js
Expand Up @@ -5,7 +5,7 @@ import Vue from 'vue';
global.chatwootWebChannel = {
avatarUrl: 'https://test.url',
hasAConnectedAgentBot: 'AgentBot',
enabledFeatures: ['emoji_picker', 'attachments'],
enabledFeatures: ['emoji_picker', 'attachments', 'end_conversation'],
preChatFormOptions: { require_email: false, pre_chat_message: '' },
};

Expand All @@ -24,14 +24,15 @@ describe('configMixin', () => {
const vm = new Constructor().$mount();
const wrapper = createWrapper(vm);
expect(wrapper.vm.hasEmojiPickerEnabled).toBe(true);
expect(wrapper.vm.hasEndConversationEnabled).toBe(true);
expect(wrapper.vm.hasAttachmentsEnabled).toBe(true);
expect(wrapper.vm.hasAConnectedAgentBot).toBe(true);
expect(wrapper.vm.useInboxAvatarForBot).toBe(true);
expect(wrapper.vm.inboxAvatarUrl).toBe('https://test.url');
expect(wrapper.vm.channelConfig).toEqual({
avatarUrl: 'https://test.url',
hasAConnectedAgentBot: 'AgentBot',
enabledFeatures: ['emoji_picker', 'attachments'],
enabledFeatures: ['emoji_picker', 'attachments', 'end_conversation'],
preChatFormOptions: {
pre_chat_message: '',
require_email: false,
Expand Down
3 changes: 2 additions & 1 deletion app/models/channel/web_widget.rb
Expand Up @@ -4,7 +4,7 @@
#
# id :integer not null, primary key
# continuity_via_email :boolean default(TRUE), not null
# feature_flags :integer default(3), not null
# feature_flags :integer default(7), not null
# hmac_mandatory :boolean default(FALSE)
# hmac_token :string
# pre_chat_form_enabled :boolean default(FALSE)
Expand Down Expand Up @@ -43,6 +43,7 @@ class Channel::WebWidget < ApplicationRecord

has_flags 1 => :attachments,
2 => :emoji_picker,
3 => :end_conversation,
:column => 'feature_flags',
:check_for_column => false

Expand Down
16 changes: 16 additions & 0 deletions db/migrate/20220405092033_update_web_widget_feature_flags.rb
@@ -0,0 +1,16 @@
class UpdateWebWidgetFeatureFlags < ActiveRecord::Migration[6.1]
def change
change_column_default(:channel_web_widgets, :feature_flags, from: 3, to: 7)

set_end_conversation_to_default
end

def set_end_conversation_to_default
::Channel::WebWidget.find_in_batches do |widget_batch|
widget_batch.each do |widget|
widget.end_conversation = true
widget.save!
end
end
end
end
4 changes: 2 additions & 2 deletions db/schema.rb
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2022_02_18_120357) do
ActiveRecord::Schema.define(version: 2022_04_05_092033) do

# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
Expand Down Expand Up @@ -280,7 +280,7 @@
t.string "widget_color", default: "#1f93ff"
t.string "welcome_title"
t.string "welcome_tagline"
t.integer "feature_flags", default: 3, null: false
t.integer "feature_flags", default: 7, null: false
t.integer "reply_time", default: 0
t.string "hmac_token"
t.boolean "pre_chat_form_enabled", default: false
Expand Down
34 changes: 34 additions & 0 deletions spec/controllers/api/v1/widget/conversations_controller_spec.rb
Expand Up @@ -5,9 +5,13 @@
let(:web_widget) { create(:channel_widget, account: account) }
let(:contact) { create(:contact, account: account, email: nil) }
let(:contact_inbox) { create(:contact_inbox, contact: contact, inbox: web_widget.inbox) }
let(:second_session) { create(:contact_inbox, contact: contact, inbox: web_widget.inbox) }
let!(:conversation) { create(:conversation, contact: contact, account: account, inbox: web_widget.inbox, contact_inbox: contact_inbox) }
let(:payload) { { source_id: contact_inbox.source_id, inbox_id: web_widget.inbox.id } }
let(:token) { ::Widget::TokenService.new(payload: payload).generate_token }
let(:token_without_conversation) do
::Widget::TokenService.new(payload: { source_id: second_session.source_id, inbox_id: web_widget.inbox.id }).generate_token
end

describe 'GET /api/v1/widget/conversations' do
context 'with a conversation' do
Expand Down Expand Up @@ -142,5 +146,35 @@
)
end
end

context 'when end conversation is not permitted' do
before do
web_widget.end_conversation = false
web_widget.save!
end

it 'returns action not permitted status' do
expect(conversation.open?).to be true

get '/api/v1/widget/conversations/toggle_status',
headers: { 'X-Auth-Token' => token },
params: { website_token: web_widget.website_token },
as: :json

expect(response).to have_http_status(:forbidden)
expect(conversation.reload.resolved?).to be false
end
end

context 'when a token without any conversation is used' do
it 'returns not found status' do
get '/api/v1/widget/conversations/toggle_status',
headers: { 'X-Auth-Token' => token_without_conversation },
params: { website_token: web_widget.website_token },
as: :json

expect(response).to have_http_status(:not_found)
end
end
end
end

0 comments on commit 0b03e4b

Please sign in to comment.