chore: Allow more filetypes in uploads (#3557)

- Allowing the ability to upload more common file types like zip, Docx etc
- Fallback for image bubble when the image URL isn't available

fixes: #3270

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Nithin David <1277421+nithindavid@users.noreply.github.com>
This commit is contained in:
Sojan Jose 2021-12-20 23:50:37 +05:30 committed by GitHub
parent 76e8acd3c6
commit 6fe5484119
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 99 additions and 20 deletions

View file

@ -1,16 +1,29 @@
module FileTypeHelper
# NOTE: video, audio, image, etc are filetypes previewable in frontend
def file_type(content_type)
return :image if [
'image/jpeg',
'image/png',
'image/gif',
'image/tiff',
'image/bmp'
].include?(content_type)
return :video if content_type.include?('video/')
return :image if image_file?(content_type)
return :video if video_file?(content_type)
return :audio if content_type.include?('audio/')
:file
end
def image_file?(content_type)
[
'image/jpeg',
'image/png',
'image/gif',
'image/bmp',
'image/webp'
].include?(content_type)
end
def video_file?(content_type)
[
'video/ogg',
'video/mp4',
'video/webm',
'video/quicktime'
].include?(content_type)
end
end

View file

@ -45,6 +45,9 @@
// 1. Global
// ---------
// Disable contrast warnings in Foundation.
$contrast-warnings: false;
$global-font-size: 10px;
$global-width: 100%;
$global-lineheight: 1.5;

View file

@ -15,7 +15,7 @@
<file-upload
ref="upload"
:size="4096 * 4096"
accept="image/png, image/jpeg, image/gif, image/bmp, image/tiff, application/pdf, audio/mpeg, video/mp4, audio/ogg, text/csv"
:accept="allowedFileTypes"
:drop="true"
:drop-directory="false"
@input-file="onFileUpload"
@ -84,6 +84,7 @@ import {
hasPressedAltAndAKey,
} from 'shared/helpers/KeyboardHelpers';
import eventListenerMixins from 'shared/mixins/eventListenerMixins';
import { ALLOWED_FILE_TYPES } from 'shared/constants/messages';
import { REPLY_EDITOR_MODES } from './constants';
export default {
@ -161,6 +162,9 @@ export default {
showAttachButton() {
return this.showFileUpload || this.isNote;
},
allowedFileTypes() {
return ALLOWED_FILE_TYPES;
},
},
methods: {
handleKeyEvents(e) {

View file

@ -24,9 +24,10 @@
<div v-if="!isPending && hasAttachments">
<div v-for="attachment in data.attachments" :key="attachment.id">
<bubble-image
v-if="attachment.file_type === 'image'"
v-if="attachment.file_type === 'image' && !hasImageError"
:url="attachment.data_url"
:readable-time="readableTime"
@error="onImageLoadError"
/>
<audio v-else-if="attachment.file_type === 'audio'" controls>
<source :src="attachment.data_url" />
@ -133,6 +134,7 @@ export default {
data() {
return {
showContextMenu: false,
hasImageError: false,
};
},
computed: {
@ -287,12 +289,20 @@ export default {
return messageType ? 'right' : 'left';
},
},
watch: {
data() {
this.hasImageError = false;
},
},
mounted() {
this.hasImageError = false;
},
methods: {
hasMediaAttachment(type) {
if (this.hasAttachments && this.data.attachments.length > 0) {
const { attachments = [{}] } = this.data;
const { file_type: fileType } = attachments[0];
return fileType === type;
return fileType === type && !this.hasImageError;
}
return false;
},
@ -317,6 +327,9 @@ export default {
this.showAlert(this.$t('CONTACT_PANEL.COPY_SUCCESSFUL'));
this.showContextMenu = false;
},
onImageLoadError() {
this.hasImageError = true;
},
},
};
</script>

View file

@ -1,6 +1,6 @@
<template>
<div class="image message-text__wrap">
<img :src="url" @click="onClick" />
<img :src="url" @click="onClick" @error="onImgError()" />
<woot-modal :full-width="true" :show.sync="show" :on-close="onClose">
<img :src="url" class="modal-image" />
</woot-modal>
@ -9,6 +9,7 @@
<script>
export default {
components: {},
props: {
url: {
type: String,
@ -27,6 +28,9 @@ export default {
onClick() {
this.show = true;
},
onImgError() {
this.$emit('error');
},
},
};
</script>

View file

@ -32,7 +32,11 @@
:label="inboxNameLabel"
:placeholder="inboxNamePlaceHolder"
/>
<label for="toggle-business-hours" class="toggle-input-wrap" v-if="isATwitterInbox">
<label
v-if="isATwitterInbox"
for="toggle-business-hours"
class="toggle-input-wrap"
>
<input
v-model="tweetsEnabled"
type="checkbox"

View file

@ -13,6 +13,17 @@ export const MESSAGE_TYPE = {
// Size in mega bytes
export const MAXIMUM_FILE_UPLOAD_SIZE = 40;
export const ALLOWED_FILE_TYPES =
'image/*,' +
'audio/*,' +
'video/*,' +
'.3gpp,' +
'text/csv, text/plain, application/json, application/pdf, text/rtf,' +
'application/zip, application/x-7z-compressed application/vnd.rar application/x-tar,' +
'application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/vnd.oasis.opendocument.text,' +
'application/vnd.openxmlformats-officedocument.presentationml.presentation, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,' +
'application/vnd.openxmlformats-officedocument.wordprocessingml.document,';
export const CSAT_RATINGS = [
{
key: 'disappointed',

View file

@ -1,7 +1,7 @@
<template>
<file-upload
:size="4096 * 2048"
accept="image/*, application/pdf, audio/mpeg, video/mp4, audio/ogg, text/csv"
:accept="allowedFileTypes"
@input-file="onFileUpload"
>
<button class="icon-button flex items-center justify-center">
@ -15,7 +15,10 @@
import FileUpload from 'vue-upload-component';
import Spinner from 'shared/components/Spinner.vue';
import { checkFileSizeLimit } from 'shared/helpers/FileHelper';
import { MAXIMUM_FILE_UPLOAD_SIZE } from 'shared/constants/messages';
import {
MAXIMUM_FILE_UPLOAD_SIZE,
ALLOWED_FILE_TYPES,
} from 'shared/constants/messages';
import { BUS_EVENTS } from 'shared/constants/busEvents';
import FluentIcon from 'shared/components/FluentIcon/Index.vue';
export default {
@ -33,6 +36,9 @@ export default {
fileUploadSizeLimit() {
return MAXIMUM_FILE_UPLOAD_SIZE;
},
allowedFileTypes() {
return ALLOWED_FILE_TYPES;
},
},
methods: {
getFileType(fileType) {

View file

@ -17,6 +17,18 @@
class Attachment < ApplicationRecord
include Rails.application.routes.url_helpers
ACCEPTABLE_FILE_TYPES = %w[
text/csv text/plain text/rtf
application/json application/pdf
application/zip application/x-7z-compressed application/vnd.rar application/x-tar
application/msword application/vnd.ms-excel application/vnd.ms-powerpoint application/rtf
application/vnd.oasis.opendocument.text
application/vnd.openxmlformats-officedocument.presentationml.presentation
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
application/vnd.openxmlformats-officedocument.wordprocessingml.document
].freeze
belongs_to :account
belongs_to :message
has_one_attached :file
@ -90,10 +102,19 @@ class Attachment < ApplicationRecord
def acceptable_file
return unless should_validate_file?
errors.add(:file, 'is too big') if file.byte_size > 40.megabytes
validate_file_size(file.byte_size)
validate_file_content_type(file.content_type)
end
acceptable_types = ['image/png', 'image/jpeg', 'image/gif', 'image/bmp', 'image/tiff', 'application/pdf', 'audio/mpeg', 'video/mp4', 'audio/ogg',
'text/csv'].freeze
errors.add(:file, 'filetype not supported') unless acceptable_types.include?(file.content_type)
def validate_file_content_type(file_content_type)
errors.add(:file, 'type not supported') unless media_file?(file_content_type) || ACCEPTABLE_FILE_TYPES.include?(file_content_type)
end
def validate_file_size(byte_size)
errors.add(:file, 'size is too big') if byte_size > 40.megabytes
end
def media_file?(file_content_type)
file_content_type.start_with?('image/', 'video/', 'audio/')
end
end