- progress not working yet,
- yarn add activestorage
active-storage-upload
= f.file_field :attachments, multiple: true, direct_upload: true
- f.object.attachments.each do |att|
.list-group-item
= att.filename
<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> |