mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-01 03:27:52 +00:00
[Enhancement] Add ApiClient, refactor CannedResponse (#183)
This commit is contained in:
31
app/javascript/dashboard/api/ApiClient.js
Normal file
31
app/javascript/dashboard/api/ApiClient.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/* global axios */
|
||||||
|
|
||||||
|
const API_VERSION = `/api/v1`;
|
||||||
|
|
||||||
|
class ApiClient {
|
||||||
|
constructor(url) {
|
||||||
|
this.url = `${API_VERSION}/${url}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
get() {
|
||||||
|
return axios.get(this.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
show(id) {
|
||||||
|
return axios.get(`${this.url}/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
create(data) {
|
||||||
|
return axios.post(this.url, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(id, data) {
|
||||||
|
return axios.patch(`${this.url}/${id}`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(id) {
|
||||||
|
return axios.delete(`${this.url}/${id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ApiClient;
|
||||||
@@ -1,112 +1,16 @@
|
|||||||
/* eslint no-console: 0 */
|
|
||||||
/* global axios */
|
/* global axios */
|
||||||
/* eslint no-undef: "error" */
|
|
||||||
/* eslint no-unused-expressions: ["error", { "allowShortCircuit": true }] */
|
|
||||||
import endPoints from './endPoints';
|
|
||||||
|
|
||||||
export default {
|
import ApiClient from './ApiClient';
|
||||||
getAllCannedResponses() {
|
|
||||||
const urlData = endPoints('cannedResponse').get();
|
|
||||||
const fetchPromise = new Promise((resolve, reject) => {
|
|
||||||
axios
|
|
||||||
.get(urlData.url)
|
|
||||||
.then(response => {
|
|
||||||
resolve(response);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
reject(Error(error));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return fetchPromise;
|
|
||||||
},
|
|
||||||
|
|
||||||
searchCannedResponse({ searchKey }) {
|
class CannedResponse extends ApiClient {
|
||||||
let urlData = endPoints('cannedResponse').get();
|
constructor() {
|
||||||
urlData = `${urlData.url}?search=${searchKey}`;
|
super('canned_responses');
|
||||||
const fetchPromise = new Promise((resolve, reject) => {
|
}
|
||||||
axios
|
|
||||||
.get(urlData)
|
|
||||||
.then(response => {
|
|
||||||
resolve(response);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
reject(Error(error));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return fetchPromise;
|
|
||||||
},
|
|
||||||
|
|
||||||
addCannedResponse(cannedResponseObj) {
|
get({ searchKey }) {
|
||||||
const urlData = endPoints('cannedResponse').post();
|
const url = searchKey ? `${this.url}?search=${searchKey}` : this.url;
|
||||||
const fetchPromise = new Promise((resolve, reject) => {
|
return axios.get(url);
|
||||||
axios
|
}
|
||||||
.post(urlData.url, cannedResponseObj)
|
}
|
||||||
.then(response => {
|
|
||||||
resolve(response);
|
export default new CannedResponse();
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
reject(Error(error));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return fetchPromise;
|
|
||||||
},
|
|
||||||
editCannedResponse(cannedResponseObj) {
|
|
||||||
const urlData = endPoints('cannedResponse').put(cannedResponseObj.id);
|
|
||||||
const fetchPromise = new Promise((resolve, reject) => {
|
|
||||||
axios
|
|
||||||
.put(urlData.url, cannedResponseObj)
|
|
||||||
.then(response => {
|
|
||||||
resolve(response);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
reject(Error(error));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return fetchPromise;
|
|
||||||
},
|
|
||||||
deleteCannedResponse(responseId) {
|
|
||||||
const urlData = endPoints('cannedResponse').delete(responseId);
|
|
||||||
const fetchPromise = new Promise((resolve, reject) => {
|
|
||||||
axios
|
|
||||||
.delete(urlData.url)
|
|
||||||
.then(response => {
|
|
||||||
resolve(response);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
reject(Error(error));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return fetchPromise;
|
|
||||||
},
|
|
||||||
getLabels() {
|
|
||||||
const urlData = endPoints('fetchLabels');
|
|
||||||
const fetchPromise = new Promise((resolve, reject) => {
|
|
||||||
axios
|
|
||||||
.get(urlData.url)
|
|
||||||
.then(response => {
|
|
||||||
resolve(response);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
reject(Error(error));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return fetchPromise;
|
|
||||||
},
|
|
||||||
// Get Inbox related to the account
|
|
||||||
getInboxes() {
|
|
||||||
const urlData = endPoints('fetchInboxes');
|
|
||||||
const fetchPromise = new Promise((resolve, reject) => {
|
|
||||||
axios
|
|
||||||
.get(urlData.url)
|
|
||||||
.then(response => {
|
|
||||||
console.log('fetch inboxes success');
|
|
||||||
resolve(response);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.log('fetch inboxes failure');
|
|
||||||
reject(Error(error));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return fetchPromise;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,49 +1,71 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="reply-box">
|
<div class="reply-box">
|
||||||
<div class="reply-box__top" :class="{ 'is-private': private }">
|
<div class="reply-box__top" :class="{ 'is-private': isPrivate }">
|
||||||
<canned-response
|
<canned-response
|
||||||
|
v-if="showCannedModal"
|
||||||
v-on-clickaway="hideCannedResponse"
|
v-on-clickaway="hideCannedResponse"
|
||||||
data-dropdown-menu
|
data-dropdown-menu
|
||||||
:on-keyenter="replaceText"
|
:on-keyenter="replaceText"
|
||||||
:on-click="replaceText"
|
:on-click="replaceText"
|
||||||
v-if="showCannedModal"
|
|
||||||
/>
|
/>
|
||||||
<emoji-input v-on-clickaway="hideEmojiPicker" :on-click="emojiOnClick" v-if="showEmojiPicker"/>
|
<emoji-input
|
||||||
|
v-if="showEmojiPicker"
|
||||||
|
v-on-clickaway="hideEmojiPicker"
|
||||||
|
:on-click="emojiOnClick"
|
||||||
|
/>
|
||||||
<textarea
|
<textarea
|
||||||
rows="1"
|
ref="messageInput"
|
||||||
v-model="message"
|
v-model="message"
|
||||||
|
rows="1"
|
||||||
class="input"
|
class="input"
|
||||||
type="text"
|
type="text"
|
||||||
|
:placeholder="$t(messagePlaceHolder())"
|
||||||
@click="onClick()"
|
@click="onClick()"
|
||||||
@blur="onBlur()"
|
@blur="onBlur()"
|
||||||
v-bind:placeholder="$t(messagePlaceHolder())"
|
|
||||||
ref="messageInput"
|
|
||||||
/>
|
/>
|
||||||
<i class="icon ion-happy-outline" :class="{ active: showEmojiPicker}" @click="toggleEmojiPicker()"></i>
|
<i
|
||||||
|
class="icon ion-happy-outline"
|
||||||
|
:class="{ active: showEmojiPicker }"
|
||||||
|
@click="toggleEmojiPicker()"
|
||||||
|
></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="reply-box__bottom" >
|
<div class="reply-box__bottom">
|
||||||
<ul class="tabs">
|
<ul class="tabs">
|
||||||
<li class="tabs-title" v-bind:class="{ 'is-active': !private }">
|
<li class="tabs-title" :class="{ 'is-active': !isPrivate }">
|
||||||
<a href="#" @click="makeReply" >Reply</a>
|
<a href="#" @click="makeReply">Reply</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="tabs-title is-private" v-bind:class="{ 'is-active': private }">
|
<li class="tabs-title is-private" :class="{ 'is-active': isPrivate }">
|
||||||
<a href="#" @click="makePrivate">Private Note</a>
|
<a href="#" @click="makePrivate">Private Note</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="tabs-title message-length" v-if="message.length">
|
<li v-if="message.length" class="tabs-title message-length">
|
||||||
<a :class="{ 'message-error': message.length > 620 }">{{ message.length }} / 640</a>
|
<a :class="{ 'message-error': message.length > 620 }">
|
||||||
|
{{ message.length }} / 640
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<button
|
<button
|
||||||
@click="sendMessage"
|
|
||||||
type="button"
|
type="button"
|
||||||
class="button send-button"
|
class="button send-button"
|
||||||
:disabled="disableButton()"
|
:disabled="disableButton()"
|
||||||
v-bind:class="{ 'disabled': message.length === 0 || message.length > 640,
|
:class="{
|
||||||
'warning': private }"
|
disabled: message.length === 0 || message.length > 640,
|
||||||
|
warning: isPrivate,
|
||||||
|
}"
|
||||||
|
@click="sendMessage"
|
||||||
>
|
>
|
||||||
{{ private ? $t('CONVERSATION.REPLYBOX.CREATE') : $t('CONVERSATION.REPLYBOX.SEND') }}
|
{{
|
||||||
<i class="icon" :class="{ 'ion-android-send': !private, 'ion-android-lock': private }"></i>
|
isPrivate
|
||||||
|
? $t('CONVERSATION.REPLYBOX.CREATE')
|
||||||
|
: $t('CONVERSATION.REPLYBOX.SEND')
|
||||||
|
}}
|
||||||
|
<i
|
||||||
|
class="icon"
|
||||||
|
:class="{
|
||||||
|
'ion-android-send': !isPrivate,
|
||||||
|
'ion-android-lock': isPrivate,
|
||||||
|
}"
|
||||||
|
></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -76,21 +98,6 @@ export default {
|
|||||||
EmojiInput,
|
EmojiInput,
|
||||||
CannedResponse,
|
CannedResponse,
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
/* eslint-disable no-confusing-arrow */
|
|
||||||
document.addEventListener('keydown', (e) => {
|
|
||||||
if (this.isEscape(e)) {
|
|
||||||
this.hideEmojiPicker();
|
|
||||||
this.hideCannedResponse();
|
|
||||||
}
|
|
||||||
if (this.isEnter(e)) {
|
|
||||||
if (!e.shiftKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
this.sendMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
watch: {
|
watch: {
|
||||||
message(val) {
|
message(val) {
|
||||||
if (this.private) {
|
if (this.private) {
|
||||||
@@ -103,34 +110,51 @@ export default {
|
|||||||
this.showCannedModal = true;
|
this.showCannedModal = true;
|
||||||
if (val.length > 1) {
|
if (val.length > 1) {
|
||||||
const searchKey = val.substr(1, val.length);
|
const searchKey = val.substr(1, val.length);
|
||||||
this.$store.dispatch('searchCannedResponse', {
|
this.$store.dispatch('getCannedResponse', {
|
||||||
searchKey,
|
searchKey,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.$store.dispatch('fetchCannedResponse');
|
this.$store.dispatch('getCannedResponse');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.showCannedModal = false;
|
this.showCannedModal = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
/* eslint-disable no-confusing-arrow */
|
||||||
|
document.addEventListener('keydown', e => {
|
||||||
|
if (this.isEscape(e)) {
|
||||||
|
this.hideEmojiPicker();
|
||||||
|
this.hideCannedResponse();
|
||||||
|
}
|
||||||
|
if (this.isEnter(e)) {
|
||||||
|
if (!e.shiftKey) {
|
||||||
|
e.preventDefault();
|
||||||
|
this.sendMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
isEnter(e) {
|
isEnter(e) {
|
||||||
return e.keyCode === 13;
|
return e.keyCode === 13;
|
||||||
},
|
},
|
||||||
isEscape(e) {
|
isEscape(e) {
|
||||||
return e.keyCode === 27; // ESCAPE
|
return e.keyCode === 27; // ESCAPE
|
||||||
},
|
},
|
||||||
sendMessage() {
|
sendMessage() {
|
||||||
const messageHasOnlyNewLines = !this.message.replace(/\n/g, '').length;
|
const messageHasOnlyNewLines = !this.message.replace(/\n/g, '').length;
|
||||||
if (messageHasOnlyNewLines) {
|
if (messageHasOnlyNewLines) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const messageAction = this.private ? 'addPrivateNote' : 'sendMessage';
|
const messageAction = this.isPrivate ? 'addPrivateNote' : 'sendMessage';
|
||||||
if (this.message.length !== 0 && !this.showCannedModal) {
|
if (this.message.length !== 0 && !this.showCannedModal) {
|
||||||
this.$store.dispatch(messageAction, [this.currentChat.id, this.message]).then(() => {
|
this.$store
|
||||||
this.$emit('scrollToMessage');
|
.dispatch(messageAction, [this.currentChat.id, this.message])
|
||||||
});
|
.then(() => {
|
||||||
|
this.$emit('scrollToMessage');
|
||||||
|
});
|
||||||
this.clearMessage();
|
this.clearMessage();
|
||||||
this.hideEmojiPicker();
|
this.hideEmojiPicker();
|
||||||
}
|
}
|
||||||
@@ -141,15 +165,17 @@ export default {
|
|||||||
}, 200);
|
}, 200);
|
||||||
},
|
},
|
||||||
makePrivate() {
|
makePrivate() {
|
||||||
this.private = true;
|
this.isPrivate = true;
|
||||||
this.$refs.messageInput.focus();
|
this.$refs.messageInput.focus();
|
||||||
},
|
},
|
||||||
makeReply() {
|
makeReply() {
|
||||||
this.private = false;
|
this.isPrivate = false;
|
||||||
this.$refs.messageInput.focus();
|
this.$refs.messageInput.focus();
|
||||||
},
|
},
|
||||||
emojiOnClick(emoji) {
|
emojiOnClick(emoji) {
|
||||||
this.message = emojione.shortnameToUnicode(`${this.message}${emoji.shortname} `);
|
this.message = emojione.shortnameToUnicode(
|
||||||
|
`${this.message}${emoji.shortname} `
|
||||||
|
);
|
||||||
},
|
},
|
||||||
clearMessage() {
|
clearMessage() {
|
||||||
this.message = '';
|
this.message = '';
|
||||||
@@ -189,11 +215,17 @@ export default {
|
|||||||
},
|
},
|
||||||
disableButton() {
|
disableButton() {
|
||||||
const messageHasOnlyNewLines = !this.message.replace(/\n/g, '').length;
|
const messageHasOnlyNewLines = !this.message.replace(/\n/g, '').length;
|
||||||
return this.message.length === 0 || this.message.length > 640 || messageHasOnlyNewLines;
|
return (
|
||||||
|
this.message.length === 0 ||
|
||||||
|
this.message.length > 640 ||
|
||||||
|
messageHasOnlyNewLines
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
messagePlaceHolder() {
|
messagePlaceHolder() {
|
||||||
const placeHolder = this.private ? 'CONVERSATION.FOOTER.PRIVATE_MSG_INPUT' : 'CONVERSATION.FOOTER.MSG_INPUT';
|
const placeHolder = this.isPrivate
|
||||||
|
? 'CONVERSATION.FOOTER.PRIVATE_MSG_INPUT'
|
||||||
|
: 'CONVERSATION.FOOTER.MSG_INPUT';
|
||||||
return placeHolder;
|
return placeHolder;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -201,7 +233,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.send-button {
|
.send-button {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -6,24 +6,38 @@
|
|||||||
:header-title="$t('CANNED_MGMT.ADD.TITLE')"
|
:header-title="$t('CANNED_MGMT.ADD.TITLE')"
|
||||||
:header-content="$t('CANNED_MGMT.ADD.DESC')"
|
:header-content="$t('CANNED_MGMT.ADD.DESC')"
|
||||||
/>
|
/>
|
||||||
<form class="row" v-on:submit.prevent="addAgent()">
|
<form class="row" @submit.prevent="addAgent()">
|
||||||
<div class="medium-12 columns">
|
<div class="medium-12 columns">
|
||||||
<label :class="{ 'error': $v.shortCode.$error }">
|
<label :class="{ error: $v.shortCode.$error }">
|
||||||
{{ $t('CANNED_MGMT.ADD.FORM.SHORT_CODE.LABEL') }}
|
{{ $t('CANNED_MGMT.ADD.FORM.SHORT_CODE.LABEL') }}
|
||||||
<input type="text" v-model.trim="shortCode" @input="$v.shortCode.$touch" :placeholder="$t('CANNED_MGMT.ADD.FORM.SHORT_CODE.PLACEHOLDER')">
|
<input
|
||||||
|
v-model.trim="shortCode"
|
||||||
|
type="text"
|
||||||
|
:placeholder="$t('CANNED_MGMT.ADD.FORM.SHORT_CODE.PLACEHOLDER')"
|
||||||
|
@input="$v.shortCode.$touch"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="medium-12 columns">
|
<div class="medium-12 columns">
|
||||||
<label :class="{ 'error': $v.content.$error }">
|
<label :class="{ error: $v.content.$error }">
|
||||||
{{ $t('CANNED_MGMT.ADD.FORM.CONTENT.LABEL') }}
|
{{ $t('CANNED_MGMT.ADD.FORM.CONTENT.LABEL') }}
|
||||||
<input type="text" v-model.trim="content" @input="$v.content.$touch" :placeholder="$t('CANNED_MGMT.ADD.FORM.CONTENT.PLACEHOLDER')">
|
<input
|
||||||
|
v-model.trim="content"
|
||||||
|
type="text"
|
||||||
|
:placeholder="$t('CANNED_MGMT.ADD.FORM.CONTENT.PLACEHOLDER')"
|
||||||
|
@input="$v.content.$touch"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<div class="medium-12 columns">
|
<div class="medium-12 columns">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:disabled="$v.content.$invalid || $v.shortCode.$invalid || addCanned.showLoading"
|
:disabled="
|
||||||
|
$v.content.$invalid ||
|
||||||
|
$v.shortCode.$invalid ||
|
||||||
|
addCanned.showLoading
|
||||||
|
"
|
||||||
:button-text="$t('CANNED_MGMT.ADD.FORM.SUBMIT')"
|
:button-text="$t('CANNED_MGMT.ADD.FORM.SUBMIT')"
|
||||||
:loading="addCanned.showLoading"
|
:loading="addCanned.showLoading"
|
||||||
/>
|
/>
|
||||||
@@ -40,20 +54,17 @@
|
|||||||
/* eslint no-console: 0 */
|
/* eslint no-console: 0 */
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from 'vuelidate/lib/validators';
|
||||||
|
|
||||||
import PageHeader from '../SettingsSubPageHeader';
|
|
||||||
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton';
|
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton';
|
||||||
import Modal from '../../../../components/Modal';
|
import Modal from '../../../../components/Modal';
|
||||||
|
|
||||||
const cannedImg = require('assets/images/canned.svg');
|
const cannedImg = require('assets/images/canned.svg');
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['onClose'],
|
|
||||||
components: {
|
components: {
|
||||||
PageHeader,
|
|
||||||
WootSubmitButton,
|
WootSubmitButton,
|
||||||
Modal,
|
Modal,
|
||||||
},
|
},
|
||||||
|
props: ['onClose'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
shortCode: '',
|
shortCode: '',
|
||||||
@@ -97,7 +108,8 @@ export default {
|
|||||||
bus.$emit('newToastMessage', this.addCanned.message);
|
bus.$emit('newToastMessage', this.addCanned.message);
|
||||||
},
|
},
|
||||||
resetForm() {
|
resetForm() {
|
||||||
this.shortCode = this.content = '';
|
this.shortCode = '';
|
||||||
|
this.content = '';
|
||||||
this.$v.shortCode.$reset();
|
this.$v.shortCode.$reset();
|
||||||
this.$v.content.$reset();
|
this.$v.content.$reset();
|
||||||
},
|
},
|
||||||
@@ -105,23 +117,26 @@ export default {
|
|||||||
// Show loading on button
|
// Show loading on button
|
||||||
this.addCanned.showLoading = true;
|
this.addCanned.showLoading = true;
|
||||||
// Make API Calls
|
// Make API Calls
|
||||||
this.$store.dispatch('addCannedResponse', {
|
this.$store
|
||||||
short_code: this.shortCode,
|
.dispatch('createCannedResponse', {
|
||||||
content: this.content,
|
short_code: this.shortCode,
|
||||||
})
|
content: this.content,
|
||||||
.then(() => {
|
})
|
||||||
// Reset Form, Show success message
|
.then(() => {
|
||||||
this.addCanned.showLoading = false;
|
// Reset Form, Show success message
|
||||||
this.addCanned.message = this.$t('CANNED_MGMT.ADD.API.SUCCESS_MESSAGE');
|
this.addCanned.showLoading = false;
|
||||||
this.showAlert();
|
this.addCanned.message = this.$t(
|
||||||
this.resetForm();
|
'CANNED_MGMT.ADD.API.SUCCESS_MESSAGE'
|
||||||
this.onClose();
|
);
|
||||||
})
|
this.showAlert();
|
||||||
.catch(() => {
|
this.resetForm();
|
||||||
this.addCanned.showLoading = false;
|
this.onClose();
|
||||||
this.addCanned.message = this.$t('CANNED_MGMT.ADD.API.ERROR_MESSAGE');
|
})
|
||||||
this.showAlert();
|
.catch(() => {
|
||||||
});
|
this.addCanned.showLoading = false;
|
||||||
|
this.addCanned.message = this.$t('CANNED_MGMT.ADD.API.ERROR_MESSAGE');
|
||||||
|
this.showAlert();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<modal
|
<modal :show.sync="show" :on-close="onClose">
|
||||||
:show.sync="show"
|
<woot-modal-header :header-title="title" :header-content="message" />
|
||||||
:on-close="onClose"
|
|
||||||
>
|
|
||||||
|
|
||||||
<woot-modal-header
|
|
||||||
:header-title="title"
|
|
||||||
:header-content="message"
|
|
||||||
/>
|
|
||||||
<div class="modal-footer delete-item">
|
<div class="modal-footer delete-item">
|
||||||
<button class="button" @click="onClose">
|
<button class="button" @click="onClose">
|
||||||
{{ rejectText }}
|
{{ rejectText }}
|
||||||
@@ -20,13 +13,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import PageHeader from '../SettingsSubPageHeader';
|
|
||||||
import Modal from '../../../../components/Modal';
|
import Modal from '../../../../components/Modal';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Modal,
|
Modal,
|
||||||
PageHeader,
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
|
|||||||
@@ -1,27 +1,39 @@
|
|||||||
<template>
|
<template>
|
||||||
<modal :show.sync="show" :on-close="onClose">
|
<modal :show.sync="show" :on-close="onClose">
|
||||||
<div class="column content-box">
|
<div class="column content-box">
|
||||||
<woot-modal-header
|
<woot-modal-header :header-title="pageTitle" />
|
||||||
:header-title="pageTitle"
|
<form class="row medium-8" @submit.prevent="editCannedResponse()">
|
||||||
/>
|
|
||||||
<form class="row medium-8" v-on:submit.prevent="editCannedResponse()">
|
|
||||||
<div class="medium-12 columns">
|
<div class="medium-12 columns">
|
||||||
<label :class="{ 'error': $v.shortCode.$error }">
|
<label :class="{ error: $v.shortCode.$error }">
|
||||||
{{ $t('CANNED_MGMT.EDIT.FORM.SHORT_CODE.LABEL') }}
|
{{ $t('CANNED_MGMT.EDIT.FORM.SHORT_CODE.LABEL') }}
|
||||||
<input type="text" v-model.trim="shortCode" @input="$v.shortCode.$touch" :placeholder="$t('CANNED_MGMT.EDIT.FORM.SHORT_CODE.PLACEHOLDER')">
|
<input
|
||||||
|
v-model.trim="shortCode"
|
||||||
|
type="text"
|
||||||
|
:placeholder="$t('CANNED_MGMT.EDIT.FORM.SHORT_CODE.PLACEHOLDER')"
|
||||||
|
@input="$v.shortCode.$touch"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="medium-12 columns">
|
<div class="medium-12 columns">
|
||||||
<label :class="{ 'error': $v.content.$error }">
|
<label :class="{ error: $v.content.$error }">
|
||||||
{{ $t('CANNED_MGMT.EDIT.FORM.CONTENT.LABEL') }}
|
{{ $t('CANNED_MGMT.EDIT.FORM.CONTENT.LABEL') }}
|
||||||
<input type="text" v-model.trim="content" @input="$v.content.$touch" :placeholder="$t('CANNED_MGMT.EDIT.FORM.CONTENT.PLACEHOLDER')">
|
<input
|
||||||
|
v-model.trim="content"
|
||||||
|
type="text"
|
||||||
|
:placeholder="$t('CANNED_MGMT.EDIT.FORM.CONTENT.PLACEHOLDER')"
|
||||||
|
@input="$v.content.$touch"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<div class="medium-12 columns">
|
<div class="medium-12 columns">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:disabled="$v.content.$invalid || $v.shortCode.$invalid || editCanned.showLoading"
|
:disabled="
|
||||||
|
$v.content.$invalid ||
|
||||||
|
$v.shortCode.$invalid ||
|
||||||
|
editCanned.showLoading
|
||||||
|
"
|
||||||
:button-text="$t('CANNED_MGMT.EDIT.FORM.SUBMIT')"
|
:button-text="$t('CANNED_MGMT.EDIT.FORM.SUBMIT')"
|
||||||
:loading="editCanned.showLoading"
|
:loading="editCanned.showLoading"
|
||||||
/>
|
/>
|
||||||
@@ -38,13 +50,11 @@
|
|||||||
/* eslint no-console: 0 */
|
/* eslint no-console: 0 */
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from 'vuelidate/lib/validators';
|
||||||
|
|
||||||
import PageHeader from '../SettingsSubPageHeader';
|
|
||||||
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton';
|
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton';
|
||||||
import Modal from '../../../../components/Modal';
|
import Modal from '../../../../components/Modal';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
PageHeader,
|
|
||||||
WootSubmitButton,
|
WootSubmitButton,
|
||||||
Modal,
|
Modal,
|
||||||
},
|
},
|
||||||
@@ -89,7 +99,8 @@ export default {
|
|||||||
bus.$emit('newToastMessage', this.editCanned.message);
|
bus.$emit('newToastMessage', this.editCanned.message);
|
||||||
},
|
},
|
||||||
resetForm() {
|
resetForm() {
|
||||||
this.shortCode = this.content = '';
|
this.shortCode = '';
|
||||||
|
this.content = '';
|
||||||
this.$v.shortCode.$reset();
|
this.$v.shortCode.$reset();
|
||||||
this.$v.content.$reset();
|
this.$v.content.$reset();
|
||||||
},
|
},
|
||||||
@@ -97,26 +108,31 @@ export default {
|
|||||||
// Show loading on button
|
// Show loading on button
|
||||||
this.editCanned.showLoading = true;
|
this.editCanned.showLoading = true;
|
||||||
// Make API Calls
|
// Make API Calls
|
||||||
this.$store.dispatch('editCannedResponse', {
|
this.$store
|
||||||
id: this.id,
|
.dispatch('updateCannedResponse', {
|
||||||
name: this.shortCode,
|
id: this.id,
|
||||||
content: this.content,
|
name: this.shortCode,
|
||||||
})
|
content: this.content,
|
||||||
.then(() => {
|
})
|
||||||
// Reset Form, Show success message
|
.then(() => {
|
||||||
this.editCanned.showLoading = false;
|
// Reset Form, Show success message
|
||||||
this.editCanned.message = this.$t('CANNED_MGMT.EDIT.API.SUCCESS_MESSAGE');
|
this.editCanned.showLoading = false;
|
||||||
this.showAlert();
|
this.editCanned.message = this.$t(
|
||||||
this.resetForm();
|
'CANNED_MGMT.EDIT.API.SUCCESS_MESSAGE'
|
||||||
setTimeout(() => {
|
);
|
||||||
this.onClose();
|
this.showAlert();
|
||||||
}, 10);
|
this.resetForm();
|
||||||
})
|
setTimeout(() => {
|
||||||
.catch(() => {
|
this.onClose();
|
||||||
this.editCanned.showLoading = false;
|
}, 10);
|
||||||
this.editCanned.message = this.$t('CANNED_MGMT.EDIT.API.ERROR_MESSAGE');
|
})
|
||||||
this.showAlert();
|
.catch(() => {
|
||||||
});
|
this.editCanned.showLoading = false;
|
||||||
|
this.editCanned.message = this.$t(
|
||||||
|
'CANNED_MGMT.EDIT.API.ERROR_MESSAGE'
|
||||||
|
);
|
||||||
|
this.showAlert();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,18 +11,18 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="small-8 columns">
|
<div class="small-8 columns">
|
||||||
<p
|
<p
|
||||||
v-if="!fetchStatus && !cannedResponseList.length"
|
v-if="!uiFlags.fetchingList && !records.length"
|
||||||
class="no-items-error-message"
|
class="no-items-error-message"
|
||||||
>
|
>
|
||||||
{{ $t('CANNED_MGMT.LIST.404') }}
|
{{ $t('CANNED_MGMT.LIST.404') }}
|
||||||
</p>
|
</p>
|
||||||
<woot-loading-state
|
<woot-loading-state
|
||||||
v-if="fetchStatus"
|
v-if="uiFlags.fetchingList"
|
||||||
:message="$t('CANNED_MGMT.LOADING')"
|
:message="$t('CANNED_MGMT.LOADING')"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<table
|
<table
|
||||||
v-if="!fetchStatus && cannedResponseList.length"
|
v-if="!uiFlags.fetchingList && records.length"
|
||||||
class="woot-table"
|
class="woot-table"
|
||||||
>
|
>
|
||||||
<thead>
|
<thead>
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr
|
<tr
|
||||||
v-for="(cannedItem, index) in cannedResponseList"
|
v-for="(cannedItem, index) in records"
|
||||||
:key="cannedItem.short_code"
|
:key="cannedItem.short_code"
|
||||||
>
|
>
|
||||||
<!-- Short Code -->
|
<!-- Short Code -->
|
||||||
@@ -126,8 +126,8 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
cannedResponseList: 'getCannedResponses',
|
records: 'getCannedResponses',
|
||||||
fetchStatus: 'getCannedFetchStatus',
|
uiFlags: 'getUIFlags',
|
||||||
}),
|
}),
|
||||||
// Delete Modal
|
// Delete Modal
|
||||||
deleteConfirmText() {
|
deleteConfirmText() {
|
||||||
@@ -148,7 +148,7 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// Fetch API Call
|
// Fetch API Call
|
||||||
this.$store.dispatch('fetchCannedResponse');
|
this.$store.dispatch('getCannedResponse');
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
showAlert(message) {
|
showAlert(message) {
|
||||||
@@ -192,9 +192,7 @@ export default {
|
|||||||
},
|
},
|
||||||
deleteCannedResponse(id) {
|
deleteCannedResponse(id) {
|
||||||
this.$store
|
this.$store
|
||||||
.dispatch('deleteCannedResponse', {
|
.dispatch('deleteCannedResponse', id)
|
||||||
id,
|
|
||||||
})
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.showAlert(this.$t('CANNED_MGMT.DELETE.API.SUCCESS_MESSAGE'));
|
this.showAlert(this.$t('CANNED_MGMT.DELETE.API.SUCCESS_MESSAGE'));
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,108 +2,110 @@
|
|||||||
/* eslint no-param-reassign: 0 */
|
/* eslint no-param-reassign: 0 */
|
||||||
/* eslint no-shadow: 0 */
|
/* eslint no-shadow: 0 */
|
||||||
import * as types from '../mutation-types';
|
import * as types from '../mutation-types';
|
||||||
import CannedApi from '../../api/cannedResponse';
|
import CannedResponseAPI from '../../api/cannedResponse';
|
||||||
import { setLoadingStatus, getLoadingStatus } from '../utils/api';
|
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
cannedResponse: [],
|
records: [],
|
||||||
fetchAPIloadingStatus: false,
|
uiFlags: {
|
||||||
|
fetchingList: false,
|
||||||
|
fetchingItem: false,
|
||||||
|
creatingItem: false,
|
||||||
|
updatingItem: false,
|
||||||
|
deletingItem: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const getters = {
|
const getters = {
|
||||||
getCannedResponses(_state) {
|
getCannedResponses(_state) {
|
||||||
return _state.cannedResponse;
|
return _state.records;
|
||||||
|
},
|
||||||
|
getUIFlags(_state) {
|
||||||
|
return _state.uiFlags;
|
||||||
},
|
},
|
||||||
getCannedFetchStatus: getLoadingStatus,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
fetchCannedResponse({ commit }) {
|
getCannedResponse: async function getCannedResponse(
|
||||||
commit(types.default.SET_CANNED_FETCHING_STATUS, true);
|
{ commit },
|
||||||
CannedApi.getAllCannedResponses()
|
{ searchKey } = {}
|
||||||
.then(response => {
|
) {
|
||||||
commit(types.default.SET_CANNED_FETCHING_STATUS, false);
|
commit(types.default.SET_CANNED_UI_FLAG, { fetchingList: true });
|
||||||
commit(types.default.SET_CANNED, response);
|
try {
|
||||||
})
|
const response = await CannedResponseAPI.get({ searchKey });
|
||||||
.catch();
|
commit(types.default.SET_CANNED, response.data);
|
||||||
|
commit(types.default.SET_CANNED_UI_FLAG, { fetchingList: false });
|
||||||
|
} catch (error) {
|
||||||
|
commit(types.default.SET_CANNED_UI_FLAG, { fetchingList: false });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
searchCannedResponse({ commit }, { searchKey }) {
|
|
||||||
commit(types.default.SET_CANNED_FETCHING_STATUS, true);
|
createCannedResponse: async function createCannedResponse(
|
||||||
CannedApi.searchCannedResponse({ searchKey })
|
{ commit },
|
||||||
.then(response => {
|
cannedObj
|
||||||
commit(types.default.SET_CANNED_FETCHING_STATUS, false);
|
) {
|
||||||
commit(types.default.SET_CANNED, response);
|
commit(types.default.SET_CANNED_UI_FLAG, { creatingItem: true });
|
||||||
})
|
try {
|
||||||
.catch();
|
const response = await CannedResponseAPI.create(cannedObj);
|
||||||
|
commit(types.default.ADD_CANNED, response.data);
|
||||||
|
commit(types.default.SET_CANNED_UI_FLAG, { creatingItem: false });
|
||||||
|
} catch (error) {
|
||||||
|
commit(types.default.SET_CANNED_UI_FLAG, { creatingItem: false });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
addCannedResponse({ commit }, cannedObj) {
|
|
||||||
return new Promise((resolve, reject) => {
|
updateCannedResponse: async function updateCannedResponse(
|
||||||
CannedApi.addCannedResponse(cannedObj)
|
{ commit },
|
||||||
.then(response => {
|
{ id, ...updateObj }
|
||||||
commit(types.default.ADD_CANNED, response);
|
) {
|
||||||
resolve();
|
commit(types.default.SET_CANNED_UI_FLAG, { updatingItem: true });
|
||||||
})
|
try {
|
||||||
.catch(response => {
|
const response = await CannedResponseAPI.update(id, updateObj);
|
||||||
reject(response);
|
commit(types.default.EDIT_CANNED, response.data);
|
||||||
});
|
commit(types.default.SET_CANNED_UI_FLAG, { updatingItem: false });
|
||||||
});
|
} catch (error) {
|
||||||
|
commit(types.default.SET_CANNED_UI_FLAG, { updatingItem: false });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
editCannedResponse({ commit }, cannedObj) {
|
|
||||||
return new Promise((resolve, reject) => {
|
deleteCannedResponse: async function deleteCannedResponse({ commit }, id) {
|
||||||
CannedApi.editCannedResponse(cannedObj)
|
commit(types.default.SET_CANNED_UI_FLAG, { deletingItem: true });
|
||||||
.then(response => {
|
try {
|
||||||
commit(types.default.EDIT_CANNED, response, cannedObj.id);
|
await CannedResponseAPI.delete(id);
|
||||||
resolve();
|
commit(types.default.DELETE_CANNED, id);
|
||||||
})
|
commit(types.default.SET_CANNED_UI_FLAG, { deletingItem: true });
|
||||||
.catch(response => {
|
} catch (error) {
|
||||||
reject(response);
|
commit(types.default.SET_CANNED_UI_FLAG, { deletingItem: true });
|
||||||
});
|
}
|
||||||
});
|
|
||||||
},
|
|
||||||
deleteCannedResponse({ commit }, responseId) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
CannedApi.deleteCannedResponse(responseId.id)
|
|
||||||
.then(response => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
commit(types.default.DELETE_CANNED, responseId);
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.catch(response => {
|
|
||||||
reject(response);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
// List
|
[types.default.SET_CANNED_UI_FLAG](_state, data) {
|
||||||
[types.default.SET_CANNED_FETCHING_STATUS]: setLoadingStatus,
|
_state.uiFlags = {
|
||||||
// List
|
..._state.uiFlags,
|
||||||
[types.default.SET_CANNED](_state, response) {
|
...data,
|
||||||
_state.cannedResponse = response.data;
|
};
|
||||||
},
|
|
||||||
// Add Agent
|
|
||||||
[types.default.ADD_CANNED](_state, response) {
|
|
||||||
if (response.status === 200) {
|
|
||||||
_state.cannedResponse.push(response.data);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// Edit Agent
|
|
||||||
[types.default.EDIT_CANNED](_state, response) {
|
|
||||||
if (response.status === 200) {
|
|
||||||
_state.cannedResponse.forEach((element, index) => {
|
|
||||||
if (element.id === response.data.id) {
|
|
||||||
_state.cannedResponse[index] = response.data;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Delete CannedResponse
|
[types.default.SET_CANNED](_state, data) {
|
||||||
[types.default.DELETE_CANNED](_state, { id }) {
|
_state.records = data;
|
||||||
_state.cannedResponse = _state.cannedResponse.filter(
|
},
|
||||||
agent => agent.id !== id
|
|
||||||
|
[types.default.ADD_CANNED](_state, data) {
|
||||||
|
_state.records.push(data);
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.EDIT_CANNED](_state, data) {
|
||||||
|
_state.records.forEach((element, index) => {
|
||||||
|
if (element.id === data.id) {
|
||||||
|
_state.records[index] = data;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.DELETE_CANNED](_state, id) {
|
||||||
|
_state.records = _state.records.filter(
|
||||||
|
cannedResponse => cannedResponse.id !== id
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export default {
|
|||||||
DELETE_AGENT: 'DELETE_AGENT',
|
DELETE_AGENT: 'DELETE_AGENT',
|
||||||
|
|
||||||
// Canned Response
|
// Canned Response
|
||||||
SET_CANNED_FETCHING_STATUS: 'SET_CANNED_FETCHING_STATUS',
|
SET_CANNED_UI_FLAG: 'SET_CANNED_UI_FLAG',
|
||||||
SET_CANNED: 'SET_CANNED',
|
SET_CANNED: 'SET_CANNED',
|
||||||
ADD_CANNED: 'ADD_CANNED',
|
ADD_CANNED: 'ADD_CANNED',
|
||||||
EDIT_CANNED: 'EDIT_CANNED',
|
EDIT_CANNED: 'EDIT_CANNED',
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Rails.application.routes.draw do
|
|||||||
|
|
||||||
match '/status', to: 'home#status', via: [:get]
|
match '/status', to: 'home#status', via: [:get]
|
||||||
|
|
||||||
namespace :api do
|
namespace :api, :defaults => { :format => 'json' } do
|
||||||
namespace :v1 do
|
namespace :v1 do
|
||||||
resources :callbacks, only: [] do
|
resources :callbacks, only: [] do
|
||||||
collection do
|
collection do
|
||||||
|
|||||||
Reference in New Issue
Block a user