|
<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 }') |
|
slot(ref='slot') |
|
|
|
.list-group |
|
.list-group-item(v-for='file in finished') |
|
input(:name='input.name' type='hidden' :value='file.blob.signed_id') |
|
|{{file.blob.filename}} |
|
.list-group-item(v-for='file in uploads') |
|
i Upload: {{file.file.filename }} |
|
|
|
</template> |
|
|
|
<script> |
|
/* eslint-disable no-restricted-globals */ |
|
/* eslint-disable prefer-destructuring */ |
|
import { DirectUpload } from 'activestorage' |
|
|
|
export default { |
|
data() { |
|
return { |
|
isDragging: false, |
|
finished: [], |
|
uploads: [], |
|
} |
|
}, |
|
beforeDestroy() { |
|
removeEventListener("direct-upload:progress", this.onProgress.bind(this)) |
|
}, |
|
mounted() { |
|
addEventListener("direct-upload:progress", this.onProgress.bind(this)) |
|
this.input.addEventListener('change', (_event) => { |
|
Array.from(this.input.files).forEach(file => this.upload(file)) |
|
this.input.value = null |
|
}) |
|
}, |
|
methods: { |
|
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) { |
|
console.log('progress', event) |
|
}, |
|
upload(file) { |
|
if (!this.uploadInProgress) { |
|
addEventListener("direct-upload:progress", this.onProgress.bind(this)) |
|
} |
|
const upload = new DirectUpload(file, this.uploadUrl) |
|
this.uploads.push({ file, upload }) |
|
upload.create((error, blob) => { |
|
if (error) { |
|
// TODO |
|
} else { |
|
this.uploads = this.uploads.filter(payload => payload.file.filename !== file.filename) |
|
this.finished.push({ file, blob }) |
|
if (this.uploads.length === 0) { |
|
removeEventListener("direct-upload:progress", this.onProgress.bind(this)) |
|
} |
|
} |
|
}) |
|
}, |
|
}, |
|
computed: { |
|
uploadInProgress() { return this.uploads.length > 0 }, |
|
uploadUrl() { return this.input.dataset.directUploadUrl }, |
|
input() { |
|
return this.$el.querySelector('input[type=file]'); |
|
} |
|
} |
|
} |
|
</script> |
|
|
|
<style lang='scss'> |
|
.drop-zone { |
|
border: 3px solid transparent; |
|
margin: -3px; |
|
} |
|
.drop-zone.dragging { |
|
border: 3px dashed #444; |
|
position: relative; |
|
} |
|
.drop-zone.dragging:before { |
|
content: "Drop the file here to upload"; |
|
display: block; |
|
position: absolute; |
|
top: 0; |
|
right: 5px; |
|
font-style: italic; |
|
color: #555; |
|
} |
|
|
|
input[type=file][data-direct-upload-url][disabled] { |
|
display: none; |
|
} |
|
</style> |