105 lines
3.9 KiB
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>
|