370 lines
9.0 KiB
Vue
370 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>
|
|
<!– <UButton
|
|
@click="downloadSelected"
|
|
:disabled="dataStore.documents.filter(doc => doc.selected).length === 0"
|
|
>Herunterladen</UButton>–>
|
|
</template>
|
|
<!– <template #right>
|
|
<USelectMenu
|
|
:options="tags"
|
|
v-model="selectedTags"
|
|
class="w-40"
|
|
>
|
|
<template #label>
|
|
{{selectedTags}}
|
|
</template>
|
|
</USelectMenu>
|
|
</template>–>
|
|
|
|
</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> |