Chore: Add an option to upload a business logo to inbox (#905)

Chore: Add an option to upload a business logo to inbox
This commit is contained in:
Pranav Raj S 2020-05-31 16:16:22 +05:30 committed by GitHub
parent 47ec7ad7c9
commit 884a1c5971
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 236 additions and 127 deletions

View file

@ -1,10 +1,11 @@
/* eslint no-plusplus: 0 */
/* eslint-env browser */
import AvatarUploader from './widgets/forms/AvatarUploader.vue';
import Bar from './widgets/chart/BarChart';
import Code from './Code';
import ColorPicker from './widgets/ColorPicker';
import DeleteModal from './widgets/modal/DeleteModal.vue';
import Input from './widgets/forms/Input.vue';
import LoadingState from './widgets/LoadingState';
import Modal from './Modal';
import ModalHeader from './ModalHeader';
@ -14,12 +15,15 @@ import Spinner from 'shared/components/Spinner';
import SubmitButton from './buttons/FormSubmitButton';
import Tabs from './ui/Tabs/Tabs';
import TabsItem from './ui/Tabs/TabsItem';
import Thumbnail from './widgets/Thumbnail.vue';
const WootUIKit = {
AvatarUploader,
Bar,
Code,
ColorPicker,
DeleteModal,
Input,
LoadingState,
Modal,
ModalHeader,
@ -29,6 +33,7 @@ const WootUIKit = {
SubmitButton,
Tabs,
TabsItem,
Thumbnail,
install(Vue) {
const keys = Object.keys(this);
keys.pop(); // remove 'install' from keys

View file

@ -105,6 +105,15 @@ export default {
return `user-thumbnail ${classname}`;
},
},
watch: {
src: {
handler(value, oldValue) {
if (value !== oldValue && this.imgError) {
this.imgError = false;
}
},
},
},
methods: {
onImgError() {
this.imgError = true;

View file

@ -0,0 +1,39 @@
<template>
<label>
<span v-if="label">{{ label }}</span>
<woot-thumbnail v-if="src" size="80px" :src="src" />
<input
id="file"
ref="file"
type="file"
accept="image/*"
@change="handleImageUpload"
/>
<slot></slot>
</label>
</template>
<script>
export default {
props: {
label: {
type: String,
default: '',
},
src: {
type: String,
default: '',
},
},
methods: {
handleImageUpload(event) {
const [file] = event.target.files;
this.$emit('change', {
file,
url: URL.createObjectURL(file),
});
},
},
};
</script>

View file

@ -0,0 +1,44 @@
<template>
<label>
<span v-if="label">{{ label }}</span>
<input
:value="value"
:type="type"
:placeholder="placeholder"
@input="onChange"
/>
<p v-if="helpText" class="help-text"></p>
</label>
</template>
<script>
export default {
props: {
label: {
type: String,
default: '',
},
value: {
type: [String, Number],
default: '',
},
type: {
type: String,
default: 'text',
},
placeholder: {
type: String,
default: '',
},
helpText: {
type: String,
default: '',
},
},
methods: {
onChange(e) {
this.$emit('input', e.target.value);
},
},
};
</script>

View file

@ -44,6 +44,9 @@
"TITLE": "Website channel",
"DESC": "Create a channel for your website and start supporting your customers via our website widget.",
"LOADING_MESSAGE": "Creating Website Support Channel",
"CHANNEL_AVATAR": {
"LABEL": "Channel Avatar"
},
"CHANNEL_NAME": {
"LABEL": "Website Name",
"PLACEHOLDER": "Enter your website name (eg: Acme Inc)"

View file

@ -10,95 +10,76 @@
:title="$t('INBOX_MGMT.SETTINGS_POPUP.INBOX_UPDATE_TITLE')"
:sub-title="$t('INBOX_MGMT.SETTINGS_POPUP.INBOX_UPDATE_SUB_TEXT')"
>
<div v-if="inbox.channel_type === 'Channel::WebWidget'">
<div class="medium-12 columns">
<label>
{{ $t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_NAME.LABEL') }}
<input
<woot-avatar-uploader
:label="$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_AVATAR.LABEL')"
:src="avatarUrl"
@change="handleImageUpload"
/>
<woot-input
v-if="isAWidgetInbox"
v-model.trim="selectedInboxName"
type="text"
class="medium-12 columns"
:label="$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_NAME.LABEL')"
:placeholder="
$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_NAME.PLACEHOLDER')
"
/>
</label>
</div>
<div class="medium-12 columns">
<label>
{{ $t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_DOMAIN.LABEL') }}
<input
<woot-input
v-if="isAWidgetInbox"
v-model.trim="channelWebsiteUrl"
type="text"
class="medium-12 columns"
:label="$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_DOMAIN.LABEL')"
:placeholder="
$t(
'INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_DOMAIN.PLACEHOLDER'
)
$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_DOMAIN.PLACEHOLDER')
"
/>
</label>
</div>
<div class="medium-12 columns">
<label>
{{
$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WELCOME_TITLE.LABEL')
}}
<input
<woot-input
v-if="isAWidgetInbox"
v-model.trim="channelWelcomeTitle"
type="text"
class="medium-12 columns"
:label="
$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WELCOME_TITLE.LABEL')
"
:placeholder="
$t(
'INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WELCOME_TITLE.PLACEHOLDER'
)
"
/>
</label>
</div>
<div class="medium-12 columns">
<label>
{{
$t(
'INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WELCOME_TAGLINE.LABEL'
)
}}
<input
<woot-input
v-if="isAWidgetInbox"
v-model.trim="channelWelcomeTagline"
type="text"
class="medium-12 columns"
:label="
$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WELCOME_TAGLINE.LABEL')
"
:placeholder="
$t(
'INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WELCOME_TAGLINE.PLACEHOLDER'
)
"
/>
</label>
</div>
<div class="medium-12 columns">
<label>
{{
<woot-input
v-if="isAWidgetInbox"
v-model.trim="channelAgentAwayMessage"
class="medium-12 columns"
:label="
$t(
'INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_AGENT_AWAY_MESSAGE.LABEL'
)
}}
<input
v-model.trim="channelAgentAwayMessage"
type="text"
"
:placeholder="
$t(
'INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_AGENT_AWAY_MESSAGE.PLACEHOLDER'
)
"
/>
</label>
</div>
<div class="medium-12 columns">
<label>
<label v-if="isAWidgetInbox" class="medium-12 columns">
{{ $t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.WIDGET_COLOR.LABEL') }}
<woot-color-picker v-model="inbox.widget_color" />
</label>
</div>
<div class="medium-12 columns">
<label>
<label class="medium-12 columns">
{{ $t('INBOX_MGMT.SETTINGS_POPUP.AUTO_ASSIGNMENT') }}
<select v-model="autoAssignment">
<option value="true">
@ -112,8 +93,6 @@
{{ $t('INBOX_MGMT.SETTINGS_POPUP.AUTO_ASSIGNMENT_SUB_TEXT') }}
</p>
</label>
</div>
</div>
<woot-submit-button
:button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')"
:loading="uiFlags.isUpdatingInbox"
@ -201,15 +180,26 @@ export default {
mixins: [configMixin],
data() {
return {
avatarFile: null,
avatarUrl: '',
selectedAgents: [],
autoAssignment: false,
isUpdating: false,
isAgentListUpdating: false,
selectedInboxName: '',
channelWebsiteUrl: '',
channelWelcomeTitle: '',
channelWelcomeTagline: '',
channelAgentAwayMessage: '',
autoAssignmentOptions: [
{
value: true,
label: this.$t('INBOX_MGMT.EDIT.AUTO_ASSIGNMENT.ENABLED'),
},
{
value: false,
label: this.$t('INBOX_MGMT.EDIT.AUTO_ASSIGNMENT.DISABLED'),
},
],
};
},
computed: {
@ -223,6 +213,9 @@ export default {
inbox() {
return this.$store.getters['inboxes/getInbox'](this.currentInboxId);
},
isAWidgetInbox() {
return this.inbox.channel_type === 'Channel::WebWidget';
},
inboxName() {
if (this.inbox.channel_type === 'Channel::TwilioSms') {
return `${this.inbox.name} (${this.inbox.phone_number})`;
@ -252,6 +245,7 @@ export default {
this.$store.dispatch('agents/get');
this.$store.dispatch('inboxes/get').then(() => {
this.fetchAttachedAgents();
this.avatarUrl = this.inbox.avatar_url;
this.selectedInboxName = this.inbox.name;
this.autoAssignment = this.inbox.enable_auto_assignment;
this.channelWebsiteUrl = this.inbox.website_url;
@ -296,7 +290,7 @@ export default {
},
async updateInbox() {
try {
await this.$store.dispatch('inboxes/updateInbox', {
const payload = {
id: this.currentInboxId,
name: this.selectedInboxName,
enable_auto_assignment: this.autoAssignment,
@ -307,12 +301,21 @@ export default {
welcome_tagline: this.channelWelcomeTagline,
agent_away_message: this.channelAgentAwayMessage,
},
});
};
if (this.avatarFile) {
payload.avatar = this.avatarFile;
}
await this.$store.dispatch('inboxes/updateInbox', payload);
this.showAlert(this.$t('INBOX_MGMT.EDIT.API.SUCCESS_MESSAGE'));
} catch (error) {
this.showAlert(this.$t('INBOX_MGMT.EDIT.API.SUCCESS_MESSAGE'));
}
},
handleImageUpload({ file, url }) {
this.avatarFile = file;
this.avatarUrl = url;
console.log(this.avatarUrl);
},
},
validations: {
selectedAgents: {

View file

@ -141,7 +141,7 @@ export default {
channel: {
type: 'web_widget',
website_url: this.channelWebsiteUrl,
widget_color: this.channelWidgetColor.hex,
widget_color: this.channelWidgetColor,
welcome_title: this.channelWelcomeTitle,
welcome_tagline: this.channelWelcomeTagline,
agent_away_message: this.channelAgentAwayMessage,

View file

@ -9,17 +9,11 @@
<p>{{ $t('PROFILE_SETTINGS.FORM.PROFILE_SECTION.NOTE') }}</p>
</div>
<div class="columns small-9 medium-5">
<label>
{{ $t('PROFILE_SETTINGS.FORM.PROFILE_IMAGE.LABEL') }}
<thumbnail size="80px" :src="avatarUrl"></thumbnail>
<input
id="file"
ref="file"
type="file"
accept="image/*"
<woot-avatar-uploader
:label="$t('PROFILE_SETTINGS.FORM.PROFILE_IMAGE.LABEL')"
:src="avatarUrl"
@change="handleImageUpload"
/>
</label>
<label :class="{ error: $v.name.$error }">
{{ $t('PROFILE_SETTINGS.FORM.NAME.LABEL') }}
<input
@ -106,8 +100,6 @@
<script>
/* global bus */
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
import { required, minLength, email } from 'vuelidate/lib/validators';
import { mapGetters } from 'vuex';
import { clearCookiesOnLogout } from '../../../../store/utils/api';
@ -116,7 +108,6 @@ import NotificationSettings from './NotificationSettings';
export default {
components: {
NotificationSettings,
Thumbnail,
},
data() {
return {
@ -202,10 +193,9 @@ export default {
this.isUpdating = false;
}
},
handleImageUpload(event) {
const [file] = event.target.files;
handleImageUpload({ file, url }) {
this.avatarFile = file;
this.avatarUrl = URL.createObjectURL(file);
this.avatarUrl = url;
},
},
};

View file

@ -5,6 +5,18 @@ import WebChannel from '../../api/channel/webChannel';
import FBChannel from '../../api/channel/fbChannel';
import TwilioChannel from '../../api/channel/twilioChannel';
const buildInboxData = inboxParams => {
const formData = new FormData();
const { channel = {}, ...inboxProperties } = inboxParams;
Object.keys(inboxProperties).forEach(key => {
formData.append(key, inboxProperties[key]);
});
Object.keys(channel).forEach(key => {
formData.append(`channel[${key}]`, channel[key]);
});
return formData;
};
export const state = {
records: [],
uiFlags: {
@ -46,7 +58,7 @@ export const actions = {
createWebsiteChannel: async ({ commit }, params) => {
try {
commit(types.default.SET_INBOXES_UI_FLAG, { isCreating: true });
const response = await WebChannel.create(params);
const response = await WebChannel.create(buildInboxData(params));
commit(types.default.ADD_INBOXES, response.data);
commit(types.default.SET_INBOXES_UI_FLAG, { isCreating: false });
return response.data;
@ -84,7 +96,7 @@ export const actions = {
isUpdatingAutoAssignment: true,
});
try {
const response = await InboxesAPI.update(id, inboxParams);
const response = await InboxesAPI.update(id, buildInboxData(inboxParams));
commit(types.default.EDIT_INBOXES, response.data);
commit(types.default.SET_INBOXES_UI_FLAG, {
isUpdatingAutoAssignment: false,

View file

@ -58,6 +58,10 @@ export default {
.header-branding {
display: flex;
align-items: center;
img {
border-radius: 50%;
}
}
.title {