feat: Allow agent-bots to be created from the UI (#4153)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
parent
9bfbd528ef
commit
47676c3cce
17 changed files with 1573 additions and 40 deletions
|
@ -16,8 +16,7 @@ class DashboardController < ActionController::Base
|
||||||
@global_config = GlobalConfig.get(
|
@global_config = GlobalConfig.get(
|
||||||
'LOGO', 'LOGO_THUMBNAIL',
|
'LOGO', 'LOGO_THUMBNAIL',
|
||||||
'INSTALLATION_NAME',
|
'INSTALLATION_NAME',
|
||||||
'WIDGET_BRAND_URL',
|
'WIDGET_BRAND_URL', 'TERMS_URL',
|
||||||
'TERMS_URL',
|
|
||||||
'PRIVACY_URL',
|
'PRIVACY_URL',
|
||||||
'DISPLAY_MANIFEST',
|
'DISPLAY_MANIFEST',
|
||||||
'CREATE_NEW_ACCOUNT_FROM_DASHBOARD',
|
'CREATE_NEW_ACCOUNT_FROM_DASHBOARD',
|
||||||
|
@ -30,7 +29,8 @@ class DashboardController < ActionController::Base
|
||||||
'HCAPTCHA_SITE_KEY',
|
'HCAPTCHA_SITE_KEY',
|
||||||
'LOGOUT_REDIRECT_LINK',
|
'LOGOUT_REDIRECT_LINK',
|
||||||
'DISABLE_USER_PROFILE_UPDATE',
|
'DISABLE_USER_PROFILE_UPDATE',
|
||||||
'DEPLOYMENT_ENV'
|
'DEPLOYMENT_ENV',
|
||||||
|
'CSML_EDITOR_HOST'
|
||||||
).merge(app_config)
|
).merge(app_config)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<span>
|
<span>
|
||||||
{{ textToBeDisplayed }}
|
{{ textToBeDisplayed }}
|
||||||
<button class="show-more--button" @click="toggleShowMore">
|
<button
|
||||||
|
v-if="text.length > limit"
|
||||||
|
class="show-more--button"
|
||||||
|
@click="toggleShowMore"
|
||||||
|
>
|
||||||
{{ buttonLabel }}
|
{{ buttonLabel }}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
|
@ -25,7 +29,7 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
textToBeDisplayed() {
|
textToBeDisplayed() {
|
||||||
if (this.showMore) {
|
if (this.showMore || this.text.length <= this.limit) {
|
||||||
return this.text;
|
return this.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,62 @@
|
||||||
{
|
{
|
||||||
"AGENT_BOTS": {
|
"AGENT_BOTS": {
|
||||||
"HEADER": "Bots"
|
"HEADER": "Bots",
|
||||||
|
"LOADING_EDITOR": "Loading Editor...",
|
||||||
|
"HEADER_BTN_TXT": "Add Bot Configuration",
|
||||||
|
"SIDEBAR_TXT": "<p><b>Agent Bots</b> <p>Agent bots allows you to automate the conversations</p>",
|
||||||
|
"CSML_BOT_EDITOR": {
|
||||||
|
"NAME": {
|
||||||
|
"LABEL": "Bot Name",
|
||||||
|
"PLACEHOLDER": "Give your bot a name",
|
||||||
|
"ERROR": "Bot name is required"
|
||||||
|
},
|
||||||
|
"DESCRIPTION": {
|
||||||
|
"LABEL": "Bot Description",
|
||||||
|
"PLACEHOLDER": "What does this bot do?"
|
||||||
|
},
|
||||||
|
"BOT_CONFIG": {
|
||||||
|
"ERROR": "Please enter your CSML bot configuration above",
|
||||||
|
"API_ERROR": "Your CSML configuration is invalid, please fix it and try again."
|
||||||
|
},
|
||||||
|
"SUBMIT": "Validate and save"
|
||||||
|
},
|
||||||
|
"ADD": {
|
||||||
|
"TITLE": "Configure new bot",
|
||||||
|
"CANCEL_BUTTON_TEXT": "Cancel",
|
||||||
|
"API": {
|
||||||
|
"SUCCESS_MESSAGE": "Bot added successfully",
|
||||||
|
"ERROR_MESSAGE": "Could not add bot, Please try again later"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"LIST": {
|
||||||
|
"404": "No Bots found, you can create a bot by clicking the 'Configure new bot' Button ↗",
|
||||||
|
"LOADING": "Fetching Bots...",
|
||||||
|
"TYPE": "Bot Type"
|
||||||
|
},
|
||||||
|
"DELETE": {
|
||||||
|
"BUTTON_TEXT": "Delete",
|
||||||
|
"TITLE": "Delete Bot",
|
||||||
|
"SUBMIT": "Delete",
|
||||||
|
"CANCEL_BUTTON_TEXT": "Cancel",
|
||||||
|
"DESCRIPTION": "Are you sure you want to delete this bot? This action is irreversible",
|
||||||
|
"API": {
|
||||||
|
"SUCCESS_MESSAGE": "Bot deleted successfully",
|
||||||
|
"ERROR_MESSAGE": "Could not able to delete bot, Please try again later"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"EDIT": {
|
||||||
|
"BUTTON_TEXT": "Edit",
|
||||||
|
"LOADING": "Fetching Bots...",
|
||||||
|
"TITLE": "Edit Bot",
|
||||||
|
"CANCEL_BUTTON_TEXT": "Cancel",
|
||||||
|
"API": {
|
||||||
|
"SUCCESS_MESSAGE": "Bot updated successfully",
|
||||||
|
"ERROR_MESSAGE": "Could not update bot, Please try again later"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TYPES": {
|
||||||
|
"WEBHOOK": "Webhook Bot",
|
||||||
|
"CSML": "CSML Bot"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,103 @@
|
||||||
<template>
|
<template>
|
||||||
<div>Agent Bot list</div>
|
<div class="column content-box">
|
||||||
|
<div class="row">
|
||||||
|
<div class="small-8 columns with-right-space">
|
||||||
|
<woot-loading-state
|
||||||
|
v-if="uiFlags.isFetching"
|
||||||
|
:message="$t('AGENT_BOTS.LIST.LOADING')"
|
||||||
|
/>
|
||||||
|
<table v-else-if="agentBots.length" class="woot-table">
|
||||||
|
<tbody>
|
||||||
|
<agent-bot-row
|
||||||
|
v-for="(agentBot, index) in agentBots"
|
||||||
|
:key="agentBot.id"
|
||||||
|
:agent-bot="agentBot"
|
||||||
|
:index="index"
|
||||||
|
@delete="onDeleteAgentBot"
|
||||||
|
@edit="onEditAgentBot"
|
||||||
|
/>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p v-else class="no-items-error-message">
|
||||||
|
{{ $t('AGENT_BOTS.LIST.404') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="small-4 columns content-box">
|
||||||
|
<p v-html="$t('AGENT_BOTS.SIDEBAR_TXT')" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<woot-button
|
||||||
|
color-scheme="success"
|
||||||
|
class-names="button--fixed-right-top"
|
||||||
|
icon="add-circle"
|
||||||
|
>
|
||||||
|
<router-link :to="newAgentBotsURL" class="white-text">
|
||||||
|
{{ $t('AGENT_BOTS.ADD.TITLE') }}
|
||||||
|
</router-link>
|
||||||
|
</woot-button>
|
||||||
|
<woot-confirm-modal
|
||||||
|
ref="confirmDialog"
|
||||||
|
:title="$t('AGENT_BOTS.DELETE.TITLE')"
|
||||||
|
:description="$t('AGENT_BOTS.DELETE.DESCRIPTION')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import { frontendURL } from '../../../../helper/URLHelper';
|
||||||
|
import AgentBotRow from './components/AgentBotRow.vue';
|
||||||
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: { AgentBotRow },
|
||||||
|
mixins: [alertMixin],
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
|
accountId: 'getCurrentAccountId',
|
||||||
agentBots: 'agentBots/getBots',
|
agentBots: 'agentBots/getBots',
|
||||||
uiFlags: 'agentBots/getUIFlags',
|
uiFlags: 'agentBots/getUIFlags',
|
||||||
}),
|
}),
|
||||||
|
newAgentBotsURL() {
|
||||||
|
return frontendURL(
|
||||||
|
`accounts/${this.accountId}/settings/agent-bots/csml/new`
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$store.dispatch('agentBots/get');
|
this.$store.dispatch('agentBots/get');
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
|
async onDeleteAgentBot(bot) {
|
||||||
|
const ok = await this.$refs.confirmDialog.showConfirmation();
|
||||||
|
if (ok) {
|
||||||
|
try {
|
||||||
|
await this.$store.dispatch('agentBots/delete', bot.id);
|
||||||
|
this.showAlert(this.$t('AGENT_BOTS.DELETE.API.SUCCESS_MESSAGE'));
|
||||||
|
} catch (error) {
|
||||||
|
this.showAlert(this.$t('AGENT_BOTS.DELETE.API.ERROR_MESSAGE'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onEditAgentBot(bot) {
|
||||||
|
this.$router.push(
|
||||||
|
frontendURL(
|
||||||
|
`accounts/${this.accountId}/settings/agent-bots/csml/${bot.id}`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.bots-list {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
.nowrap {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.white-text {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
<template>
|
||||||
|
<tr>
|
||||||
|
<td class="agent-bot--details">
|
||||||
|
<div class="agent-bot--link">
|
||||||
|
{{ agentBot.name }}
|
||||||
|
(<agent-bot-type :bot-type="agentBot.bot_type" />)
|
||||||
|
</div>
|
||||||
|
<div class="agent-bot--description">
|
||||||
|
<show-more :text="agentBot.description" :limit="120" />
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="button-wrapper">
|
||||||
|
<woot-button
|
||||||
|
v-if="isACSMLTypeBot"
|
||||||
|
v-tooltip.top="$t('AGENT_BOTS.EDIT.BUTTON_TEXT')"
|
||||||
|
variant="smooth"
|
||||||
|
size="tiny"
|
||||||
|
color-scheme="secondary"
|
||||||
|
icon="edit"
|
||||||
|
@click="$emit('edit', agentBot)"
|
||||||
|
/>
|
||||||
|
<woot-button
|
||||||
|
v-tooltip.top="$t('AGENT_BOTS.DELETE.BUTTON_TEXT')"
|
||||||
|
variant="smooth"
|
||||||
|
color-scheme="alert"
|
||||||
|
size="tiny"
|
||||||
|
icon="dismiss-circle"
|
||||||
|
@click="$emit('delete', agentBot, index)"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import ShowMore from 'dashboard/components/widgets/ShowMore';
|
||||||
|
import AgentBotType from './AgentBotType.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { ShowMore, AgentBotType },
|
||||||
|
props: {
|
||||||
|
agentBot: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isACSMLTypeBot() {
|
||||||
|
const { bot_type: botType } = this.agentBot;
|
||||||
|
return botType === 'csml';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.agent-bot--link {
|
||||||
|
align-items: center;
|
||||||
|
color: var(--s-800);
|
||||||
|
display: flex;
|
||||||
|
font-weight: var(--font-weight-medium);
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-bot--description {
|
||||||
|
color: var(--s-700);
|
||||||
|
font-size: var(--font-size-mini);
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-bot--type {
|
||||||
|
color: var(--s-600);
|
||||||
|
font-weight: var(--font-weight-medium);
|
||||||
|
margin-bottom: var(--space-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-bot--details {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-wrapper {
|
||||||
|
max-width: var(--space-mega);
|
||||||
|
min-width: auto;
|
||||||
|
|
||||||
|
button:nth-child(2) {
|
||||||
|
margin-left: var(--space-normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,41 @@
|
||||||
|
<template>
|
||||||
|
<span>
|
||||||
|
<img
|
||||||
|
v-tooltip="botTypeConfig[botType].label"
|
||||||
|
class="agent-bot-type--thumbnail"
|
||||||
|
:src="botTypeConfig[botType].thumbnail"
|
||||||
|
:alt="botTypeConfig[botType].label"
|
||||||
|
/>
|
||||||
|
<span>{{ botTypeConfig[botType].label }}</span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
botType: {
|
||||||
|
type: String,
|
||||||
|
default: 'webhook',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
botTypeConfig: {
|
||||||
|
csml: {
|
||||||
|
label: this.$t('AGENT_BOTS.TYPES.CSML'),
|
||||||
|
thumbnail: '/dashboard/images/agent-bots/csml.png',
|
||||||
|
},
|
||||||
|
webhook: {
|
||||||
|
label: this.$t('AGENT_BOTS.TYPES.WEBHOOK'),
|
||||||
|
thumbnail: '/dashboard/images/agent-bots/webhook.svg',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.agent-bot-type--thumbnail {
|
||||||
|
width: auto;
|
||||||
|
height: var(--space-slab);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,121 @@
|
||||||
|
<template>
|
||||||
|
<div class="column content-box no-padding">
|
||||||
|
<div class="row">
|
||||||
|
<div class="small-8 columns">
|
||||||
|
<div class="full-height editor-wrapper">
|
||||||
|
<csml-monaco-editor v-model="bot.csmlContent" class="bot-editor" />
|
||||||
|
<div v-if="$v.bot.csmlContent.$error" class="editor-error-message">
|
||||||
|
<span>{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.BOT_CONFIG.ERROR') }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="small-4 columns content-box full-height">
|
||||||
|
<form class="details-editor" @submit.prevent="onSubmit">
|
||||||
|
<div>
|
||||||
|
<label :class="{ error: $v.bot.name.$error }">
|
||||||
|
{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.NAME.LABEL') }}
|
||||||
|
<input
|
||||||
|
v-model="bot.name"
|
||||||
|
type="text"
|
||||||
|
:placeholder="$t('AGENT_BOTS.CSML_BOT_EDITOR.NAME.PLACEHOLDER')"
|
||||||
|
/>
|
||||||
|
<span v-if="$v.bot.name.$error" class="message">
|
||||||
|
{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.NAME.ERROR') }}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.DESCRIPTION.LABEL') }}
|
||||||
|
<textarea
|
||||||
|
v-model="bot.description"
|
||||||
|
rows="4"
|
||||||
|
:placeholder="
|
||||||
|
$t('AGENT_BOTS.CSML_BOT_EDITOR.DESCRIPTION.PLACEHOLDER')
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<woot-button>
|
||||||
|
{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.SUBMIT') }}
|
||||||
|
</woot-button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { required } from 'vuelidate/lib/validators';
|
||||||
|
import CsmlMonacoEditor from './CSMLMonacoEditor.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { CsmlMonacoEditor },
|
||||||
|
props: {
|
||||||
|
agentBot: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
validations: {
|
||||||
|
bot: {
|
||||||
|
name: { required },
|
||||||
|
csmlContent: { required },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
bot: {
|
||||||
|
name: this.agentBot.name || '',
|
||||||
|
description: this.agentBot.description || '',
|
||||||
|
csmlContent: this.agentBot.bot_config.csml_content || '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onSubmit() {
|
||||||
|
this.$v.$touch();
|
||||||
|
if (this.$v.$invalid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$emit('submit', {
|
||||||
|
id: this.agentBot.id || '',
|
||||||
|
...this.bot,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.no-padding {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
.full-height {
|
||||||
|
height: calc(100vh - 56px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bot-editor {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.details-editor {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.editor-wrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.editor-error-message {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: #e0bbbb;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,69 @@
|
||||||
|
<template>
|
||||||
|
<div class="csml-editor--container">
|
||||||
|
<loading-state
|
||||||
|
v-if="iframeLoading"
|
||||||
|
:message="$t('AGENT_BOTS.LOADING_EDITOR')"
|
||||||
|
class="dashboard-app_loading-container"
|
||||||
|
/>
|
||||||
|
<iframe
|
||||||
|
id="csml-editor--frame"
|
||||||
|
:src="globalConfig.csmlEditorHost"
|
||||||
|
@load="onEditorLoad"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import LoadingState from 'dashboard/components/widgets/LoadingState';
|
||||||
|
import { mapGetters } from 'vuex';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { LoadingState },
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
iframeLoading: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters({
|
||||||
|
globalConfig: 'globalConfig/get',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
window.onmessage = e => {
|
||||||
|
if (
|
||||||
|
typeof e.data !== 'string' ||
|
||||||
|
!e.data.startsWith('chatwoot-csml-editor:update')
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const csmlContent = e.data.replace('chatwoot-csml-editor:update', '');
|
||||||
|
this.$emit('input', csmlContent);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onEditorLoad() {
|
||||||
|
const frameElement = document.getElementById(`csml-editor--frame`);
|
||||||
|
const eventData = {
|
||||||
|
event: 'editorContext',
|
||||||
|
data: this.value || '',
|
||||||
|
};
|
||||||
|
frameElement.contentWindow.postMessage(JSON.stringify(eventData), '*');
|
||||||
|
this.iframeLoading = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#csml-editor--frame {
|
||||||
|
border: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,6 +1,48 @@
|
||||||
<template>
|
<template>
|
||||||
<div>Component to edit CSML Bots</div>
|
<csml-bot-editor
|
||||||
|
v-if="agentBot.id"
|
||||||
|
:agent-bot="agentBot"
|
||||||
|
@submit="updateBot"
|
||||||
|
/>
|
||||||
|
<div v-else class="column content-box no-padding">
|
||||||
|
<spinner />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
export default {};
|
import Spinner from 'shared/components/Spinner';
|
||||||
|
import CsmlBotEditor from '../components/CSMLBotEditor.vue';
|
||||||
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
|
||||||
|
import { mapGetters } from 'vuex';
|
||||||
|
export default {
|
||||||
|
components: { Spinner, CsmlBotEditor },
|
||||||
|
mixins: [alertMixin],
|
||||||
|
computed: {
|
||||||
|
...mapGetters({ uiFlags: 'agentBots/uiFlags' }),
|
||||||
|
agentBot() {
|
||||||
|
return this.$store.getters['agentBots/getBot'](this.$route.params.botId);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$store.dispatch('agentBots/show', this.$route.params.botId);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async updateBot(bot) {
|
||||||
|
try {
|
||||||
|
await this.$store.dispatch('agentBots/update', {
|
||||||
|
id: bot.id,
|
||||||
|
name: bot.name,
|
||||||
|
description: bot.description,
|
||||||
|
bot_type: 'csml',
|
||||||
|
bot_config: { csml_content: bot.csmlContent },
|
||||||
|
});
|
||||||
|
this.showAlert(this.$t('AGENT_BOTS.EDIT.API.SUCCESS_MESSAGE'));
|
||||||
|
} catch (error) {
|
||||||
|
this.showAlert(
|
||||||
|
this.$t('AGENT_BOTS.CSML_BOT_EDITOR.BOT_CONFIG.API_ERROR')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,6 +1,42 @@
|
||||||
<template>
|
<template>
|
||||||
<div>Component to create CSML Bots</div>
|
<csml-bot-editor :agent-bot="{ bot_config: {} }" @submit="saveBot" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {};
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
import CsmlBotEditor from '../components/CSMLBotEditor.vue';
|
||||||
|
import { frontendURL } from '../../../../../helper/URLHelper';
|
||||||
|
import { mapGetters } from 'vuex';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { CsmlBotEditor },
|
||||||
|
mixins: [alertMixin],
|
||||||
|
computed: {
|
||||||
|
...mapGetters({
|
||||||
|
accountId: 'getCurrentAccountId',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async saveBot(bot) {
|
||||||
|
try {
|
||||||
|
const agentBot = await this.$store.dispatch('agentBots/create', {
|
||||||
|
name: bot.name,
|
||||||
|
description: bot.description,
|
||||||
|
bot_type: 'csml',
|
||||||
|
bot_config: { csml_content: bot.csmlContent },
|
||||||
|
});
|
||||||
|
if (agentBot) {
|
||||||
|
this.$router.replace(
|
||||||
|
frontendURL(
|
||||||
|
`accounts/${this.accountId}/settings/agent-bots/csml/${agentBot.id}`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.showAlert(this.$t('AGENT_BOTS.ADD.API.SUCCESS_MESSAGE'));
|
||||||
|
} catch (error) {
|
||||||
|
this.showAlert(this.$t('AGENT_BOTS.ADD.API.ERROR_MESSAGE'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -16,7 +16,7 @@ const state = {
|
||||||
|
|
||||||
export const getters = {
|
export const getters = {
|
||||||
getAccount: $state => id => {
|
getAccount: $state => id => {
|
||||||
return $state.records.find(record => record.id === Number(id));
|
return $state.records.find(record => record.id === Number(id)) || {};
|
||||||
},
|
},
|
||||||
getUIFlags($state) {
|
getUIFlags($state) {
|
||||||
return $state.uiFlags;
|
return $state.uiFlags;
|
||||||
|
|
|
@ -44,11 +44,13 @@ export const actions = {
|
||||||
try {
|
try {
|
||||||
const response = await AgentBotsAPI.create(agentBotObj);
|
const response = await AgentBotsAPI.create(agentBotObj);
|
||||||
commit(types.ADD_AGENT_BOT, response.data);
|
commit(types.ADD_AGENT_BOT, response.data);
|
||||||
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throwErrorMessage(error);
|
throwErrorMessage(error);
|
||||||
} finally {
|
} finally {
|
||||||
commit(types.SET_AGENT_BOT_UI_FLAG, { isCreating: false });
|
commit(types.SET_AGENT_BOT_UI_FLAG, { isCreating: false });
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
},
|
},
|
||||||
update: async ({ commit }, { id, ...agentBotObj }) => {
|
update: async ({ commit }, { id, ...agentBotObj }) => {
|
||||||
commit(types.SET_AGENT_BOT_UI_FLAG, { isUpdating: true });
|
commit(types.SET_AGENT_BOT_UI_FLAG, { isUpdating: true });
|
||||||
|
@ -76,7 +78,7 @@ export const actions = {
|
||||||
commit(types.SET_AGENT_BOT_UI_FLAG, { isFetchingItem: true });
|
commit(types.SET_AGENT_BOT_UI_FLAG, { isFetchingItem: true });
|
||||||
try {
|
try {
|
||||||
const { data } = await AgentBotsAPI.show(id);
|
const { data } = await AgentBotsAPI.show(id);
|
||||||
commit(types.DELETE_AGENT_BOT, data);
|
commit(types.ADD_AGENT_BOT, data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throwErrorMessage(error);
|
throwErrorMessage(error);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -92,7 +94,7 @@ export const mutations = {
|
||||||
...data,
|
...data,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[types.ADD_AGENT_BOT]: MutationHelpers.create,
|
[types.ADD_AGENT_BOT]: MutationHelpers.setSingleRecord,
|
||||||
[types.SET_AGENT_BOTS]: MutationHelpers.set,
|
[types.SET_AGENT_BOTS]: MutationHelpers.set,
|
||||||
[types.EDIT_AGENT_BOT]: MutationHelpers.update,
|
[types.EDIT_AGENT_BOT]: MutationHelpers.update,
|
||||||
[types.DELETE_AGENT_BOT]: MutationHelpers.destroy,
|
[types.DELETE_AGENT_BOT]: MutationHelpers.destroy,
|
||||||
|
|
|
@ -4,6 +4,7 @@ const {
|
||||||
APP_VERSION: appVersion,
|
APP_VERSION: appVersion,
|
||||||
BRAND_NAME: brandName,
|
BRAND_NAME: brandName,
|
||||||
CHATWOOT_INBOX_TOKEN: chatwootInboxToken,
|
CHATWOOT_INBOX_TOKEN: chatwootInboxToken,
|
||||||
|
CSML_EDITOR_HOST: csmlEditorHost,
|
||||||
CREATE_NEW_ACCOUNT_FROM_DASHBOARD: createNewAccountFromDashboard,
|
CREATE_NEW_ACCOUNT_FROM_DASHBOARD: createNewAccountFromDashboard,
|
||||||
DIRECT_UPLOADS_ENABLED: directUploadsEnabled,
|
DIRECT_UPLOADS_ENABLED: directUploadsEnabled,
|
||||||
DISPLAY_MANIFEST: displayManifest,
|
DISPLAY_MANIFEST: displayManifest,
|
||||||
|
@ -24,6 +25,7 @@ const state = {
|
||||||
appVersion,
|
appVersion,
|
||||||
brandName,
|
brandName,
|
||||||
chatwootInboxToken,
|
chatwootInboxToken,
|
||||||
|
csmlEditorHost,
|
||||||
deploymentEnv,
|
deploymentEnv,
|
||||||
createNewAccountFromDashboard,
|
createNewAccountFromDashboard,
|
||||||
directUploadsEnabled: directUploadsEnabled === 'true',
|
directUploadsEnabled: directUploadsEnabled === 'true',
|
||||||
|
|
|
@ -72,3 +72,5 @@
|
||||||
value:
|
value:
|
||||||
- name: DEPLOYMENT_ENV
|
- name: DEPLOYMENT_ENV
|
||||||
value: self-hosted
|
value: self-hosted
|
||||||
|
- name: CSML_EDITOR_HOST
|
||||||
|
value:
|
||||||
|
|
BIN
public/dashboard/images/agent-bots/csml.png
Normal file
BIN
public/dashboard/images/agent-bots/csml.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.2 KiB |
64
public/dashboard/images/agent-bots/webhook.svg
Normal file
64
public/dashboard/images/agent-bots/webhook.svg
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||||
|
<path style="fill:#4D4D4D;" d="M188.287,512c-41.473,0-75.213-33.74-75.213-75.213V246.75c0-4.142,3.358-7.5,7.5-7.5
|
||||||
|
s7.5,3.358,7.5,7.5v190.037c0,33.202,27.011,60.213,60.213,60.213c16.082,0,31.204-6.266,42.582-17.644
|
||||||
|
c11.37-11.37,17.631-26.488,17.631-42.569V75.213C248.5,33.74,282.24,0,323.713,0c20.088,0,38.978,7.826,53.189,22.037
|
||||||
|
c14.203,14.202,22.024,33.087,22.024,53.176V256c0,4.142-3.358,7.5-7.5,7.5s-7.5-3.358-7.5-7.5V75.213
|
||||||
|
c0-16.082-6.261-31.2-17.63-42.569C354.918,21.266,339.794,15,323.713,15C290.511,15,263.5,42.011,263.5,75.213v361.574
|
||||||
|
c0,20.088-7.822,38.973-22.024,53.176C227.265,504.174,208.376,512,188.287,512z"/>
|
||||||
|
<g>
|
||||||
|
<rect x="113.07" y="246.75" style="fill:#3B3B3B;" width="15" height="26.875"/>
|
||||||
|
<rect x="383.93" y="235.31" style="fill:#3B3B3B;" width="15" height="26.875"/>
|
||||||
|
</g>
|
||||||
|
<rect x="361.9" y="385" style="fill:#CCCCCC;" width="57.983" height="39.944"/>
|
||||||
|
<rect x="361.9" y="385" style="fill:#ADADAD;" width="57.983" height="22.19"/>
|
||||||
|
<path style="fill:#A6E2E3;" d="M432.802,298.678v86.977c0,3.616-2.932,6.548-6.548,6.548h-70.721c-3.617,0-6.548-2.932-6.548-6.548
|
||||||
|
v-87.746c0-23.439,19.239-42.39,42.803-41.899C414.709,256.486,432.802,275.751,432.802,298.678z"/>
|
||||||
|
<rect x="92.11" y="87.06" style="fill:#CCCCCC;" width="57.983" height="36.28"/>
|
||||||
|
<rect x="92.11" y="105.43" style="fill:#ADADAD;" width="57.983" height="17.907"/>
|
||||||
|
<path style="fill:#FFA638;" d="M163.015,126.345v86.977c0,22.927-18.093,42.191-41.015,42.668
|
||||||
|
c-23.564,0.49-42.803-18.461-42.803-41.899v-87.746c0-3.616,2.932-6.548,6.548-6.548l0,0h70.721l0,0
|
||||||
|
C160.083,119.797,163.015,122.729,163.015,126.345z"/>
|
||||||
|
<path style="fill:#7CCBCC;" d="M391.787,256.009c-5.066-0.105-9.93,0.693-14.447,2.236c0.396-0.081,0.781-0.166,1.142-0.257
|
||||||
|
c2.982-0.755,5.201-0.896,7.513-0.85c18.954,0.395,34.375,16.494,34.375,35.888v86.981c0,3.614-2.93,6.544-6.544,6.544H355.53
|
||||||
|
c-3.614,0-6.544-2.93-6.544-6.544l0,0v5.648c0,3.616,2.932,6.548,6.548,6.548h70.721c3.617,0,6.548-2.932,6.548-6.548v-86.977
|
||||||
|
C432.802,275.751,414.709,256.486,391.787,256.009z"/>
|
||||||
|
<path style="fill:#EB7100;" d="M79.527,217.153l-0.23-0.322c0.081,1.261,0.209,2.509,0.399,3.737
|
||||||
|
C79.586,219.444,79.527,218.305,79.527,217.153z"/>
|
||||||
|
<path style="fill:#ED8300;" d="M156.467,119.797h-11.188c2.613,0.858,4.502,3.314,4.502,6.215v90.372
|
||||||
|
c0,19.395-15.42,35.494-34.375,35.888c-0.251,0.005-0.503,0.008-0.753,0.008c-9.651,0-18.405-3.914-24.76-10.236
|
||||||
|
c7.856,8.766,19.342,14.212,32.106,13.947c22.922-0.477,41.015-19.741,41.015-42.668v-86.977
|
||||||
|
C163.015,122.728,160.083,119.797,156.467,119.797z"/>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3 KiB |
Loading…
Reference in a new issue