medialibrary-helper/assets/components/MultipleFiles.vue

105 lines
3.9 KiB
Vue

<template>
<div class="space-y-2">
<div v-if="label" class="text-sm font-semibold text-gray-400" v-text="label"></div>
<label class="flex items-center justify-center h-[35px] border-2 border-solid border-gray-600 rounded-lg text-sm text-gray-300 bg-gray-700 relative" :for="id">
<div class="relative">Klicken oder Datei hierhin ziehen zum hochladen</div>
<input :id="id" ref="uploader" class="hidden" type="file" :name="name" multiple @change="upload($event.target.files)" />
<div class="absolute w-full h-full top-0 left-0 cursor-pointer" @drop="onDropping" @dragenter="onDragEnter" @dragover="onDragOver" @dragleave="onDragLeave"></div>
</label>
<div v-for="file in inner" :key="file.id" class="flex h-[35px] justify-between items-center space-x-2 px-2 border-2 border-solid border-gray-600 rounded-lg text-gray-300 bg-gray-700">
<img :src="file.icon" class="w-6 h-6" />
<div class="text-sm text-gray-300 leading-none grow" v-text="file.file_name"></div>
<a v-tooltip="`Löschen`" href="#" class="flex justify-center items-center w-6 h-6 rounded-full bg-red-200" @click.prevent="onDelete(file)">
<trash-icon class="text-red-800 w-3 h-3"></trash-icon>
</a>
<a v-tooltip="`Öffnen`" :href="file.original_url" class="flex justify-center items-center w-6 h-6 rounded-full bg-primary-700" target="_BLANK">
<external-icon class="text-primary-200 w-3 h-3"></external-icon>
</a>
</div>
</div>
</template>
<script setup>
import {ref, inject} from 'vue';
import TrashIcon from './TrashIcon.vue';
import ExternalIcon from './ExternalIcon.vue';
import useReadFile from '../composables/useReadFile.js';
import {useToast} from 'vue-toastification';
const emit = defineEmits(['update:modelValue']);
const axios = inject('axios');
const toast = useToast();
const queue = ref([]);
const inner = ref([]);
const {onDragEnter, onDragOver, onDragLeave, processDrop, read} = useReadFile();
const props = defineProps({
collection: {
required: true,
type: String,
},
parentName: {
required: true,
type: String,
},
parentId: {
required: true,
validator: (value) => typeof value === 'number' || value === null,
},
name: {
type: String,
required: true,
},
id: {
required: true,
type: String,
},
label: {
required: false,
default: () => null,
validator: (value) => value === null || typeof value === 'string',
},
});
async function onDropping(e) {
await upload(await processDrop(e, 1));
}
async function upload(files) {
[...files].forEach((f) => realUpload(f));
}
async function realUpload(file) {
var payload = await read(file);
var identifier = Math.random().toString(36) + Date.now() + payload.content.substring(2, 15);
queue.value = [...queue.value, {file_name: payload.name, size: payload.size, identifier: identifier}];
var response = await axios.post('/mediaupload', {
parent: {model: props.parentName, collection_name: props.collection, id: props.parentId ? props.parentId : null},
payload: [payload],
});
queue.value = queue.value.filter((f) => f.identifier !== identifier);
inner.value.push(response.data[0]);
emit('update:modelValue', inner.value);
toast.success('Dateien hochgeladen');
}
async function onDelete(file) {
await axios.delete(`/mediaupload/${file.id}`);
inner.value = inner.value.filter((f) => f.id !== file.id);
emit('update:modelValue', inner.value);
toast.success('Datei entfernt');
}
async function reload() {
var response = await axios.get(`/mediaupload/${props.parentName}/${props.parentId}/${props.collection}`);
inner.value = response.data;
emit('update:modelValue', response.data);
}
if (props.parentId !== null) {
reload();
}
</script>