StatelessFIleInput: add maxSize and showIcon (#544)

This commit is contained in:
John Paul
2022-06-20 17:04:08 -04:00
committed by GitHub
parent 405a3eda60
commit 69a437a1a8
4 changed files with 89 additions and 43 deletions

View File

@@ -16,6 +16,7 @@
</template> </template>
<script> <script>
import { fileIsValid } from '~/plugins/fileUtils'
import UploadIcon from '~/assets/images/utils/upload.svg?inline' import UploadIcon from '~/assets/images/utils/upload.svg?inline'
export default { export default {
@@ -36,6 +37,9 @@ export default {
type: String, type: String,
default: null, default: null,
}, },
/**
* The max file size in bytes
*/
maxSize: { maxSize: {
type: Number, type: Number,
default: null, default: null,
@@ -54,22 +58,10 @@ export default {
onChange(files, shouldNotReset) { onChange(files, shouldNotReset) {
if (!shouldNotReset) this.files = files.target.files if (!shouldNotReset) this.files = files.target.files
this.files = [...this.files].filter((file) => { const validationOptions = { maxSize: this.maxSize, alertOnInvalid: true }
if (this.maxSize === null) { this.files = [...this.files].filter((file) =>
return true fileIsValid(file, validationOptions)
} else if (file.size > this.maxSize) { )
console.log('File size: ' + file.size + ', max size: ' + this.maxSize)
alert(
'File ' +
file.name +
' is too big! Must be less than ' +
this.$formatBytes(this.maxSize)
)
return false
} else {
return true
}
})
if (this.files.length > 0) { if (this.files.length > 0) {
this.$emit('change', this.files) this.$emit('change', this.files)

View File

@@ -2,7 +2,7 @@
<div class="columns"> <div class="columns">
<label class="button" @drop.prevent="handleDrop" @dragover.prevent> <label class="button" @drop.prevent="handleDrop" @dragover.prevent>
<span> <span>
<UploadIcon /> <UploadIcon v-if="showIcon" />
{{ prompt }} {{ prompt }}
</span> </span>
<input <input
@@ -16,6 +16,7 @@
</template> </template>
<script> <script>
import { fileIsValid } from '~/plugins/fileUtils'
import UploadIcon from '~/assets/images/utils/upload.svg?inline' import UploadIcon from '~/assets/images/utils/upload.svg?inline'
export default { export default {
@@ -36,24 +37,46 @@ export default {
type: String, type: String,
default: null, default: null,
}, },
/**
* The max file size in bytes
*/
maxSize: {
type: Number,
default: null,
},
showIcon: {
type: Boolean,
default: true,
},
}, },
methods: { methods: {
onChange(addedFiles) { onChange(addedFiles) {
this.$emit('change', addedFiles) this.$emit('change', addedFiles)
}, },
/**
* @param {FileList} filesToAdd
*/
addFiles(filesToAdd) { addFiles(filesToAdd) {
if (!filesToAdd) return if (!filesToAdd) return
if (!this.multiple && filesToAdd.length > 0) { const validationOptions = { maxSize: this.maxSize, alertOnInvalid: true }
this.onChange([filesToAdd[0]]) const validFiles = [...filesToAdd].filter((file) =>
return fileIsValid(file, validationOptions)
} )
this.onChange(filesToAdd) if (validFiles.length > 0) {
this.onChange(this.multiple ? validFiles : [validFiles[0]])
}
}, },
/**
* @param {DragEvent} e
*/
handleDrop(e) { handleDrop(e) {
this.addFiles(e.dataTransfer.files) this.addFiles(e.dataTransfer.files)
}, },
/**
* @param {Event} e native file input event
*/
handleChange(e) { handleChange(e) {
this.addFiles(e.target.files) this.addFiles(e.target.files)
}, },

27
plugins/fileUtils.js Normal file
View File

@@ -0,0 +1,27 @@
import { formatBytes } from '~/plugins/shorthands'
/**
* @param {File | Blob} file the file to validate
* @param {{ maxSize: number, alertOnInvalid: boolean }} validationOptions the
* constraints to validate the file against
* @param validationOptions.maxSize the max file size in bytes
* @param validationOptions.alertOnInvalid if an alert should pop up describing
* each validation error
* @returns `true` if the file is valid; `false` otherise
*/
export const fileIsValid = (file, validationOptions) => {
const { maxSize, alertOnInvalid } = validationOptions
if (maxSize !== null && maxSize !== undefined && file.size > maxSize) {
console.log(`File size: ${file.size}, max size: ${maxSize}`)
if (alertOnInvalid) {
alert(
`File ${file.name} is too big! Must be less than ${formatBytes(
maxSize
)}`
)
}
return false
}
return true
}

View File

@@ -2,16 +2,7 @@ export default ({ store }, inject) => {
inject('user', store.state.user) inject('user', store.state.user)
inject('tag', store.state.tag) inject('tag', store.state.tag)
inject('auth', store.state.auth) inject('auth', store.state.auth)
inject('formatNumber', (number) => { inject('formatNumber', formatNumber)
const x = +number
if (x >= 1000000) {
return (x / 1000000).toFixed(2).toString() + 'M'
} else if (x >= 10000) {
return (x / 1000).toFixed(1).toString() + 'K'
} else {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}
})
inject('formatVersion', (versionArray) => { inject('formatVersion', (versionArray) => {
const allVersions = store.state.tag.gameVersions.slice().reverse() const allVersions = store.state.tag.gameVersions.slice().reverse()
const allReleases = allVersions.filter((x) => x.version_type === 'release') const allReleases = allVersions.filter((x) => x.version_type === 'release')
@@ -98,15 +89,28 @@ export default ({ store }, inject) => {
return output.join(', ') return output.join(', ')
}) })
inject('formatBytes', (bytes, decimals = 2) => { inject('formatBytes', formatBytes)
if (bytes === 0) return '0 Bytes' }
const k = 1024 export const formatNumber = (number) => {
const dm = decimals < 0 ? 0 : decimals const x = +number
const sizes = ['Bytes', 'KiB', 'MiB', 'GiB'] if (x >= 1000000) {
return (x / 1000000).toFixed(2).toString() + 'M'
const i = Math.floor(Math.log(bytes) / Math.log(k)) } else if (x >= 10000) {
return (x / 1000).toFixed(1).toString() + 'K'
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i] } else {
}) return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}
}
export const formatBytes = (bytes, decimals = 2) => {
if (bytes === 0) return '0 Bytes'
const k = 1024
const dm = decimals < 0 ? 0 : decimals
const sizes = ['Bytes', 'KiB', 'MiB', 'GiB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
} }