Feature: Support file type messages on widget and dashboard (#659)

- Adds support for file upload

Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
Co-authored-by: Sojan <sojan@pepalo.com>
This commit is contained in:
Nithin David Thomas
2020-04-02 12:28:38 +05:30
committed by GitHub
parent 0afa5c297f
commit 7fcd2d0e85
28 changed files with 338 additions and 69 deletions

View File

@@ -17,8 +17,13 @@
:message-type="messageType"
:message="message.content"
/>
<div v-if="hasImage" class="chat-bubble has-attachment agent">
<div v-if="hasAttachment" class="chat-bubble has-attachment agent">
<file-bubble
v-if="message.attachment && message.attachment.file_type !== 'image'"
:url="message.attachment.data_url"
/>
<image-bubble
v-else
:url="message.attachment.data_url"
:thumb="message.attachment.thumb_url"
:readable-time="readableTime"
@@ -35,6 +40,7 @@
import AgentMessageBubble from 'widget/components/AgentMessageBubble';
import timeMixin from 'dashboard/mixins/time';
import ImageBubble from 'widget/components/ImageBubble';
import FileBubble from 'widget/components/FileBubble';
import Thumbnail from 'dashboard/components/widgets/Thumbnail';
import { MESSAGE_TYPE } from 'widget/helpers/constants';
@@ -44,6 +50,7 @@ export default {
AgentMessageBubble,
Thumbnail,
ImageBubble,
FileBubble,
},
mixins: [timeMixin],
props: {
@@ -53,10 +60,8 @@ export default {
},
},
computed: {
hasImage() {
const { attachment = {} } = this.message;
const { file_type: fileType } = attachment;
return fileType === 'image';
hasAttachment() {
return !!this.message.attachment;
},
showTextBubble() {
const { message } = this;

View File

@@ -1,5 +1,5 @@
<template>
<file-upload accept="image/*" @input-file="onFileUpload">
<file-upload :size="4096 * 2048" @input-file="onFileUpload">
<span class="attachment-button ">
<i v-if="!isUploading.image"></i>
<spinner v-if="isUploading" size="small" />
@@ -23,12 +23,15 @@ export default {
return { isUploading: false };
},
methods: {
getFileType(fileType) {
return fileType.includes('image') ? 'image' : 'file';
},
async onFileUpload(file) {
this.isUploading = true;
try {
const thumbUrl = window.URL.createObjectURL(file.file);
await this.onAttach({
file_type: file.type,
fileType: this.getFileType(file.type),
file: file.file,
thumbUrl,
});

View File

@@ -1,6 +1,6 @@
<template>
<div class="chat-message--input">
<chat-attchment-button :on-attach="onSendAttachment" />
<chat-attachment-button :on-attach="onSendAttachment" />
<ChatInputArea v-model="userInput" :placeholder="placeholder" />
<ChatSendButton
:on-click="handleButtonClick"
@@ -13,13 +13,13 @@
<script>
import { mapGetters } from 'vuex';
import ChatSendButton from 'widget/components/ChatSendButton.vue';
import ChatAttchmentButton from 'widget/components/ChatAttachment.vue';
import ChatAttachmentButton from 'widget/components/ChatAttachment.vue';
import ChatInputArea from 'widget/components/ChatInputArea.vue';
export default {
name: 'ChatInputWrap',
components: {
ChatAttchmentButton,
ChatAttachmentButton,
ChatSendButton,
ChatInputArea,
},
@@ -44,6 +44,13 @@ export default {
userInput: '',
};
},
computed: {
...mapGetters({
widgetColor: 'appConfig/getWidgetColor',
}),
},
destroyed() {
document.removeEventListener('keypress', this.handleEnterKeyPress);
},
@@ -51,11 +58,6 @@ export default {
document.addEventListener('keypress', this.handleEnterKeyPress);
},
computed: {
...mapGetters({
widgetColor: 'appConfig/getWidgetColor',
}),
},
methods: {
handleButtonClick() {
if (this.userInput && this.userInput.trim()) {

View File

@@ -0,0 +1,93 @@
<template>
<div class="file message-text__wrap" @click="openLink">
<div class="icon-wrap">
<i class="ion-document-text"></i>
</div>
<div class="meta">
<div class="title">
{{ title }}
</div>
<div class="link-wrap">
<a
class="download"
rel="noreferrer noopener nofollow"
target="_blank"
:href="url"
>
{{ $t('COMPONENTS.FILE_BUBBLE.DOWNLOAD') }}
</a>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
url: {
type: String,
default: '',
},
isInProgress: {
type: Boolean,
default: false,
},
},
computed: {
title() {
return this.isInProgress
? this.$t('COMPONENTS.FILE_BUBBLE.UPLOADING')
: decodeURI(this.fileName);
},
fileName() {
const filename = this.url.substring(this.url.lastIndexOf('/') + 1);
return filename;
},
},
methods: {
openLink() {
const win = window.open(this.url, '_blank');
win.focus();
},
},
};
</script>
<style lang="scss" scoped>
@import '~widget/assets/scss/variables.scss';
.file {
display: flex;
flex-direction: row;
padding: $space-one $space-slab;
cursor: pointer;
.icon-wrap {
font-size: $font-size-bigger;
color: $color-woot;
line-height: 1;
margin-left: $space-smaller;
margin-right: $space-small;
}
.title {
font-weight: $font-weight-medium;
font-size: $font-size-small;
margin: 0;
}
.download {
padding: 0;
margin: 0;
font-size: $font-size-small;
text-decoration: none;
}
.link-wrap {
line-height: 1;
}
.meta {
padding-right: $space-smaller;
}
}
</style>

View File

@@ -1,5 +1,10 @@
<template>
<a :href="url" target="_blank" class="image">
<a
:href="url"
target="_blank"
rel="noreferrer noopener nofollow"
class="image"
>
<div class="wrap">
<img :src="thumb" alt="Picture message" />
<span class="time">{{ readableTime }}</span>

View File

@@ -6,8 +6,14 @@
:message="message.content"
:status="message.status"
/>
<div v-if="hasImage" class="chat-bubble has-attachment user">
<div v-if="hasAttachment" class="chat-bubble has-attachment user">
<file-bubble
v-if="message.attachment && message.attachment.file_type !== 'image'"
:url="message.attachment.data_url"
:is-in-progress="isInProgress"
/>
<image-bubble
v-else
:url="message.attachment.data_url"
:thumb="message.attachment.thumb_url"
:readable-time="readableTime"
@@ -20,6 +26,7 @@
<script>
import UserMessageBubble from 'widget/components/UserMessageBubble';
import ImageBubble from 'widget/components/ImageBubble';
import FileBubble from 'widget/components/FileBubble';
import timeMixin from 'dashboard/mixins/time';
export default {
@@ -27,6 +34,7 @@ export default {
components: {
UserMessageBubble,
ImageBubble,
FileBubble,
},
mixins: [timeMixin],
props: {
@@ -40,11 +48,8 @@ export default {
const { status = '' } = this.message;
return status === 'in_progress';
},
hasImage() {
const { attachment = {} } = this.message;
const { file_type: fileType } = attachment;
return fileType === 'image';
hasAttachment() {
return !!this.message.attachment;
},
showTextBubble() {
const { message } = this;
@@ -94,5 +99,14 @@ export default {
padding: 0;
overflow: hidden;
}
.user.has-attachment {
.icon-wrap {
color: $color-white;
}
.download {
opacity: 0.8;
}
}
}
</style>

View File

@@ -45,7 +45,6 @@ export default {
display: inline-block;
font-size: $font-size-default;
line-height: 1.5;
max-width: 80%;
padding: $space-small $space-normal;
text-align: left;