Feature: Send attachments to widget user (#621)

This commit is contained in:
Nithin David Thomas
2020-03-22 15:54:36 +05:30
committed by GitHub
parent fe70843fae
commit f7e5f1fabf
16 changed files with 317 additions and 92 deletions

View File

@@ -19,6 +19,17 @@ class MessageApi extends ApiClient {
params: { before },
});
}
sendAttachment([conversationId, { file, file_type }]) {
const formData = new FormData();
formData.append('attachment[file]', file);
formData.append('attachment[file_type]', file_type);
return axios({
method: 'post',
url: `${this.url}/${conversationId}/messages`,
data: formData,
});
}
}
export default new MessageApi();

View File

@@ -31,26 +31,36 @@
}
.image {
@include flex;
align-items: flex-end;
justify-content: center;
text-align: center;
img {
@include padding($space-small);
max-height: 30rem;
max-width: 20rem;
}
cursor: pointer;
position: relative;
.time {
margin-left: -$space-large;
bottom: $space-smaller;
color: $color-white;
position: absolute;
right: $space-small;
white-space: nowrap;
}
.modal-container {
text-align: center;
}
.modal-image {
max-height: 80%;
max-width: 80%;
}
&::before {
$color-black: #000;
background-image: linear-gradient(-180deg, transparent 3%, $color-black 70%);
bottom: 0;
content: '';
height: 20%;
left: 0;
opacity: .8;
position: absolute;
width: 100%;
}
}
.map {

View File

@@ -47,7 +47,7 @@
}
}
>.icon {
.icon {
color: $medium-gray;
cursor: pointer;
font-size: $font-size-medium;
@@ -58,6 +58,16 @@
}
}
.file-uploads>label {
cursor: pointer;
}
.attachment {
cursor: pointer;
margin-right: $space-one;
padding: 0 $space-small;
}
>textarea {
@include ghost-input();
@include margin(0);

View File

@@ -1,10 +1,7 @@
<template>
<li v-if="data.attachment || data.content" :class="alignBubble">
<div :class="wrapClass">
<p
v-tooltip.top-start="sentByMessage"
:class="{ bubble: isBubble, 'is-private': isPrivate }"
>
<p v-tooltip.top-start="sentByMessage" :class="bubbleClass">
<bubble-image
v-if="data.attachment && data.attachment.file_type === 'image'"
:url="data.attachment.data_url"
@@ -81,6 +78,11 @@ export default {
isBubble() {
return [0, 1, 3].includes(this.data.message_type);
},
hasImageAttachment() {
const { attachment = {} } = this.data;
const { file_type: fileType } = attachment;
return fileType === 'image';
},
isPrivate() {
return this.data.private;
},
@@ -102,9 +104,30 @@ export default {
'activity-wrap': !this.isBubble,
};
},
bubbleClass() {
return {
bubble: this.isBubble,
'is-private': this.isPrivate,
'is-image': this.hasImageAttachment,
};
},
},
methods: {
getEmojiSVG,
},
};
</script>
<style lang="scss" scoped>
@import '~dashboard/assets/scss/variables.scss';
.wrap {
.is-image {
padding: 0;
overflow: hidden;
}
.image {
max-width: 32rem;
padding: 0;
}
}
</style>

View File

@@ -23,6 +23,17 @@
@click="onClick()"
@blur="onBlur()"
/>
<file-upload
v-if="!showFileUpload"
accept="image/*"
@input-file="onFileUpload"
>
<i
v-if="!isUploading.image"
class="icon ion-android-attach attachment"
/>
<woot-spinner v-if="isUploading.image" />
</file-upload>
<i
class="icon ion-happy-outline"
:class="{ active: showEmojiPicker }"
@@ -77,6 +88,7 @@
import { mapGetters } from 'vuex';
import emojione from 'emojione';
import { mixin as clickaway } from 'vue-clickaway';
import FileUpload from 'vue-upload-component';
import EmojiInput from '../emoji/EmojiInput';
import CannedResponse from './CannedResponse';
@@ -85,6 +97,7 @@ export default {
components: {
EmojiInput,
CannedResponse,
FileUpload,
},
mixins: [clickaway],
data() {
@@ -92,7 +105,13 @@ export default {
message: '',
isPrivate: false,
showEmojiPicker: false,
showFileUpload: false,
showCannedResponsesList: false,
isUploading: {
audio: false,
video: false,
image: false,
},
};
},
computed: {
@@ -180,21 +199,21 @@ export default {
isEscape(e) {
return e.keyCode === 27; // ESCAPE
},
sendMessage() {
async sendMessage() {
const isMessageEmpty = !this.message.replace(/\n/g, '').length;
if (isMessageEmpty) {
return;
}
if (isMessageEmpty) return;
if (!this.showCannedResponsesList) {
this.$store
.dispatch('sendMessage', {
try {
await this.$store.dispatch('sendMessage', {
conversationId: this.currentChat.id,
message: this.message,
private: this.isPrivate,
})
.then(() => {
this.$emit('scrollToMessage');
});
this.$emit('scrollToMessage');
} catch (error) {
// Error
}
this.clearMessage();
this.hideEmojiPicker();
}
@@ -272,6 +291,26 @@ export default {
: 'CONVERSATION.FOOTER.MSG_INPUT';
return placeHolder;
},
onFileUpload(file) {
this.isUploading.image = true;
this.$store
.dispatch('sendAttachment', [
this.currentChat.id,
{
file_type: file.type,
file: file.file,
},
])
.then(() => {
this.isUploading.image = false;
this.$emit('scrollToMessage');
})
.catch(() => {
this.isUploading.image = false;
this.$emit('scrollToMessage');
});
},
},
};
</script>

View File

@@ -189,6 +189,15 @@ const actions = {
setActiveInbox({ commit }, inboxId) {
commit(types.default.SET_ACTIVE_INBOX, inboxId);
},
sendAttachment: async ({ commit }, data) => {
try {
const response = MessageApi.sendAttachment(data);
commit(types.default.SEND_MESSAGE, response.data);
} catch (error) {
// Handle error
}
},
};
export default actions;