Feature: API Channel (#1052)
This commit is contained in:
BIN
app/javascript/dashboard/assets/images/channels/api.png
Normal file
BIN
app/javascript/dashboard/assets/images/channels/api.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
BIN
app/javascript/dashboard/assets/images/channels/email.png
Normal file
BIN
app/javascript/dashboard/assets/images/channels/email.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
@@ -63,6 +63,8 @@ const INBOX_TYPES = {
|
||||
FB: 'Channel::FacebookPage',
|
||||
TWITTER: 'Channel::TwitterProfile',
|
||||
TWILIO: 'Channel::TwilioSms',
|
||||
API: 'Channel::Api',
|
||||
EMAIL: 'Channel::Email',
|
||||
};
|
||||
const getInboxClassByType = type => {
|
||||
switch (type) {
|
||||
@@ -78,6 +80,12 @@ const getInboxClassByType = type => {
|
||||
case INBOX_TYPES.TWILIO:
|
||||
return 'ion-android-textsms';
|
||||
|
||||
case INBOX_TYPES.API:
|
||||
return 'ion-cloud';
|
||||
|
||||
case INBOX_TYPES.EMAIL:
|
||||
return 'ion-email';
|
||||
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -16,6 +16,14 @@
|
||||
v-if="channel === 'telegram'"
|
||||
src="~dashboard/assets/images/channels/telegram.png"
|
||||
/>
|
||||
<img
|
||||
v-if="channel === 'api'"
|
||||
src="~dashboard/assets/images/channels/api.png"
|
||||
/>
|
||||
<img
|
||||
v-if="channel === 'email'"
|
||||
src="~dashboard/assets/images/channels/email.png"
|
||||
/>
|
||||
<img
|
||||
v-if="channel === 'line'"
|
||||
src="~dashboard/assets/images/channels/line.png"
|
||||
@@ -56,7 +64,10 @@ export default {
|
||||
if (channel === 'twitter') {
|
||||
return this.enabledFeatures.channel_twitter;
|
||||
}
|
||||
return ['website', 'twilio'].includes(channel);
|
||||
if (channel === 'email') {
|
||||
return this.enabledFeatures.channel_email;
|
||||
}
|
||||
return ['website', 'twilio', 'api'].includes(channel);
|
||||
},
|
||||
onItemClick() {
|
||||
if (this.isActive(this.channel)) {
|
||||
|
||||
@@ -115,6 +115,43 @@
|
||||
"ERROR_MESSAGE": "We were not able to authenticate Twilio credentials, please try again"
|
||||
}
|
||||
},
|
||||
"API_CHANNEL": {
|
||||
"TITLE": "API Channel",
|
||||
"DESC": "Integrate with API channel and start supporting your customers via chatwoot.",
|
||||
"CHANNEL_NAME": {
|
||||
"LABEL": "Channel Name",
|
||||
"PLACEHOLDER": "Please enter a channel name",
|
||||
"ERROR": "This field is required"
|
||||
},
|
||||
"WEBHOOK_URL": {
|
||||
"LABEL": "Webhook Url",
|
||||
"SUBTITLE": "Configure the url where you want to recieve callbacks from chatwoot on events.",
|
||||
"PLACEHOLDER": "Webhook Url"
|
||||
},
|
||||
"SUBMIT_BUTTON": "Create API Channel",
|
||||
"API": {
|
||||
"ERROR_MESSAGE": "We were not able to save the api channel"
|
||||
}
|
||||
},
|
||||
"EMAIL_CHANNEL": {
|
||||
"TITLE": "Email Channel",
|
||||
"DESC": "Integrate you email inbox with chatwoot.",
|
||||
"CHANNEL_NAME": {
|
||||
"LABEL": "Channel Name",
|
||||
"PLACEHOLDER": "Please enter a channel name",
|
||||
"ERROR": "This field is required"
|
||||
},
|
||||
"EMAIL": {
|
||||
"LABEL": "Email",
|
||||
"SUBTITLE": "Email where your customers sends you support tickets",
|
||||
"PLACEHOLDER": "Email"
|
||||
},
|
||||
"SUBMIT_BUTTON": "Create Email Channel",
|
||||
"API": {
|
||||
"ERROR_MESSAGE": "We were not able to save the email channel"
|
||||
},
|
||||
"FINISH_MESSAGE" : "Start forwarding your emails to the following email address."
|
||||
},
|
||||
"AUTH": {
|
||||
"TITLE": "Channels",
|
||||
"DESC": "Currently we support Website live chat widgets, Facebook Pages and Twitter profiles as platforms. We have more platforms like Whatsapp, Email, Telegram and Line in the works, which will be out soon."
|
||||
|
||||
@@ -34,6 +34,8 @@ export default {
|
||||
'facebook',
|
||||
'twitter',
|
||||
'twilio',
|
||||
'email',
|
||||
'api',
|
||||
'telegram',
|
||||
'line',
|
||||
],
|
||||
|
||||
@@ -21,6 +21,14 @@
|
||||
>
|
||||
</woot-code>
|
||||
</div>
|
||||
<div class="medium-6 small-offset-3">
|
||||
<woot-code
|
||||
v-if="isAEmailInbox"
|
||||
lang="html"
|
||||
:script="currentInbox.forward_to_address"
|
||||
>
|
||||
</woot-code>
|
||||
</div>
|
||||
<router-link
|
||||
class="button success nice"
|
||||
:to="{
|
||||
@@ -53,6 +61,9 @@ export default {
|
||||
isATwilioInbox() {
|
||||
return this.currentInbox.channel_type === 'Channel::TwilioSms';
|
||||
},
|
||||
isAEmailInbox() {
|
||||
return this.currentInbox.channel_type === 'Channel::Email';
|
||||
},
|
||||
message() {
|
||||
if (this.isATwilioInbox) {
|
||||
return `${this.$t('INBOX_MGMT.FINISH.MESSAGE')}. ${this.$t(
|
||||
@@ -60,6 +71,10 @@ export default {
|
||||
)}`;
|
||||
}
|
||||
|
||||
if (this.isAEmailInbox) {
|
||||
return this.$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.FINISH_MESSAGE');
|
||||
}
|
||||
|
||||
if (!this.currentInbox.website_token) {
|
||||
return this.$t('INBOX_MGMT.FINISH.MESSAGE');
|
||||
}
|
||||
|
||||
@@ -45,6 +45,12 @@
|
||||
<span v-if="item.channel_type === 'Channel::TwilioSms'">
|
||||
Twilio SMS
|
||||
</span>
|
||||
<span v-if="item.channel_type === 'Channel::Email'">
|
||||
Email
|
||||
</span>
|
||||
<span v-if="item.channel_type === 'Channel::Api'">
|
||||
Api
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
|
||||
@@ -2,12 +2,16 @@ import Facebook from './channels/Facebook';
|
||||
import Website from './channels/Website';
|
||||
import Twitter from './channels/Twitter';
|
||||
import Twilio from './channels/Twilio';
|
||||
import Api from './channels/Api';
|
||||
import Email from './channels/Email';
|
||||
|
||||
const channelViewList = {
|
||||
facebook: Facebook,
|
||||
website: Website,
|
||||
twitter: Twitter,
|
||||
twilio: Twilio,
|
||||
api: Api,
|
||||
email: Email,
|
||||
};
|
||||
|
||||
export default {
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<div class="wizard-body small-9 columns">
|
||||
<page-header
|
||||
:header-title="$t('INBOX_MGMT.ADD.API_CHANNEL.TITLE')"
|
||||
:header-content="$t('INBOX_MGMT.ADD.API_CHANNEL.DESC')"
|
||||
/>
|
||||
<form class="row" @submit.prevent="createChannel()">
|
||||
<div class="medium-8 columns">
|
||||
<label :class="{ error: $v.channelName.$error }">
|
||||
{{ $t('INBOX_MGMT.ADD.API_CHANNEL.CHANNEL_NAME.LABEL') }}
|
||||
<input
|
||||
v-model.trim="channelName"
|
||||
type="text"
|
||||
:placeholder="
|
||||
$t('INBOX_MGMT.ADD.API_CHANNEL.CHANNEL_NAME.PLACEHOLDER')
|
||||
"
|
||||
@blur="$v.channelName.$touch"
|
||||
/>
|
||||
<span v-if="$v.channelName.$error" class="message">{{
|
||||
$t('INBOX_MGMT.ADD.API_CHANNEL.CHANNEL_NAME.ERROR')
|
||||
}}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="medium-8 columns">
|
||||
<label :class="{ error: $v.webhookUrl.$error }">
|
||||
{{ $t('INBOX_MGMT.ADD.API_CHANNEL.WEBHOOK_URL.LABEL') }}
|
||||
<input
|
||||
v-model.trim="webhookUrl"
|
||||
type="text"
|
||||
:placeholder="
|
||||
$t('INBOX_MGMT.ADD.API_CHANNEL.WEBHOOK_URL.PLACEHOLDER')
|
||||
"
|
||||
@blur="$v.webhookUrl.$touch"
|
||||
/>
|
||||
</label>
|
||||
<p class="help-text">
|
||||
{{ $t('INBOX_MGMT.ADD.API_CHANNEL.WEBHOOK_URL.SUBTITLE') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="medium-12 columns">
|
||||
<woot-submit-button
|
||||
:loading="uiFlags.isCreating"
|
||||
:button-text="$t('INBOX_MGMT.ADD.API_CHANNEL.SUBMIT_BUTTON')"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { required } from 'vuelidate/lib/validators';
|
||||
import router from '../../../../index';
|
||||
import PageHeader from '../../SettingsSubPageHeader';
|
||||
|
||||
const shouldBeWebhookUrl = (value = '') => value.startsWith('http');
|
||||
|
||||
export default {
|
||||
components: {
|
||||
PageHeader,
|
||||
},
|
||||
mixins: [alertMixin],
|
||||
data() {
|
||||
return {
|
||||
channelName: '',
|
||||
webhookUrl: '',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
uiFlags: 'inboxes/getUIFlags',
|
||||
}),
|
||||
},
|
||||
validations: {
|
||||
channelName: { required },
|
||||
webhookUrl: { required, shouldBeWebhookUrl },
|
||||
},
|
||||
methods: {
|
||||
async createChannel() {
|
||||
this.$v.$touch();
|
||||
if (this.$v.$invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const apiChannel = await this.$store.dispatch('inboxes/createChannel', {
|
||||
name: this.channelName,
|
||||
channel: {
|
||||
type: 'api',
|
||||
webhook_url: this.webhookUrl,
|
||||
},
|
||||
});
|
||||
|
||||
router.replace({
|
||||
name: 'settings_inboxes_add_agents',
|
||||
params: {
|
||||
page: 'new',
|
||||
inbox_id: apiChannel.id,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
this.showAlert(this.$t('INBOX_MGMT.ADD.API_CHANNEL.API.ERROR_MESSAGE'));
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<div class="wizard-body small-9 columns">
|
||||
<page-header
|
||||
:header-title="$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.TITLE')"
|
||||
:header-content="$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.DESC')"
|
||||
/>
|
||||
<form class="row" @submit.prevent="createChannel()">
|
||||
<div class="medium-8 columns">
|
||||
<label :class="{ error: $v.channelName.$error }">
|
||||
{{ $t('INBOX_MGMT.ADD.EMAIL_CHANNEL.CHANNEL_NAME.LABEL') }}
|
||||
<input
|
||||
v-model.trim="channelName"
|
||||
type="text"
|
||||
:placeholder="
|
||||
$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.CHANNEL_NAME.PLACEHOLDER')
|
||||
"
|
||||
@blur="$v.channelName.$touch"
|
||||
/>
|
||||
<span v-if="$v.channelName.$error" class="message">{{
|
||||
$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.CHANNEL_NAME.ERROR')
|
||||
}}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="medium-8 columns">
|
||||
<label :class="{ error: $v.email.$error }">
|
||||
{{ $t('INBOX_MGMT.ADD.EMAIL_CHANNEL.EMAIL.LABEL') }}
|
||||
<input
|
||||
v-model.trim="email"
|
||||
type="text"
|
||||
:placeholder="$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.EMAIL.PLACEHOLDER')"
|
||||
@blur="$v.email.$touch"
|
||||
/>
|
||||
</label>
|
||||
<p class="help-text">
|
||||
{{ $t('INBOX_MGMT.ADD.EMAIL_CHANNEL.EMAIL.SUBTITLE') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="medium-12 columns">
|
||||
<woot-submit-button
|
||||
:loading="uiFlags.isCreating"
|
||||
:button-text="$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.SUBMIT_BUTTON')"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { required } from 'vuelidate/lib/validators';
|
||||
import router from '../../../../index';
|
||||
import PageHeader from '../../SettingsSubPageHeader';
|
||||
|
||||
const validEmail = (value = '') => value.includes('@');
|
||||
|
||||
export default {
|
||||
components: {
|
||||
PageHeader,
|
||||
},
|
||||
mixins: [alertMixin],
|
||||
data() {
|
||||
return {
|
||||
channelName: '',
|
||||
email: '',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
uiFlags: 'inboxes/getUIFlags',
|
||||
}),
|
||||
},
|
||||
validations: {
|
||||
channelName: { required },
|
||||
email: { required, validEmail },
|
||||
},
|
||||
methods: {
|
||||
async createChannel() {
|
||||
this.$v.$touch();
|
||||
if (this.$v.$invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const emailChannel = await this.$store.dispatch(
|
||||
'inboxes/createChannel',
|
||||
{
|
||||
name: this.channelName,
|
||||
channel: {
|
||||
type: 'email',
|
||||
email: this.email,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
router.replace({
|
||||
name: 'settings_inboxes_add_agents',
|
||||
params: {
|
||||
page: 'new',
|
||||
inbox_id: emailChannel.id,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
this.showAlert(
|
||||
this.$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.API.ERROR_MESSAGE')
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -55,6 +55,18 @@ export const actions = {
|
||||
commit(types.default.SET_INBOXES_UI_FLAG, { isFetching: false });
|
||||
}
|
||||
},
|
||||
createChannel: async ({ commit }, params) => {
|
||||
try {
|
||||
commit(types.default.SET_INBOXES_UI_FLAG, { isCreating: true });
|
||||
const response = await WebChannel.create(params);
|
||||
commit(types.default.ADD_INBOXES, response.data);
|
||||
commit(types.default.SET_INBOXES_UI_FLAG, { isCreating: false });
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
commit(types.default.SET_INBOXES_UI_FLAG, { isCreating: false });
|
||||
throw new Error(error);
|
||||
}
|
||||
},
|
||||
createWebsiteChannel: async ({ commit }, params) => {
|
||||
try {
|
||||
commit(types.default.SET_INBOXES_UI_FLAG, { isCreating: true });
|
||||
|
||||
Reference in New Issue
Block a user