diff --git a/composables/useFiles.js b/composables/useFiles.js
new file mode 100644
index 0000000..b79346a
--- /dev/null
+++ b/composables/useFiles.js
@@ -0,0 +1,210 @@
+import index from "v-calendar";
+
+export const useFiles = () => {
+ const supabase = useSupabaseClient()
+ const toast = useToast()
+
+ let bucket = "filesdev"
+
+ const profileStore = useProfileStore()
+
+ const uploadFiles = async (formData, files,tags, upsert) => {
+ const uploadSingleFile = async (file) => {
+ //Create File Entry to Get ID for Folder
+ const {data:createdFileData,error:createdFileError} = await supabase
+ .from("files")
+ .insert({
+ tenant: profileStore.currentTenant,
+ })
+ .select()
+ .single()
+
+ if(createdFileError){
+ console.log(createdFileError)
+ toast.add({title: "Hochladen fehlgeschlagen", icon: "i-heroicons-x-circle", color: "rose", timeout: 10000})
+ } else if(createdFileData) {
+ //Upload File to ID Folder
+ const {data:uploadData, error: uploadError} = await supabase
+ .storage
+ .from(bucket)
+ .upload(`${profileStore.currentTenant}/filesbyid/${createdFileData.id}/${file.name}`, file, {upsert: upsert})
+
+ if(uploadError) {
+ console.log(uploadError)
+ console.log(uploadError.statusCode)
+
+ if(uploadError.statusCode === '400') {
+ console.log("is 400")
+ toast.add({title: "Hochladen fehlgeschlagen", description: "Die Datei enthält ungültige Zeichen", icon: "i-heroicons-x-circle", color: "rose", timeout: 10000})
+ } else if(uploadError.statusCode === '409') {
+ console.log("is 409")
+ toast.add({title: "Hochladen fehlgeschlagen", description: "Es existiert bereits eine Datei mit diesem Namen", icon: "i-heroicons-x-circle", color: "rose", timeout: 10000})
+ } else {
+ toast.add({title: "Hochladen fehlgeschlagen", icon: "i-heroicons-x-circle", color: "rose", timeout: 10000})
+
+ }
+ } else if(uploadData) {
+ //Update File with Corresponding Path
+ const {data:updateFileData, error:updateFileError} = await supabase
+ .from("files")
+ .update({
+ ...formData,
+ path: uploadData.path,
+ })
+ .eq("id", createdFileData.id)
+
+ if(updateFileError) {
+ console.log(updateFileError)
+ toast.add({title: "Hochladen fehlgeschlagen", icon: "i-heroicons-x-circle", color: "rose", timeout: 10000})
+ } else {
+ const {data:tagData, error:tagError} = await supabase
+ .from("filetagmembers")
+ .insert(tags.map(tag => {
+ return {
+ file_id: createdFileData.id,
+ tag_id: tag
+ }
+ }))
+
+
+
+ toast.add({title: "Hochladen erfolgreich"})
+
+ }
+ }
+ }
+ }
+
+ if(files.length === 1) {
+ await uploadSingleFile(files[0])
+ } else if( files.length > 1) {
+
+ for(let i = 0; i < files.length; i++){
+ await uploadSingleFile(files[i])
+ }
+
+ }
+ }
+
+ const selectDocuments = async (sortColumn = null, folder = null) => {
+ let data = null
+
+ if(sortColumn !== null ) {
+ data = (await supabase
+ .from("files")
+ .select('*, filetags(*)')
+ .eq("tenant", profileStore.currentTenant)
+ .not("path","is",null)
+ .order(sortColumn, {ascending: true})).data
+ } else {
+ data = (await supabase
+ .from("files")
+ .select('*, filetags(*)')
+ .eq("tenant", profileStore.currentTenant)
+ .not("path","is",null)).data
+
+ }
+
+ if(data.length > 0){
+ let paths = []
+ data.forEach(doc => {
+ paths.push(doc.path)
+ })
+
+ const {data: supabaseData,error} = await supabase.storage.from(bucket).createSignedUrls(paths,3600)
+
+ data = data.map((doc,index) => {
+
+ return {
+ ...doc,
+ url: supabaseData[index].signedUrl
+ }
+ })
+ }
+
+ //console.log(data)
+
+ return data
+ }
+
+ const selectSomeDocuments = async (documentIds, sortColumn = null, folder = null) => {
+ let data = null
+
+ if(sortColumn !== null ) {
+ data = (await supabase
+ .from("files")
+ .select('*, filetags(*)')
+ .in("id",documentIds)
+ .eq("tenant", profileStore.currentTenant)
+ .not("path","is",null)
+ .order(sortColumn, {ascending: true})).data
+ } else {
+ data = (await supabase
+ .from("files")
+ .select('*, filetags(*)')
+ .in("id",documentIds)
+ .not("path","is",null)
+ .eq("tenant", profileStore.currentTenant)).data
+
+ }
+
+ if(data.length > 0){
+ let paths = []
+ data.forEach(doc => {
+ paths.push(doc.path)
+ })
+
+ const {data: supabaseData,error} = await supabase.storage.from(bucket).createSignedUrls(paths,3600)
+
+ data = data.map((doc,index) => {
+
+ return {
+ ...doc,
+ url: supabaseData[index].signedUrl
+ }
+ })
+ }
+
+ //console.log(data)
+
+ return data
+ }
+
+ const selectDocument = async (id) => {
+ const {data,error} = await supabase
+ .from("files")
+ .select('*, filetags(*)')
+ .eq("id",id)
+ .single()
+
+ const {data: supabaseData,error:supabaseError} = await supabase.storage.from(bucket).createSignedUrl(data.path,3600)
+
+ return {
+ ...data,
+ url: supabaseData.signedUrl
+ }
+/*
+ if(data.length > 0){
+ let paths = []
+ data.forEach(doc => {
+ paths.push(doc.path)
+ })
+
+ const {data: supabaseData,error} = await supabase.storage.from(bucket).createSignedUrls(paths,3600)
+
+ data = data.map((doc,index) => {
+
+ return {
+ ...doc,
+ url: supabaseData[index].signedUrl
+ }
+ })
+ }
+
+ //console.log(data)
+
+ return data[0]*/
+ }
+
+ return {uploadFiles, selectDocuments, selectSomeDocuments, selectDocument}
+}
\ No newline at end of file
diff --git a/composables/useSupabase.js b/composables/useSupabase.js
index 350d46f..b45e94e 100644
--- a/composables/useSupabase.js
+++ b/composables/useSupabase.js
@@ -22,97 +22,6 @@ export const useSupabaseSelect = async (relation,select = '*', sortColumn = null
return data
}
-export const useSupabaseSelectDocuments = async (select = '*', sortColumn = null, folderPath = "_") => {
- const supabase = useSupabaseClient()
- const profileStore = useProfileStore()
-
- let data = null
-
-
- if(sortColumn !== null ) {
- data = (await supabase
- .from("documents")
- .select(select)
- .eq("tenant", profileStore.currentTenant)
- .order(sortColumn, {ascending: true})).data
- } else {
- data = (await supabase
- .from("documents")
- .select(select)
- .eq("tenant", profileStore.currentTenant)).data
-
- }
-
- if(data.length > 0){
- let paths = []
- data.forEach(doc => {
- paths.push(doc.path)
- })
-
- const {data: supabaseData,error} = await supabase.storage.from('files').createSignedUrls(paths,3600)
-
- data = data.map((doc,index) => {
-
- return {
- ...doc,
- url: supabaseData[index].signedUrl
- }
- })
-
-
- }
-
- //console.log(data)
-
- return data
-}
-
-export const useSupabaseSelectSomeDocuments = async (documentIds, select = '*', sortColumn = null, folderPath = "_") => {
- const supabase = useSupabaseClient()
- const profileStore = useProfileStore()
-
- let data = null
-
- if(sortColumn !== null ) {
- data = (await supabase
- .from("documents")
- .select(select)
- .in("id",documentIds)
- .eq("tenant", profileStore.currentTenant)
- .order(sortColumn, {ascending: true})).data
- } else {
- data = (await supabase
- .from("documents")
- .select(select)
- .in("id",documentIds)
- .eq("tenant", profileStore.currentTenant)).data
-
- }
-
- if(data.length > 0){
- let paths = []
- data.forEach(doc => {
- paths.push(doc.path)
- })
-
- const {data: supabaseData,error} = await supabase.storage.from('files').createSignedUrls(paths,3600)
-
- data = data.map((doc,index) => {
-
- return {
- ...doc,
- url: supabaseData[index].signedUrl
- }
- })
-
-
- }
-
- //console.log(data)
-
- return data
-}
-
export const useSupabaseSelectSingle = async (relation,idToEq,select = '*' ) => {
const supabase = useSupabaseClient()
const profileStore = useProfileStore()
diff --git a/layouts/default.vue b/layouts/default.vue
index 68f5edb..9448b76 100644
--- a/layouts/default.vue
+++ b/layouts/default.vue
@@ -125,18 +125,8 @@ const footerLinks = [/*{
-
-
-
-
diff --git a/pages/createDocument/edit/[[id]].vue b/pages/createDocument/edit/[[id]].vue
index af85e66..73ad84e 100644
--- a/pages/createDocument/edit/[[id]].vue
+++ b/pages/createDocument/edit/[[id]].vue
@@ -457,7 +457,7 @@ const renderCurrency = (value, currency = "€") => {
const documentTotal = computed(() => {
let totalNet = 0
let total19 = 0
- let totalGross = 0
+ let total7 = 0
itemInfo.value.rows.forEach(row => {
if(!['pagebreak','title','text'].includes(row.mode)){
@@ -466,11 +466,13 @@ const documentTotal = computed(() => {
if(row.taxPercent === 19) {
total19 = total19 + Number(rowPrice * 0.19)
+ } else if(row.taxPercent === 7) {
+ total7 = total7 + Number(rowPrice * 0.07)
}
}
})
- totalGross = totalNet + total19
+ let totalGross = Number(totalNet.toFixed(2)) + Number(total19.toFixed(2)) + Number(total7.toFixed(2))
let totalGrossAlreadyPaid = 0
@@ -488,19 +490,14 @@ const documentTotal = computed(() => {
let sumToPay = totalGross - totalGrossAlreadyPaid
-
-
return {
totalNet: totalNet,
total19: total19,
+ total7: total7,
totalGross: totalGross,
totalGrossAlreadyPaid: totalGrossAlreadyPaid,
totalSumToPay: sumToPay
-
}
-
-
-
})
const processDieselPosition = () => {
@@ -831,14 +828,13 @@ const closeDocument = async () => {
await generateDocument()
- let fileData = {
- tags: [],
- project: null
- }
+ let fileData = {}
fileData.project = itemInfo.value.project
- fileData.createdDocument = itemInfo.value.id
- fileData.tags.push(dataStore.documentTypesForCreation[itemInfo.value.type].labelSingle)
+ fileData.createddocument = itemInfo.value.id
+ fileData.folder = (await supabase.from("folders").select("id").eq("tenant", profileStore.currentTenant).eq("function", itemInfo.value.type).eq("year",dayjs().format("YYYY")).single()).data.id
+
+ let tag = (await supabase.from("filetags").select("id").eq("tenant", profileStore.currentTenant).eq("createddocumenttype", itemInfo.value.type).single()).data
function dataURLtoFile(dataurl, filename) {
var arr = dataurl.split(","),
@@ -854,7 +850,7 @@ const closeDocument = async () => {
let file = dataURLtoFile(uri.value, `${itemInfo.value.documentNumber}.pdf`)
- await dataStore.uploadFiles(fileData, [file], true)
+ await dataStore.uploadFiles(fileData, [file],[tag.id], true)
await router.push(`/createDocument/show/${itemInfo.value.id}`)
@@ -894,13 +890,28 @@ const setRowData = (row) => {
+
- Entwurf
+ Entwurf speichern
{
v-model="itemInfo.type"
value-attribute="type"
option-attribute="label"
- @input="setDocumentTypeConfig"
+ @change="setDocumentTypeConfig"
class="flex-auto"
>
diff --git a/pages/createDocument/show/[id].vue b/pages/createDocument/show/[id].vue
index 2b52db2..9e058c0 100644
--- a/pages/createDocument/show/[id].vue
+++ b/pages/createDocument/show/[id].vue
@@ -21,9 +21,16 @@ const linkedDocument =ref({})
const currentTenant = ref({})
const setupPage = async () => {
if(route.params) {
- if(route.params.id) itemInfo.value = await useSupabaseSelectSingle("createddocuments",route.params.id,"*")
- const {data,error} = await supabase.from("documents").select("id").eq("createdDocument", route.params.id).order("id",{ascending:true})
- linkedDocument.value = data[data.length -1]
+ if(route.params.id) itemInfo.value = await useSupabaseSelectSingle("createddocuments",route.params.id,"*, files(*)")
+
+ console.log(itemInfo.value)
+
+ linkedDocument.value = await useFiles().selectDocument(itemInfo.value.files[0].id)
+
+
+
+ //const {data,error} = await supabase.from("files").select("id").eq("createddocument", route.params.id).order("id",{ascending:true})
+ //linkedDocument.value = data[data.length -1]
}
@@ -72,11 +79,19 @@ const openEmail = () => {
>
E-Mail
+
+ Projekt
+
diff --git a/pages/documents.vue b/pages/files/index.vue
similarity index 53%
rename from pages/documents.vue
rename to pages/files/index.vue
index 9753c16..a461500 100644
--- a/pages/documents.vue
+++ b/pages/files/index.vue
@@ -2,22 +2,66 @@
import {BlobReader, BlobWriter, ZipWriter} from "@zip.js/zip.js";
-import {useSupabaseSelectDocuments, useSupabaseSelectSingle} from "~/composables/useSupabase.js";
+import {useSupabaseSelectSingle} from "~/composables/useSupabase.js";
+import DocumentDisplayModal from "~/components/DocumentDisplayModal.vue";
+import dayjs from "dayjs";
definePageMeta({
middleware: "auth"
})
+
+defineShortcuts({
+ /*'/': () => {
+ //console.log(searchinput)
+ //searchinput.value.focus()
+ document.getElementById("searchinput").focus()
+ },*/
+ '+': () => {
+ //Hochladen
+ uploadModalOpen.value = true
+ },
+ 'Enter': {
+ usingInput: true,
+ handler: () => {
+ let entry = renderedFileList.value[selectedFileIndex.value]
+
+ if(entry.type === "file") {
+ showFile(entry.id)
+ console.log(entry)
+ } else {
+ changeFolder(currentFolders.value.find(i => i.id === entry.id))
+ }
+
+ }
+ },
+ 'arrowdown': () => {
+ if(selectedFileIndex.value < renderedFileList.value.length - 1) {
+ selectedFileIndex.value += 1
+ } else {
+ selectedFileIndex.value = 0
+ }
+ },
+ 'arrowup': () => {
+ if(selectedFileIndex.value === 0) {
+ selectedFileIndex.value = renderedFileList.value.length - 1
+ } else {
+ selectedFileIndex.value -= 1
+ }
+ }
+})
+
const dataStore = useDataStore()
const profileStore = useProfileStore()
const supabase = useSupabaseClient()
-const user = useSupabaseUser()
-const toast = useToast()
const router = useRouter()
const route = useRoute()
+const slideover = useSlideover()
+const modal = useModal()
dataStore.fetchDocuments()
const uploadModalOpen = ref(false)
+const createFolderModalOpen = ref(false)
const uploadInProgress = ref(false)
const fileUploadFormData = ref({
tags: ["Eingang"],
@@ -26,11 +70,18 @@ const fileUploadFormData = ref({
folder: null
})
+const files = useFiles()
let tags = dataStore.getDocumentTags
+const displayMode = ref("list")
+const displayModes = ref([{label: 'Liste',key:'list', icon: 'i-heroicons-list-bullet'},{label: 'Kacheln',key:'rectangles', icon: 'i-heroicons-squares-2x2'}])
+
+
+
const documents = ref([])
const folders = ref([])
+const filetags = ref([])
const currentFolder = ref(null)
@@ -39,11 +90,12 @@ const isDragTarget = ref(false)
const setupPage = async () => {
folders.value = await useSupabaseSelect("folders")
- documents.value = await useSupabaseSelectDocuments("*",null)
+ documents.value = await files.selectDocuments()
+
+ filetags.value = await useSupabaseSelect("filetags")
if(route.query) {
if(route.query.folder) {
- console.log(route.query.folder)
currentFolder.value = await useSupabaseSelectSingle("folders", route.query.folder)
}
}
@@ -135,10 +187,6 @@ const breadcrumbLinks = computed(() => {
}
})
-
-
-
-
const filteredDocuments = computed(() => {
return documents.value.filter(i => currentFolder.value ? i.folder === currentFolder.value.id : !i.folder)
@@ -151,20 +199,38 @@ const changeFolder = async (newFolder) => {
if(newFolder) {
fileUploadFormData.value.folder = newFolder.id
- await router.push(`/documents?folder=${newFolder.id}`)
+ await router.push(`/files?folder=${newFolder.id}`)
} else {
fileUploadFormData.value.folder = null
- await router.push(`/documents`)
+ await router.push(`/files`)
}
setupPage()
}
+const createFolderData = ref({})
+const createFolder = async () => {
+ const {data,error} = await supabase
+ .from("folders")
+ .insert({
+ tenant: profileStore.currentTenant,
+ parent: currentFolder.value ? currentFolder.value.id : undefined,
+ name: createFolderData.value.name,
+
+ })
+
+ createFolderModalOpen.value = false
+
+ setupPage()
+
+}
+
const uploadFiles = async (files) => {
uploadInProgress.value = true;
if(files) {
- await dataStore.uploadFiles({tags: ["Ablage"],tenant: profileStore.currentTenant,folder: currentFolder.value.id}, files, true)
+ //await dataStore.uploadFiles({tags: ["Ablage"],tenant: profileStore.currentTenant,folder: currentFolder.value.id}, files, true)
+ await dataStore.uploadFiles({tags: ["Ablage"],tenant: profileStore.currentTenant}, files, true)
} else {
await dataStore.uploadFiles(fileUploadFormData.value, document.getElementById("fileUploadInput").files, true)
@@ -237,37 +303,46 @@ const downloadSelected = async () => {
link.click();
}
+const renderedFileList = computed(() => {
+ let files = filteredDocuments.value.map(i => {
+ return {
+ label: i.path.split("/")[i.path.split("/").length -1],
+ id: i.id,
+ type: "file"
+ }
+ })
+
+ let folders = currentFolders.value.map(i => {
+ return {
+ label: i.name,
+ id: i.id,
+ type: "folder"
+ }
+ })
+
+ return [...folders,...files]
+
+})
+const selectedFileIndex = ref(0)
+
+const showFile = (fileId) => {
+ console.log(fileId)
+ modal.open(DocumentDisplayModal,{
+ documentData: documents.value.find(i => i.id === fileId),
+ })
+}
+
+
-
{
/>
- Hochladen
+
+
+
+
+
+
+ + Hochladen
+ + Ordner
+
+
+
+ Ordner Erstellen
+
+
+
+
+
+
+
+
+
+
+ Erstellen
+
+
+
+
+
+