Document Restructure
Introduced ExternalDevices Settingspage Added DocumentDisplay.vue Component Some Changes to Spaces
This commit is contained in:
@@ -1,176 +1,3 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="controlHeader">
|
||||
<UButton @click="uploadModalOpen = true">Hochladen</UButton>
|
||||
<UButton
|
||||
@click="downloadSelected"
|
||||
class="ml-2"
|
||||
:disabled="documents.filter(doc => doc.selected).length === 0"
|
||||
>Herunterladen</UButton>
|
||||
<UModal
|
||||
v-model="uploadModalOpen"
|
||||
>
|
||||
<UCard class="p-4">
|
||||
|
||||
<template #header>
|
||||
Datei hochladen
|
||||
</template>
|
||||
|
||||
<UFormGroup
|
||||
label="Datei:"
|
||||
>
|
||||
<UInput
|
||||
type="file"
|
||||
id="fileUploadInput"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<!-- <UFormGroup
|
||||
label="Name:"
|
||||
class="mt-3"
|
||||
>
|
||||
<UInput
|
||||
v-model="fileUploadFormData.name"
|
||||
/>
|
||||
</UFormGroup>-->
|
||||
<UFormGroup
|
||||
label="Tags:"
|
||||
class="mt-3"
|
||||
>
|
||||
<USelectMenu
|
||||
multiple
|
||||
searchable
|
||||
searchable-placeholder="Suchen..."
|
||||
:options="tags"
|
||||
v-model="fileUploadFormData.tags"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Ordner:"
|
||||
class="mt-3"
|
||||
>
|
||||
<USelectMenu
|
||||
:options="folders"
|
||||
v-model="fileUploadFormData.folder"
|
||||
value-attribute="label"
|
||||
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<template #footer>
|
||||
<UButton
|
||||
class="mt-3"
|
||||
@click="uploadFile"
|
||||
>Hochladen</UButton>
|
||||
</template>
|
||||
|
||||
|
||||
</UCard>
|
||||
|
||||
</UModal>
|
||||
</div>
|
||||
<div >
|
||||
<USlideover
|
||||
v-model="showDocumentModal"
|
||||
fullscreen
|
||||
>
|
||||
<UCard class="h-full">
|
||||
<embed
|
||||
class="bigPreview mb-3"
|
||||
:src="selectedDocument.url"
|
||||
/>
|
||||
|
||||
<UBadge
|
||||
v-for="tag in selectedDocument.tags"
|
||||
class="ml-2"
|
||||
>
|
||||
{{tag}}
|
||||
</UBadge>
|
||||
|
||||
|
||||
<UFormGroup
|
||||
label="Ordner ändern:"
|
||||
>
|
||||
<USelectMenu
|
||||
:options="folders"
|
||||
v-on:change="changeFolder"
|
||||
v-model="newFolder"
|
||||
value-attribute="label"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup
|
||||
label="Tags ändern:"
|
||||
>
|
||||
<USelectMenu
|
||||
:options="tags"
|
||||
v-model="selectedDocument.tags"
|
||||
@change="updateDocument"
|
||||
multiple
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
</UCard>
|
||||
</USlideover>
|
||||
<!-- TODO: Tab Height always Full -->
|
||||
<UTabs
|
||||
:items="folders"
|
||||
orientation="vertical"
|
||||
v-model="tabOpen"
|
||||
:ui="{ wrapper: 'flex items-top gap-4', list: { width: 'w-72', padding: 'p-3' } }"
|
||||
>
|
||||
<template #item="{item}">
|
||||
<div class="documentList">
|
||||
<a
|
||||
v-if="documents.filter(doc => doc.folder === item.label).length > 0"
|
||||
v-for="document in documents.filter(doc => doc.folder === item.label)"
|
||||
class="documentListItem"
|
||||
>
|
||||
<embed
|
||||
:src="document.url"
|
||||
class="previewEmbed"
|
||||
/>
|
||||
<UButton
|
||||
@click="openDocument(document)"
|
||||
class="mt-3"
|
||||
>
|
||||
<UIcon name="i-heroicons-eye-solid" />
|
||||
</UButton>
|
||||
<UToggle
|
||||
v-model="document.selected"
|
||||
class="ml-2"
|
||||
/>
|
||||
|
||||
<!-- {{document.name}}<br>-->
|
||||
<!-- <UBadge
|
||||
v-for="tag in document.tags"
|
||||
variant="outline"
|
||||
color="primary"
|
||||
>{{tag}}</UBadge>
|
||||
<UBadge
|
||||
color="rose"
|
||||
variant="outline"
|
||||
>{{document.state}}</UBadge>-->
|
||||
|
||||
</a>
|
||||
<div v-else>
|
||||
<p>Keine Dokumente in diesem Ordner</p>
|
||||
<UButton
|
||||
@click="uploadModalOpen = true"
|
||||
>
|
||||
Hochladen
|
||||
</UButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</UTabs>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
import {BlobReader, BlobWriter, ZipWriter} from "@zip.js/zip.js";
|
||||
@@ -182,145 +9,93 @@ const supabase = useSupabaseClient()
|
||||
const user = useSupabaseUser()
|
||||
const toast = useToast()
|
||||
|
||||
const {documents} = storeToRefs(useDataStore())
|
||||
const {fetchDocuments} = useDataStore()
|
||||
const {documents, projects, customers} = storeToRefs(useDataStore())
|
||||
const {fetchDocuments, getDocumentTags} = useDataStore()
|
||||
|
||||
fetchDocuments()
|
||||
|
||||
const tabOpen = ref(0)
|
||||
const uploadModalOpen = ref(false)
|
||||
const uploadInProgress = ref(false)
|
||||
const fileUploadFormData = ref({
|
||||
tags: [],
|
||||
folder: "",
|
||||
object: "",
|
||||
tags: ["Eingang"],
|
||||
project: null,
|
||||
customer: null,
|
||||
path: ""
|
||||
})
|
||||
|
||||
const selectedDocuments = ref([])
|
||||
|
||||
let tags = ["Eingangsrechnung","Ausgangrechnung","Mahnung", "Dokument", "E-Mail Anhang"]
|
||||
const folders = [
|
||||
{
|
||||
label: "Eingang",
|
||||
},
|
||||
{
|
||||
label: "Eingangsrechnungen"
|
||||
},
|
||||
{
|
||||
label: "Ausgangsrechnungen"
|
||||
},
|
||||
{
|
||||
label: "Fahrzeuge"
|
||||
},
|
||||
{
|
||||
label: "Dokumente"
|
||||
},
|
||||
{
|
||||
label: "Archiv"
|
||||
let tags = getDocumentTags
|
||||
|
||||
const selectedTags = ref(["Eingang"])
|
||||
|
||||
const filteredDocuments = computed(() => {
|
||||
|
||||
return documents.value.filter(doc => doc.tags.filter(tag => selectedTags.value.find(t => t === tag)).length > 0)
|
||||
|
||||
|
||||
})
|
||||
|
||||
const uploadFiles = async () => {
|
||||
const uploadSingleFile = async (file) => {
|
||||
|
||||
const {data, error} = await supabase
|
||||
.storage
|
||||
.from("files")
|
||||
.upload(`${user.value.app_metadata.tenant}/${file.name}`, file)
|
||||
|
||||
if (error) {
|
||||
console.log(error)
|
||||
} else if (data) {
|
||||
const returnPath = data.path
|
||||
|
||||
if (error) {
|
||||
|
||||
} else {
|
||||
const files = (await supabase.storage.from('files').list(`${user.value.app_metadata.tenant}/`, {
|
||||
limit: 100,
|
||||
offset: 0,
|
||||
sortBy: {column: 'name', order: 'asc'}
|
||||
})).data
|
||||
|
||||
fileUploadFormData.value.path = returnPath
|
||||
|
||||
const {data, error} = await supabase
|
||||
.from("documents")
|
||||
.insert([fileUploadFormData.value])
|
||||
.select()
|
||||
if(error) console.log(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
const uploadFile = async () => {
|
||||
const file = document.getElementById("fileUploadInput").files[0]
|
||||
|
||||
const {data,error} = await supabase
|
||||
.storage
|
||||
.from("documents")
|
||||
.upload(`${user.value.app_metadata.tenant}/${fileUploadFormData.value.folder}/${file.name}`,file)
|
||||
uploadInProgress.value = true
|
||||
|
||||
const returnPath = data.path
|
||||
let files = document.getElementById("fileUploadInput").files
|
||||
|
||||
if(error) {
|
||||
if(files.length === 1) {
|
||||
await uploadSingleFile(files[0])
|
||||
} else if( files.length > 1) {
|
||||
|
||||
} else {
|
||||
console.log(returnPath)
|
||||
const files = (await supabase.storage.from('documents').list(`${user.value.app_metadata.tenant}/${fileUploadFormData.value.folder}/`, {limit: 100, offset: 0, sortBy: { column: 'name', order: 'asc' }})).data
|
||||
console.log(files)
|
||||
const fileId = files.find(temp => returnPath.includes(temp.name)).id
|
||||
for(let i = 0; i < files.length; i++){
|
||||
uploadSingleFile(files[i])
|
||||
}
|
||||
|
||||
fileUploadFormData.value.object = fileId
|
||||
fileUploadFormData.value.path = returnPath
|
||||
console.log(fileUploadFormData.value)
|
||||
|
||||
const {data,error} = await supabase
|
||||
.from("documents")
|
||||
.insert([fileUploadFormData.value])
|
||||
.select()
|
||||
console.log(data)
|
||||
console.log(error)
|
||||
}
|
||||
|
||||
uploadModalOpen.value = false;
|
||||
uploadInProgress.value = false;
|
||||
fetchDocuments()
|
||||
}
|
||||
|
||||
const updateDocument = async () => {
|
||||
console.log(selectedDocument.value)
|
||||
|
||||
let objData = selectedDocument.value
|
||||
delete objData.url
|
||||
|
||||
const {data,error} = await supabase
|
||||
.from("documents")
|
||||
.update(objData)
|
||||
.eq('id',objData.id)
|
||||
.select()
|
||||
console.log(data)
|
||||
|
||||
if(error) {
|
||||
console.log(error)
|
||||
} else {
|
||||
toast.add({title: "Dokument aktualisiert"})
|
||||
selectedDocument.value = data[0]
|
||||
showDocumentModal.value = false
|
||||
fetchDocuments()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const changeFolder = async () => {
|
||||
console.log("Change Folder")
|
||||
console.log(selectedDocument.value)
|
||||
|
||||
let filename = selectedDocument.value.path.split("/")[2]
|
||||
let oldPath = selectedDocument.value.path
|
||||
let newPath = `${user.value.app_metadata.tenant}/${newFolder.value}/${filename}`
|
||||
console.log(oldPath)
|
||||
console.log(newPath)
|
||||
|
||||
const { data, error } = await supabase
|
||||
.storage
|
||||
.from('documents')
|
||||
.move(oldPath,newPath )
|
||||
|
||||
if(error) {
|
||||
console.log(error)
|
||||
} else {
|
||||
console.log(data)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const newFolder = ref("")
|
||||
|
||||
const selectedDocument = ref({})
|
||||
const showDocumentModal = ref(false)
|
||||
|
||||
const openDocument = async (document) => {
|
||||
console.log("open")
|
||||
selectedDocument.value = document
|
||||
showDocumentModal.value = true
|
||||
|
||||
}
|
||||
|
||||
|
||||
const downloadSelected = async () => {
|
||||
const bucket = "documents";
|
||||
const bucket = "files";
|
||||
|
||||
let files = []
|
||||
documents.value.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 there are no files in the folder, throw an error
|
||||
if (!files || !files.length) {
|
||||
throw new Error("No files to download");
|
||||
}
|
||||
@@ -373,44 +148,91 @@ const downloadSelected = async () => {
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<UButton @click="uploadModalOpen = true">Hochladen</UButton>
|
||||
<UButton
|
||||
@click="downloadSelected"
|
||||
:disabled="documents.filter(doc => doc.selected).length === 0"
|
||||
>Herunterladen</UButton>
|
||||
|
||||
<USelectMenu
|
||||
:options="tags"
|
||||
v-model="selectedTags"
|
||||
multiple
|
||||
>
|
||||
<template #label>
|
||||
<span v-if="selectedTags.length" class="truncate">{{ selectedTags.length }} ausgewählt</span>
|
||||
<span v-else>Tags auswählen</span>
|
||||
</template>
|
||||
</USelectMenu>
|
||||
|
||||
|
||||
</div>
|
||||
<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>
|
||||
|
||||
<div class="documentList">
|
||||
<DocumentDisplay
|
||||
v-for="document in filteredDocuments"
|
||||
:document="document"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
<style scoped>
|
||||
.documentList {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
height: 85vh;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.documentListItem {
|
||||
display:block;
|
||||
width: 15vw;
|
||||
height: 30vh;
|
||||
padding:1em;
|
||||
margin: 0.7em;
|
||||
border: 1px solid lightgrey;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.documentListItem:hover {
|
||||
border: 1px solid #69c350;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.previewEmbed {
|
||||
width: 100%;
|
||||
height: 22vh;
|
||||
overflow: hidden;
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
|
||||
.previewEmbed::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bigPreview {
|
||||
height: 70vh;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user