This PR improves the voice call creation flow by simplifying configuration and automating setup with Twilio APIs. references: #11602 , #11481 ## Key changes - Removed the requirement for twiml_app_sid – provisioning is now automated through APIs. - Auto-configured webhook URLs for: - Voice number callbacks - Status callbacks - twiML callbacks - Disabled business hours, help center, and related options until voice inbox is fully supported. - Added a configuration tab in the voice inbox to display the required Twilio URLs (to make verification easier in Twilio console). ## Test Cases - Provisioning - Create a new voice inbox → verify that Twilio app provisioning happens automatically. - Verify twiML callback - Webhook configuration - Check that both voice number callback and status callback URLs are auto-populated in Twilio. - Disabled features - Confirm that business hours and help center options are hidden/disabled for voice inbox. - Configuration tab - Open the voice inbox configuration tab → verify that the displayed Twilio URLs match what’s set in Twilio.
351 lines
11 KiB
Vue
351 lines
11 KiB
Vue
<script>
|
|
import { useAlert } from 'dashboard/composables';
|
|
import inboxMixin from 'shared/mixins/inboxMixin';
|
|
import SettingsSection from '../../../../../components/SettingsSection.vue';
|
|
import ImapSettings from '../ImapSettings.vue';
|
|
import SmtpSettings from '../SmtpSettings.vue';
|
|
import { useVuelidate } from '@vuelidate/core';
|
|
import { required } from '@vuelidate/validators';
|
|
import NextButton from 'dashboard/components-next/button/Button.vue';
|
|
import WhatsappReauthorize from '../channels/whatsapp/Reauthorize.vue';
|
|
|
|
export default {
|
|
components: {
|
|
SettingsSection,
|
|
ImapSettings,
|
|
SmtpSettings,
|
|
NextButton,
|
|
WhatsappReauthorize,
|
|
},
|
|
mixins: [inboxMixin],
|
|
props: {
|
|
inbox: {
|
|
type: Object,
|
|
default: () => ({}),
|
|
},
|
|
},
|
|
setup() {
|
|
return { v$: useVuelidate() };
|
|
},
|
|
data() {
|
|
return {
|
|
hmacMandatory: false,
|
|
whatsAppInboxAPIKey: '',
|
|
isRequestingReauthorization: false,
|
|
isSyncingTemplates: false,
|
|
};
|
|
},
|
|
validations: {
|
|
whatsAppInboxAPIKey: { required },
|
|
},
|
|
computed: {
|
|
isEmbeddedSignupWhatsApp() {
|
|
return this.inbox.provider_config?.source === 'embedded_signup';
|
|
},
|
|
whatsappAppId() {
|
|
return window.chatwootConfig?.whatsappAppId;
|
|
},
|
|
},
|
|
watch: {
|
|
inbox() {
|
|
this.setDefaults();
|
|
},
|
|
},
|
|
mounted() {
|
|
this.setDefaults();
|
|
},
|
|
methods: {
|
|
setDefaults() {
|
|
this.hmacMandatory = this.inbox.hmac_mandatory || false;
|
|
},
|
|
handleHmacFlag() {
|
|
this.updateInbox();
|
|
},
|
|
async updateInbox() {
|
|
try {
|
|
const payload = {
|
|
id: this.inbox.id,
|
|
formData: false,
|
|
channel: {
|
|
hmac_mandatory: this.hmacMandatory,
|
|
},
|
|
};
|
|
await this.$store.dispatch('inboxes/updateInbox', payload);
|
|
useAlert(this.$t('INBOX_MGMT.EDIT.API.SUCCESS_MESSAGE'));
|
|
} catch (error) {
|
|
useAlert(this.$t('INBOX_MGMT.EDIT.API.ERROR_MESSAGE'));
|
|
}
|
|
},
|
|
async updateWhatsAppInboxAPIKey() {
|
|
try {
|
|
const payload = {
|
|
id: this.inbox.id,
|
|
formData: false,
|
|
channel: {},
|
|
};
|
|
|
|
payload.channel.provider_config = {
|
|
...this.inbox.provider_config,
|
|
api_key: this.whatsAppInboxAPIKey,
|
|
};
|
|
|
|
await this.$store.dispatch('inboxes/updateInbox', payload);
|
|
useAlert(this.$t('INBOX_MGMT.EDIT.API.SUCCESS_MESSAGE'));
|
|
} catch (error) {
|
|
useAlert(this.$t('INBOX_MGMT.EDIT.API.ERROR_MESSAGE'));
|
|
}
|
|
},
|
|
async handleReconfigure() {
|
|
if (this.$refs.whatsappReauth) {
|
|
await this.$refs.whatsappReauth.requestAuthorization();
|
|
}
|
|
},
|
|
async syncTemplates() {
|
|
this.isSyncingTemplates = true;
|
|
try {
|
|
await this.$store.dispatch('inboxes/syncTemplates', this.inbox.id);
|
|
useAlert(
|
|
this.$t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_TEMPLATES_SYNC_SUCCESS')
|
|
);
|
|
} catch (error) {
|
|
useAlert(this.$t('INBOX_MGMT.EDIT.API.ERROR_MESSAGE'));
|
|
} finally {
|
|
this.isSyncingTemplates = false;
|
|
}
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div v-if="isATwilioChannel" class="mx-8">
|
|
<SettingsSection
|
|
:title="$t('INBOX_MGMT.ADD.TWILIO.API_CALLBACK.TITLE')"
|
|
:sub-title="$t('INBOX_MGMT.ADD.TWILIO.API_CALLBACK.SUBTITLE')"
|
|
>
|
|
<woot-code :script="inbox.callback_webhook_url" lang="html" />
|
|
</SettingsSection>
|
|
</div>
|
|
<div v-else-if="isAVoiceChannel" class="mx-8">
|
|
<SettingsSection
|
|
:title="$t('INBOX_MGMT.ADD.VOICE.CONFIGURATION.TWILIO_VOICE_URL_TITLE')"
|
|
:sub-title="
|
|
$t('INBOX_MGMT.ADD.VOICE.CONFIGURATION.TWILIO_VOICE_URL_SUBTITLE')
|
|
"
|
|
>
|
|
<woot-code :script="inbox.voice_call_webhook_url" lang="html" />
|
|
</SettingsSection>
|
|
<SettingsSection
|
|
:title="$t('INBOX_MGMT.ADD.VOICE.CONFIGURATION.TWILIO_STATUS_URL_TITLE')"
|
|
:sub-title="
|
|
$t('INBOX_MGMT.ADD.VOICE.CONFIGURATION.TWILIO_STATUS_URL_SUBTITLE')
|
|
"
|
|
>
|
|
<woot-code :script="inbox.voice_status_webhook_url" lang="html" />
|
|
</SettingsSection>
|
|
</div>
|
|
|
|
<div v-else-if="isALineChannel" class="mx-8">
|
|
<SettingsSection
|
|
:title="$t('INBOX_MGMT.ADD.LINE_CHANNEL.API_CALLBACK.TITLE')"
|
|
:sub-title="$t('INBOX_MGMT.ADD.LINE_CHANNEL.API_CALLBACK.SUBTITLE')"
|
|
>
|
|
<woot-code :script="inbox.callback_webhook_url" lang="html" />
|
|
</SettingsSection>
|
|
</div>
|
|
<div v-else-if="isAWebWidgetInbox">
|
|
<div class="mx-8">
|
|
<SettingsSection
|
|
:title="$t('INBOX_MGMT.SETTINGS_POPUP.MESSENGER_HEADING')"
|
|
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.MESSENGER_SUB_HEAD')"
|
|
>
|
|
<woot-code
|
|
:script="inbox.web_widget_script"
|
|
lang="html"
|
|
:codepen-title="`${inbox.name} - Chatwoot Widget Test`"
|
|
enable-code-pen
|
|
/>
|
|
</SettingsSection>
|
|
|
|
<SettingsSection
|
|
:title="$t('INBOX_MGMT.SETTINGS_POPUP.HMAC_VERIFICATION')"
|
|
>
|
|
<woot-code :script="inbox.hmac_token" />
|
|
<template #subTitle>
|
|
{{ $t('INBOX_MGMT.SETTINGS_POPUP.HMAC_DESCRIPTION') }}
|
|
<a
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
href="https://www.chatwoot.com/docs/product/channels/live-chat/sdk/identity-validation/"
|
|
>
|
|
{{ $t('INBOX_MGMT.SETTINGS_POPUP.HMAC_LINK_TO_DOCS') }}
|
|
</a>
|
|
</template>
|
|
</SettingsSection>
|
|
<SettingsSection
|
|
:title="$t('INBOX_MGMT.SETTINGS_POPUP.HMAC_MANDATORY_VERIFICATION')"
|
|
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.HMAC_MANDATORY_DESCRIPTION')"
|
|
>
|
|
<div class="flex gap-2 items-center">
|
|
<input
|
|
id="hmacMandatory"
|
|
v-model="hmacMandatory"
|
|
type="checkbox"
|
|
@change="handleHmacFlag"
|
|
/>
|
|
<label for="hmacMandatory">
|
|
{{ $t('INBOX_MGMT.EDIT.ENABLE_HMAC.LABEL') }}
|
|
</label>
|
|
</div>
|
|
</SettingsSection>
|
|
</div>
|
|
</div>
|
|
<div v-else-if="isAPIInbox" class="mx-8">
|
|
<SettingsSection
|
|
:title="$t('INBOX_MGMT.SETTINGS_POPUP.INBOX_IDENTIFIER')"
|
|
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.INBOX_IDENTIFIER_SUB_TEXT')"
|
|
>
|
|
<woot-code :script="inbox.inbox_identifier" />
|
|
</SettingsSection>
|
|
|
|
<SettingsSection
|
|
:title="$t('INBOX_MGMT.SETTINGS_POPUP.HMAC_VERIFICATION')"
|
|
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.HMAC_DESCRIPTION')"
|
|
>
|
|
<woot-code :script="inbox.hmac_token" />
|
|
</SettingsSection>
|
|
<SettingsSection
|
|
:title="$t('INBOX_MGMT.SETTINGS_POPUP.HMAC_MANDATORY_VERIFICATION')"
|
|
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.HMAC_MANDATORY_DESCRIPTION')"
|
|
>
|
|
<div class="flex gap-2 items-center">
|
|
<input
|
|
id="hmacMandatory"
|
|
v-model="hmacMandatory"
|
|
type="checkbox"
|
|
@change="handleHmacFlag"
|
|
/>
|
|
<label for="hmacMandatory">
|
|
{{ $t('INBOX_MGMT.EDIT.ENABLE_HMAC.LABEL') }}
|
|
</label>
|
|
</div>
|
|
</SettingsSection>
|
|
</div>
|
|
<div v-else-if="isAnEmailChannel">
|
|
<div class="mx-8">
|
|
<SettingsSection
|
|
:title="$t('INBOX_MGMT.SETTINGS_POPUP.FORWARD_EMAIL_TITLE')"
|
|
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.FORWARD_EMAIL_SUB_TEXT')"
|
|
>
|
|
<woot-code :script="inbox.forward_to_email" />
|
|
</SettingsSection>
|
|
</div>
|
|
<ImapSettings :inbox="inbox" />
|
|
<SmtpSettings v-if="inbox.imap_enabled" :inbox="inbox" />
|
|
</div>
|
|
<div v-else-if="isAWhatsAppChannel && !isATwilioChannel">
|
|
<div v-if="inbox.provider_config" class="mx-8">
|
|
<!-- Embedded Signup Section -->
|
|
<template v-if="isEmbeddedSignupWhatsApp">
|
|
<SettingsSection
|
|
v-if="whatsappAppId"
|
|
:title="
|
|
$t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_EMBEDDED_SIGNUP_TITLE')
|
|
"
|
|
:sub-title="
|
|
$t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_EMBEDDED_SIGNUP_SUBHEADER')
|
|
"
|
|
>
|
|
<div class="flex gap-4 items-center">
|
|
<p class="text-sm text-slate-600">
|
|
{{
|
|
$t(
|
|
'INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_EMBEDDED_SIGNUP_DESCRIPTION'
|
|
)
|
|
}}
|
|
</p>
|
|
<NextButton @click="handleReconfigure">
|
|
{{ $t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_RECONFIGURE_BUTTON') }}
|
|
</NextButton>
|
|
</div>
|
|
</SettingsSection>
|
|
</template>
|
|
|
|
<!-- Manual Setup Section -->
|
|
<template v-else>
|
|
<SettingsSection
|
|
:title="$t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_WEBHOOK_TITLE')"
|
|
:sub-title="
|
|
$t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_WEBHOOK_SUBHEADER')
|
|
"
|
|
>
|
|
<woot-code :script="inbox.provider_config.webhook_verify_token" />
|
|
</SettingsSection>
|
|
<SettingsSection
|
|
:title="$t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_SECTION_TITLE')"
|
|
:sub-title="
|
|
$t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_SECTION_SUBHEADER')
|
|
"
|
|
>
|
|
<woot-code :script="inbox.provider_config.api_key" />
|
|
</SettingsSection>
|
|
<SettingsSection
|
|
:title="$t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_SECTION_UPDATE_TITLE')"
|
|
:sub-title="
|
|
$t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_SECTION_UPDATE_SUBHEADER')
|
|
"
|
|
>
|
|
<div
|
|
class="flex flex-1 justify-between items-center mt-2 whatsapp-settings--content"
|
|
>
|
|
<woot-input
|
|
v-model="whatsAppInboxAPIKey"
|
|
type="text"
|
|
class="flex-1 mr-2 [&>input]:!mb-0"
|
|
:placeholder="
|
|
$t(
|
|
'INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_SECTION_UPDATE_PLACEHOLDER'
|
|
)
|
|
"
|
|
/>
|
|
<NextButton
|
|
:disabled="v$.whatsAppInboxAPIKey.$invalid"
|
|
@click="updateWhatsAppInboxAPIKey"
|
|
>
|
|
{{
|
|
$t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_SECTION_UPDATE_BUTTON')
|
|
}}
|
|
</NextButton>
|
|
</div>
|
|
</SettingsSection>
|
|
</template>
|
|
<SettingsSection
|
|
:title="$t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_TEMPLATES_SYNC_TITLE')"
|
|
:sub-title="
|
|
$t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_TEMPLATES_SYNC_SUBHEADER')
|
|
"
|
|
>
|
|
<div class="flex justify-start items-center mt-2">
|
|
<NextButton :disabled="isSyncingTemplates" @click="syncTemplates">
|
|
{{ $t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_TEMPLATES_SYNC_BUTTON') }}
|
|
</NextButton>
|
|
</div>
|
|
</SettingsSection>
|
|
</div>
|
|
<WhatsappReauthorize
|
|
v-if="isEmbeddedSignupWhatsApp"
|
|
ref="whatsappReauth"
|
|
:inbox="inbox"
|
|
class="hidden"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
.whatsapp-settings--content {
|
|
::v-deep input {
|
|
margin-bottom: 0;
|
|
}
|
|
}
|
|
</style>
|