Files
FEDEO/pages/documents.vue
2024-12-20 17:49:24 +00:00

369 lines
9.0 KiB
Vue

<script setup>
import {BlobReader, BlobWriter, ZipWriter} from "@zip.js/zip.js";
import {useSupabaseSelectDocuments} from "~/composables/useSupabase.js";
definePageMeta({
middleware: "auth"
})
const dataStore = useDataStore()
const supabase = useSupabaseClient()
const user = useSupabaseUser()
const toast = useToast()
dataStore.fetchDocuments()
const uploadModalOpen = ref(false)
const uploadInProgress = ref(false)
const fileUploadFormData = ref({
tags: ["Eingang"],
path: "",
tenant: dataStore.currentTenant
})
let tags = dataStore.getDocumentTags
const selectedTags = ref("Eingang")
const documents = ref([])
const folders = ref([])
const selectedPath = ref("_")
const loadingDocs = ref(false)
const isDragTarget = ref(false)
const setupPage = async () => {
//documents.value = await useSupabaseSelectDocuments("*, project(id,name), customer(id,name), contract(id,name), vendor(id,name), plant(id,name), vehicle(id,licensePlate), product(id,name), profile(id,fullName) ")
//documents.value = await useSupabaseSelectDocuments("*",null, selectedPath.value)
//console.log(documents.value)
folders.value = dataStore.ownTenant.documentFolders
documents.value = await useSupabaseSelectDocuments("*",null,selectedPath.value)
//await supabase.from("documents").select().eq("folderPath",selectedPath.value).eq("tenant",dataStore.currentTenant)
//console.log(await supabase.from("documents").select().eq("folderPath",selectedPath.value))
const dropZone = document.getElementById("drop_zone")
dropZone.ondragover = function (event) {
console.log(event)
isDragTarget.value = true
event.preventDefault()
}
dropZone.ondragleave = function (event) {
isDragTarget.value = false
}
dropZone.ondrop = async function (event) {
console.log("files dropped")
event.preventDefault()
await uploadFiles(event.dataTransfer.files)
isDragTarget.value = false
setupPage()
}
loadingDocs.value = false
}
setupPage()
const currentFolders = computed(() => {
if(folders.value.length > 0) {
/*console.log(folders.value[0].path.split("/").filter(x => x.length > 0))
console.log(selectedPath.value.split("/").filter(x => x.length > 0))*/
let tempFolders = folders.value.filter(i => (i.path.split("_").filter(x => x.length > 0) || []).length === selectedPath.value.split("_").filter(x => x.length > 0).length + 1)
tempFolders = tempFolders.filter(i => i.path.includes(selectedPath.value))
return tempFolders
}
})
const breadcrumbLinks = computed(() => {
return [{
label: "Home",
click: () => {
changePath("_")
},
icon: "i-heroicons-folder"
},...selectedPath.value.split("_").filter(x => x.length > 0).map((i,index) => {
let re = new RegExp(".+?" + i )
let path = selectedPath.value.match(re)[0]
return {
label: folders.value.find(x => x.path === path).name ||path,
click: () => {
changePath(path)
},
icon: "i-heroicons-folder"
}
})]
})
const filteredDocuments = computed(() => {
/*if(selectedTags.value !== "Archiviert") {
return documents.value.filter(i => i.tags.find(t => selectedTags.value === t) && !i.tags.includes("Archiviert"))
} else {
return documents.value.filter(i => i.tags.find(t => selectedTags.value === t))
}*/
return documents.value
})
const changePath = async (newPath) => {
loadingDocs.value = true
selectedPath.value = newPath
setupPage()
}
const uploadFiles = async (files) => {
uploadInProgress.value = true;
if(files) {
await dataStore.uploadFiles({tags: ["Ablage"],tenant: dataStore.currentTenant, folderPath: selectedPath.value}, files, true)
} else {
await dataStore.uploadFiles(fileUploadFormData.value, document.getElementById("fileUploadInput").files, true)
}
uploadModalOpen.value = false;
uploadInProgress.value = false;
}
const downloadSelected = async () => {
const bucket = "files";
let files = []
dataStore.documents.filter(doc => doc.selected).forEach(doc => files.push(doc.path))
console.log(files)
// If there are no files in the folder, throw an error
if (!files || !files.length) {
throw new Error("No files to download");
}
const promises = [];
// Download each file in the folder
files.forEach((file) => {
promises.push(
supabase.storage.from(bucket).download(`${file}`)
);
});
// Wait for all the files to download
const response = await Promise.allSettled(promises);
// Map the response to an array of objects containing the file name and blob
const downloadedFiles = response.map((result, index) => {
if (result.status === "fulfilled") {
console.log(files[index].split("/")[files[index].split("/").length -1])
return {
name: files[index].split("/")[files[index].split("/").length -1],
blob: result.value.data,
};
}
});
// Create a new zip file
const zipFileWriter = new BlobWriter("application/zip");
const zipWriter = new ZipWriter(zipFileWriter, { bufferedWrite: true });
// Add each file to the zip file
downloadedFiles.forEach((downloadedFile) => {
if (downloadedFile) {
zipWriter.add(downloadedFile.name, new BlobReader(downloadedFile.blob));
}
});
// Download the zip file
const url = URL.createObjectURL(await zipWriter.close());
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "documents.zip");
document.body.appendChild(link);
link.click();
}
</script>
<template>
<UDashboardNavbar
title="Dokumente"
>
</UDashboardNavbar>
<!-- <UDashboardToolbar>
<template #right>
<UButton @click="uploadModalOpen = true">Hochladen</UButton>
&lt;!&ndash; <UButton
@click="downloadSelected"
:disabled="dataStore.documents.filter(doc => doc.selected).length === 0"
>Herunterladen</UButton>&ndash;&gt;
</template>
&lt;!&ndash; <template #right>
<USelectMenu
:options="tags"
v-model="selectedTags"
class="w-40"
>
<template #label>
{{selectedTags}}
</template>
</USelectMenu>
</template>&ndash;&gt;
</UDashboardToolbar>-->
<UDashboardToolbar>
<template #left>
<UBreadcrumb
:links="breadcrumbLinks"
/>
</template>
<template #right>
<UButton @click="uploadModalOpen = true">Hochladen</UButton>
</template>
</UDashboardToolbar>
<div id="drop_zone" class="h-full scrollList">
<UDashboardPanelContent v-if="!isDragTarget" >
<div class="flex flex-row w-full flex-wrap" v-if="currentFolders.length > 0">
<a
class="w-1/6 folderIcon flex flex-col p-5 m-2"
v-for="folder in currentFolders"
@click="changePath(folder.path)"
>
<UIcon
name="i-heroicons-folder"
class="w-20 h-20"
/>
<span class="text-center truncate">{{folder.name}}</span>
</a>
</div>
<UDivider class="my-5" v-if="currentFolders.length > 0">Dokumente</UDivider>
<div v-if="!loadingDocs">
<DocumentList
v-if="filteredDocuments.length > 0"
:documents="filteredDocuments"
@selectDocument="(info) => console.log(info)"
/>
<UAlert
v-else
class="mt-5 w-1/2 mx-auto"
icon="i-heroicons-light-bulb"
title="Keine Dokumente vorhanden"
color="primary"
variant="outline"
/>
</div>
<UProgress
animation="carousel"
v-else
class="w-2/3 my-5 mx-auto"
/>
</UDashboardPanelContent>
<UCard
class=" m-5"
v-else>
<template #header>
<p class="mx-auto">Dateien zum hochladen hierher ziehen</p>
</template>
</UCard>
</div>
<USlideover
v-model="uploadModalOpen"
>
<UCard class="flex flex-col flex-1" :ui="{ body: { base: 'flex-1' }, ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
<template #header>
Datei Hochladen
</template>
<div class="h-full">
<UFormGroup
label="Datei:"
>
<UInput
type="file"
id="fileUploadInput"
multiple
/>
</UFormGroup>
<UFormGroup
label="Tags:"
class="mt-3"
>
<USelectMenu
multiple
searchable
searchable-placeholder="Suchen..."
:options="tags"
v-model="fileUploadFormData.tags"
/>
</UFormGroup>
</div>
<template #footer>
<UButton
v-if="!uploadInProgress"
class="mt-3"
@click="uploadFiles"
>Hochladen</UButton>
<UProgress
v-else
animation="carousel"
/>
</template>
</UCard>
</USlideover>
</template>
<style scoped>
.folderIcon {
border: 1px solid lightgrey;
border-radius: 10px;
color: dimgrey;
}
.folderIcon:hover {
border: 1px solid #69c350;
color: #69c350;
}
</style>