Many Changes
This commit is contained in:
2
app.vue
2
app.vue
@@ -50,6 +50,8 @@ useSeoMeta({
|
|||||||
</NuxtLayout>
|
</NuxtLayout>
|
||||||
|
|
||||||
<UNotifications/>
|
<UNotifications/>
|
||||||
|
<USlideovers />
|
||||||
|
<UModals />
|
||||||
<VitePwaManifest/>
|
<VitePwaManifest/>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ const updateDocument = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const archiveDocument = () => {
|
const archiveDocument = () => {
|
||||||
documentData.tags.push("Archiviert")
|
//documentData.tags.push("Archiviert")
|
||||||
updateDocument()
|
//updateDocument()
|
||||||
}
|
}
|
||||||
|
|
||||||
const resourceOptions = ref([
|
const resourceOptions = ref([
|
||||||
@@ -106,7 +106,7 @@ const updateDocumentAssignment = async () => {
|
|||||||
<iframe
|
<iframe
|
||||||
:src="`${documentData.url}#toolbar=0&navpanes=0&scrollbar=0`"
|
:src="`${documentData.url}#toolbar=0&navpanes=0&scrollbar=0`"
|
||||||
class="previewEmbed"
|
class="previewEmbed"
|
||||||
v-if="!documentData.tags.includes('Bild')"
|
v-if="!documentData.filetags.includes('Bild')"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
@@ -121,9 +121,9 @@ const updateDocumentAssignment = async () => {
|
|||||||
|
|
||||||
<InputGroup class="mt-3 flex-wrap">
|
<InputGroup class="mt-3 flex-wrap">
|
||||||
<UBadge
|
<UBadge
|
||||||
v-for="tag in documentData.tags"
|
v-for="tag in documentData.filetags"
|
||||||
|
|
||||||
><span class="text-nowrap">{{ tag }}</span></UBadge>
|
><span class="text-nowrap">{{ tag.name }}</span></UBadge>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
|
|
||||||
|
|
||||||
@@ -157,9 +157,9 @@ const updateDocumentAssignment = async () => {
|
|||||||
<div class="flex flex-row justify-between">
|
<div class="flex flex-row justify-between">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<UBadge
|
<UBadge
|
||||||
v-for="tag in documentData.tags"
|
v-for="tag in documentData.filetags"
|
||||||
>
|
>
|
||||||
{{tag}}
|
{{tag.name}}
|
||||||
</UBadge>
|
</UBadge>
|
||||||
</div>
|
</div>
|
||||||
<UButton color="gray" variant="ghost" icon="i-heroicons-x-mark-20-solid" class="-my-1" @click="openShowModal = false" />
|
<UButton color="gray" variant="ghost" icon="i-heroicons-x-mark-20-solid" class="-my-1" @click="openShowModal = false" />
|
||||||
@@ -172,7 +172,7 @@ const updateDocumentAssignment = async () => {
|
|||||||
class="bigPreview"
|
class="bigPreview"
|
||||||
:data="`${documentData.url}#toolbar=0&navpanes=0&scrollbar=0`"
|
:data="`${documentData.url}#toolbar=0&navpanes=0&scrollbar=0`"
|
||||||
type="application/pdf"
|
type="application/pdf"
|
||||||
v-if="!documentData.tags.includes('Bild')"
|
v-if="!documentData.filetags.includes('Bild')"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
@@ -186,11 +186,11 @@ const updateDocumentAssignment = async () => {
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
|
|
||||||
<UButtonGroup>
|
<UButtonGroup>
|
||||||
<UButton
|
<!-- <UButton
|
||||||
@click="archiveDocument"
|
@click="archiveDocument"
|
||||||
>
|
>
|
||||||
Archivieren
|
Archivieren
|
||||||
</UButton>
|
</UButton>-->
|
||||||
<UButton
|
<UButton
|
||||||
:to="documentData.url"
|
:to="documentData.url"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
@@ -206,12 +206,12 @@ const updateDocumentAssignment = async () => {
|
|||||||
>
|
>
|
||||||
<USelectMenu
|
<USelectMenu
|
||||||
:options="tags"
|
:options="tags"
|
||||||
v-model="documentData.tags"
|
v-model="documentData.filetags"
|
||||||
@change="updateDocument"
|
@change="updateDocument"
|
||||||
multiple
|
multiple
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
{{documentData.tags.length}} ausgewählt
|
{{documentData.filetags.length}} ausgewählt
|
||||||
</template>
|
</template>
|
||||||
</USelectMenu>
|
</USelectMenu>
|
||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
|
|||||||
196
components/DocumentDisplayModal.vue
Normal file
196
components/DocumentDisplayModal.vue
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
<script setup>
|
||||||
|
|
||||||
|
const toast = useToast()
|
||||||
|
const supabase = useSupabaseClient()
|
||||||
|
const dataStore = useDataStore()
|
||||||
|
const profileStore = useProfileStore()
|
||||||
|
const router = useRouter()
|
||||||
|
const modal = useModal()
|
||||||
|
const props = defineProps({
|
||||||
|
documentData: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
openShowModal: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
returnEmit: {
|
||||||
|
type: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits("close")
|
||||||
|
|
||||||
|
const showSlideover = ref(props.openShowModal)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Functions
|
||||||
|
const openDocument = async () => {
|
||||||
|
//selectedDocument.value = doc
|
||||||
|
openShowModal.value = true
|
||||||
|
console.log("open")
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateDocument = async () => {
|
||||||
|
console.log("Update")
|
||||||
|
|
||||||
|
const {url, ...objData} = props.documentData
|
||||||
|
delete objData.url
|
||||||
|
delete objData.filetags
|
||||||
|
|
||||||
|
|
||||||
|
const {data,error} = await supabase
|
||||||
|
.from("files")
|
||||||
|
.update(objData)
|
||||||
|
.eq('id',objData.id)
|
||||||
|
.select()
|
||||||
|
|
||||||
|
if(error) {
|
||||||
|
console.log(error)
|
||||||
|
} else {
|
||||||
|
toast.add({title: "Datei aktualisiert"})
|
||||||
|
//openShowModal.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const archiveDocument = () => {
|
||||||
|
//documentData.tags.push("Archiviert")
|
||||||
|
//updateDocument()
|
||||||
|
}
|
||||||
|
|
||||||
|
const resourceOptions = ref([
|
||||||
|
{label: 'Projekt', value: 'project', optionAttr: "name"},
|
||||||
|
{label: 'Kunde', value: 'customer', optionAttr: "name"},
|
||||||
|
{label: 'Lieferant', value: 'vendor', optionAttr: "name"},
|
||||||
|
{label: 'Fahrzeug', value: 'vehicle', optionAttr: "licensePlate"},
|
||||||
|
{label: 'Objekt', value: 'plant', optionAttr: "name"},
|
||||||
|
{label: 'Vertrag', value: 'contract', optionAttr: "name"},
|
||||||
|
{label: 'Produkt', value: 'product', optionAttr: "name"}
|
||||||
|
])
|
||||||
|
const resourceToAssign = ref("project")
|
||||||
|
const itemOptions = ref([])
|
||||||
|
const idToAssign = ref(null)
|
||||||
|
const getItemsBySelectedResource = () => {
|
||||||
|
if(resourceToAssign.value === "project") {
|
||||||
|
itemOptions.value = dataStore.projects
|
||||||
|
} else if(resourceToAssign.value === "customer") {
|
||||||
|
itemOptions.value = dataStore.customers
|
||||||
|
} else if(resourceToAssign.value === "vendor") {
|
||||||
|
itemOptions.value = dataStore.vendors
|
||||||
|
} else if(resourceToAssign.value === "vehicle") {
|
||||||
|
itemOptions.value = dataStore.vehicles
|
||||||
|
} else if(resourceToAssign.value === "product") {
|
||||||
|
itemOptions.value = dataStore.products
|
||||||
|
} else if(resourceToAssign.value === "plant") {
|
||||||
|
itemOptions.value = dataStore.plants
|
||||||
|
} else if(resourceToAssign.value === "contract") {
|
||||||
|
itemOptions.value = dataStore.contracts
|
||||||
|
} else {
|
||||||
|
itemOptions.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getItemsBySelectedResource()
|
||||||
|
|
||||||
|
const updateDocumentAssignment = async () => {
|
||||||
|
props.documentData[resourceToAssign.value] = idToAssign.value
|
||||||
|
await updateDocument()
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UModal >
|
||||||
|
<UCard :ui="{ body: { base: 'flex-1' }, ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
|
||||||
|
<template #header>
|
||||||
|
<div class="flex flex-row justify-between">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<UBadge
|
||||||
|
v-for="tag in props.documentData.filetags"
|
||||||
|
>
|
||||||
|
{{tag.name}}
|
||||||
|
</UBadge>
|
||||||
|
</div>
|
||||||
|
<UButton color="gray" variant="ghost" icon="i-heroicons-x-mark-20-solid" class="-my-1" @click="modal.close()" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<div class="w-1/2">
|
||||||
|
<object
|
||||||
|
class="bigPreview"
|
||||||
|
:data="`${props.documentData.url}#toolbar=0&navpanes=0&scrollbar=0`"
|
||||||
|
type="application/pdf"
|
||||||
|
v-if="!props.documentData.filetags.includes('Bild')"
|
||||||
|
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
class=" w-full"
|
||||||
|
:src="props.documentData.url"
|
||||||
|
alt=""
|
||||||
|
v-else
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="w-1/2 p-5">
|
||||||
|
<UButtonGroup>
|
||||||
|
<!-- <UButton
|
||||||
|
@click="archiveDocument"
|
||||||
|
>
|
||||||
|
Archivieren
|
||||||
|
</UButton>-->
|
||||||
|
<UButton
|
||||||
|
:to="props.documentData.url"
|
||||||
|
variant="outline"
|
||||||
|
icon="i-heroicons-arrow-top-right-on-square"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
Öffnen
|
||||||
|
</UButton>
|
||||||
|
</UButtonGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<p>Dokument zuweisen:</p>
|
||||||
|
<UFormGroup
|
||||||
|
label="Resource auswählen"
|
||||||
|
>
|
||||||
|
<USelectMenu
|
||||||
|
:options="resourceOptions"
|
||||||
|
v-model="resourceToAssign"
|
||||||
|
value-attribute="value"
|
||||||
|
option-attribute="label"
|
||||||
|
@change="getItemsBySelectedResource"
|
||||||
|
>
|
||||||
|
|
||||||
|
</USelectMenu>
|
||||||
|
</UFormGroup>
|
||||||
|
<UFormGroup
|
||||||
|
label="Eintrag auswählen:"
|
||||||
|
>
|
||||||
|
|
||||||
|
</UFormGroup>
|
||||||
|
|
||||||
|
<USelectMenu
|
||||||
|
:options="itemOptions"
|
||||||
|
v-model="idToAssign"
|
||||||
|
:option-attribute="resourceOptions.find(i => i.value === resourceToAssign)? resourceOptions.find(i => i.value === resourceToAssign).optionAttr : 'name'"
|
||||||
|
value-attribute="id"
|
||||||
|
@change="updateDocumentAssignment"
|
||||||
|
></USelectMenu>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</UCard>
|
||||||
|
</UModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.bigPreview {
|
||||||
|
width: 100%;
|
||||||
|
aspect-ratio: 1/ 1.414;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -145,6 +145,19 @@ const contentChanged = (content, datapoint) => {
|
|||||||
>{{item.id ? `${dataType.labelSingle} bearbeiten` : `${dataType.labelSingle} erstellen` }}</h1>
|
>{{item.id ? `${dataType.labelSingle} bearbeiten` : `${dataType.labelSingle} erstellen` }}</h1>
|
||||||
</template>
|
</template>
|
||||||
<template #right>
|
<template #right>
|
||||||
|
<ButtonWithConfirm
|
||||||
|
color="rose"
|
||||||
|
variant="outline"
|
||||||
|
@confirmed="dataStore.updateItem(type,{...item,archived: true}, oldItem)"
|
||||||
|
>
|
||||||
|
<template #button>
|
||||||
|
Archivieren
|
||||||
|
</template>
|
||||||
|
<template #header>
|
||||||
|
<span class="text-md text-black font-bold">Archivieren bestätigen</span>
|
||||||
|
</template>
|
||||||
|
Möchten Sie das {{dataType.labelSingle}} {{item[dataType.templateColumns.find(i => i.title).key]}} wirklich archivieren?
|
||||||
|
</ButtonWithConfirm>
|
||||||
<UButton
|
<UButton
|
||||||
v-if="item.id"
|
v-if="item.id"
|
||||||
@click="dataStore.updateItem(type,item, oldItem)"
|
@click="dataStore.updateItem(type,item, oldItem)"
|
||||||
@@ -172,8 +185,8 @@ const contentChanged = (content, datapoint) => {
|
|||||||
>
|
>
|
||||||
<div class="flex flex-row">
|
<div class="flex flex-row">
|
||||||
<div
|
<div
|
||||||
v-for="columnName in dataType.inputColumns"
|
v-for="(columnName,index) in dataType.inputColumns"
|
||||||
class="w-1/2 mr-5"
|
:class="['w-1/2', ... index < dataType.inputColumns.length -1 ? ['mr-5'] : []]"
|
||||||
>
|
>
|
||||||
<UDivider>{{columnName}}</UDivider>
|
<UDivider>{{columnName}}</UDivider>
|
||||||
|
|
||||||
@@ -192,8 +205,9 @@ const contentChanged = (content, datapoint) => {
|
|||||||
:item="item"
|
:item="item"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="datapoint.key.includes('.')">
|
<InputGroup class="w-full" v-if="datapoint.key.includes('.')">
|
||||||
<UInput
|
<UInput
|
||||||
|
class="flex-auto"
|
||||||
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
||||||
v-if="['text','number'].includes(datapoint.inputType)"
|
v-if="['text','number'].includes(datapoint.inputType)"
|
||||||
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
|
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
|
||||||
@@ -212,6 +226,7 @@ const contentChanged = (content, datapoint) => {
|
|||||||
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
|
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
|
||||||
/>
|
/>
|
||||||
<USelectMenu
|
<USelectMenu
|
||||||
|
class="flex-auto"
|
||||||
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
||||||
v-else-if="datapoint.inputType === 'select'"
|
v-else-if="datapoint.inputType === 'select'"
|
||||||
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
|
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
|
||||||
@@ -228,6 +243,7 @@ const contentChanged = (content, datapoint) => {
|
|||||||
</template>
|
</template>
|
||||||
</USelectMenu>
|
</USelectMenu>
|
||||||
<UTextarea
|
<UTextarea
|
||||||
|
class="flex-auto"
|
||||||
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
||||||
v-else-if="datapoint.inputType === 'textarea'"
|
v-else-if="datapoint.inputType === 'textarea'"
|
||||||
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
|
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
|
||||||
@@ -275,9 +291,18 @@ const contentChanged = (content, datapoint) => {
|
|||||||
@updateContent="(i) => contentChanged(i,datapoint)"
|
@updateContent="(i) => contentChanged(i,datapoint)"
|
||||||
:preloadedContent="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]].html"
|
:preloadedContent="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]].html"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div v-else>
|
<UButton
|
||||||
|
v-if="['text','number','select','date','datetime','textarea'].includes(datapoint.inputType)"
|
||||||
|
@click="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]] = null"
|
||||||
|
variant="outline"
|
||||||
|
color="white"
|
||||||
|
icon="i-heroicons-x-mark"
|
||||||
|
/>
|
||||||
|
</InputGroup>
|
||||||
|
<InputGroup class="w-full" v-else>
|
||||||
<UInput
|
<UInput
|
||||||
|
class="flex-auto"
|
||||||
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
||||||
v-if="['text','number'].includes(datapoint.inputType)"
|
v-if="['text','number'].includes(datapoint.inputType)"
|
||||||
v-model="item[datapoint.key]"
|
v-model="item[datapoint.key]"
|
||||||
@@ -296,6 +321,7 @@ const contentChanged = (content, datapoint) => {
|
|||||||
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
|
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
|
||||||
/>
|
/>
|
||||||
<USelectMenu
|
<USelectMenu
|
||||||
|
class="flex-auto"
|
||||||
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
||||||
v-else-if="datapoint.inputType === 'select'"
|
v-else-if="datapoint.inputType === 'select'"
|
||||||
v-model="item[datapoint.key]"
|
v-model="item[datapoint.key]"
|
||||||
@@ -313,6 +339,7 @@ const contentChanged = (content, datapoint) => {
|
|||||||
</template>
|
</template>
|
||||||
</USelectMenu>
|
</USelectMenu>
|
||||||
<UTextarea
|
<UTextarea
|
||||||
|
class="flex-auto"
|
||||||
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
||||||
v-else-if="datapoint.inputType === 'textarea'"
|
v-else-if="datapoint.inputType === 'textarea'"
|
||||||
v-model="item[datapoint.key]"
|
v-model="item[datapoint.key]"
|
||||||
@@ -358,7 +385,15 @@ const contentChanged = (content, datapoint) => {
|
|||||||
@updateContent="(i) => contentChanged(i,datapoint)"
|
@updateContent="(i) => contentChanged(i,datapoint)"
|
||||||
:preloadedContent="item[datapoint.key].html"
|
:preloadedContent="item[datapoint.key].html"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
<UButton
|
||||||
|
v-if="['text','number','select','date','datetime','textarea'].includes(datapoint.inputType)"
|
||||||
|
@click="item[datapoint.key] = null"
|
||||||
|
variant="outline"
|
||||||
|
color="white"
|
||||||
|
icon="i-heroicons-x-mark"
|
||||||
|
/>
|
||||||
|
</InputGroup>
|
||||||
<div
|
<div
|
||||||
v-if="profileStore.ownTenant.ownFields"
|
v-if="profileStore.ownTenant.ownFields"
|
||||||
>
|
>
|
||||||
@@ -387,7 +422,7 @@ const contentChanged = (content, datapoint) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<UFormGroup
|
<UFormGroup
|
||||||
v-for="datapoint in dataType.templateColumns.filter(i => i.inputType && i.inputColumn === columnName)"
|
v-for="datapoint in dataType.templateColumns.filter(i => i.inputType && !i.inputColumn)"
|
||||||
:label="datapoint.label"
|
:label="datapoint.label"
|
||||||
>
|
>
|
||||||
<template #help>
|
<template #help>
|
||||||
@@ -397,8 +432,9 @@ const contentChanged = (content, datapoint) => {
|
|||||||
:item="item"
|
:item="item"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="datapoint.key.includes('.')">
|
<InputGroup class="w-full" v-if="datapoint.key.includes('.')">
|
||||||
<UInput
|
<UInput
|
||||||
|
class="flex-auto"
|
||||||
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
||||||
v-if="['text','number'].includes(datapoint.inputType)"
|
v-if="['text','number'].includes(datapoint.inputType)"
|
||||||
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
|
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
|
||||||
@@ -417,6 +453,7 @@ const contentChanged = (content, datapoint) => {
|
|||||||
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
|
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
|
||||||
/>
|
/>
|
||||||
<USelectMenu
|
<USelectMenu
|
||||||
|
class="flex-auto"
|
||||||
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
||||||
v-else-if="datapoint.inputType === 'select'"
|
v-else-if="datapoint.inputType === 'select'"
|
||||||
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
|
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
|
||||||
@@ -433,6 +470,7 @@ const contentChanged = (content, datapoint) => {
|
|||||||
</template>
|
</template>
|
||||||
</USelectMenu>
|
</USelectMenu>
|
||||||
<UTextarea
|
<UTextarea
|
||||||
|
class="flex-auto"
|
||||||
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
||||||
v-else-if="datapoint.inputType === 'textarea'"
|
v-else-if="datapoint.inputType === 'textarea'"
|
||||||
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
|
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
|
||||||
@@ -480,9 +518,18 @@ const contentChanged = (content, datapoint) => {
|
|||||||
@updateContent="(i) => contentChanged(i,datapoint)"
|
@updateContent="(i) => contentChanged(i,datapoint)"
|
||||||
:preloadedContent="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]].html"
|
:preloadedContent="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]].html"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div v-else>
|
<UButton
|
||||||
|
v-if="['text','number','select','date','datetime','textarea'].includes(datapoint.inputType)"
|
||||||
|
@click="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]] = null"
|
||||||
|
variant="outline"
|
||||||
|
color="white"
|
||||||
|
icon="i-heroicons-x-mark"
|
||||||
|
/>
|
||||||
|
</InputGroup>
|
||||||
|
<InputGroup class="w-full" v-else>
|
||||||
<UInput
|
<UInput
|
||||||
|
class="flex-auto"
|
||||||
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
||||||
v-if="['text','number'].includes(datapoint.inputType)"
|
v-if="['text','number'].includes(datapoint.inputType)"
|
||||||
v-model="item[datapoint.key]"
|
v-model="item[datapoint.key]"
|
||||||
@@ -501,6 +548,7 @@ const contentChanged = (content, datapoint) => {
|
|||||||
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
|
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
|
||||||
/>
|
/>
|
||||||
<USelectMenu
|
<USelectMenu
|
||||||
|
class="flex-auto"
|
||||||
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
||||||
v-else-if="datapoint.inputType === 'select'"
|
v-else-if="datapoint.inputType === 'select'"
|
||||||
v-model="item[datapoint.key]"
|
v-model="item[datapoint.key]"
|
||||||
@@ -518,6 +566,7 @@ const contentChanged = (content, datapoint) => {
|
|||||||
</template>
|
</template>
|
||||||
</USelectMenu>
|
</USelectMenu>
|
||||||
<UTextarea
|
<UTextarea
|
||||||
|
class="flex-auto"
|
||||||
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
@change="datapoint.inputChangeFunction ? datapoint.inputChangeFunction(item,loadedOptions) : null"
|
||||||
v-else-if="datapoint.inputType === 'textarea'"
|
v-else-if="datapoint.inputType === 'textarea'"
|
||||||
v-model="item[datapoint.key]"
|
v-model="item[datapoint.key]"
|
||||||
@@ -563,7 +612,15 @@ const contentChanged = (content, datapoint) => {
|
|||||||
@updateContent="(i) => contentChanged(i,datapoint)"
|
@updateContent="(i) => contentChanged(i,datapoint)"
|
||||||
:preloadedContent="item[datapoint.key].html"
|
:preloadedContent="item[datapoint.key].html"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
<UButton
|
||||||
|
v-if="['text','number','select','date','datetime','textarea'].includes(datapoint.inputType)"
|
||||||
|
@click="item[datapoint.key] = null"
|
||||||
|
variant="outline"
|
||||||
|
color="white"
|
||||||
|
icon="i-heroicons-x-mark"
|
||||||
|
/>
|
||||||
|
</InputGroup>
|
||||||
<div
|
<div
|
||||||
v-if="profileStore.ownTenant.ownFields"
|
v-if="profileStore.ownTenant.ownFields"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import {useSupabaseSelectSomeDocuments} from "~/composables/useSupabase.js";
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
type: {
|
type: {
|
||||||
@@ -36,14 +35,15 @@ const router = useRouter()
|
|||||||
const dataStore = useDataStore()
|
const dataStore = useDataStore()
|
||||||
const profileStore = useProfileStore()
|
const profileStore = useProfileStore()
|
||||||
const supabase = useSupabaseClient()
|
const supabase = useSupabaseClient()
|
||||||
|
const files = useFiles()
|
||||||
|
|
||||||
const dataType = dataStore.dataTypes[type]
|
const dataType = dataStore.dataTypes[type]
|
||||||
|
|
||||||
const documents = ref([])
|
const availableFiles = ref([])
|
||||||
|
|
||||||
const setup = async () => {
|
const setup = async () => {
|
||||||
if(props.item.documents) {
|
if(props.item.files) {
|
||||||
documents.value = await useSupabaseSelectSomeDocuments(props.item.documents.map(i => i.id)) || []
|
availableFiles.value = await files.selectSomeDocuments(props.item.files.map(i => i.id)) || []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,19 +154,6 @@ const getAvailableQueryStringData = () => {
|
|||||||
>{{item ? `${dataType.labelSingle}${props.item[dataType.templateColumns.find(i => i.title).key] ? ': ' + props.item[dataType.templateColumns.find(i => i.title).key] : ''}`: '' }}</h1>
|
>{{item ? `${dataType.labelSingle}${props.item[dataType.templateColumns.find(i => i.title).key] ? ': ' + props.item[dataType.templateColumns.find(i => i.title).key] : ''}`: '' }}</h1>
|
||||||
</template>
|
</template>
|
||||||
<template #right>
|
<template #right>
|
||||||
<ButtonWithConfirm
|
|
||||||
color="rose"
|
|
||||||
variant="outline"
|
|
||||||
@confirmed="dataStore.updateItem(type,{...item, archived: true})"
|
|
||||||
>
|
|
||||||
<template #button>
|
|
||||||
Archivieren
|
|
||||||
</template>
|
|
||||||
<template #header>
|
|
||||||
<span class="text-md text-black font-bold">Archivieren bestätigen</span>
|
|
||||||
</template>
|
|
||||||
Möchten Sie das Fahrzeug {{item.name}} wirklich archivieren?
|
|
||||||
</ButtonWithConfirm>
|
|
||||||
<UButton
|
<UButton
|
||||||
@click="router.push(`/standardEntity/${type}/edit/${item.id}`)"
|
@click="router.push(`/standardEntity/${type}/edit/${item.id}`)"
|
||||||
>
|
>
|
||||||
@@ -174,25 +161,22 @@ const getAvailableQueryStringData = () => {
|
|||||||
</UButton>
|
</UButton>
|
||||||
</template>
|
</template>
|
||||||
</UDashboardNavbar>
|
</UDashboardNavbar>
|
||||||
<UDashboardPanelContent>
|
|
||||||
|
|
||||||
</UDashboardPanelContent>
|
|
||||||
<UTabs
|
<UTabs
|
||||||
:items="dataType.showTabs"
|
:items="dataType.showTabs"
|
||||||
v-if="props.item.id"
|
v-if="props.item.id"
|
||||||
class="p-5"
|
class="p-5"
|
||||||
v-model="openTab"
|
v-model="openTab"
|
||||||
>
|
>
|
||||||
<template #item="{item}">
|
<template #item="{item:tab}">
|
||||||
<div class="scroll">
|
<div class="scroll">
|
||||||
<div v-if="item.label === 'Informationen'" class="flex flex-row mt-5">
|
<div v-if="tab.label === 'Informationen'" class="flex flex-row mt-5">
|
||||||
<UCard class="w-1/2 mr-5">
|
<UCard class="w-1/2 mr-5">
|
||||||
<UAlert
|
<UAlert
|
||||||
v-if="item.archived"
|
v-if="item.archived"
|
||||||
color="rose"
|
color="rose"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
:title="`${dataType.labelSingle} archiviert`"
|
:title="`${dataType.labelSingle} archiviert`"
|
||||||
icon="i-heroicons-light-bulb"
|
icon="i-heroicons-archive-box"
|
||||||
class="mb-5"
|
class="mb-5"
|
||||||
/>
|
/>
|
||||||
<div class="text-wrap">
|
<div class="text-wrap">
|
||||||
@@ -225,7 +209,7 @@ const getAvailableQueryStringData = () => {
|
|||||||
/>
|
/>
|
||||||
</UCard>
|
</UCard>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="item.label === 'Dokumente'">
|
<div v-else-if="tab.label === 'Dateien'">
|
||||||
<UCard class="mt-5">
|
<UCard class="mt-5">
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<DocumentUpload
|
<DocumentUpload
|
||||||
@@ -235,11 +219,17 @@ const getAvailableQueryStringData = () => {
|
|||||||
</Toolbar>
|
</Toolbar>
|
||||||
|
|
||||||
<DocumentList
|
<DocumentList
|
||||||
:documents="documents"
|
:documents="availableFiles"
|
||||||
|
v-if="availableFiles.length > 0"
|
||||||
|
/>
|
||||||
|
<UAlert
|
||||||
|
v-else
|
||||||
|
icon="i-heroicons-x-mark"
|
||||||
|
title="Keine Dateien verfügbar"
|
||||||
/>
|
/>
|
||||||
</UCard>
|
</UCard>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="item.label === 'Projekte'">
|
<div v-else-if="tab.label === 'Projekte'">
|
||||||
<UCard class="mt-5">
|
<UCard class="mt-5">
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<UButton
|
<UButton
|
||||||
@@ -262,7 +252,7 @@ const getAvailableQueryStringData = () => {
|
|||||||
|
|
||||||
</UCard>
|
</UCard>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="item.label === 'Objekte'">
|
<div v-else-if="tab.label === 'Objekte'">
|
||||||
<UCard class="mt-5">
|
<UCard class="mt-5">
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<UButton
|
<UButton
|
||||||
@@ -288,7 +278,7 @@ const getAvailableQueryStringData = () => {
|
|||||||
</UTable>
|
</UTable>
|
||||||
</UCard>
|
</UCard>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="item.label === 'Aufgaben'">
|
<div v-else-if="tab.label === 'Aufgaben'">
|
||||||
<UCard class="mt-5">
|
<UCard class="mt-5">
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<UButton
|
<UButton
|
||||||
@@ -305,7 +295,7 @@ const getAvailableQueryStringData = () => {
|
|||||||
/>
|
/>
|
||||||
</UCard>
|
</UCard>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="item.label === 'Verträge'">
|
<div v-else-if="tab.label === 'Verträge'">
|
||||||
<UCard class="mt-5">
|
<UCard class="mt-5">
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<UButton
|
<UButton
|
||||||
@@ -323,7 +313,7 @@ const getAvailableQueryStringData = () => {
|
|||||||
></UTable>
|
></UTable>
|
||||||
</UCard>
|
</UCard>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="item.label === 'Überprüfungen'">
|
<div v-else-if="tab.label === 'Überprüfungen'">
|
||||||
<UCard class="mt-5">
|
<UCard class="mt-5">
|
||||||
<UTable
|
<UTable
|
||||||
:rows="props.item.checks"
|
:rows="props.item.checks"
|
||||||
@@ -341,7 +331,7 @@ const getAvailableQueryStringData = () => {
|
|||||||
</UTable>
|
</UTable>
|
||||||
</UCard>
|
</UCard>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="item.label === 'Phasen'">
|
<div v-else-if="tab.label === 'Phasen'">
|
||||||
<UCard class="mt-5">
|
<UCard class="mt-5">
|
||||||
<UAccordion
|
<UAccordion
|
||||||
:items="renderedPhases"
|
:items="renderedPhases"
|
||||||
@@ -404,7 +394,8 @@ const getAvailableQueryStringData = () => {
|
|||||||
</template>
|
</template>
|
||||||
</UAccordion>
|
</UAccordion>
|
||||||
</UCard>
|
</UCard>
|
||||||
</div><div v-else-if="item.label === 'Ausgangsbelege'">
|
</div>
|
||||||
|
<div v-else-if="tab.label === 'Ausgangsbelege'">
|
||||||
<UCard class="mt-5">
|
<UCard class="mt-5">
|
||||||
|
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
|
|||||||
@@ -2,11 +2,9 @@
|
|||||||
import dayjs from "dayjs"
|
import dayjs from "dayjs"
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
type: {
|
type: {
|
||||||
required: true,
|
|
||||||
type: String
|
type: String
|
||||||
},
|
},
|
||||||
elementId: {
|
elementId: {
|
||||||
required: true,
|
|
||||||
type: String
|
type: String
|
||||||
},
|
},
|
||||||
renderHeadline: {
|
renderHeadline: {
|
||||||
@@ -26,43 +24,12 @@ const items = ref([])
|
|||||||
|
|
||||||
const setup = async () => {
|
const setup = async () => {
|
||||||
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq(type,elementId).order("created_at",{ascending: true})).data || []
|
if(type && elementId){
|
||||||
|
items.value = (await supabase.from("historyitems").select().eq(type,elementId).order("created_at",{ascending: true})).data || []
|
||||||
|
} else {
|
||||||
|
items.value = (await supabase.from("historyitems").select().order("created_at",{ascending: true})).data || []
|
||||||
|
|
||||||
/*if(type === "customer") {
|
}
|
||||||
items.value = (await supabase.from("historyitems").select().eq("customer",elementId)).data || []
|
|
||||||
} else if(type === "vendor") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("vendor",elementId)).data || []
|
|
||||||
} else if(type === "project") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("project",elementId)).data || []
|
|
||||||
} else if(type === "plant") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("plant",elementId)).data || []
|
|
||||||
} else if(type === "incomingInvoice") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("incomingInvoice",elementId)).data || []
|
|
||||||
} else if(type === "document") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("document",elementId)).data || []
|
|
||||||
} else if(type === "contact") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("contact",elementId)).data || []
|
|
||||||
} else if(type === "contract") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("contract",elementId)).data || []
|
|
||||||
} else if(type === "inventoryitem") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("inventoryitem",elementId)).data || []
|
|
||||||
} else if(type === "product") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("product",elementId)).data || []
|
|
||||||
} else if(type === "profile") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("profile",elementId)).data || []
|
|
||||||
} else if(type === "absencerequest") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("absenceRequest",elementId)).data || []
|
|
||||||
} else if(type === "event") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("event",elementId)).data || []
|
|
||||||
} else if(type === "task") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("task",elementId)).data || []
|
|
||||||
} else if(type === "vehicle") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("vehicle",elementId)).data || []
|
|
||||||
} else if(type === "space") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("space",elementId)).data || []
|
|
||||||
} else if(type === "trackingtrip") {
|
|
||||||
items.value = (await supabase.from("historyitems").select().eq("trackingtrip",elementId)).data || []
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setup()
|
setup()
|
||||||
@@ -162,7 +129,7 @@ const renderText = (text) => {
|
|||||||
</UCard>
|
</UCard>
|
||||||
</UModal>
|
</UModal>
|
||||||
<Toolbar
|
<Toolbar
|
||||||
v-if="!renderHeadline"
|
v-if="!renderHeadline && elementId && type"
|
||||||
>
|
>
|
||||||
<UButton
|
<UButton
|
||||||
@click="showAddHistoryItemModal = true"
|
@click="showAddHistoryItemModal = true"
|
||||||
@@ -170,7 +137,7 @@ const renderText = (text) => {
|
|||||||
+ Eintrag
|
+ Eintrag
|
||||||
</UButton>
|
</UButton>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
<div v-else>
|
<div v-else-if="renderHeadline && elementId && type">
|
||||||
<div :class="`flex justify-between`">
|
<div :class="`flex justify-between`">
|
||||||
<p class=""><span class="text-xl">Logbuch</span> <UBadge variant="outline">{{items.length}}</UBadge></p>
|
<p class=""><span class="text-xl">Logbuch</span> <UBadge variant="outline">{{items.length}}</UBadge></p>
|
||||||
<UButton
|
<UButton
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ const links = computed(() => {
|
|||||||
label: "Dashboard",
|
label: "Dashboard",
|
||||||
to: "/",
|
to: "/",
|
||||||
icon: "i-heroicons-home"
|
icon: "i-heroicons-home"
|
||||||
|
}, {
|
||||||
|
id: 'historyitems',
|
||||||
|
label: "Logbuch",
|
||||||
|
to: "/historyitems",
|
||||||
|
icon: "i-heroicons-book-open"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Organisation",
|
label: "Organisation",
|
||||||
@@ -46,7 +51,7 @@ const links = computed(() => {
|
|||||||
}] : [],
|
}] : [],
|
||||||
{
|
{
|
||||||
label: "Dateien",
|
label: "Dateien",
|
||||||
to: "/documents",
|
to: "/files",
|
||||||
icon: "i-heroicons-document"
|
icon: "i-heroicons-document"
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@@ -113,6 +118,11 @@ const links = computed(() => {
|
|||||||
to: "/standardEntity/absencerequests",
|
to: "/standardEntity/absencerequests",
|
||||||
icon: "i-heroicons-document-text"
|
icon: "i-heroicons-document-text"
|
||||||
}] : [],
|
}] : [],
|
||||||
|
{
|
||||||
|
label: "Fahrten",
|
||||||
|
to: "/trackingTrips",
|
||||||
|
icon: "i-heroicons-map"
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
... profileStore.ownTenant.features.accounting ? [{
|
... profileStore.ownTenant.features.accounting ? [{
|
||||||
@@ -156,30 +166,9 @@ const links = computed(() => {
|
|||||||
},
|
},
|
||||||
... role.checkRight("spaces") ? [{
|
... role.checkRight("spaces") ? [{
|
||||||
label: "Lagerplätze",
|
label: "Lagerplätze",
|
||||||
to: "/spaces",
|
to: "/standardEntity/spaces",
|
||||||
icon: "i-heroicons-square-3-stack-3d"
|
icon: "i-heroicons-square-3-stack-3d"
|
||||||
}] : [],
|
}] : [],
|
||||||
... role.checkRight("inventoryitems") ? [{
|
|
||||||
label: "Inventar",
|
|
||||||
to: "/standardEntity/inventoryitems",
|
|
||||||
icon: "i-heroicons-puzzle-piece"
|
|
||||||
}] : [],
|
|
||||||
]
|
|
||||||
},] : [],
|
|
||||||
... role.checkRight("vehicles") ? [{
|
|
||||||
label: "Fuhrpark",
|
|
||||||
defaultOpen: false,
|
|
||||||
icon: "i-heroicons-truck",
|
|
||||||
children: [
|
|
||||||
... role.checkRight("vehicles") ? [{
|
|
||||||
label: "Fahrzeuge",
|
|
||||||
to: "/standardEntity/vehicles",
|
|
||||||
icon: "i-heroicons-truck"
|
|
||||||
}] : [],{
|
|
||||||
label: "Fahrten",
|
|
||||||
to: "/trackingTrips",
|
|
||||||
icon: "i-heroicons-map"
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
},] : [],
|
},] : [],
|
||||||
{
|
{
|
||||||
@@ -200,11 +189,26 @@ const links = computed(() => {
|
|||||||
... role.checkRight("services") ? [{
|
... role.checkRight("services") ? [{
|
||||||
label: "Leistungen",
|
label: "Leistungen",
|
||||||
to: "/standardEntity/services",
|
to: "/standardEntity/services",
|
||||||
icon: "i-heroicons-puzzle-piece"
|
icon: "i-heroicons-wrench-screwdriver"
|
||||||
}] : [],
|
}] : [],
|
||||||
... role.checkRight("servicecategories") ? [{
|
... role.checkRight("servicecategories") ? [{
|
||||||
label: "Leistungskategorien",
|
label: "Leistungskategorien",
|
||||||
to: "/standardEntity/servicecategories",
|
to: "/standardEntity/servicecategories",
|
||||||
|
icon: "i-heroicons-wrench-screwdriver"
|
||||||
|
}] : [],
|
||||||
|
{
|
||||||
|
label: "Mitarbeiter",
|
||||||
|
to: "/profiles",
|
||||||
|
icon: "i-heroicons-user-group"
|
||||||
|
},
|
||||||
|
... role.checkRight("vehicles") ? [{
|
||||||
|
label: "Fahrzeuge",
|
||||||
|
to: "/standardEntity/vehicles",
|
||||||
|
icon: "i-heroicons-truck"
|
||||||
|
}] : [],
|
||||||
|
... role.checkRight("inventoryitems") ? [{
|
||||||
|
label: "Inventar",
|
||||||
|
to: "/standardEntity/inventoryitems",
|
||||||
icon: "i-heroicons-puzzle-piece"
|
icon: "i-heroicons-puzzle-piece"
|
||||||
}] : [],
|
}] : [],
|
||||||
]
|
]
|
||||||
@@ -244,10 +248,6 @@ const links = computed(() => {
|
|||||||
label: "Nummernkreise",
|
label: "Nummernkreise",
|
||||||
to: "/settings/numberRanges",
|
to: "/settings/numberRanges",
|
||||||
icon: "i-heroicons-clipboard-document-list"
|
icon: "i-heroicons-clipboard-document-list"
|
||||||
},{
|
|
||||||
label: "Mitarbeiter",
|
|
||||||
to: "/profiles",
|
|
||||||
icon: "i-heroicons-clipboard-document-list"
|
|
||||||
},{
|
},{
|
||||||
label: "Rollen",
|
label: "Rollen",
|
||||||
to: "/roles",
|
to: "/roles",
|
||||||
@@ -276,63 +276,15 @@ const links = computed(() => {
|
|||||||
label: "Projekttypen",
|
label: "Projekttypen",
|
||||||
to: "/projecttypes",
|
to: "/projecttypes",
|
||||||
icon: "i-heroicons-clipboard-document-list"
|
icon: "i-heroicons-clipboard-document-list"
|
||||||
}/*,{
|
|
||||||
label: "Integrationen",
|
|
||||||
to: "/settings/integrations",
|
|
||||||
icon: "i-heroicons-clipboard-document-list"
|
|
||||||
}*/,{
|
|
||||||
label: "Labels",
|
|
||||||
to: "/settings/labels/",
|
|
||||||
icon: "i-heroicons-bars-3-solid"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
/*const setOpen = (index,open) => {
|
|
||||||
console.log(!open)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<!--
|
|
||||||
<UAccordion :items="links" :ui="{ wrapper: 'flex flex-col w-full' }">
|
|
||||||
<template #default="{ item, index, open }">
|
|
||||||
<UButton color="gray" variant="ghost" class="border-b border-gray-200 dark:border-gray-700" :ui="{ rounded: 'rounded-none', padding: { sm: 'p-3' } }">
|
|
||||||
<template #leading>
|
|
||||||
<!– <div class="w-6 h-6 rounded-full bg-primary-500 dark:bg-primary-400 flex items-center justify-center -my-1">
|
|
||||||
<UIcon :name="item.icon" class="w-4 h-4 text-white dark:text-gray-900" />
|
|
||||||
</div>–>
|
|
||||||
<UIcon :name="item.icon" class="w-4 h-4 dark:text-white text-gray-900" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<span class="truncate">{{ item.label }}</span>
|
|
||||||
|
|
||||||
<template #trailing>
|
|
||||||
<UIcon
|
|
||||||
name="i-heroicons-chevron-right-20-solid"
|
|
||||||
class="w-5 h-5 ms-auto transform transition-transform duration-200"
|
|
||||||
:class="[open && 'rotate-90']"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</UButton>
|
|
||||||
</template>
|
|
||||||
<template #item="{item}">
|
|
||||||
<div v-if="item.children" class="flex flex-col">
|
|
||||||
<UButton
|
|
||||||
v-for="child in item.children"
|
|
||||||
variant="ghost"
|
|
||||||
color="gray"
|
|
||||||
>
|
|
||||||
{{child.label}}
|
|
||||||
</UButton>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</UAccordion>
|
|
||||||
-->
|
|
||||||
<div
|
<div
|
||||||
v-for="item in links"
|
v-for="item in links"
|
||||||
>
|
>
|
||||||
|
|||||||
210
composables/useFiles.js
Normal file
210
composables/useFiles.js
Normal file
@@ -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}
|
||||||
|
}
|
||||||
@@ -22,97 +22,6 @@ export const useSupabaseSelect = async (relation,select = '*', sortColumn = null
|
|||||||
return data
|
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 = '*' ) => {
|
export const useSupabaseSelectSingle = async (relation,idToEq,select = '*' ) => {
|
||||||
const supabase = useSupabaseClient()
|
const supabase = useSupabaseClient()
|
||||||
const profileStore = useProfileStore()
|
const profileStore = useProfileStore()
|
||||||
|
|||||||
@@ -125,18 +125,8 @@ const footerLinks = [/*{
|
|||||||
<UDashboardSearchButton label="Suche..."/>
|
<UDashboardSearchButton label="Suche..."/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- <UDashboardSidebarLinks :links="links">
|
|
||||||
|
|
||||||
</UDashboardSidebarLinks>-->
|
|
||||||
<MainNav/>
|
<MainNav/>
|
||||||
|
|
||||||
<!-- <UAccordion
|
|
||||||
:items="links"
|
|
||||||
>
|
|
||||||
|
|
||||||
</UAccordion>-->
|
|
||||||
|
|
||||||
|
|
||||||
<div class="flex-1" />
|
<div class="flex-1" />
|
||||||
|
|
||||||
<UDashboardSidebarLinks :links="footerLinks" />
|
<UDashboardSidebarLinks :links="footerLinks" />
|
||||||
|
|||||||
@@ -457,7 +457,7 @@ const renderCurrency = (value, currency = "€") => {
|
|||||||
const documentTotal = computed(() => {
|
const documentTotal = computed(() => {
|
||||||
let totalNet = 0
|
let totalNet = 0
|
||||||
let total19 = 0
|
let total19 = 0
|
||||||
let totalGross = 0
|
let total7 = 0
|
||||||
|
|
||||||
itemInfo.value.rows.forEach(row => {
|
itemInfo.value.rows.forEach(row => {
|
||||||
if(!['pagebreak','title','text'].includes(row.mode)){
|
if(!['pagebreak','title','text'].includes(row.mode)){
|
||||||
@@ -466,11 +466,13 @@ const documentTotal = computed(() => {
|
|||||||
|
|
||||||
if(row.taxPercent === 19) {
|
if(row.taxPercent === 19) {
|
||||||
total19 = total19 + Number(rowPrice * 0.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
|
let totalGrossAlreadyPaid = 0
|
||||||
|
|
||||||
@@ -488,19 +490,14 @@ const documentTotal = computed(() => {
|
|||||||
|
|
||||||
let sumToPay = totalGross - totalGrossAlreadyPaid
|
let sumToPay = totalGross - totalGrossAlreadyPaid
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
totalNet: totalNet,
|
totalNet: totalNet,
|
||||||
total19: total19,
|
total19: total19,
|
||||||
|
total7: total7,
|
||||||
totalGross: totalGross,
|
totalGross: totalGross,
|
||||||
totalGrossAlreadyPaid: totalGrossAlreadyPaid,
|
totalGrossAlreadyPaid: totalGrossAlreadyPaid,
|
||||||
totalSumToPay: sumToPay
|
totalSumToPay: sumToPay
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const processDieselPosition = () => {
|
const processDieselPosition = () => {
|
||||||
@@ -831,14 +828,13 @@ const closeDocument = async () => {
|
|||||||
|
|
||||||
await generateDocument()
|
await generateDocument()
|
||||||
|
|
||||||
let fileData = {
|
let fileData = {}
|
||||||
tags: [],
|
|
||||||
project: null
|
|
||||||
}
|
|
||||||
|
|
||||||
fileData.project = itemInfo.value.project
|
fileData.project = itemInfo.value.project
|
||||||
fileData.createdDocument = itemInfo.value.id
|
fileData.createddocument = itemInfo.value.id
|
||||||
fileData.tags.push(dataStore.documentTypesForCreation[itemInfo.value.type].labelSingle)
|
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) {
|
function dataURLtoFile(dataurl, filename) {
|
||||||
var arr = dataurl.split(","),
|
var arr = dataurl.split(","),
|
||||||
@@ -854,7 +850,7 @@ const closeDocument = async () => {
|
|||||||
|
|
||||||
let file = dataURLtoFile(uri.value, `${itemInfo.value.documentNumber}.pdf`)
|
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}`)
|
await router.push(`/createDocument/show/${itemInfo.value.id}`)
|
||||||
|
|
||||||
@@ -894,13 +890,28 @@ const setRowData = (row) => {
|
|||||||
<template>
|
<template>
|
||||||
<UDashboardNavbar>
|
<UDashboardNavbar>
|
||||||
<template #right>
|
<template #right>
|
||||||
|
<!-- <ButtonWithConfirm
|
||||||
|
v-if="itemInfo.state === 'Entwurf'"
|
||||||
|
color="rose"
|
||||||
|
variant="outline"
|
||||||
|
@confirmed="dataStore.updateItem('createddocuments',{id:itemInfo.id,archived: true}),
|
||||||
|
router.push('/createDocument')"
|
||||||
|
>
|
||||||
|
<template #button>
|
||||||
|
Archivieren
|
||||||
|
</template>
|
||||||
|
<template #header>
|
||||||
|
<span class="text-md text-black font-bold">Archivieren bestätigen</span>
|
||||||
|
</template>
|
||||||
|
Möchten Sie diesen Ausgangsbeleg wirklich archivieren?
|
||||||
|
</ButtonWithConfirm>-->
|
||||||
<UButton
|
<UButton
|
||||||
icon="i-mdi-content-save"
|
icon="i-mdi-content-save"
|
||||||
@click="saveDocument('Entwurf',true)"
|
@click="saveDocument('Entwurf',true)"
|
||||||
v-if="itemInfo.type !== 'serialInvoices' "
|
v-if="itemInfo.type !== 'serialInvoices' "
|
||||||
:disabled="!itemInfo.customer"
|
:disabled="!itemInfo.customer"
|
||||||
>
|
>
|
||||||
Entwurf
|
Entwurf speichern
|
||||||
</UButton>
|
</UButton>
|
||||||
<UButton
|
<UButton
|
||||||
@click="closeDocument"
|
@click="closeDocument"
|
||||||
@@ -952,7 +963,7 @@ const setRowData = (row) => {
|
|||||||
v-model="itemInfo.type"
|
v-model="itemInfo.type"
|
||||||
value-attribute="type"
|
value-attribute="type"
|
||||||
option-attribute="label"
|
option-attribute="label"
|
||||||
@input="setDocumentTypeConfig"
|
@change="setDocumentTypeConfig"
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
|
|||||||
@@ -21,9 +21,16 @@ const linkedDocument =ref({})
|
|||||||
const currentTenant = ref({})
|
const currentTenant = ref({})
|
||||||
const setupPage = async () => {
|
const setupPage = async () => {
|
||||||
if(route.params) {
|
if(route.params) {
|
||||||
if(route.params.id) itemInfo.value = await useSupabaseSelectSingle("createddocuments",route.params.id,"*")
|
if(route.params.id) itemInfo.value = await useSupabaseSelectSingle("createddocuments",route.params.id,"*, files(*)")
|
||||||
const {data,error} = await supabase.from("documents").select("id").eq("createdDocument", route.params.id).order("id",{ascending:true})
|
|
||||||
linkedDocument.value = data[data.length -1]
|
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
|
E-Mail
|
||||||
</UButton>
|
</UButton>
|
||||||
|
<UButton
|
||||||
|
v-if="itemInfo.project"
|
||||||
|
@click="router.push(`/standardEntity/projects/show/${itemInfo.project}`)"
|
||||||
|
icon="i-heroicons-arrow-right-end-on-rectangle"
|
||||||
|
variant="outline"
|
||||||
|
>
|
||||||
|
Projekt
|
||||||
|
</UButton>
|
||||||
</template>
|
</template>
|
||||||
</UDashboardToolbar>
|
</UDashboardToolbar>
|
||||||
<UDashboardPanelContent>
|
<UDashboardPanelContent>
|
||||||
<object
|
<object
|
||||||
:data="dataStore.documents.find(i => i.id === linkedDocument.id) ? dataStore.documents.find(i => i.id === linkedDocument.id).url : ''"
|
:data="linkedDocument.url"
|
||||||
class="h-full"
|
class="h-full"
|
||||||
/>
|
/>
|
||||||
</UDashboardPanelContent>
|
</UDashboardPanelContent>
|
||||||
|
|||||||
@@ -2,22 +2,66 @@
|
|||||||
|
|
||||||
|
|
||||||
import {BlobReader, BlobWriter, ZipWriter} from "@zip.js/zip.js";
|
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({
|
definePageMeta({
|
||||||
middleware: "auth"
|
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 dataStore = useDataStore()
|
||||||
const profileStore = useProfileStore()
|
const profileStore = useProfileStore()
|
||||||
const supabase = useSupabaseClient()
|
const supabase = useSupabaseClient()
|
||||||
const user = useSupabaseUser()
|
|
||||||
const toast = useToast()
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const slideover = useSlideover()
|
||||||
|
const modal = useModal()
|
||||||
|
|
||||||
dataStore.fetchDocuments()
|
dataStore.fetchDocuments()
|
||||||
|
|
||||||
const uploadModalOpen = ref(false)
|
const uploadModalOpen = ref(false)
|
||||||
|
const createFolderModalOpen = ref(false)
|
||||||
const uploadInProgress = ref(false)
|
const uploadInProgress = ref(false)
|
||||||
const fileUploadFormData = ref({
|
const fileUploadFormData = ref({
|
||||||
tags: ["Eingang"],
|
tags: ["Eingang"],
|
||||||
@@ -26,11 +70,18 @@ const fileUploadFormData = ref({
|
|||||||
folder: null
|
folder: null
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const files = useFiles()
|
||||||
|
|
||||||
let tags = dataStore.getDocumentTags
|
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 documents = ref([])
|
||||||
const folders = ref([])
|
const folders = ref([])
|
||||||
|
const filetags = ref([])
|
||||||
|
|
||||||
const currentFolder = ref(null)
|
const currentFolder = ref(null)
|
||||||
|
|
||||||
@@ -39,11 +90,12 @@ const isDragTarget = ref(false)
|
|||||||
const setupPage = async () => {
|
const setupPage = async () => {
|
||||||
folders.value = await useSupabaseSelect("folders")
|
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) {
|
||||||
if(route.query.folder) {
|
if(route.query.folder) {
|
||||||
console.log(route.query.folder)
|
|
||||||
currentFolder.value = await useSupabaseSelectSingle("folders", route.query.folder)
|
currentFolder.value = await useSupabaseSelectSingle("folders", route.query.folder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,10 +187,6 @@ const breadcrumbLinks = computed(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const filteredDocuments = computed(() => {
|
const filteredDocuments = computed(() => {
|
||||||
|
|
||||||
return documents.value.filter(i => currentFolder.value ? i.folder === currentFolder.value.id : !i.folder)
|
return documents.value.filter(i => currentFolder.value ? i.folder === currentFolder.value.id : !i.folder)
|
||||||
@@ -151,20 +199,38 @@ const changeFolder = async (newFolder) => {
|
|||||||
|
|
||||||
if(newFolder) {
|
if(newFolder) {
|
||||||
fileUploadFormData.value.folder = newFolder.id
|
fileUploadFormData.value.folder = newFolder.id
|
||||||
await router.push(`/documents?folder=${newFolder.id}`)
|
await router.push(`/files?folder=${newFolder.id}`)
|
||||||
} else {
|
} else {
|
||||||
fileUploadFormData.value.folder = null
|
fileUploadFormData.value.folder = null
|
||||||
await router.push(`/documents`)
|
await router.push(`/files`)
|
||||||
}
|
}
|
||||||
|
|
||||||
setupPage()
|
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) => {
|
const uploadFiles = async (files) => {
|
||||||
uploadInProgress.value = true;
|
uploadInProgress.value = true;
|
||||||
|
|
||||||
if(files) {
|
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 {
|
} else {
|
||||||
await dataStore.uploadFiles(fileUploadFormData.value, document.getElementById("fileUploadInput").files, true)
|
await dataStore.uploadFiles(fileUploadFormData.value, document.getElementById("fileUploadInput").files, true)
|
||||||
@@ -237,37 +303,46 @@ const downloadSelected = async () => {
|
|||||||
link.click();
|
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),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<UDashboardNavbar
|
<UDashboardNavbar
|
||||||
title="Dateien"
|
title="Dateien"
|
||||||
>
|
>
|
||||||
|
|
||||||
</UDashboardNavbar>
|
</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>
|
<UDashboardToolbar>
|
||||||
<template #left>
|
<template #left>
|
||||||
<UBreadcrumb
|
<UBreadcrumb
|
||||||
@@ -275,49 +350,125 @@ const downloadSelected = async () => {
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #right>
|
<template #right>
|
||||||
<UButton @click="uploadModalOpen = true">Hochladen</UButton>
|
<USelectMenu
|
||||||
|
:options="displayModes"
|
||||||
|
value-attribute="key"
|
||||||
|
option-attribute="label"
|
||||||
|
v-model="displayMode"
|
||||||
|
:ui-menu="{ width: 'min-w-max'}"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<UIcon class="w-5 h-5" :name="displayModes.find(i => i.key === displayMode).icon"/>
|
||||||
|
</template>
|
||||||
|
</USelectMenu>
|
||||||
|
|
||||||
|
<UButton @click="uploadModalOpen = true">+ Hochladen</UButton>
|
||||||
|
<UButton
|
||||||
|
@click="createFolderModalOpen = true"
|
||||||
|
variant="outline"
|
||||||
|
>+ Ordner</UButton>
|
||||||
|
<UModal
|
||||||
|
v-model="createFolderModalOpen"
|
||||||
|
>
|
||||||
|
<UCard>
|
||||||
|
<template #header>
|
||||||
|
Ordner Erstellen
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<UFormGroup
|
||||||
|
label="Ordner erstellen"
|
||||||
|
>
|
||||||
|
<UInput
|
||||||
|
v-model="createFolderData.name"
|
||||||
|
/>
|
||||||
|
</UFormGroup>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<UButton
|
||||||
|
@click="createFolder"
|
||||||
|
>
|
||||||
|
Erstellen
|
||||||
|
</UButton>
|
||||||
|
</template>
|
||||||
|
</UCard>
|
||||||
|
|
||||||
|
</UModal>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
</UDashboardToolbar>
|
</UDashboardToolbar>
|
||||||
<div id="drop_zone" class="h-full scrollList">
|
<div id="drop_zone" class="h-full scrollList">
|
||||||
<UDashboardPanelContent v-if="!isDragTarget" >
|
<UDashboardPanelContent v-if="!isDragTarget" >
|
||||||
<div class="flex flex-row w-full flex-wrap" v-if="currentFolders.length > 0">
|
<div v-if="displayMode === 'list'">
|
||||||
<a
|
<table class="w-full">
|
||||||
class="w-1/6 folderIcon flex flex-col p-5 m-2"
|
<thead>
|
||||||
v-for="folder in currentFolders"
|
<td class="font-bold">Name</td>
|
||||||
@click="changeFolder(folder)"
|
<td class="font-bold">Erstellt am</td>
|
||||||
>
|
</thead>
|
||||||
|
<tr v-for="(entry,index) in renderedFileList">
|
||||||
|
<td>
|
||||||
|
<UIcon :name="entry.type === 'folder' ? 'i-heroicons-folder' : 'i-heroicons-document'"/>
|
||||||
|
<a
|
||||||
|
:class="[...index === selectedFileIndex ? ['text-primary'] : ['dark:text-white','text-black']]"
|
||||||
|
@click="entry.type === 'folder' ? changeFolder(currentFolders.find(i => i.id === entry.id)) : showFile(entry.id)"
|
||||||
|
>{{entry.label}}</a>
|
||||||
|
|
||||||
<UIcon
|
</td>
|
||||||
name="i-heroicons-folder"
|
<td>
|
||||||
class="w-20 h-20"
|
<span v-if="entry.type === 'file'">{{dayjs(documents.find(i => i.id === entry.id).created_at).format("DD.MM.YY HH:mm")}}</span>
|
||||||
|
<span v-if="entry.type === 'folder'">{{dayjs(currentFolders.find(i => i.id === entry.id).created_at).format("DD.MM.YY HH:mm")}}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="displayMode === 'rectangles'">
|
||||||
|
<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="changeFolder(folder)"
|
||||||
|
>
|
||||||
|
|
||||||
|
<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="currentFolder">{{currentFolder.name}}</UDivider>
|
||||||
|
<UDivider class="my-5" v-else>Ablage</UDivider>
|
||||||
|
|
||||||
|
<div v-if="!loadingDocs">
|
||||||
|
<DocumentList
|
||||||
|
v-if="filteredDocuments.length > 0"
|
||||||
|
:documents="filteredDocuments"
|
||||||
|
@selectDocument="(info) => console.log(info)"
|
||||||
/>
|
/>
|
||||||
<span class="text-center truncate">{{folder.name}}</span>
|
<UAlert
|
||||||
</a>
|
v-else
|
||||||
</div>
|
class="mt-5 w-1/2 mx-auto"
|
||||||
|
icon="i-heroicons-light-bulb"
|
||||||
<UDivider class="my-5" v-if="currentFolder">{{currentFolder.name}}</UDivider>
|
title="Keine Dokumente vorhanden"
|
||||||
<UDivider class="my-5" v-else>Ablage</UDivider>
|
color="primary"
|
||||||
|
variant="outline"
|
||||||
<div v-if="!loadingDocs">
|
/>
|
||||||
<DocumentList
|
</div>
|
||||||
v-if="filteredDocuments.length > 0"
|
<UProgress
|
||||||
:documents="filteredDocuments"
|
animation="carousel"
|
||||||
@selectDocument="(info) => console.log(info)"
|
|
||||||
/>
|
|
||||||
<UAlert
|
|
||||||
v-else
|
v-else
|
||||||
class="mt-5 w-1/2 mx-auto"
|
class="w-2/3 my-5 mx-auto"
|
||||||
icon="i-heroicons-light-bulb"
|
|
||||||
title="Keine Dokumente vorhanden"
|
|
||||||
color="primary"
|
|
||||||
variant="outline"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<UProgress
|
|
||||||
animation="carousel"
|
|
||||||
v-else
|
|
||||||
class="w-2/3 my-5 mx-auto"
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</UDashboardPanelContent>
|
</UDashboardPanelContent>
|
||||||
<UCard
|
<UCard
|
||||||
@@ -361,7 +512,9 @@ const downloadSelected = async () => {
|
|||||||
multiple
|
multiple
|
||||||
searchable
|
searchable
|
||||||
searchable-placeholder="Suchen..."
|
searchable-placeholder="Suchen..."
|
||||||
:options="tags"
|
option-attribute="name"
|
||||||
|
value-attribute="id"
|
||||||
|
:options="filetags"
|
||||||
v-model="fileUploadFormData.tags"
|
v-model="fileUploadFormData.tags"
|
||||||
/>
|
/>
|
||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
@@ -382,8 +535,6 @@ const downloadSelected = async () => {
|
|||||||
</USlideover>
|
</USlideover>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.folderIcon {
|
.folderIcon {
|
||||||
border: 1px solid lightgrey;
|
border: 1px solid lightgrey;
|
||||||
@@ -396,4 +547,8 @@ const downloadSelected = async () => {
|
|||||||
color: #69c350;
|
color: #69c350;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tr:nth-child(odd) {
|
||||||
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
20
pages/historyitems/index.vue
Normal file
20
pages/historyitems/index.vue
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UDashboardNavbar>
|
||||||
|
<template #center>
|
||||||
|
<h1
|
||||||
|
:class="['text-xl','font-medium']"
|
||||||
|
>Zentrales Logbuch</h1>
|
||||||
|
</template>
|
||||||
|
</UDashboardNavbar>
|
||||||
|
<UDashboardPanelContent>
|
||||||
|
<HistoryDisplay/>
|
||||||
|
</UDashboardPanelContent>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -96,11 +96,15 @@ const columns = computed(() => templateColumns.filter((column) => selectedColumn
|
|||||||
</UModal>
|
</UModal>
|
||||||
<UDashboardNavbar title="E-Mail Konten">
|
<UDashboardNavbar title="E-Mail Konten">
|
||||||
<template #right>
|
<template #right>
|
||||||
<UButton
|
<UTooltip title="In der Beta nicht verfügbar">
|
||||||
@click="showEmailAddressModal = true"
|
<UButton
|
||||||
>
|
:disabled="true"
|
||||||
+ E-Mail Konto
|
@click="showEmailAddressModal = true"
|
||||||
</UButton>
|
>
|
||||||
|
+ E-Mail Konto
|
||||||
|
</UButton>
|
||||||
|
</UTooltip>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
</UDashboardNavbar>
|
</UDashboardNavbar>
|
||||||
<UTable
|
<UTable
|
||||||
|
|||||||
196
stores/data.js
196
stores/data.js
@@ -122,7 +122,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
numberRangeHolder: "customerNumber",
|
numberRangeHolder: "customerNumber",
|
||||||
historyItemHolder: "customer",
|
historyItemHolder: "customer",
|
||||||
supabaseSortColumn: "customerNumber",
|
supabaseSortColumn: "customerNumber",
|
||||||
supabaseSelectWithInformation: "*, projects(*), plants(*), contracts(*), contacts(*), createddocuments(*), documents(*)",
|
supabaseSelectWithInformation: "*, projects(*), plants(*), contracts(*), contacts(*), createddocuments(*), files(*)",
|
||||||
filters: [],
|
filters: [],
|
||||||
templateColumns: [
|
templateColumns: [
|
||||||
{
|
{
|
||||||
@@ -228,7 +228,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
component: profiles
|
component: profiles
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
showTabs: [{label: 'Informationen'},{label: 'Dokumente'},{label: 'Ausgangsbelege'},{label: 'Projekte'},{label: 'Objekte'},{label: 'Verträge'}]
|
showTabs: [{label: 'Informationen'},{label: 'Dateien'},{label: 'Ausgangsbelege'},{label: 'Projekte'},{label: 'Objekte'},{label: 'Verträge'}]
|
||||||
},
|
},
|
||||||
contacts: {
|
contacts: {
|
||||||
label: "Kontakte",
|
label: "Kontakte",
|
||||||
@@ -329,23 +329,30 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
isStandardEntity: true,
|
isStandardEntity: true,
|
||||||
redirect:true,
|
redirect:true,
|
||||||
filters:[],
|
filters:[],
|
||||||
supabaseSelectWithInformation: "*, customer(*), documents(*)",
|
inputColumns: [
|
||||||
|
"Allgemeines",
|
||||||
|
"Abrechnung"
|
||||||
|
],
|
||||||
|
supabaseSelectWithInformation: "*, customer(*), files(*)",
|
||||||
templateColumns: [
|
templateColumns: [
|
||||||
{
|
{
|
||||||
key: "name",
|
key: "name",
|
||||||
label: "Name",
|
label: "Name",
|
||||||
title: true,
|
title: true,
|
||||||
inputType: "text"
|
inputType: "text",
|
||||||
|
inputColumn: "Allgemeines"
|
||||||
},{
|
},{
|
||||||
key: "active",
|
key: "active",
|
||||||
label: "Aktiv",
|
label: "Aktiv",
|
||||||
component: active,
|
component: active,
|
||||||
inputType: "bool"
|
inputType: "bool",
|
||||||
|
inputColumn: "Allgemeines"
|
||||||
},{
|
},{
|
||||||
key: "recurring",
|
key: "recurring",
|
||||||
label: "Wiederkehrend",
|
label: "Wiederkehrend",
|
||||||
component: recurring,
|
component: recurring,
|
||||||
inputType: "bool"
|
inputType: "bool",
|
||||||
|
inputColumn: "Allgemeines"
|
||||||
},{
|
},{
|
||||||
key: 'customer',
|
key: 'customer',
|
||||||
label: "Kunde",
|
label: "Kunde",
|
||||||
@@ -354,6 +361,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
selectDataType: "customers",
|
selectDataType: "customers",
|
||||||
selectOptionAttribute: "name",
|
selectOptionAttribute: "name",
|
||||||
selectSearchAttributes: ['name'],
|
selectSearchAttributes: ['name'],
|
||||||
|
inputColumn: "Allgemeines"
|
||||||
},{
|
},{
|
||||||
key: 'contact',
|
key: 'contact',
|
||||||
label: "Ansprechpartner",
|
label: "Ansprechpartner",
|
||||||
@@ -365,64 +373,91 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
},
|
},
|
||||||
selectOptionAttribute: "fullName",
|
selectOptionAttribute: "fullName",
|
||||||
selectSearchAttributes: ['fullName'],
|
selectSearchAttributes: ['fullName'],
|
||||||
|
inputColumn: "Allgemeines"
|
||||||
},{
|
},{
|
||||||
key: 'duration',
|
key: 'duration',
|
||||||
label: "mindest Vertragslaufzeit",
|
label: "mindest Vertragslaufzeit",
|
||||||
inputType: "select",
|
inputType: "select",
|
||||||
selectManualOptions: ['12 Monate','24 Monate','36 Monate','48 Monate']
|
selectValueAttribute:"label",
|
||||||
|
selectManualOptions: [
|
||||||
|
{label:'12 Monate'},
|
||||||
|
{label:'24 Monate'},
|
||||||
|
{label:'36 Monate'},
|
||||||
|
{label:'48 Monate'},
|
||||||
|
],
|
||||||
|
inputColumn: "Allgemeines"
|
||||||
},{
|
},{
|
||||||
key: 'invoiceDispatch',
|
key: 'invoiceDispatch',
|
||||||
label: "Rechnungsversand",
|
label: "Rechnungsversand",
|
||||||
inputType: "select",
|
inputType: "select",
|
||||||
selectManualOptions: ['E-Mail','Post']
|
selectValueAttribute: "label",
|
||||||
|
selectManualOptions: [
|
||||||
|
{label:'E-Mail'},
|
||||||
|
{label:'Post'}
|
||||||
|
],
|
||||||
|
inputColumn: "Abrechnung"
|
||||||
},{
|
},{
|
||||||
key: 'paymentType',
|
key: 'paymentType',
|
||||||
label: "Zahlungsart",
|
label: "Zahlungsart",
|
||||||
inputType: "select",
|
inputType: "select",
|
||||||
selectManualOptions: ['Einzug','Überweisung']
|
selectValueAttribute: "label",
|
||||||
|
selectManualOptions: [
|
||||||
|
{label:'Einzug'},
|
||||||
|
{label:'Überweisung'}
|
||||||
|
],
|
||||||
|
inputColumn: "Abrechnung"
|
||||||
},{
|
},{
|
||||||
key: 'startDate',
|
key: 'startDate',
|
||||||
label: "Vertragsstart",
|
label: "Vertragsstart",
|
||||||
inputType: "date",
|
inputType: "date",
|
||||||
|
inputColumn: "Allgemeines"
|
||||||
},{
|
},{
|
||||||
key: 'endDate',
|
key: 'endDate',
|
||||||
label: "Vertragsende",
|
label: "Vertragsende",
|
||||||
inputType: "date",
|
inputType: "date",
|
||||||
|
inputColumn: "Allgemeines"
|
||||||
},{
|
},{
|
||||||
key: 'signDate',
|
key: 'signDate',
|
||||||
label: "Unterschrieben am",
|
label: "Unterschrieben am",
|
||||||
inputType: "date",
|
inputType: "date",
|
||||||
|
inputColumn: "Allgemeines"
|
||||||
},{
|
},{
|
||||||
key: 'sepaDate',
|
key: 'sepaDate',
|
||||||
label: "SEPA Datum",
|
label: "SEPA Datum",
|
||||||
inputType: "date",
|
inputType: "date",
|
||||||
|
inputColumn: "Abrechnung"
|
||||||
},{
|
},{
|
||||||
key: 'sepaRef',
|
key: 'sepaRef',
|
||||||
label: "Mandatsreferenz",
|
label: "Mandatsreferenz",
|
||||||
inputType: "text",
|
inputType: "text",
|
||||||
|
inputColumn: "Abrechnung"
|
||||||
},{
|
},{
|
||||||
key: 'bankingIban',
|
key: 'bankingIban',
|
||||||
label: "IBAN",
|
label: "IBAN",
|
||||||
inputType: "text",
|
inputType: "text",
|
||||||
|
inputColumn: "Abrechnung"
|
||||||
},{
|
},{
|
||||||
key: 'bankingOwner',
|
key: 'bankingOwner',
|
||||||
label: "Inhaber",
|
label: "Inhaber",
|
||||||
inputType: "text",
|
inputType: "text",
|
||||||
|
inputColumn: "Abrechnung"
|
||||||
},{
|
},{
|
||||||
key: 'bankingName',
|
key: 'bankingName',
|
||||||
label: "Bank",
|
label: "Bank",
|
||||||
inputType: "text",
|
inputType: "text",
|
||||||
|
inputColumn: "Abrechnung"
|
||||||
},{
|
},{
|
||||||
key: 'bankinBIC',
|
key: 'bankinBIC',
|
||||||
label: "BIC",
|
label: "BIC",
|
||||||
inputType: "text",
|
inputType: "text",
|
||||||
|
inputColumn: "Abrechnung"
|
||||||
},{
|
},{
|
||||||
key: "notes",
|
key: "notes",
|
||||||
label: "Notizen",
|
label: "Notizen",
|
||||||
inputType: "textarea"
|
inputType: "textarea",
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
showTabs: [{label: 'Informationen'},{label: 'Dokumente'}]
|
showTabs: [{label: 'Informationen'},{label: 'Dateien'}]
|
||||||
},
|
},
|
||||||
absencerequests: {
|
absencerequests: {
|
||||||
label: "Abwesenheitsanträge",
|
label: "Abwesenheitsanträge",
|
||||||
@@ -527,7 +562,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
},{
|
},{
|
||||||
label: "Aufgaben"
|
label: "Aufgaben"
|
||||||
},{
|
},{
|
||||||
label: "Dokumente"
|
label: "Dateien"
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
products: {
|
products: {
|
||||||
@@ -536,6 +571,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
isStandardEntity: true,
|
isStandardEntity: true,
|
||||||
redirect:true,
|
redirect:true,
|
||||||
supabaseSelectWithInformation: "*, unit(name)",
|
supabaseSelectWithInformation: "*, unit(name)",
|
||||||
|
historyItemHolder: "product",
|
||||||
filters: [],
|
filters: [],
|
||||||
templateColumns: [
|
templateColumns: [
|
||||||
{
|
{
|
||||||
@@ -568,6 +604,16 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
label: "Verkaufpreispreis",
|
label: "Verkaufpreispreis",
|
||||||
component: sellingPrice,
|
component: sellingPrice,
|
||||||
inputType: "number"
|
inputType: "number"
|
||||||
|
},{
|
||||||
|
key: "taxPercentage",
|
||||||
|
label: "Umsatzsteuer",
|
||||||
|
inputType: "select",
|
||||||
|
selectOptionAttribute: "label",
|
||||||
|
selectValueAttribute: 'key',
|
||||||
|
selectManualOptions: [
|
||||||
|
{label: "19 %", key: 19},
|
||||||
|
{label: "7 %", key: 7},
|
||||||
|
{label: "0 %", key: 0}]
|
||||||
},
|
},
|
||||||
/*{
|
/*{
|
||||||
key: "tags",
|
key: "tags",
|
||||||
@@ -601,7 +647,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
redirect:true,
|
redirect:true,
|
||||||
historyItemHolder: "project",
|
historyItemHolder: "project",
|
||||||
numberRangeHolder: "projectNumber",
|
numberRangeHolder: "projectNumber",
|
||||||
supabaseSelectWithInformation: "*, customer(id,name), plant(id,name), projecttype(name, id), tasks(*), documents(*), createddocuments(*)",
|
supabaseSelectWithInformation: "*, customer(id,name), plant(id,name), projecttype(name, id), tasks(*), files(*), createddocuments(*)",
|
||||||
supabaseSortColumn: "projectNumber",
|
supabaseSortColumn: "projectNumber",
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
@@ -685,8 +731,8 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
key: "tasks",
|
key: "tasks",
|
||||||
label: "Aufgaben"
|
label: "Aufgaben"
|
||||||
},{
|
},{
|
||||||
key: "documents",
|
key: "files",
|
||||||
label: "Dokumente"
|
label: "Dateien"
|
||||||
},{
|
},{
|
||||||
label: "Ausgangsbelege"
|
label: "Ausgangsbelege"
|
||||||
}/*,{
|
}/*,{
|
||||||
@@ -706,7 +752,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
isStandardEntity: true,
|
isStandardEntity: true,
|
||||||
redirect:true,
|
redirect:true,
|
||||||
historyItemHolder: "vehicle",
|
historyItemHolder: "vehicle",
|
||||||
supabaseSelectWithInformation: "*, checks(*), documents(*)",
|
supabaseSelectWithInformation: "*, checks(*), files(*)",
|
||||||
filters:[],
|
filters:[],
|
||||||
templateColumns:[
|
templateColumns:[
|
||||||
{
|
{
|
||||||
@@ -779,7 +825,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
{
|
{
|
||||||
label: 'Informationen',
|
label: 'Informationen',
|
||||||
}, {
|
}, {
|
||||||
label: 'Dokumente',
|
label: 'Dateien',
|
||||||
}, {
|
}, {
|
||||||
label: 'Überprüfungen',
|
label: 'Überprüfungen',
|
||||||
}
|
}
|
||||||
@@ -902,7 +948,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
{
|
{
|
||||||
label: 'Informationen',
|
label: 'Informationen',
|
||||||
}, {
|
}, {
|
||||||
label: 'Dokumente',
|
label: 'Dateien',
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -914,7 +960,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
label: "Lagerplätze",
|
label: "Lagerplätze",
|
||||||
labelSingle: "Lagerplatz",
|
labelSingle: "Lagerplatz",
|
||||||
isStandardEntity: true,
|
isStandardEntity: true,
|
||||||
supabaseSelectWithInformation: "*, documents(*)",
|
supabaseSelectWithInformation: "*, files(*)",
|
||||||
supabaseSortColumn: "spaceNumber",
|
supabaseSortColumn: "spaceNumber",
|
||||||
redirect: true,
|
redirect: true,
|
||||||
numberRangeHolder: "spaceNumber",
|
numberRangeHolder: "spaceNumber",
|
||||||
@@ -943,7 +989,14 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
key: "type",
|
key: "type",
|
||||||
label: "Typ",
|
label: "Typ",
|
||||||
inputType: "select",
|
inputType: "select",
|
||||||
selectManualOptions: ["Standort","Regalplatz", "Kiste", "Palettenplatz", "Sonstiges"],
|
selectValueAttribute: "label",
|
||||||
|
selectManualOptions: [
|
||||||
|
{label:"Standort"},
|
||||||
|
{label:"Regalplatz"},
|
||||||
|
{label:"Kiste"},
|
||||||
|
{label:"Palettenplatz"},
|
||||||
|
{label:"Sonstiges"}
|
||||||
|
],
|
||||||
inputColumn: "Allgemeines"
|
inputColumn: "Allgemeines"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1013,7 +1066,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
{
|
{
|
||||||
label: 'Informationen',
|
label: 'Informationen',
|
||||||
}, {
|
}, {
|
||||||
label: 'Dokumente',
|
label: 'Dateien',
|
||||||
},{label: 'Inventarartikel'}
|
},{label: 'Inventarartikel'}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -1034,7 +1087,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
label: "Inventarartikel",
|
label: "Inventarartikel",
|
||||||
labelSingle: "Inventarartikel",
|
labelSingle: "Inventarartikel",
|
||||||
isStandardEntity: true,
|
isStandardEntity: true,
|
||||||
supabaseSelectWithInformation: "*, documents(*), vendor(id,name), currentSpace(id,name)",
|
supabaseSelectWithInformation: "*, files(*), vendor(id,name), currentSpace(id,name)",
|
||||||
redirect: true,
|
redirect: true,
|
||||||
numberRangeHolder: "articleNumber",
|
numberRangeHolder: "articleNumber",
|
||||||
inputColumns: [
|
inputColumns: [
|
||||||
@@ -1151,7 +1204,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
{
|
{
|
||||||
label: 'Informationen',
|
label: 'Informationen',
|
||||||
}, {
|
}, {
|
||||||
label: 'Dokumente',
|
label: 'Dateien',
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -1405,7 +1458,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
label: "Überprüfungen",
|
label: "Überprüfungen",
|
||||||
labelSingle: "Überprüfung",
|
labelSingle: "Überprüfung",
|
||||||
isStandardEntity: true,
|
isStandardEntity: true,
|
||||||
supabaseSelectWithInformation: "*, vehicle(id,licensePlate), profile(id, fullName), inventoryitem(name), documents(*)",
|
supabaseSelectWithInformation: "*, vehicle(id,licensePlate), profile(id, fullName), inventoryitem(name), files(*)",
|
||||||
redirect: true,
|
redirect: true,
|
||||||
historyItemHolder: "check",
|
historyItemHolder: "check",
|
||||||
filters: [],
|
filters: [],
|
||||||
@@ -1451,7 +1504,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
showTabs: [
|
showTabs: [
|
||||||
{
|
{
|
||||||
label: 'Informationen',
|
label: 'Informationen',
|
||||||
}, {label: 'Dokumente'}, {label: 'Ausführungen'}]
|
}, {label: 'Dateien'}, {label: 'Ausführungen'}]
|
||||||
},
|
},
|
||||||
roles: {
|
roles: {
|
||||||
label: "Rollen",
|
label: "Rollen",
|
||||||
@@ -2060,44 +2113,60 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uploadFiles = async (formData, files, upsert) => {
|
const uploadFiles = async (formData, files, upsert) => {
|
||||||
//console.log(files)
|
|
||||||
//console.log(formData)
|
|
||||||
let documentsToInsert = []
|
|
||||||
|
|
||||||
const uploadSingleFile = async (file) => {
|
const uploadSingleFile = async (file) => {
|
||||||
|
|
||||||
const {data, error} = await supabase
|
const {data:createdFileData,error:createdFileError} = await supabase
|
||||||
.storage
|
|
||||||
.from("files")
|
.from("files")
|
||||||
.upload(`${profileStore.currentTenant}/${file.name}`, file, {upsert: upsert})
|
.insert({
|
||||||
|
tenant: profileStore.currentTenant,
|
||||||
|
})
|
||||||
|
.select()
|
||||||
|
.single()
|
||||||
|
|
||||||
if (error) {
|
if(createdFileError){
|
||||||
console.log(error)
|
console.log(createdFileError)
|
||||||
console.log(error.statusCode)
|
toast.add({title: "Hochladen fehlgeschlagen", icon: "i-heroicons-x-circle", color: "rose", timeout: 10000})
|
||||||
|
} else if(createdFileData) {
|
||||||
|
console.log(createdFileData)
|
||||||
|
const {data:uploadData, error: uploadError} = await supabase
|
||||||
|
.storage
|
||||||
|
.from("filesdev")
|
||||||
|
.upload(`${profileStore.currentTenant}/filesbyid/${createdFileData.id}/${file.name}`, file, {upsert: upsert})
|
||||||
|
|
||||||
if(error.statusCode === '400') {
|
if(uploadError) {
|
||||||
console.log("is 400")
|
console.log(uploadError)
|
||||||
toast.add({title: "Hochladen fehlgeschlagen", description: "Die Datei enthält ungültige Zeichen", icon: "i-heroicons-x-circle", color: "rose", timeout: 10000})
|
console.log(uploadError.statusCode)
|
||||||
} else if(error.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})
|
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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 {
|
||||||
|
toast.add({title: "Hochladen erfolgreich"})
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (data) {
|
|
||||||
const returnPath = data.path
|
|
||||||
|
|
||||||
documentsToInsert.push({...formData, path: returnPath, tenant: profileStore.currentTenant})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log(data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//uploadInProgress.value = true
|
|
||||||
|
|
||||||
|
|
||||||
if(files.length === 1) {
|
if(files.length === 1) {
|
||||||
await uploadSingleFile(files[0])
|
await uploadSingleFile(files[0])
|
||||||
} else if( files.length > 1) {
|
} else if( files.length > 1) {
|
||||||
@@ -2107,25 +2176,6 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log(documentsToInsert)
|
|
||||||
|
|
||||||
const {data, error} = await supabase
|
|
||||||
.from("documents")
|
|
||||||
.insert(documentsToInsert)
|
|
||||||
.select()
|
|
||||||
if(error) console.log(error)
|
|
||||||
else {
|
|
||||||
//console.log(data)
|
|
||||||
|
|
||||||
await fetchDocuments()
|
|
||||||
|
|
||||||
//documents.value.push(...data)
|
|
||||||
}
|
|
||||||
//uploadModalOpen.value = false;
|
|
||||||
//uploadInProgress.value = false;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchBankAccounts () {
|
async function fetchBankAccounts () {
|
||||||
@@ -2177,7 +2227,7 @@ export const useDataStore = defineStore('data', () => {
|
|||||||
vehicles.value = (await supabase.from("vehicles").select().eq('tenant', profileStore.currentTenant)).data
|
vehicles.value = (await supabase.from("vehicles").select().eq('tenant', profileStore.currentTenant)).data
|
||||||
}
|
}
|
||||||
async function fetchTimes () {
|
async function fetchTimes () {
|
||||||
times.value = (await supabase.from("times").select().eq('tenant', profileStore.currentTenant).order("start", {ascending:false})).data
|
times.value = (await supabase.from("times").select().eq('tenant', profileStore.currentTenant).order("startDate", {ascending:false})).data
|
||||||
}
|
}
|
||||||
async function fetchHistoryItems () {
|
async function fetchHistoryItems () {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user