feat: Update the slack integration-flow to allow users to select the channel (#7637)
This commit is contained in:
@@ -1,23 +1,23 @@
|
||||
<template>
|
||||
<div class="flex">
|
||||
<div class="flex h-[6.25rem] w-[6.25rem]">
|
||||
<div class="flex flex-col md:flex-row items-start md:items-center">
|
||||
<div class="flex items-center justify-center m-0 mx-4 flex-1">
|
||||
<img
|
||||
:src="'/dashboard/images/integrations/' + integrationLogo"
|
||||
class="max-w-full p-6"
|
||||
class="p-2 h-16 w-16 mr-4"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col justify-center m-0 mx-4 flex-1">
|
||||
<h3 class="text-xl text-slate-800 dark:text-slate-100">
|
||||
{{ integrationName }}
|
||||
</h3>
|
||||
<p>
|
||||
{{
|
||||
useInstallationName(
|
||||
integrationDescription,
|
||||
globalConfig.installationName
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
<div>
|
||||
<h3 class="text-xl text-slate-800 dark:text-slate-100">
|
||||
{{ integrationName }}
|
||||
</h3>
|
||||
<p>
|
||||
{{
|
||||
useInstallationName(
|
||||
integrationDescription,
|
||||
globalConfig.installationName
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-center items-center mb-0 w-[15%]">
|
||||
<router-link
|
||||
@@ -29,13 +29,13 @@
|
||||
>
|
||||
<div v-if="integrationEnabled">
|
||||
<div v-if="integrationAction === 'disconnect'">
|
||||
<div @click="openDeletePopup()">
|
||||
<div @click="openDeletePopup">
|
||||
<woot-submit-button
|
||||
:button-text="
|
||||
$t('INTEGRATION_SETTINGS.WEBHOOK.DELETE.BUTTON_TEXT')
|
||||
actionButtonText ||
|
||||
$t('INTEGRATION_SETTINGS.WEBHOOK.DELETE.BUTTON_TEXT')
|
||||
"
|
||||
icon-class="dismiss-circle"
|
||||
button-class="nice alert"
|
||||
button-class="smooth alert"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -56,8 +56,14 @@
|
||||
:show.sync="showDeleteConfirmationPopup"
|
||||
:on-close="closeDeletePopup"
|
||||
:on-confirm="confirmDeletion"
|
||||
:title="$t('INTEGRATION_SETTINGS.WEBHOOK.DELETE.CONFIRM.TITLE')"
|
||||
:message="$t('INTEGRATION_SETTINGS.WEBHOOK.DELETE.CONFIRM.MESSAGE')"
|
||||
:title="
|
||||
deleteConfirmationText.title ||
|
||||
$t('INTEGRATION_SETTINGS.WEBHOOK.DELETE.CONFIRM.TITLE')
|
||||
"
|
||||
:message="
|
||||
deleteConfirmationText.message ||
|
||||
$t('INTEGRATION_SETTINGS.WEBHOOK.DELETE.CONFIRM.MESSAGE')
|
||||
"
|
||||
:confirm-text="$t('INTEGRATION_SETTINGS.WEBHOOK.DELETE.CONFIRM.YES')"
|
||||
:reject-text="$t('INTEGRATION_SETTINGS.WEBHOOK.DELETE.CONFIRM.NO')"
|
||||
/>
|
||||
@@ -81,6 +87,8 @@ export default {
|
||||
integrationDescription: { type: String, default: '' },
|
||||
integrationEnabled: { type: Boolean, default: false },
|
||||
integrationAction: { type: String, default: '' },
|
||||
actionButtonText: { type: String, default: '' },
|
||||
deleteConfirmationText: { type: Object, default: () => ({}) },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
@@ -65,7 +65,7 @@ export default {
|
||||
}),
|
||||
},
|
||||
mounted() {
|
||||
this.intializeSlackIntegration();
|
||||
this.fetchIntegrations();
|
||||
},
|
||||
methods: {
|
||||
integrationAction() {
|
||||
@@ -74,13 +74,8 @@ export default {
|
||||
}
|
||||
return this.integration.action;
|
||||
},
|
||||
async intializeSlackIntegration() {
|
||||
async fetchIntegrations() {
|
||||
await this.$store.dispatch('integrations/get', this.integrationId);
|
||||
if (this.code) {
|
||||
await this.$store.dispatch('integrations/connectSlack', this.code);
|
||||
// we are clearing code from the path as subsequent request would throw error
|
||||
this.$router.replace(this.$route.path);
|
||||
}
|
||||
this.integrationLoaded = true;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="integrationLoaded && !uiFlags.isCreatingSlack"
|
||||
class="flex flex-col flex-1 overflow-auto"
|
||||
>
|
||||
<div
|
||||
class="bg-white dark:bg-slate-800 border-b border-solid border-slate-75 dark:border-slate-700/50 rounded-sm p-4"
|
||||
>
|
||||
<integration
|
||||
:integration-id="integration.id"
|
||||
:integration-logo="integration.logo"
|
||||
:integration-name="integration.name"
|
||||
:integration-description="integration.description"
|
||||
:integration-enabled="integration.enabled"
|
||||
:integration-action="integrationAction"
|
||||
:action-button-text="$t('INTEGRATION_SETTINGS.SLACK.DELETE')"
|
||||
:delete-confirmation-text="{
|
||||
title: $t('INTEGRATION_SETTINGS.SLACK.DELETE_CONFIRMATION.TITLE'),
|
||||
message: $t('INTEGRATION_SETTINGS.SLACK.DELETE_CONFIRMATION.MESSAGE'),
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="areHooksAvailable" class="p-6 flex-1">
|
||||
<select-channel-warning v-if="!isIntegrationHookEnabled" />
|
||||
<slack-integration-help-text
|
||||
:selected-channel-name="selectedChannelName"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="flex flex-1 items-center justify-center">
|
||||
<spinner size="" color-scheme="primary" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import globalConfigMixin from 'shared/mixins/globalConfigMixin';
|
||||
import Integration from './Integration.vue';
|
||||
import messageFormatterMixin from 'shared/mixins/messageFormatterMixin';
|
||||
import SelectChannelWarning from './Slack/SelectChannelWarning.vue';
|
||||
import SlackIntegrationHelpText from './Slack/SlackIntegrationHelpText.vue';
|
||||
import Spinner from 'shared/components/Spinner';
|
||||
export default {
|
||||
components: {
|
||||
Spinner,
|
||||
Integration,
|
||||
SelectChannelWarning,
|
||||
SlackIntegrationHelpText,
|
||||
},
|
||||
mixins: [globalConfigMixin, messageFormatterMixin],
|
||||
props: {
|
||||
code: { type: String, default: '' },
|
||||
},
|
||||
data() {
|
||||
return { integrationLoaded: false };
|
||||
},
|
||||
computed: {
|
||||
integration() {
|
||||
return this.$store.getters['integrations/getIntegration']('slack');
|
||||
},
|
||||
areHooksAvailable() {
|
||||
const { hooks = [] } = this.integration || {};
|
||||
return !!hooks.length;
|
||||
},
|
||||
isIntegrationHookEnabled() {
|
||||
const { hooks = [] } = this.integration || {};
|
||||
const [hook = {}] = hooks;
|
||||
return hook.status || false;
|
||||
},
|
||||
selectedChannelName() {
|
||||
const { hooks = [] } = this.integration || {};
|
||||
const [hook = {}] = hooks;
|
||||
if (hook.status) {
|
||||
const { settings: { channel_name: channelName = '' } = {} } = hook;
|
||||
return channelName || 'customer-conversations';
|
||||
}
|
||||
return this.$t('INTEGRATION_SETTINGS.SLACK.HELP_TEXT.SELECTED');
|
||||
},
|
||||
...mapGetters({
|
||||
currentUser: 'getCurrentUser',
|
||||
globalConfig: 'globalConfig/get',
|
||||
accountId: 'getCurrentAccountId',
|
||||
uiFlags: 'integrations/getUIFlags',
|
||||
}),
|
||||
|
||||
integrationAction() {
|
||||
if (this.integration.enabled) {
|
||||
return 'disconnect';
|
||||
}
|
||||
return this.integration.action;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.intializeSlackIntegration();
|
||||
},
|
||||
methods: {
|
||||
async intializeSlackIntegration() {
|
||||
await this.$store.dispatch('integrations/get', 'slack');
|
||||
if (this.code) {
|
||||
await this.$store.dispatch('integrations/connectSlack', this.code);
|
||||
// Clear the query param `code` from the URL as the
|
||||
// subsequent reloads would result in an error
|
||||
this.$router.replace(this.$route.path);
|
||||
}
|
||||
this.integrationLoaded = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<div
|
||||
class="rounded-md bg-yellow-50 border border-yellow-200 dark:border-slate-700 dark:bg-slate-800 px-6 py-4 mb-4"
|
||||
>
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0 mt-0.5">
|
||||
<fluent-icon
|
||||
icon="alert"
|
||||
class="text-yellow-500 dark:text-yellow-400"
|
||||
size="24"
|
||||
/>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<p
|
||||
class="text-base font-semibold text-yellow-900 dark:text-yellow-500 mb-1"
|
||||
>
|
||||
{{
|
||||
$t('INTEGRATION_SETTINGS.SLACK.SELECT_CHANNEL.ATTENTION_REQUIRED')
|
||||
}}
|
||||
</p>
|
||||
<div class="text-sm text-yellow-800 dark:text-yellow-600 mt-2">
|
||||
<p
|
||||
v-dompurify-html="
|
||||
formatMessage(
|
||||
useInstallationName(
|
||||
$t('INTEGRATION_SETTINGS.SLACK.SELECT_CHANNEL.DESCRIPTION'),
|
||||
globalConfig.installationName
|
||||
),
|
||||
false
|
||||
)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-8 mt-2">
|
||||
<woot-submit-button
|
||||
v-if="!availableChannels.length"
|
||||
button-class="smooth small warning"
|
||||
:loading="uiFlags.isFetchingSlackChannels"
|
||||
:button-text="
|
||||
$t('INTEGRATION_SETTINGS.SLACK.SELECT_CHANNEL.BUTTON_TEXT')
|
||||
"
|
||||
spinner-class="warning"
|
||||
@click="fetchChannels"
|
||||
/>
|
||||
<div v-else class="inline-flex">
|
||||
<select
|
||||
v-model="selectedChannelId"
|
||||
class="h-8 border-yellow-300 border mr-4 text-xs leading-4 py-1"
|
||||
>
|
||||
<option value="">
|
||||
{{ $t('INTEGRATION_SETTINGS.SLACK.SELECT_CHANNEL.OPTION_LABEL') }}
|
||||
</option>
|
||||
<option
|
||||
v-for="channel in availableChannels"
|
||||
:key="channel.id"
|
||||
:value="channel.id"
|
||||
>
|
||||
#{{ channel.name }}
|
||||
</option>
|
||||
</select>
|
||||
<woot-submit-button
|
||||
button-class="smooth small success"
|
||||
:button-text="$t('INTEGRATION_SETTINGS.SLACK.SELECT_CHANNEL.UPDATE')"
|
||||
spinner-class="success"
|
||||
:loading="uiFlags.isUpdatingSlack"
|
||||
@click="updateIntegration"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import globalConfigMixin from 'shared/mixins/globalConfigMixin';
|
||||
import messageFormatterMixin from 'shared/mixins/messageFormatterMixin';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
|
||||
export default {
|
||||
mixins: [alertMixin, globalConfigMixin, messageFormatterMixin],
|
||||
data() {
|
||||
return { selectedChannelId: '', availableChannels: [] };
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
globalConfig: 'globalConfig/get',
|
||||
uiFlags: 'integrations/getUIFlags',
|
||||
}),
|
||||
},
|
||||
methods: {
|
||||
async fetchChannels() {
|
||||
try {
|
||||
this.availableChannels = await this.$store.dispatch(
|
||||
'integrations/listAllSlackChannels'
|
||||
);
|
||||
this.availableChannels.sort((c1, c2) => c1.name - c2.name);
|
||||
} catch {
|
||||
this.$t('INTEGRATION_SETTINGS.SLACK.FAILED_TO_FETCH_CHANNELS');
|
||||
this.availableChannels = [];
|
||||
}
|
||||
},
|
||||
async updateIntegration() {
|
||||
try {
|
||||
await this.$store.dispatch('integrations/updateSlack', {
|
||||
referenceId: this.selectedChannelId,
|
||||
});
|
||||
this.showAlert(this.$t('INTEGRATION_SETTINGS.SLACK.UPDATE_SUCCESS'));
|
||||
} catch (error) {
|
||||
this.showAlert(
|
||||
error.message || 'INTEGRATION_SETTINGS.SLACK.UPDATE_ERROR'
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div
|
||||
class="flex-1 w-full p-6 bg-white rounded-md border border-slate-50 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-200 "
|
||||
>
|
||||
<div class="prose-lg max-w-5xl">
|
||||
<h5 class="dark:text-slate-100">
|
||||
{{ $t('INTEGRATION_SETTINGS.SLACK.HELP_TEXT.TITLE') }}
|
||||
</h5>
|
||||
<p>
|
||||
<span
|
||||
v-dompurify-html="
|
||||
formatMessage(
|
||||
$t('INTEGRATION_SETTINGS.SLACK.HELP_TEXT.BODY', {
|
||||
selectedChannelName: selectedChannelName,
|
||||
}),
|
||||
false
|
||||
)
|
||||
"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import messageFormatterMixin from 'shared/mixins/messageFormatterMixin';
|
||||
export default {
|
||||
mixins: [messageFormatterMixin],
|
||||
props: {
|
||||
selectedChannelName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -3,6 +3,7 @@ import SettingsContent from '../Wrapper';
|
||||
import Webhook from './Webhooks/Index';
|
||||
import DashboardApps from './DashboardApps/Index';
|
||||
import ShowIntegration from './ShowIntegration';
|
||||
import Slack from './Slack';
|
||||
import { frontendURL } from '../../../../helper/URLHelper';
|
||||
|
||||
export default {
|
||||
@@ -42,6 +43,13 @@ export default {
|
||||
name: 'settings_integrations_dashboard_apps',
|
||||
roles: ['administrator'],
|
||||
},
|
||||
{
|
||||
path: 'slack',
|
||||
name: 'settings_integrations_slack',
|
||||
component: Slack,
|
||||
roles: ['administrator'],
|
||||
props: route => ({ code: route.query.code }),
|
||||
},
|
||||
{
|
||||
path: ':integration_id',
|
||||
name: 'settings_integrations_integration',
|
||||
|
||||
Reference in New Issue
Block a user