179 lines
3.0 KiB
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>
|