fix: Update email alerts for Slack integration (#7739)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This commit is contained in:
@@ -85,7 +85,8 @@
|
|||||||
"UPDATE": "Update",
|
"UPDATE": "Update",
|
||||||
"BUTTON_TEXT": "Connect channel",
|
"BUTTON_TEXT": "Connect channel",
|
||||||
"DESCRIPTION": "Your Slack workspace is now linked with Chatwoot. However, the integration is currently inactive. To activate the integration and connect a channel to Chatwoot, please click the button below.\n\n**Note:** If you are attempting to connect a private channel, add the Chatwoot app to the Slack channel before proceeding with this step.",
|
"DESCRIPTION": "Your Slack workspace is now linked with Chatwoot. However, the integration is currently inactive. To activate the integration and connect a channel to Chatwoot, please click the button below.\n\n**Note:** If you are attempting to connect a private channel, add the Chatwoot app to the Slack channel before proceeding with this step.",
|
||||||
"ATTENTION_REQUIRED": "Attention required"
|
"ATTENTION_REQUIRED": "Attention required",
|
||||||
|
"EXPIRED": "Your Slack integration has expired. To continue receiving messages on Slack, please delete the integration and connect your workspace again."
|
||||||
},
|
},
|
||||||
"UPDATE_ERROR": "There was an error updating the integration, please try again",
|
"UPDATE_ERROR": "There was an error updating the integration, please try again",
|
||||||
"UPDATE_SUCCESS": "The channel is connected successfully",
|
"UPDATE_SUCCESS": "The channel is connected successfully",
|
||||||
|
|||||||
@@ -21,7 +21,10 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="areHooksAvailable" class="p-6 flex-1">
|
<div v-if="areHooksAvailable" class="p-6 flex-1">
|
||||||
<select-channel-warning v-if="!isIntegrationHookEnabled" />
|
<select-channel-warning
|
||||||
|
v-if="!isIntegrationHookEnabled"
|
||||||
|
:has-connected-a-channel="hasConnectedAChannel"
|
||||||
|
/>
|
||||||
<slack-integration-help-text
|
<slack-integration-help-text
|
||||||
:selected-channel-name="selectedChannelName"
|
:selected-channel-name="selectedChannelName"
|
||||||
/>
|
/>
|
||||||
@@ -61,16 +64,20 @@ export default {
|
|||||||
const { hooks = [] } = this.integration || {};
|
const { hooks = [] } = this.integration || {};
|
||||||
return !!hooks.length;
|
return !!hooks.length;
|
||||||
},
|
},
|
||||||
isIntegrationHookEnabled() {
|
hook() {
|
||||||
const { hooks = [] } = this.integration || {};
|
const { hooks = [] } = this.integration || {};
|
||||||
const [hook = {}] = hooks;
|
const [hook] = hooks;
|
||||||
return hook.status || false;
|
return hook || {};
|
||||||
|
},
|
||||||
|
isIntegrationHookEnabled() {
|
||||||
|
return this.hook.status || false;
|
||||||
|
},
|
||||||
|
hasConnectedAChannel() {
|
||||||
|
return !!this.hook.reference_id;
|
||||||
},
|
},
|
||||||
selectedChannelName() {
|
selectedChannelName() {
|
||||||
const { hooks = [] } = this.integration || {};
|
if (this.hook.status) {
|
||||||
const [hook = {}] = hooks;
|
const { settings: { channel_name: channelName = '' } = {} } = this.hook;
|
||||||
if (hook.status) {
|
|
||||||
const { settings: { channel_name: channelName = '' } = {} } = hook;
|
|
||||||
return channelName || 'customer-conversations';
|
return channelName || 'customer-conversations';
|
||||||
}
|
}
|
||||||
return this.$t('INTEGRATION_SETTINGS.SLACK.HELP_TEXT.SELECTED');
|
return this.$t('INTEGRATION_SETTINGS.SLACK.HELP_TEXT.SELECTED');
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
v-dompurify-html="
|
v-dompurify-html="
|
||||||
formatMessage(
|
formatMessage(
|
||||||
useInstallationName(
|
useInstallationName(
|
||||||
$t('INTEGRATION_SETTINGS.SLACK.SELECT_CHANNEL.DESCRIPTION'),
|
errorDescription,
|
||||||
globalConfig.installationName
|
globalConfig.installationName
|
||||||
),
|
),
|
||||||
false
|
false
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-8 mt-2">
|
<div v-if="!hasConnectedAChannel" class="ml-8 mt-2">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
v-if="!availableChannels.length"
|
v-if="!availableChannels.length"
|
||||||
button-class="smooth small warning"
|
button-class="smooth small warning"
|
||||||
@@ -79,6 +79,12 @@ import alertMixin from 'shared/mixins/alertMixin';
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [alertMixin, globalConfigMixin, messageFormatterMixin],
|
mixins: [alertMixin, globalConfigMixin, messageFormatterMixin],
|
||||||
|
props: {
|
||||||
|
hasConnectedAChannel: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return { selectedChannelId: '', availableChannels: [] };
|
return { selectedChannelId: '', availableChannels: [] };
|
||||||
},
|
},
|
||||||
@@ -87,6 +93,11 @@ export default {
|
|||||||
globalConfig: 'globalConfig/get',
|
globalConfig: 'globalConfig/get',
|
||||||
uiFlags: 'integrations/getUIFlags',
|
uiFlags: 'integrations/getUIFlags',
|
||||||
}),
|
}),
|
||||||
|
errorDescription() {
|
||||||
|
return !this.hasConnectedAChannel
|
||||||
|
? this.$t('INTEGRATION_SETTINGS.SLACK.SELECT_CHANNEL.DESCRIPTION')
|
||||||
|
: this.$t('INTEGRATION_SETTINGS.SLACK.SELECT_CHANNEL.EXPIRED');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchChannels() {
|
async fetchChannels() {
|
||||||
|
|||||||
@@ -6,3 +6,4 @@ json.account_id resource.account_id
|
|||||||
json.hook_type resource.hook_type
|
json.hook_type resource.hook_type
|
||||||
|
|
||||||
json.settings resource.settings if Current.account_user&.administrator?
|
json.settings resource.settings if Current.account_user&.administrator?
|
||||||
|
json.reference_id resource.reference_id if Current.account_user&.administrator?
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<p>Hello,</p>
|
<p>Hello,</p>
|
||||||
|
|
||||||
<p>Your Slack integration has expired. </p>
|
<p>Your Slack integration has expired. To continue receiving messages on Slack, please delete the integration and connect your workspace again. </p>
|
||||||
<p>Please reconnect Slack to continue receiving messages on Slack</p>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Click <a href="{{action_url}}">here</a> to re-connect.
|
Click <a href="{{action_url}}">here</a> to re-connect.
|
||||||
|
|||||||
@@ -80,10 +80,10 @@ class Integrations::Slack::SendOnSlackService < Base::SendOnChannelService
|
|||||||
def send_message
|
def send_message
|
||||||
post_message if message_content.present?
|
post_message if message_content.present?
|
||||||
upload_file if message.attachments.any?
|
upload_file if message.attachments.any?
|
||||||
rescue Slack::Web::Api::Errors::AccountInactive => e
|
rescue Slack::Web::Api::Errors::AccountInactive, Slack::Web::Api::Errors::MissingScope => e
|
||||||
Rails.logger.error e
|
Rails.logger.error e
|
||||||
hook.authorization_error!
|
hook.prompt_reauthorization!
|
||||||
hook.disable if hook.enabled?
|
hook.disable
|
||||||
end
|
end
|
||||||
|
|
||||||
def post_message
|
def post_message
|
||||||
|
|||||||
@@ -194,11 +194,28 @@ describe Integrations::Slack::SendOnSlackService do
|
|||||||
unfurl_links: true
|
unfurl_links: true
|
||||||
).and_raise(Slack::Web::Api::Errors::AccountInactive.new('Account disconnected'))
|
).and_raise(Slack::Web::Api::Errors::AccountInactive.new('Account disconnected'))
|
||||||
|
|
||||||
allow(hook).to receive(:authorization_error!)
|
allow(hook).to receive(:prompt_reauthorization!)
|
||||||
|
|
||||||
builder.perform
|
builder.perform
|
||||||
expect(hook).to be_disabled
|
expect(hook).to be_disabled
|
||||||
expect(hook).to have_received(:authorization_error!)
|
expect(hook).to have_received(:prompt_reauthorization!)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'disables hook on Slack MissingScope error' do
|
||||||
|
expect(slack_client).to receive(:chat_postMessage).with(
|
||||||
|
channel: hook.reference_id,
|
||||||
|
text: message.content,
|
||||||
|
username: "#{message.sender.name} (Contact)",
|
||||||
|
thread_ts: conversation.identifier,
|
||||||
|
icon_url: anything,
|
||||||
|
unfurl_links: true
|
||||||
|
).and_raise(Slack::Web::Api::Errors::MissingScope.new('Account disconnected'))
|
||||||
|
|
||||||
|
allow(hook).to receive(:prompt_reauthorization!)
|
||||||
|
|
||||||
|
builder.perform
|
||||||
|
expect(hook).to be_disabled
|
||||||
|
expect(hook).to have_received(:prompt_reauthorization!)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
require Rails.root.join 'spec/models/concerns/reauthorizable_shared.rb'
|
||||||
|
|
||||||
RSpec.describe Integrations::Hook do
|
RSpec.describe Integrations::Hook do
|
||||||
|
it_behaves_like 'reauthorizable'
|
||||||
|
|
||||||
context 'with validations' do
|
context 'with validations' do
|
||||||
it { is_expected.to validate_presence_of(:app_id) }
|
it { is_expected.to validate_presence_of(:app_id) }
|
||||||
it { is_expected.to validate_presence_of(:account_id) }
|
it { is_expected.to validate_presence_of(:account_id) }
|
||||||
|
|||||||
Reference in New Issue
Block a user