pubload/components/upload/drop.vue

179 lines
3.0 KiB
Vue

<template>
<form
class="selector"
:class="{ dragging }"
@submit.prevent="upload"
>
<div
ref="dropzone"
class="dropzone"
@drop.prevent="dropFile"
@dragover="dragging = true"
@dragleave="dragging = false"
>
<input
type="file"
@change="selectFile"
>
Drop or paste your files here
</div>
<ul class="uploads nolist">
<li
v-for="upload in thumbs"
class="upload"
>
<img
v-if="upload.file.type.indexOf('image/') === 0"
:src="upload.thumb"
class="upload-thumb"
>
<video
v-if="upload.file.type.indexOf('video/') === 0"
class="upload-thumb"
autoplay
muted
loop
>
<source :src="upload.thumb">
</video>
<span class="upload-name ellipsis">{{ upload.file.name }}</span>
</li>
</ul>
<button
class="button button-primary submit"
>Upload</button>
<label>
<input
v-model="addToAlbum"
type="checkbox"
>Add to album
</label>
</form>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { post } from '#src/api.ts';
const dropzone = ref(null);
const dragging = ref(false);
const uploads = ref([]);
const thumbs = ref([]);
const addToAlbum = ref(true);
async function upload() {
console.log('UPLOAD!', uploads.value);
const form = new FormData();
uploads.value.forEach((file) => {
form.append('files', file);
});
form.append('options', JSON.stringify({
addToAlbum: addToAlbum.value,
}));
const res = await post('/files', form);
console.log(res);
}
function addFiles(newFiles) {
console.log('NEW FILES', newFiles);
uploads.value = uploads.value.concat(newFiles);
thumbs.value = thumbs.value.concat(newFiles.map((file) => ({
file,
thumb: URL.createObjectURL(file),
})));
}
function dropFile(event) {
dragging.value = false;
const newFiles = Array.from(event.dataTransfer.items)
.filter((item) => item.kind === 'file')
.map((item) => item.getAsFile());
addFiles(newFiles);
}
function selectFile(event) {
const newFiles = Array.from(event.target.files);
addFiles(newFiles);
event.target.value = null;
}
onMounted(() => {
window.addEventListener('dragover', (event) => event.preventDefault());
window.addEventListener('drop', (event) => event.preventDefault());
});
</script>
<style scoped>
.selector {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1rem;
}
.dropzone {
width: 100%;
height: 15rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1rem;
padding: 1rem;
border: solid 1px var(--glass-weak-20);
&.dragging {
background: var(--primary);
}
}
.uploads {
width: 100%;
display: grid;
align-items: center;
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
gap: .5rem;
}
.upload {
display: inline-flex;
flex-direction: column;
}
.upload-thumb {
width: 8rem;
height: 6rem;
object-fit: cover;
margin-bottom: .25rem;
}
.upload-name {
font-size: .8rem;
}
.submit {
font-size: 1.2rem;
padding: .75rem 1rem;
}
</style>