|
<template lang='pug'> |
|
div.drop-zone(:class='{dragging: isDragging }' |
|
@dragover.prevent='dragover' |
|
@dragenter.prevent='dragover' |
|
@drop.prevent.stop='onDrop' |
|
@dragleave.prevent='dragleave') |
|
div(:class='{ hidden: uploadInProgress }' @click='openFileBrowser') |
|
slot |
|
i {{label}} |
|
input(type='file' :multiple='multiple' ref='input' style='display: none') |
|
.list-group(v-if='uploads.length > 0') |
|
.list-group-item(v-for='file in uploads') |
|
slot(name='progress' v-bind:file='file' v-bind:progress='progress') |
|
i.mdi.mdi-loading.fa-spin |
|
i Uploading: {{file.file.filename }} |
|
br |
|
b-progress(:value="progress" :max="100" :animated='true' style='max-width: 200px; height: 2px') |
|
</template> |
|
|
|
<script> |
|
import { DirectUpload } from 'activestorage' |
|
import bProgress from 'bootstrap-vue/es/components/progress/progress'; |
|
|
|
export default { |
|
components: { |
|
bProgress |
|
}, |
|
props: { |
|
uploadUrl: { |
|
type: String, |
|
required: true |
|
}, |
|
multiple: { |
|
type: Boolean, |
|
default: true |
|
}, |
|
label: { |
|
type: String, |
|
default: "Schieben Sie das Dokument hier rein oder klicken Sie hier um hochzuladen" |
|
} |
|
}, |
|
data() { |
|
return { |
|
isDragging: false, |
|
progress: 0, |
|
uploads: [], |
|
} |
|
}, |
|
mounted() { |
|
this.input.addEventListener('change', (_event) => { |
|
Array.from(this.input.files).forEach(file => this.upload(file)) |
|
this.input.value = null |
|
}) |
|
}, |
|
methods: { |
|
// callbacks from active storage |
|
directUploadWillStoreFileWithXHR(xhr) { |
|
xhr.upload.addEventListener("progress", event => this.onProgress(event)) |
|
}, |
|
directUploadWillStoreFileWithXHR(xhr) { |
|
this.lastXhr = xhr |
|
}, |
|
|
|
dragover() { |
|
this.isDragging = true |
|
}, |
|
dragleave() { |
|
this.isDragging = false |
|
}, |
|
onDrop(event) { |
|
this.dragleave(); |
|
const files = event.dataTransfer.files; |
|
Array.from(files).forEach(file => this.upload(file)) |
|
}, |
|
onProgress(event) { |
|
this.progress = (event.loaded / event.total) * 100 |
|
}, |
|
upload(file) { |
|
const upload = new DirectUpload(file, this.uploadUrl, this) |
|
this.uploads.push({ file, upload }) |
|
this.progress = 0 |
|
upload.create((error, blob) => { |
|
if (error) { |
|
// TODO |
|
} else { |
|
this.uploads = this.uploads.filter(payload => payload.file.filename !== file.filename) |
|
this.$emit('upload', { file, blob }) |
|
} |
|
}) |
|
}, |
|
openFileBrowser() { |
|
this.input.click() |
|
} |
|
}, |
|
computed: { |
|
uploadInProgress() { return this.uploads.length > 0 }, |
|
input() { |
|
return this.$refs.input; |
|
} |
|
} |
|
} |
|
</script> |
|
|
|
<style lang='scss' scoped> |
|
.drop-zone { |
|
border: 3px solid #eee; |
|
min-height: 50px; |
|
} |
|
.drop-zone.dragging { |
|
border: 3px dashed #444; |
|
position: relative; |
|
} |
|
.drop-zone.dragging:before { |
|
content: "Lassen Sie die Datei hier fallen um den Upload zu beginnen"; |
|
display: block; |
|
position: absolute; |
|
top: 0; |
|
right: 5px; |
|
font-style: italic; |
|
color: #555; |
|
} |
|
|
|
input[type=file][data-direct-upload-url][disabled] { |
|
display: none; |
|
} |
|
</style> |
|
|