You've already forked AstralRinth
forked from didirus/AstralRinth
StatelessFIleInput: add maxSize and showIcon (#544)
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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
27
plugins/fileUtils.js
Normal 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
|
||||||
|
}
|
||||||
@@ -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]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user