[Enhancement] Add CopyToClipboard action in code component (#329)
* Add CopyToClipboard action in websiteWidgetCode component * Fix codeclimate issues
This commit is contained in:
parent
a3662091c7
commit
60e96f446e
18 changed files with 283 additions and 90 deletions
|
@ -17,6 +17,9 @@ Metrics/BlockLength:
|
||||||
- spec/**/*
|
- spec/**/*
|
||||||
Style/ClassAndModuleChildren:
|
Style/ClassAndModuleChildren:
|
||||||
EnforcedStyle: compact
|
EnforcedStyle: compact
|
||||||
|
RSpec/NestedGroups:
|
||||||
|
Enabled: true
|
||||||
|
Max: 4
|
||||||
AllCops:
|
AllCops:
|
||||||
Exclude:
|
Exclude:
|
||||||
- db/*
|
- db/*
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
class Api::V1::Widget::InboxesController < ApplicationController
|
class Api::V1::Widget::InboxesController < Api::BaseController
|
||||||
|
before_action :authorize_request
|
||||||
|
|
||||||
def create
|
def create
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
channel = web_widgets.create!(
|
channel = web_widgets.create!(
|
||||||
website_name: permitted_params[:website_name],
|
website_name: permitted_params[:website_name],
|
||||||
website_url: permitted_params[:website_url]
|
website_url: permitted_params[:website_url]
|
||||||
)
|
)
|
||||||
inbox = inboxes.create!(name: permitted_params[:website_name], channel: channel)
|
@inbox = inboxes.create!(name: permitted_params[:website_name], channel: channel)
|
||||||
render json: inbox
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def authorize_request
|
||||||
|
authorize ::Inbox
|
||||||
|
end
|
||||||
|
|
||||||
def inboxes
|
def inboxes
|
||||||
current_account.inboxes
|
current_account.inboxes
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
padding: $space-jumbo $space-smaller;
|
padding: $space-jumbo $space-smaller;
|
||||||
|
|
||||||
.message {
|
.message {
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
color: $color-gray;
|
color: $color-gray;
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.spinner {
|
.spinner {
|
||||||
|
@ -31,9 +31,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.message {
|
.message {
|
||||||
width: 50%;
|
|
||||||
margin: 0 auto;
|
|
||||||
color: $color-gray;
|
color: $color-gray;
|
||||||
|
margin: $space-normal auto;
|
||||||
|
width: 90%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
|
|
48
app/javascript/dashboard/components/Code.vue
Normal file
48
app/javascript/dashboard/components/Code.vue
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<template>
|
||||||
|
<div class="code--container">
|
||||||
|
<button class="button small button--copy-code" @click="onCopy">
|
||||||
|
{{ $t('COMPONENTS.CODE.BUTTON_TEXT') }}
|
||||||
|
</button>
|
||||||
|
<highlight-code :lang="lang">
|
||||||
|
{{ script }}
|
||||||
|
</highlight-code>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/* global bus */
|
||||||
|
import 'highlight.js/styles/default.css';
|
||||||
|
import copy from 'copy-text-to-clipboard';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
script: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
lang: {
|
||||||
|
type: String,
|
||||||
|
default: 'javascript',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onCopy() {
|
||||||
|
copy(this.script);
|
||||||
|
bus.$emit('newToastMessage', this.$t('COMPONENTS.CODE.COPY_SUCCESSFUL'));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.code--container {
|
||||||
|
position: relative;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
.button--copy-code {
|
||||||
|
margin-top: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,26 +1,28 @@
|
||||||
/* eslint no-plusplus: 0 */
|
/* eslint no-plusplus: 0 */
|
||||||
/* eslint-env browser */
|
/* eslint-env browser */
|
||||||
|
|
||||||
|
import Bar from './widgets/chart/BarChart';
|
||||||
|
import Code from './Code';
|
||||||
|
import LoadingState from './widgets/LoadingState';
|
||||||
import Modal from './Modal';
|
import Modal from './Modal';
|
||||||
|
import ModalHeader from './ModalHeader';
|
||||||
|
import ReportStatsCard from './widgets/ReportStatsCard';
|
||||||
import Spinner from './Spinner';
|
import Spinner from './Spinner';
|
||||||
import SubmitButton from './buttons/FormSubmitButton';
|
import SubmitButton from './buttons/FormSubmitButton';
|
||||||
import Tabs from './ui/Tabs/Tabs';
|
import Tabs from './ui/Tabs/Tabs';
|
||||||
import TabsItem from './ui/Tabs/TabsItem';
|
import TabsItem from './ui/Tabs/TabsItem';
|
||||||
import LoadingState from './widgets/LoadingState';
|
|
||||||
import ReportStatsCard from './widgets/ReportStatsCard';
|
|
||||||
import Bar from './widgets/chart/BarChart';
|
|
||||||
import ModalHeader from './ModalHeader';
|
|
||||||
|
|
||||||
const WootUIKit = {
|
const WootUIKit = {
|
||||||
|
Bar,
|
||||||
|
Code,
|
||||||
|
LoadingState,
|
||||||
Modal,
|
Modal,
|
||||||
|
ModalHeader,
|
||||||
|
ReportStatsCard,
|
||||||
Spinner,
|
Spinner,
|
||||||
SubmitButton,
|
SubmitButton,
|
||||||
Tabs,
|
Tabs,
|
||||||
TabsItem,
|
TabsItem,
|
||||||
LoadingState,
|
|
||||||
ReportStatsCard,
|
|
||||||
Bar,
|
|
||||||
ModalHeader,
|
|
||||||
install(Vue) {
|
install(Vue) {
|
||||||
const keys = Object.keys(this);
|
const keys = Object.keys(this);
|
||||||
keys.pop(); // remove 'install' from keys
|
keys.pop(); // remove 'install' from keys
|
||||||
|
|
42
app/javascript/dashboard/helper/scriptGenerator.js
Normal file
42
app/javascript/dashboard/helper/scriptGenerator.js
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
export const createWebsiteWidgetScript = websiteToken => `
|
||||||
|
<script>
|
||||||
|
(function(d,t) {
|
||||||
|
var BASE_URL = '${window.location.origin}';
|
||||||
|
var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
|
||||||
|
g.src= BASE_URL + "/packs/js/sdk.js";
|
||||||
|
s.parentNode.insertBefore(g,s);
|
||||||
|
g.onload=function(){
|
||||||
|
window.chatwootSDK.run({
|
||||||
|
websiteToken: '${websiteToken}',
|
||||||
|
baseUrl: BASE_URL
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})(document,"script");
|
||||||
|
</script>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const createMessengerScript = pageId => `
|
||||||
|
<script>
|
||||||
|
window.fbAsyncInit = function() {
|
||||||
|
FB.init({
|
||||||
|
appId: "${window.chatwootConfig.fbAppId}",
|
||||||
|
xfbml: true,
|
||||||
|
version: "v4.0"
|
||||||
|
});
|
||||||
|
};
|
||||||
|
(function(d, s, id){
|
||||||
|
var js, fjs = d.getElementsByTagName(s)[0];
|
||||||
|
if (d.getElementById(id)) { return; }
|
||||||
|
js = d.createElement(s); js.id = id;
|
||||||
|
js.src = "//connect.facebook.net/en_US/sdk.js";
|
||||||
|
fjs.parentNode.insertBefore(js, fjs);
|
||||||
|
}(document, 'script', 'facebook-jssdk'));
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<div class="fb-messengermessageus"
|
||||||
|
messenger_app_id="${window.chatwootConfig.fbAppId}"
|
||||||
|
page_id="${pageId}"
|
||||||
|
color="blue"
|
||||||
|
size="standard" >
|
||||||
|
</div>
|
||||||
|
`;
|
|
@ -6,6 +6,12 @@ export default {
|
||||||
TRIAL_MESSAGE: 'days trial remaining.',
|
TRIAL_MESSAGE: 'days trial remaining.',
|
||||||
TRAIL_BUTTON: 'Buy Now',
|
TRAIL_BUTTON: 'Buy Now',
|
||||||
},
|
},
|
||||||
|
COMPONENTS: {
|
||||||
|
CODE: {
|
||||||
|
BUTTON_TEXT: 'Copy',
|
||||||
|
COPY_SUCCESSFUL: 'Code copied to clipboard successfully',
|
||||||
|
},
|
||||||
|
},
|
||||||
CONFIRM_EMAIL: 'Verifying...',
|
CONFIRM_EMAIL: 'Verifying...',
|
||||||
SETTINGS: {
|
SETTINGS: {
|
||||||
INBOXES: {
|
INBOXES: {
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
},
|
},
|
||||||
"AUTH": {
|
"AUTH": {
|
||||||
"TITLE": "Channels",
|
"TITLE": "Channels",
|
||||||
"DESC": "Currently we support only Facebook Pages as a platform. We have more platforms like Twitter, Telegram and Line in the works, which will be out soon."
|
"DESC": "Currently we support website live chat widgets and Facebook Pages as platforms. We have more platforms like Twitter, Telegram and Line in the works, which will be out soon."
|
||||||
},
|
},
|
||||||
"AGENTS": {
|
"AGENTS": {
|
||||||
"TITLE": "Agents",
|
"TITLE": "Agents",
|
||||||
|
@ -58,7 +58,8 @@
|
||||||
"FINISH": {
|
"FINISH": {
|
||||||
"TITLE": "Your Inbox is ready!",
|
"TITLE": "Your Inbox is ready!",
|
||||||
"MESSAGE": "You can now engage with your customers through your new Channel. Happy supporting ",
|
"MESSAGE": "You can now engage with your customers through your new Channel. Happy supporting ",
|
||||||
"BUTTON_TEXT": "Take me there"
|
"BUTTON_TEXT": "Take me there",
|
||||||
|
"WEBSITE_SUCCESS": "You have successfully finished creating a website channel. Copy the code shown below and paste it on your website. Next time a customer use the live chat, the conversation will automatically appear on your inbox."
|
||||||
},
|
},
|
||||||
"REAUTH": "Reauthorize",
|
"REAUTH": "Reauthorize",
|
||||||
"VIEW": "View",
|
"VIEW": "View",
|
||||||
|
@ -71,7 +72,7 @@
|
||||||
"NO": "No, Keep "
|
"NO": "No, Keep "
|
||||||
},
|
},
|
||||||
"API": {
|
"API": {
|
||||||
"SUCCESS_MESSAGE": "Inbox delete successfully",
|
"SUCCESS_MESSAGE": "Inbox deleted successfully",
|
||||||
"ERROR_MESSAGE": "Could not delete inbox. Please try again later."
|
"ERROR_MESSAGE": "Could not delete inbox. Please try again later."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="wizard-body columns content-box small-9">
|
<div class="wizard-body columns content-box small-9">
|
||||||
<loading-state :message="emptyStateMessage" v-if="showLoader"></loading-state>
|
<loading-state v-if="showLoader" :message="emptyStateMessage">
|
||||||
<form class="row" v-on:submit.prevent="addAgents()" v-if="!showLoader">
|
</loading-state>
|
||||||
|
<form v-if="!showLoader" class="row" @submit.prevent="addAgents()">
|
||||||
<div class="medium-12 columns">
|
<div class="medium-12 columns">
|
||||||
<page-header
|
<page-header
|
||||||
:header-title="$t('INBOX_MGMT.ADD.AGENTS.TITLE')"
|
:header-title="$t('INBOX_MGMT.ADD.AGENTS.TITLE')"
|
||||||
|
@ -10,13 +11,28 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="medium-7 columns">
|
<div class="medium-7 columns">
|
||||||
<div class="medium-12 columns">
|
<div class="medium-12 columns">
|
||||||
<label :class="{ 'error': $v.selectedAgents.$error }">Agents
|
<label :class="{ error: $v.selectedAgents.$error }">
|
||||||
<multiselect v-model="selectedAgents" :options="agentList" track-by="id" label="name" :multiple="true" :close-on-select="false" :clear-on-select="false" :hide-selected="true" placeholder="Pick some" @select="$v.selectedAgents.$touch"></multiselect>
|
Agents
|
||||||
<span class="message" v-if="$v.selectedAgents.$error">Add atleast one agent to your new Inbox</span>
|
<multiselect
|
||||||
|
v-model="selectedAgents"
|
||||||
|
:options="agentList"
|
||||||
|
track-by="id"
|
||||||
|
label="name"
|
||||||
|
:multiple="true"
|
||||||
|
:close-on-select="false"
|
||||||
|
:clear-on-select="false"
|
||||||
|
:hide-selected="true"
|
||||||
|
placeholder="Pick some"
|
||||||
|
@select="$v.selectedAgents.$touch"
|
||||||
|
>
|
||||||
|
</multiselect>
|
||||||
|
<span v-if="$v.selectedAgents.$error" class="message">
|
||||||
|
Add atleast one agent to your new Inbox
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="medium-12 columns text-right">
|
<div class="medium-12 columns text-right">
|
||||||
<input type="submit" value="Create Inbox" class="button">
|
<input type="submit" value="Create Inbox" class="button" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -28,16 +44,13 @@
|
||||||
/* global bus */
|
/* global bus */
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
|
||||||
import ChannelItem from '../../../../components/widgets/ChannelItem';
|
|
||||||
import ChannelApi from '../../../../api/channels';
|
import ChannelApi from '../../../../api/channels';
|
||||||
import router from '../../../index';
|
import router from '../../../index';
|
||||||
import PageHeader from '../SettingsSubPageHeader';
|
import PageHeader from '../SettingsSubPageHeader';
|
||||||
import LoadingState from '../../../../components/widgets/LoadingState';
|
import LoadingState from '../../../../components/widgets/LoadingState';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
ChannelItem,
|
|
||||||
PageHeader,
|
PageHeader,
|
||||||
LoadingState,
|
LoadingState,
|
||||||
},
|
},
|
||||||
|
@ -75,14 +88,20 @@ export default {
|
||||||
ChannelApi.addAgentsToChannel(inboxId, this.selectedAgents.map(x => x.id))
|
ChannelApi.addAgentsToChannel(inboxId, this.selectedAgents.map(x => x.id))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.isCreating = false;
|
this.isCreating = false;
|
||||||
router.replace({ name: 'settings_inbox_finish', params: { page: 'new', inbox_id: this.$route.params.inbox_id } });
|
router.replace({
|
||||||
}).catch((error) => {
|
name: 'settings_inbox_finish',
|
||||||
|
params: {
|
||||||
|
page: 'new',
|
||||||
|
inbox_id: this.$route.params.inbox_id,
|
||||||
|
website_token: this.$route.params.website_token,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
bus.$emit('newToastMessage', error.message);
|
bus.$emit('newToastMessage', error.message);
|
||||||
this.isCreating = false;
|
this.isCreating = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,19 +1,55 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="wizard-body columns content-box small-9">
|
<div class="wizard-body columns content-box small-9">
|
||||||
<empty-state :title="$t('INBOX_MGMT.FINISH.TITLE')" :message="$t('INBOX_MGMT.FINISH.MESSAGE')" :buttonText="$t('INBOX_MGMT.FINISH.BUTTON_TEXT')">
|
<empty-state
|
||||||
|
:title="$t('INBOX_MGMT.FINISH.TITLE')"
|
||||||
|
:message="message"
|
||||||
|
:button-text="$t('INBOX_MGMT.FINISH.BUTTON_TEXT')"
|
||||||
|
>
|
||||||
<div class="medium-12 columns text-center">
|
<div class="medium-12 columns text-center">
|
||||||
<router-link class="button success nice" :to="{ name: 'inbox_dashboard', params: { inboxId: this.$route.params.inbox_id }}">{{$t('INBOX_MGMT.FINISH.BUTTON_TEXT')}}</router-link>
|
<div class="website--code">
|
||||||
|
<woot-code v-if="$route.params.website_token" :script="websiteScript">
|
||||||
|
</woot-code>
|
||||||
|
</div>
|
||||||
|
<router-link
|
||||||
|
class="button success nice"
|
||||||
|
:to="{
|
||||||
|
name: 'inbox_dashboard',
|
||||||
|
params: { inboxId: this.$route.params.inbox_id },
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ $t('INBOX_MGMT.FINISH.BUTTON_TEXT') }}
|
||||||
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
</empty-state>
|
</empty-state>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { createWebsiteWidgetScript } from 'dashboard/helper/scriptGenerator';
|
||||||
import EmptyState from '../../../../components/widgets/EmptyState';
|
import EmptyState from '../../../../components/widgets/EmptyState';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
EmptyState,
|
EmptyState,
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
message() {
|
||||||
|
if (!this.$route.params.website_token) {
|
||||||
|
return this.$t('INBOX_MGMT.FINISH.MESSAGE');
|
||||||
|
}
|
||||||
|
return this.$t('INBOX_MGMT.FINISH.WEBSITE_SUCCESS');
|
||||||
|
},
|
||||||
|
websiteScript() {
|
||||||
|
return createWebsiteWidgetScript(this.$route.params.website_token);
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '~dashboard/assets/scss/variables';
|
||||||
|
|
||||||
|
.website--code {
|
||||||
|
margin: $space-normal auto;
|
||||||
|
max-width: 60%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -15,11 +15,7 @@
|
||||||
<p class="sub-head">
|
<p class="sub-head">
|
||||||
{{ $t('INBOX_MGMT.SETTINGS_POPUP.MESSENGER_SUB_HEAD') }}
|
{{ $t('INBOX_MGMT.SETTINGS_POPUP.MESSENGER_SUB_HEAD') }}
|
||||||
</p>
|
</p>
|
||||||
<p class="code">
|
<woot-code :script="messengerScript"></woot-code>
|
||||||
<code>
|
|
||||||
{{ messengerScript }}
|
|
||||||
</code>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else-if="inbox.channelType === 'Channel::WebWidget'"
|
v-else-if="inbox.channelType === 'Channel::WebWidget'"
|
||||||
|
@ -31,9 +27,7 @@
|
||||||
<p class="sub-head">
|
<p class="sub-head">
|
||||||
{{ $t('INBOX_MGMT.SETTINGS_POPUP.MESSENGER_SUB_HEAD') }}
|
{{ $t('INBOX_MGMT.SETTINGS_POPUP.MESSENGER_SUB_HEAD') }}
|
||||||
</p>
|
</p>
|
||||||
<highlight-code lang="javascript">
|
<woot-code :script="webWidgetScript"></woot-code>
|
||||||
{{ webWidgetScript }}
|
|
||||||
</highlight-code>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="agent-wrapper">
|
<div class="agent-wrapper">
|
||||||
<p class="title">
|
<p class="title">
|
||||||
|
@ -70,7 +64,10 @@
|
||||||
/* eslint-disable no-useless-escape */
|
/* eslint-disable no-useless-escape */
|
||||||
/* global bus */
|
/* global bus */
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import 'highlight.js/styles/default.css';
|
import {
|
||||||
|
createWebsiteWidgetScript,
|
||||||
|
createMessengerScript,
|
||||||
|
} from 'dashboard/helper/scriptGenerator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['onClose', 'inbox', 'show'],
|
props: ['onClose', 'inbox', 'show'],
|
||||||
|
@ -78,49 +75,18 @@ export default {
|
||||||
return {
|
return {
|
||||||
selectedAgents: [],
|
selectedAgents: [],
|
||||||
isUpdating: false,
|
isUpdating: false,
|
||||||
messengerScript: `<script>
|
|
||||||
window.fbAsyncInit = function() {
|
|
||||||
FB.init({
|
|
||||||
appId: "${window.chatwootConfig.fbAppId}",
|
|
||||||
xfbml: true,
|
|
||||||
version: "v4.0"
|
|
||||||
});
|
|
||||||
};
|
|
||||||
(function(d, s, id){
|
|
||||||
var js, fjs = d.getElementsByTagName(s)[0];
|
|
||||||
if (d.getElementById(id)) { return; }
|
|
||||||
js = d.createElement(s); js.id = id;
|
|
||||||
js.src = "//connect.facebook.net/en_US/sdk.js";
|
|
||||||
fjs.parentNode.insertBefore(js, fjs);
|
|
||||||
}(document, 'script', 'facebook-jssdk'));
|
|
||||||
|
|
||||||
<\/script>
|
|
||||||
<div class="fb-messengermessageus"
|
|
||||||
messenger_app_id="${window.chatwootConfig.fbAppId}"
|
|
||||||
page_id="${this.inbox.pageId}"
|
|
||||||
color="blue"
|
|
||||||
size="standard" >
|
|
||||||
</div>`,
|
|
||||||
webWidgetScript: `
|
|
||||||
(function(d,t) {
|
|
||||||
var BASE_URL = '${window.location.origin}';
|
|
||||||
var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
|
|
||||||
g.src= BASE_URL + "/packs/js/sdk.js";
|
|
||||||
s.parentNode.insertBefore(g,s);
|
|
||||||
g.onload=function(){
|
|
||||||
window.chatwootSDK.run({
|
|
||||||
websiteToken: '${this.inbox.websiteToken}',
|
|
||||||
baseUrl: BASE_URL
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})(document,"script");
|
|
||||||
`,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
agentList: 'getAgents',
|
agentList: 'getAgents',
|
||||||
}),
|
}),
|
||||||
|
webWidgetScript() {
|
||||||
|
return createWebsiteWidgetScript(this.inbox.websiteToken);
|
||||||
|
},
|
||||||
|
messengerScript() {
|
||||||
|
return createMessengerScript(this.inbox.pageId);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$store.dispatch('fetchAgents').then(() => {
|
this.$store.dispatch('fetchAgents').then(() => {
|
||||||
|
|
|
@ -4,10 +4,11 @@
|
||||||
:header-title="$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.TITLE')"
|
:header-title="$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.TITLE')"
|
||||||
:header-content="$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.DESC')"
|
:header-content="$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.DESC')"
|
||||||
/>
|
/>
|
||||||
<loading-state
|
<woot-loading-state
|
||||||
v-if="isCreating"
|
v-if="isCreating"
|
||||||
message="Creating Website Support Channel"
|
message="Creating Website Support Channel"
|
||||||
></loading-state>
|
>
|
||||||
|
</woot-loading-state>
|
||||||
<form v-if="!isCreating" class="row" @submit.prevent="createChannel()">
|
<form v-if="!isCreating" class="row" @submit.prevent="createChannel()">
|
||||||
<div class="medium-12 columns">
|
<div class="medium-12 columns">
|
||||||
<label>
|
<label>
|
||||||
|
@ -61,10 +62,14 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
bus.$on('new_website_channel', ({ inboxId }) => {
|
bus.$on('new_website_channel', ({ inboxId, websiteToken }) => {
|
||||||
router.replace({
|
router.replace({
|
||||||
name: 'settings_inboxes_add_agents',
|
name: 'settings_inboxes_add_agents',
|
||||||
params: { page: 'new', inbox_id: inboxId },
|
params: {
|
||||||
|
page: 'new',
|
||||||
|
inbox_id: inboxId,
|
||||||
|
website_token: websiteToken,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -71,7 +71,10 @@ const actions = {
|
||||||
try {
|
try {
|
||||||
const response = await WebChannel.create(params);
|
const response = await WebChannel.create(params);
|
||||||
commit(types.default.SET_INBOX_ITEM, response);
|
commit(types.default.SET_INBOX_ITEM, response);
|
||||||
bus.$emit('new_website_channel', { inboxId: response.data.id });
|
bus.$emit('new_website_channel', {
|
||||||
|
inboxId: response.data.id,
|
||||||
|
websiteToken: response.data.website_token,
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Handle error
|
// Handle error
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,10 @@ class InboxPolicy < ApplicationPolicy
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
@user.administrator?
|
||||||
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
@user.administrator?
|
@user.administrator?
|
||||||
end
|
end
|
||||||
|
|
5
app/views/api/v1/widget/inboxes/create.json.jbuilder
Normal file
5
app/views/api/v1/widget/inboxes/create.json.jbuilder
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
json.id @inbox.id
|
||||||
|
json.channel_id @inbox.channel_id
|
||||||
|
json.name @inbox.name
|
||||||
|
json.channel_type @inbox.channel_type
|
||||||
|
json.website_token @inbox.channel.try(:website_token)
|
|
@ -20,6 +20,7 @@
|
||||||
"babel-plugin-transform-vue-jsx": "^3.7.0",
|
"babel-plugin-transform-vue-jsx": "^3.7.0",
|
||||||
"bourbon": "^6.0.0",
|
"bourbon": "^6.0.0",
|
||||||
"chart.js": "~2.5.0",
|
"chart.js": "~2.5.0",
|
||||||
|
"copy-text-to-clipboard": "^2.1.1",
|
||||||
"dotenv": "^8.0.0",
|
"dotenv": "^8.0.0",
|
||||||
"emojione": "~2.2.7",
|
"emojione": "~2.2.7",
|
||||||
"foundation-sites": "~6.5.3",
|
"foundation-sites": "~6.5.3",
|
||||||
|
|
42
spec/controllers/api/v1/widget/inboxes_controller_spec.rb
Normal file
42
spec/controllers/api/v1/widget/inboxes_controller_spec.rb
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe '/api/v1/widget/inboxes', type: :request do
|
||||||
|
let(:account) { create(:account) }
|
||||||
|
let(:admin) { create(:user, account: account, role: :administrator) }
|
||||||
|
let(:agent) { create(:user, account: account, role: :agent) }
|
||||||
|
let(:params) { { website: { website_name: 'test', website_url: 'test.com' } } }
|
||||||
|
|
||||||
|
describe 'POST /api/v1/widget/inboxes' do
|
||||||
|
context 'when unauthenticated user' do
|
||||||
|
it 'returns unauthorized' do
|
||||||
|
post '/api/v1/widget/inboxes', params: params
|
||||||
|
expect(response).to have_http_status(:unauthorized)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user is logged in' do
|
||||||
|
context 'with user as administrator' do
|
||||||
|
it 'creates inbox and returns website_token' do
|
||||||
|
post '/api/v1/widget/inboxes', params: params, headers: admin.create_new_auth_token, as: :json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
json_response = JSON.parse(response.body)
|
||||||
|
|
||||||
|
expect(json_response['name']).to eq('test')
|
||||||
|
expect(json_response['website_token']).not_to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with user as agent' do
|
||||||
|
it 'returns unauthorized' do
|
||||||
|
post '/api/v1/widget/inboxes',
|
||||||
|
params: params,
|
||||||
|
headers: agent.create_new_auth_token,
|
||||||
|
as: :json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:unauthorized)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -2764,6 +2764,11 @@ copy-descriptor@^0.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
|
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
|
||||||
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
|
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
|
||||||
|
|
||||||
|
copy-text-to-clipboard@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-2.1.1.tgz#5340e8620976d2dd9de0ff11493d13a80d600fd2"
|
||||||
|
integrity sha512-oSuMj4ArDGSLcLPsDhzWOhalzOVV0ErCHNfZNNr+spC+iWJ6PVSLzPPrJw/rcdFZyOhugn8iw6O0nrpY/ZrEMg==
|
||||||
|
|
||||||
core-js-compat@^3.1.1:
|
core-js-compat@^3.1.1:
|
||||||
version "3.2.1"
|
version "3.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.2.1.tgz#0cbdbc2e386e8e00d3b85dc81c848effec5b8150"
|
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.2.1.tgz#0cbdbc2e386e8e00d3b85dc81c848effec5b8150"
|
||||||
|
|
Loading…
Reference in a new issue