Changed Backend to Supabase
This commit is contained in:
59
docker-compose.yml
Normal file
59
docker-compose.yml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
version: "3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: registry.gitlab.com/cmykmedia/spaces:main-WEB
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
environment:
|
||||||
|
STRAPI_URL: "http://federspiel-tech.spaces.software:1337"
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.docker.network=traefik"
|
||||||
|
- "traefik.port=3000"
|
||||||
|
# Middlewares
|
||||||
|
- "traefik.http.middlewares.spaces-frontend-redirect-web-secure.redirectscheme.scheme=https"
|
||||||
|
# Web Entrypoint
|
||||||
|
- "traefik.http.routers.spaces-frontend.middlewares=spaces-frontend-redirect-web-secure"
|
||||||
|
- "traefik.http.routers.spaces-frontend.rule=Host(`ft.spaces.software`)"
|
||||||
|
- "traefik.http.routers.spaces-frontend.entrypoints=web"
|
||||||
|
# Web Secure Entrypoint
|
||||||
|
- "traefik.http.routers.spaces-frontend-secure.rule=Host(`ft.spaces.software`)"
|
||||||
|
- "traefik.http.routers.spaces-frontend-secure.entrypoints=web-secured" #
|
||||||
|
- "traefik.http.routers.spaces-frontend-secure.tls.certresolver=mytlschallenge"
|
||||||
|
|
||||||
|
# backend:
|
||||||
|
# image: registry.gitlab.com/cmykmedia/manordsonne:master-BACKEND
|
||||||
|
# restart: always
|
||||||
|
# networks:
|
||||||
|
# - traefik
|
||||||
|
# expose:
|
||||||
|
# - 8080
|
||||||
|
# environment:
|
||||||
|
# COMPANY_RECIPIENT: "info@ma-nordsonne.de"
|
||||||
|
# REQUEST_PORT: 8080
|
||||||
|
# SMTP_USER: "info@ma-nordsonne.de"
|
||||||
|
# SMTP_HOST: "stmp.strato.de"
|
||||||
|
# SMTP_PASSWORD: "nM.-XiPM9rJd4y_Qk4*sTAeBr.GdVkAJxuUkzH2gugEU@BfsaYf-mf4ith6b7khXXFD29ZfmmRZfR@TTtb*WXKHYGLbBE3ubc7@4"
|
||||||
|
# SMTP_PORT: 465
|
||||||
|
# SMTP_SSL: "false"
|
||||||
|
# labels:
|
||||||
|
# - "traefik.enable=true"
|
||||||
|
# - "traefik.docker.network=traefik"
|
||||||
|
# - "traefik.port=8080"
|
||||||
|
# # Middlewares
|
||||||
|
# - "traefik.http.middlewares.manordsonne-backend-redirect-web-secure.redirectscheme.scheme=https"
|
||||||
|
# ###
|
||||||
|
# - "traefik.http.routers.manordsonne-backend.middlewares=manordsonne-backend-redirect-web-secure"
|
||||||
|
# - "traefik.http.routers.manordsonne-backend.rule=Host(`backend.ma-nordsonne.de`)"
|
||||||
|
# - "traefik.http.routers.manordsonne-backend.entrypoints=web"
|
||||||
|
# ####
|
||||||
|
# - "traefik.http.routers.manordsonne-backend-secure.rule=Host(`backend.ma-nordsonne.de`)"
|
||||||
|
# - "traefik.http.routers.manordsonne-backend-secure.entrypoints=web-secured"
|
||||||
|
# - "traefik.http.routers.manordsonne-backend-secure.tls.certresolver=mytlschallenge"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
external: true
|
||||||
|
|
||||||
2
docu
2
docu
@@ -8,6 +8,8 @@ Hetzner PW: iV5HTgj4Xt
|
|||||||
|
|
||||||
DO PW: 3Rtp39VFEr
|
DO PW: 3Rtp39VFEr
|
||||||
|
|
||||||
|
Supabase PW: MuP74MreBSMuP74MreBS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Banking Test:
|
Banking Test:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM node:17-alpine
|
FROM node:18-alpine
|
||||||
|
|
||||||
RUN mkdir -p /usr/src/nuxt-app
|
RUN mkdir -p /usr/src/nuxt-app
|
||||||
WORKDIR /usr/src/nuxt-app
|
WORKDIR /usr/src/nuxt-app
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
<script setup lang="ts">
|
<script setup>
|
||||||
const user = useStrapiUser()
|
const user = useSupabaseUser()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const {logout} = useStrapiAuth()
|
const supabase = useSupabaseClient()
|
||||||
|
const tenants = (await supabase.from("tenants").select()).data
|
||||||
|
|
||||||
|
|
||||||
|
const userTenant = ref({})
|
||||||
|
if(user) userTenant.value = tenants.find(tenant => tenant.id === user.value.app_metadata.tenant)
|
||||||
const userDropdownItems = [
|
const userDropdownItems = [
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
label: user.value ? user.value.username : "Profil",
|
label: user.value ? user.value.email : "Profil",
|
||||||
|
|
||||||
|
},{
|
||||||
|
label: userTenant.value.id ? userTenant.value.name : "",
|
||||||
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -14,7 +21,7 @@ const userDropdownItems = [
|
|||||||
{
|
{
|
||||||
label: "Logout",
|
label: "Logout",
|
||||||
click: () => {
|
click: () => {
|
||||||
logout()
|
|
||||||
router.push("/login")
|
router.push("/login")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
export default defineNuxtRouteMiddleware((to, _from) => {
|
export default defineNuxtRouteMiddleware((to, _from) => {
|
||||||
const user = useStrapiUser()
|
const user = useSupabaseUser()
|
||||||
|
const router = useRouter()
|
||||||
if (!user.value) {
|
if (!user.value) {
|
||||||
useCookie('redirect', { path: '/' }).value = to.fullPath
|
//useCookie('redirect', { path: '/' }).value = to.fullPath
|
||||||
return navigateTo('/login')
|
return router.push("/login")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -4,13 +4,13 @@ export default defineNuxtConfig({
|
|||||||
modules: [
|
modules: [
|
||||||
'@pinia/nuxt',
|
'@pinia/nuxt',
|
||||||
'@nuxt/ui',
|
'@nuxt/ui',
|
||||||
'@nuxtjs/strapi'
|
'@nuxtjs/strapi',
|
||||||
|
'@nuxtjs/supabase'
|
||||||
],
|
],
|
||||||
routeRules: {
|
routeRules: {
|
||||||
'/printing': {ssr:false}
|
'/printing': {ssr:false}
|
||||||
|
|
||||||
}
|
}
|
||||||
//Test
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
943
spaces/package-lock.json
generated
943
spaces/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/devtools": "latest",
|
"@nuxt/devtools": "latest",
|
||||||
|
"@nuxtjs/supabase": "^1.1.4",
|
||||||
"nuxt": "^3.8.0",
|
"nuxt": "^3.8.0",
|
||||||
"vue": "^3.3.7",
|
"vue": "^3.3.7",
|
||||||
"vue-router": "^4.2.5"
|
"vue-router": "^4.2.5"
|
||||||
@@ -22,7 +23,8 @@
|
|||||||
"@pinia/nuxt": "^0.5.1",
|
"@pinia/nuxt": "^0.5.1",
|
||||||
"@tato30/vue-pdf": "^1.8.1",
|
"@tato30/vue-pdf": "^1.8.1",
|
||||||
"@vicons/ionicons5": "^0.12.0",
|
"@vicons/ionicons5": "^0.12.0",
|
||||||
"axios": "^1.6.0",
|
"axios": "^1.6.2",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
"jsprintmanager": "^6.0.3",
|
"jsprintmanager": "^6.0.3",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"uuidv4": "^6.2.13",
|
"uuidv4": "^6.2.13",
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
<a v-for="item in customers" @click="selectItem(item)">
|
<a v-for="item in customers" @click="selectItem(item)">
|
||||||
<UCard class="listItem">
|
<UCard class="listItem">
|
||||||
<UBadge>{{item.attributes.customerNumber}}</UBadge> {{item.attributes.name}}
|
<UBadge>{{item.customerNumber}}</UBadge> {{item.name}}
|
||||||
</UCard>
|
</UCard>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -39,19 +39,19 @@
|
|||||||
|
|
||||||
<UCard v-if="selectedItem.id">
|
<UCard v-if="selectedItem.id">
|
||||||
<template #header>
|
<template #header>
|
||||||
<UBadge>{{selectedItem.attributes.customerNumber}}</UBadge> {{selectedItem.attributes.name}}
|
<UBadge>{{selectedItem.customerNumber}}</UBadge> {{selectedItem.name}}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
Kontakte:<br>
|
Kontakte:<br>
|
||||||
<ul>
|
<!-- <ul>
|
||||||
<li v-for="contact in selectedItem.attributes.contacts.data">{{contact.attributes.lastName}}, {{contact.attributes.firstName}}</li>
|
<li v-for="contact in selectedItem.contacts.data">{{contact.lastName}}, {{contact.firstName}}</li>
|
||||||
</ul>
|
</ul>-->
|
||||||
<!-- {{selectedItem.attributes.contacts.data}}-->
|
<!-- {{selectedItem.contacts.data}}-->
|
||||||
<br>
|
<br>
|
||||||
Projekte:<br>
|
Projekte:<br>
|
||||||
<ul>
|
<!-- <ul>
|
||||||
<li v-for="project in selectedItem.attributes.projects.data"><router-link :to="'/projects?id=' + project.id">{{project.attributes.name}}</router-link></li>
|
<li v-for="project in selectedItem.projects.data"><router-link :to="'/projects?id=' + project.id">{{project.name}}</router-link></li>
|
||||||
</ul>
|
</ul>-->
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
@@ -68,8 +68,13 @@ definePageMeta({
|
|||||||
middleware: "auth"
|
middleware: "auth"
|
||||||
})
|
})
|
||||||
|
|
||||||
const {find,create} = useStrapi4()
|
const supabase = useSupabaseClient()
|
||||||
const customers = (await find('customers',{populate: "*"})).data
|
|
||||||
|
//const {find,create} = useStrapi4()
|
||||||
|
//const customers = (await find('customers',{populate: "*"})).data
|
||||||
|
|
||||||
|
const customers = (await supabase.from("customers").select()).data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let showCreateCustomer = ref(false)
|
let showCreateCustomer = ref(false)
|
||||||
@@ -86,8 +91,15 @@ const selectItem = (item) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const createCustomer = async () => {
|
const createCustomer = async () => {
|
||||||
await create('customers', customerInfo.value)
|
//await create('customers', customerInfo.value)
|
||||||
console.log("Create")
|
const {data,error} = await supabase
|
||||||
|
.from("customers")
|
||||||
|
.insert([customerInfo.value])
|
||||||
|
.select()
|
||||||
|
|
||||||
|
console.log(error)
|
||||||
|
|
||||||
|
|
||||||
customerInfo.value = {}
|
customerInfo.value = {}
|
||||||
showCreateCustomer.value = false
|
showCreateCustomer.value = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,14 @@
|
|||||||
id="fileUploadInput"
|
id="fileUploadInput"
|
||||||
/>
|
/>
|
||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
<UFormGroup
|
<!-- <UFormGroup
|
||||||
label="Name:"
|
label="Name:"
|
||||||
class="mt-3"
|
class="mt-3"
|
||||||
>
|
>
|
||||||
<UInput
|
<UInput
|
||||||
v-model="fileUploadFormData.name"
|
v-model="fileUploadFormData.name"
|
||||||
/>
|
/>
|
||||||
</UFormGroup>
|
</UFormGroup>-->
|
||||||
<UFormGroup
|
<UFormGroup
|
||||||
label="Tags:"
|
label="Tags:"
|
||||||
class="mt-3"
|
class="mt-3"
|
||||||
@@ -39,6 +39,17 @@
|
|||||||
v-model="fileUploadFormData.tags"
|
v-model="fileUploadFormData.tags"
|
||||||
/>
|
/>
|
||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
|
<UFormGroup
|
||||||
|
label="Ordner:"
|
||||||
|
class="mt-3"
|
||||||
|
>
|
||||||
|
<USelectMenu
|
||||||
|
:options="folders"
|
||||||
|
v-model="fileUploadFormData.folder"
|
||||||
|
value-attribute="label"
|
||||||
|
|
||||||
|
/>
|
||||||
|
</UFormGroup>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<UButton
|
<UButton
|
||||||
@@ -51,21 +62,18 @@
|
|||||||
</UCard>
|
</UCard>
|
||||||
|
|
||||||
</UModal>
|
</UModal>
|
||||||
<!-- <USelectMenu :options="sortOptions"/>-->
|
|
||||||
</div>
|
</div>
|
||||||
<div class="documentList">
|
<div >
|
||||||
<USlideover
|
<USlideover
|
||||||
v-model="showDocumentModal"
|
v-model="showDocumentModal"
|
||||||
fullscreen
|
fullscreen
|
||||||
>
|
>
|
||||||
<UCard>
|
<UCard>
|
||||||
<template #header>
|
|
||||||
{{selectedDocument.attributes.name}}
|
|
||||||
</template>
|
|
||||||
<!-- <a
|
<!-- <a
|
||||||
v-if="selectedDocument.attributes"
|
v-if="selectedDocument"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
:href="`http://localhost:1337${selectedDocument.attributes.file.data.attributes.url}`"
|
:href="`http://localhost:1337${selectedDocument.file.data.url}`"
|
||||||
class="p-2"
|
class="p-2"
|
||||||
>
|
>
|
||||||
Anzeigen
|
Anzeigen
|
||||||
@@ -73,17 +81,24 @@
|
|||||||
|
|
||||||
</a>-->
|
</a>-->
|
||||||
|
|
||||||
<UFormGroup
|
{{selectedDocument}}
|
||||||
|
|
||||||
|
<embed
|
||||||
|
:src="pdfSource"
|
||||||
|
>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- <UFormGroup
|
||||||
label="Tags:"
|
label="Tags:"
|
||||||
>
|
>
|
||||||
<USelectMenu
|
<USelectMenu
|
||||||
v-if="selectedDocument.attributes"
|
v-if="selectedDocument"
|
||||||
multiple
|
multiple
|
||||||
searchable
|
searchable
|
||||||
searchable-placeholder="Suchen..."
|
searchable-placeholder="Suchen..."
|
||||||
:options="tags"
|
:options="tags"
|
||||||
v-on:change="update('documents',selectedDocument.id, {tags: selectedDocument.attributes.tags})"
|
v-on:change="update('documents',selectedDocument.id, {tags: selectedDocument.tags})"
|
||||||
v-model="selectedDocument.attributes.tags"
|
v-model="selectedDocument.tags"
|
||||||
/>
|
/>
|
||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
|
|
||||||
@@ -93,10 +108,10 @@
|
|||||||
>
|
>
|
||||||
<USelectMenu
|
<USelectMenu
|
||||||
:options="states"
|
:options="states"
|
||||||
v-model="selectedDocument.attributes.state"
|
v-model="selectedDocument.state"
|
||||||
v-on:change="update('documents',selectedDocument.id,{state: selectedDocument.attributes.state})"
|
v-on:change="update('documents',selectedDocument.id,{state: selectedDocument.state})"
|
||||||
/>
|
/>
|
||||||
</UFormGroup>
|
</UFormGroup>-->
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<VuePDF
|
<VuePDF
|
||||||
@@ -118,55 +133,55 @@
|
|||||||
|
|
||||||
</UCard>
|
</UCard>
|
||||||
</USlideover>
|
</USlideover>
|
||||||
<a
|
|
||||||
v-for="document in documents.filter(doc => doc.attributes.state != 'Archiviert')" class="documentListItem"
|
<UTabs
|
||||||
@click="openDocument(document)"
|
:items="folders"
|
||||||
|
orientation="vertical"
|
||||||
|
v-model="tabOpen"
|
||||||
|
:ui="{ wrapper: 'flex items-top gap-4', list: { width: 'w-72', padding: 'p-3' } }"
|
||||||
>
|
>
|
||||||
<div>
|
<template #item="{item}">
|
||||||
{{document.attributes.name}}<br>
|
<div class="documentList">
|
||||||
<UBadge
|
<div
|
||||||
v-for="tag in document.attributes.tags"
|
v-if="documentsComposed.filter(doc => doc.folder === item.label).length > 0"
|
||||||
|
v-for="document in documentsComposed.filter(doc => doc.folder === item.label)"
|
||||||
|
class="documentListItem"
|
||||||
|
>
|
||||||
|
<embed
|
||||||
|
:src="document.url"
|
||||||
|
class="previewEmbed"
|
||||||
|
/>
|
||||||
|
<UButton
|
||||||
|
@click="openDocument(document)"
|
||||||
|
class="mt-3"
|
||||||
|
>
|
||||||
|
<UIcon name="i-heroicons-eye-solid" />
|
||||||
|
</UButton>
|
||||||
|
|
||||||
|
<!-- {{document.name}}<br>-->
|
||||||
|
<!-- <UBadge
|
||||||
|
v-for="tag in document.tags"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
color="primary"
|
color="primary"
|
||||||
>{{tag}}</UBadge>
|
>{{tag}}</UBadge>
|
||||||
<UBadge
|
<UBadge
|
||||||
color="rose"
|
color="rose"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
>{{document.attributes.state}}</UBadge>
|
>{{document.state}}</UBadge>-->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</a>
|
<div v-else>
|
||||||
|
<p>Keine Dokumente in diesem Ordner</p>
|
||||||
|
<UButton
|
||||||
|
@click="uploadModalOpen = true"
|
||||||
|
>
|
||||||
|
Hochladen
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</UTabs>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- <div class="documentPreview" v-if="selectedDocument.attributes">
|
|
||||||
<UFormGroup
|
|
||||||
label="Tags:"
|
|
||||||
>
|
|
||||||
<USelectMenu
|
|
||||||
v-if="selectedDocument.attributes"
|
|
||||||
multiple
|
|
||||||
searchable
|
|
||||||
searchable-placeholder="Suchen..."
|
|
||||||
:options="tags"
|
|
||||||
v-on:change="update('documents',selectedDocument.id, {tags: selectedDocument.attributes.tags})"
|
|
||||||
v-model="selectedDocument.attributes.tags"
|
|
||||||
/>
|
|
||||||
</UFormGroup>
|
|
||||||
|
|
||||||
<UFormGroup
|
|
||||||
label="Status:"
|
|
||||||
>
|
|
||||||
<USelectMenu
|
|
||||||
:options="states"
|
|
||||||
v-model="selectedDocument.attributes.state"
|
|
||||||
v-on:change="update('documents',selectedDocument.id,{state: selectedDocument.attributes.state})"
|
|
||||||
/>
|
|
||||||
</UFormGroup>
|
|
||||||
<h4 v-if="selectedDocument.attributes">{{selectedDocument.attributes.name}}</h4>
|
|
||||||
<!– <embed src="http://localhost:1337/uploads/RE_1748755_cb0b16cd30.pdf">–>
|
|
||||||
{{selectedDocument}}
|
|
||||||
|
|
||||||
</div>-->
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
@@ -175,96 +190,114 @@
|
|||||||
definePageMeta({
|
definePageMeta({
|
||||||
middleware: "auth"
|
middleware: "auth"
|
||||||
})
|
})
|
||||||
|
const supabase = useSupabaseClient()
|
||||||
|
const user = useSupabaseUser()
|
||||||
|
|
||||||
const sortOptions = ['Hinzugefügt',"Bearbeitet","Name"]
|
const documents = (await supabase.from("documents").select()).data
|
||||||
|
|
||||||
const {find,create, update} = useStrapi4()
|
const documentsComposed = ref([])
|
||||||
const client = useStrapiClient()
|
async function composeDocs () {
|
||||||
const strapiMediaUrl = useStrapiMedia()
|
for(const doc of documents){
|
||||||
const documents = (await find('documents',{populate: "*"})).data
|
let fileurl = (await supabase.storage.from('documents').createSignedUrl(doc.path,60*60)).data.signedUrl
|
||||||
|
|
||||||
import { VuePDF, usePDF } from '@tato30/vue-pdf'
|
documentsComposed.value.push({...doc, url: fileurl})
|
||||||
|
|
||||||
const page = ref(1)
|
}
|
||||||
const vuePDFRef = ref(null)
|
}
|
||||||
const pdfSource = ref("https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf")
|
|
||||||
const { pdf, pages } = usePDF(pdfSource)
|
|
||||||
|
|
||||||
|
await composeDocs()
|
||||||
|
|
||||||
|
const tabOpen = ref(0)
|
||||||
const uploadModalOpen = ref(false)
|
const uploadModalOpen = ref(false)
|
||||||
let fileUploadData = null
|
|
||||||
const fileUploadFormData = ref({
|
const fileUploadFormData = ref({
|
||||||
name: "",
|
name: "",
|
||||||
tags: ["Dokument"]
|
tags: [],
|
||||||
|
folder: "",
|
||||||
|
object: "",
|
||||||
|
path: ""
|
||||||
})
|
})
|
||||||
|
|
||||||
let tags = ["Eingangsrechnung","Ausgangrechnung","Mahnung", "Dokument"]
|
let tags = ["Eingangsrechnung","Ausgangrechnung","Mahnung", "Dokument"]
|
||||||
let states = ["Eingang", "Zugeordnet", "Archiviert"]
|
const folders = [
|
||||||
|
{
|
||||||
const uploadFile = async () => {
|
label: "Eingang",
|
||||||
try {
|
},
|
||||||
|
{
|
||||||
fileUploadData = document.getElementById("fileUploadInput").files[0]
|
label: "Eingangsrechnungen"
|
||||||
|
},
|
||||||
let formData = new FormData()
|
{
|
||||||
formData.append('files.file', fileUploadData)
|
label: "Ausgangsrechnungen"
|
||||||
|
},
|
||||||
formData.append('data', JSON.stringify(fileUploadFormData.value))
|
{
|
||||||
|
label: "Fahrzeuge"
|
||||||
const {data} = await client("/documents", {
|
},
|
||||||
method: "POST",
|
{
|
||||||
body: formData
|
label: "Dokumente"
|
||||||
})
|
},
|
||||||
|
{
|
||||||
|
label: "Archiv"
|
||||||
}
|
}
|
||||||
catch (error) { alert(error)}
|
]
|
||||||
|
const uploadFile = async () => {
|
||||||
|
const file = document.getElementById("fileUploadInput").files[0]
|
||||||
|
|
||||||
|
const {data,error} = await supabase
|
||||||
|
.storage
|
||||||
|
.from("documents")
|
||||||
|
.upload(`${user.value.app_metadata.tenant}/${fileUploadFormData.value.folder}/${file.name}`,file)
|
||||||
|
|
||||||
|
const returnPath = data.path
|
||||||
|
|
||||||
|
if(error) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.log(returnPath)
|
||||||
|
const files = (await supabase.storage.from('documents').list(`${user.value.app_metadata.tenant}/${fileUploadFormData.value.folder}/`, {limit: 100, offset: 0, sortBy: { column: 'name', order: 'asc' }})).data
|
||||||
|
console.log(files)
|
||||||
|
const fileId = files.find(temp => returnPath.includes(temp.name)).id
|
||||||
|
|
||||||
|
fileUploadFormData.value.object = fileId
|
||||||
|
fileUploadFormData.value.path = returnPath
|
||||||
|
console.log(fileUploadFormData.value)
|
||||||
|
|
||||||
|
const {data,error} = await supabase
|
||||||
|
.from("documents")
|
||||||
|
.insert([fileUploadFormData.value])
|
||||||
|
.select()
|
||||||
|
console.log(data)
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
|
||||||
uploadModalOpen.value = false;
|
uploadModalOpen.value = false;
|
||||||
console.log("test")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateDocument = async () => {
|
const updateDocument = async () => {
|
||||||
await update('documents', selectedDocument.id, {tags: selectedDocument.attributes.tags, state: selectedDocument.attributes.state})
|
await update('documents', selectedDocument.id, {tags: selectedDocument.tags, state: selectedDocument.state})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const selectedDocument = ref({})
|
const selectedDocument = ref({})
|
||||||
const showDocumentModal = ref(false)
|
const showDocumentModal = ref(false)
|
||||||
const openDocument = (document) => {
|
|
||||||
|
const openDocument = async (document) => {
|
||||||
|
console.log("open")
|
||||||
selectedDocument.value = document
|
selectedDocument.value = document
|
||||||
pdfSource.value = `${strapiMediaUrl}${document.attributes.file.data.attributes.url}`
|
|
||||||
showDocumentModal.value = true
|
showDocumentModal.value = true
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#main {
|
|
||||||
|
|
||||||
padding:10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.controlHeader {
|
|
||||||
grid-area: headerleft;
|
|
||||||
}
|
|
||||||
|
|
||||||
.documentList {
|
.documentList {
|
||||||
grid-area: main;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
max-width: 80vw;
|
|
||||||
min-height: 75vh;
|
|
||||||
margin-right: 5vw;
|
|
||||||
margin-top: 1em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.documentListItem {
|
.documentListItem {
|
||||||
|
display:block;
|
||||||
width: 15vw;
|
width: 15vw;
|
||||||
height: 15vh;
|
height: 25vh;
|
||||||
margin-right: 1em;
|
|
||||||
padding:1em;
|
padding:1em;
|
||||||
|
margin: 0.7em;
|
||||||
border: 1px solid lightgrey;
|
border: 1px solid lightgrey;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
}
|
}
|
||||||
@@ -274,8 +307,15 @@ const openDocument = (document) => {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.documentPreview {
|
.previewEmbed {
|
||||||
grid-area: right;
|
width: 100%;
|
||||||
width: 30vw;
|
height: 18vh;
|
||||||
|
overflow: hidden;
|
||||||
|
-ms-overflow-style: none; /* IE and Edge */
|
||||||
|
scrollbar-width: none; /* Firefox */
|
||||||
|
}
|
||||||
|
|
||||||
|
.previewEmbed::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -6,9 +6,16 @@
|
|||||||
definePageMeta({
|
definePageMeta({
|
||||||
middleware: "auth"
|
middleware: "auth"
|
||||||
})
|
})
|
||||||
const {find} = useStrapi4()
|
|
||||||
const response = await find('customers')
|
|
||||||
console.log(response)
|
const supabase = useSupabaseClient()
|
||||||
|
|
||||||
|
const tasks = (await supabase.from("tasks").select()).data
|
||||||
|
|
||||||
|
const user = useSupabaseUser()
|
||||||
|
console.log(user)
|
||||||
|
|
||||||
|
console.log(tasks)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -3,10 +3,13 @@ definePageMeta({
|
|||||||
middleware: "auth"
|
middleware: "auth"
|
||||||
})
|
})
|
||||||
|
|
||||||
const {find,create} = useStrapi4()
|
const supabase = useSupabaseClient()
|
||||||
const spaces = (await find('spaces',{populate: "*"})).data
|
|
||||||
const products = (await find('products',{populate: "*"})).data
|
const spaces = (await supabase.from("spaces").select()).data
|
||||||
const movements = (await find('movements',{populate: "*"})).data
|
const movements = (await supabase.from("movements").select()).data
|
||||||
|
const products = (await supabase.from("products").select()).data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const searchinput = ref("")
|
const searchinput = ref("")
|
||||||
const mode = ref("")
|
const mode = ref("")
|
||||||
@@ -21,10 +24,26 @@ const inventoryChangeData = ref({
|
|||||||
|
|
||||||
const createMovement = async () => {
|
const createMovement = async () => {
|
||||||
if(mode.value === 'incoming'){
|
if(mode.value === 'incoming'){
|
||||||
await create('movements', inventoryChangeData.value)
|
//await create('movements', inventoryChangeData.value)
|
||||||
|
|
||||||
|
const {data,error} = await supabase
|
||||||
|
.from("movements")
|
||||||
|
.insert([inventoryChangeData.value])
|
||||||
|
.select()
|
||||||
|
|
||||||
|
console.log(error)
|
||||||
|
|
||||||
|
|
||||||
} else if (mode.value === 'outgoing'){
|
} else if (mode.value === 'outgoing'){
|
||||||
inventoryChangeData.value.quantity *= -1
|
inventoryChangeData.value.quantity *= -1
|
||||||
await create('movements', inventoryChangeData.value)
|
//await create('movements', inventoryChangeData.value)
|
||||||
|
|
||||||
|
const {data,error} = await supabase
|
||||||
|
.from("movements")
|
||||||
|
.insert([inventoryChangeData.value])
|
||||||
|
.select()
|
||||||
|
|
||||||
|
console.log(error)
|
||||||
} else if (mode.value === 'change'){}
|
} else if (mode.value === 'change'){}
|
||||||
|
|
||||||
inventoryChangeData.value = {
|
inventoryChangeData.value = {
|
||||||
@@ -39,7 +58,7 @@ function checkArticle(productId) {
|
|||||||
return products.filter(product => product.id === Number(productId)).length > 0;
|
return products.filter(product => product.id === Number(productId)).length > 0;
|
||||||
}
|
}
|
||||||
function checkSpaceId(spaceId) {
|
function checkSpaceId(spaceId) {
|
||||||
return spaces.filter(space => space.attributes.spaceNumber === spaceId).length > 0;
|
return spaces.filter(space => space.id === spaceId).length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@@ -75,12 +94,14 @@ function checkSpaceId(spaceId) {
|
|||||||
<UFormGroup
|
<UFormGroup
|
||||||
label="Lagerplatz:"
|
label="Lagerplatz:"
|
||||||
class="mt-3"
|
class="mt-3"
|
||||||
>
|
><!--.map(space => {return {id: space.id, name: space.spaceNumber}}-->
|
||||||
<UInput
|
<USelectMenu
|
||||||
variant="outline"
|
:options="spaces"
|
||||||
|
searchable
|
||||||
|
option-attribute="spaceNumber"
|
||||||
:color="checkSpaceId(inventoryChangeData.spaceId) ? 'primary' : 'rose'"
|
:color="checkSpaceId(inventoryChangeData.spaceId) ? 'primary' : 'rose'"
|
||||||
placeholder="Barcode / Suche"
|
|
||||||
v-model="inventoryChangeData.spaceId"
|
v-model="inventoryChangeData.spaceId"
|
||||||
|
value-attribute="id"
|
||||||
/>
|
/>
|
||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import {move} from "@antfu/utils";
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
middleware: "auth"
|
middleware: "auth"
|
||||||
})
|
})
|
||||||
|
|
||||||
const {find,create, update} = useStrapi4()
|
const supabase = useSupabaseClient()
|
||||||
const spaces = (await find('spaces',{populate: "*"})).data
|
|
||||||
const movements = (await find('movements',{populate: "*"})).data
|
const spaces = (await supabase.from("spaces").select()).data
|
||||||
const products = (await find('products',{populate: "*"})).data
|
const movements = (await supabase.from("movements").select()).data
|
||||||
|
const products = (await supabase.from("products").select()).data
|
||||||
|
const units = (await supabase.from("units").select()).data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let selectedItem = ref({})
|
let selectedItem = ref({})
|
||||||
@@ -14,9 +20,10 @@ const showCreateSpace = ref(false)
|
|||||||
|
|
||||||
const selectItem = (item) => {
|
const selectItem = (item) => {
|
||||||
selectedItem.value = item
|
selectedItem.value = item
|
||||||
spaceMovements.value = movements.filter(movement => movement.attributes.spaceId === selectedItem.value.attributes.spaceNumber)
|
spaceMovements.value = movements.filter(movement => movement.spaceId === selectedItem.value.id)
|
||||||
|
spaceProducts.value = []
|
||||||
spaceMovements.value.forEach(movement => {
|
spaceMovements.value.forEach(movement => {
|
||||||
if(!spaceProducts.value.includes(movement.attributes.productId)) spaceProducts.value.push(movement.attributes.productId)
|
if(spaceProducts.value.filter(product => product.id === movement.productId).length === 0) spaceProducts.value.push(products.find(product => product.id === movement.productId))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@@ -30,10 +37,16 @@ const createSpaceData = ref({})
|
|||||||
const createSpace = async () => {
|
const createSpace = async () => {
|
||||||
let lastSpaceNumber = 0
|
let lastSpaceNumber = 0
|
||||||
spaces.forEach(space => {
|
spaces.forEach(space => {
|
||||||
if(space.attributes.spaceNumber > lastSpaceNumber) lastSpaceNumber = space.attributes.spaceNumber
|
if(space.spaceNumber > lastSpaceNumber) lastSpaceNumber = space.spaceNumber
|
||||||
})
|
})
|
||||||
|
|
||||||
await create('spaces', {...createSpaceData.value, spaceNumber: String(Number(lastSpaceNumber)+1)})
|
const {data,error} = await supabase
|
||||||
|
.from("spaces")
|
||||||
|
.insert([ {...createSpaceData.value, spaceNumber: String(Number(lastSpaceNumber)+1)}])
|
||||||
|
.select()
|
||||||
|
|
||||||
|
console.log(error)
|
||||||
|
|
||||||
showCreateSpace.value = false
|
showCreateSpace.value = false
|
||||||
createSpaceData.value = {}
|
createSpaceData.value = {}
|
||||||
|
|
||||||
@@ -43,9 +56,9 @@ const spaceProducts = ref([])
|
|||||||
const spaceMovements = ref([])
|
const spaceMovements = ref([])
|
||||||
|
|
||||||
function getSpaceProductCount(productId) {
|
function getSpaceProductCount(productId) {
|
||||||
let productMovements = spaceMovements.value.filter(movement => movement.attributes.productId === productId)
|
let productMovements = spaceMovements.value.filter(movement => movement.productId === productId)
|
||||||
let count = 0;
|
let count = 0;
|
||||||
productMovements.forEach(movement => count += movement.attributes.quantity)
|
productMovements.forEach(movement => count += movement.quantity)
|
||||||
|
|
||||||
return count
|
return count
|
||||||
|
|
||||||
@@ -87,23 +100,25 @@ function getSpaceProductCount(productId) {
|
|||||||
</UModal>
|
</UModal>
|
||||||
<a v-for="item in spaces" @click="selectItem(item)">
|
<a v-for="item in spaces" @click="selectItem(item)">
|
||||||
<UCard class="listItem">
|
<UCard class="listItem">
|
||||||
{{item.attributes.spaceNumber}} - {{item.attributes.type}}
|
{{item.spaceNumber}} - {{item.type}}
|
||||||
</UCard>
|
</UCard>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div id="right">
|
<div id="right">
|
||||||
<UCard v-if="selectedItem.attributes">
|
<div v-if="selectedItem.id">
|
||||||
|
<UCard>
|
||||||
<template #header>
|
<template #header>
|
||||||
<UBadge class="mr-1">{{selectedItem.attributes.spaceNumber}}</UBadge>{{selectedItem.attributes.type}}
|
<UBadge class="mr-1">{{selectedItem.spaceNumber}}</UBadge>{{selectedItem.type}}
|
||||||
</template>
|
</template>
|
||||||
{{selectedItem.attributes.description}}
|
{{selectedItem.description}}
|
||||||
|
|
||||||
|
|
||||||
</UCard>
|
</UCard>
|
||||||
|
<div v-if="spaceProducts.length > 0">
|
||||||
|
|
||||||
<p class="mt-5">Artikel in diesem Lagerplatz</p>
|
<p class="mt-5">Artikel in diesem Lagerplatz</p>
|
||||||
<p v-for="product in spaceProducts">{{products.find(productItem => Number(productItem.id) === Number(product)).attributes.name}} - {{getSpaceProductCount(product)}} {{products.find(productItem => Number(productItem.id) === Number(product)).attributes.unit}}</p>
|
<p v-for="product in spaceProducts">{{product.name}} - {{getSpaceProductCount(product.id)}} {{units.find(unit => unit.id === product.unit).name}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,38 +1,35 @@
|
|||||||
<script setup >
|
<script setup >
|
||||||
|
const supabase = useSupabaseClient()
|
||||||
const { login } = useStrapiAuth()
|
const user = useSupabaseUser()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const username = ref("flfeders")
|
const email = ref("f.federspiel@federspiel.tech")
|
||||||
const password = ref("Open@all4me!")
|
const password = ref("Open@all4me!")
|
||||||
|
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const onSubmit = async () => {
|
||||||
try {
|
const { error } = await supabase.auth.signInWithPassword({
|
||||||
await login({identifier: username.value, password: password.value})
|
email: email.value,
|
||||||
console.log("Successfully Logged In")
|
password: password.value
|
||||||
router.push("/tasks")
|
})
|
||||||
|
if(error) {
|
||||||
} catch(e) {
|
console.log(error)
|
||||||
console.log(e)
|
} else {
|
||||||
|
console.log("Login Successful")
|
||||||
|
router.push("/")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = useStrapiUser()
|
|
||||||
console.log(user)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="loginSite">
|
<div id="loginSite">
|
||||||
<div id="loginForm">
|
<div id="loginForm">
|
||||||
<UFormGroup
|
<UFormGroup
|
||||||
label="Username:"
|
label="E-Mail:"
|
||||||
>
|
>
|
||||||
<UInput
|
<UInput
|
||||||
v-model="username"
|
v-model="email"
|
||||||
/>
|
/>
|
||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
<UFormGroup
|
<UFormGroup
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
<div class="listContainer">
|
<div class="listContainer">
|
||||||
<a v-for="item in products" @click="selectItem(item)">
|
<a v-for="item in products" @click="selectItem(item)">
|
||||||
<UCard class="listItem">
|
<UCard class="listItem">
|
||||||
<UBadge>{{item.id}}</UBadge> {{item.attributes.name}} - {{item.attributes.manufacturer}}
|
<UBadge>{{item.id}}</UBadge> {{item.name}} - {{item.manufacturer}}
|
||||||
</UCard>
|
</UCard>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -52,30 +52,30 @@
|
|||||||
<div id="right">
|
<div id="right">
|
||||||
<div v-if="false">
|
<div v-if="false">
|
||||||
<img
|
<img
|
||||||
v-if="selectedItem.attributes.image"
|
v-if="selectedItem.image"
|
||||||
:src="'http://localhost:1337' + selectedItem.attributes.image.data.attributes.url"/>
|
:src="'http://localhost:1337' + selectedItem.image.data.url"/>
|
||||||
{{selectedItem.attributes.image.data.attributes.url}}
|
{{selectedItem.image.data.url}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<UCard v-if="selectedItem.attributes">
|
<UCard v-if="selectedItem.id">
|
||||||
<template #header>
|
<template #header>
|
||||||
<UBadge>{{selectedItem.id}}</UBadge> {{selectedItem.attributes.name}}
|
<UBadge>{{selectedItem.id}}</UBadge> {{selectedItem.name}}
|
||||||
</template>
|
</template>
|
||||||
<!-- <UBadge
|
<UBadge
|
||||||
v-for="tag in selectedItem.tags"
|
v-for="tag in selectedItem.tags"
|
||||||
class="mr-2"
|
class="mr-2"
|
||||||
>
|
>
|
||||||
{{tag}}
|
{{tag}}
|
||||||
</UBadge>-->
|
</UBadge>
|
||||||
<UDivider class="my-3"/>
|
<UDivider class="my-3"/>
|
||||||
<div v-if="selectedItem.attributes">
|
<div v-if="selectedItem">
|
||||||
Hersteller: {{selectedItem.attributes.manufacturer}}<br>
|
Hersteller: {{selectedItem.manufacturer}}<br>
|
||||||
Einkaufspreis: {{selectedItem.attributes.purchasePriceNet.toFixed(2)}} €<br>
|
Einkaufspreis: {{selectedItem.purchasePriceNet}} €<br>
|
||||||
Aufschlag: {{selectedItem.attributes.profitPercentage}} %<br>
|
Aufschlag: {{selectedItem.profitPercentage}} %<br>
|
||||||
Verkaufspreis: {{selectedItem.attributes.retailPriceNet.toFixed(2)}} €<br>
|
Verkaufspreis: {{selectedItem.retailPriceNet}} €<br>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<UDivider class="my-3"/>
|
<!--<UDivider class="my-3"/>
|
||||||
<p>Verlauf:</p>
|
<p>Verlauf:</p>
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>-->
|
||||||
|
|
||||||
|
|
||||||
<!-- <div
|
<!-- <div
|
||||||
@@ -122,8 +122,11 @@ definePageMeta({
|
|||||||
middleware: "auth"
|
middleware: "auth"
|
||||||
})
|
})
|
||||||
|
|
||||||
const {find,create} = useStrapi4()
|
const supabase = useSupabaseClient()
|
||||||
const products = (await find('products',{populate: "*"})).data
|
|
||||||
|
|
||||||
|
|
||||||
|
const products = (await supabase.from("products").select()).data
|
||||||
|
|
||||||
const showCreateProduct = ref(false)
|
const showCreateProduct = ref(false)
|
||||||
const createProductData = ref({})
|
const createProductData = ref({})
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ const tabItems = [
|
|||||||
},{
|
},{
|
||||||
key: "forms",
|
key: "forms",
|
||||||
label: "Formulare"
|
label: "Formulare"
|
||||||
|
},{
|
||||||
|
key: "timetracking",
|
||||||
|
label: "Zeiterfassung"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
const selectedPhase = ref({})
|
const selectedPhase = ref({})
|
||||||
@@ -51,8 +54,11 @@ const addPhase = async (phaseBefore) => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="main">
|
<div>
|
||||||
<div id="left">
|
<UTabs :items="tabItems" class="w-full">
|
||||||
|
<template #item="{ item }">
|
||||||
|
<div v-if="item.key === 'phases'" class="space-y-3">
|
||||||
|
<div id="phaseList">
|
||||||
<a
|
<a
|
||||||
v-for="phase in project.attributes.phases"
|
v-for="phase in project.attributes.phases"
|
||||||
@click="selectedPhase = phase"
|
@click="selectedPhase = phase"
|
||||||
@@ -64,7 +70,31 @@ const addPhase = async (phaseBefore) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a class="plusIcon" @click="addPhase(phase)">
|
<a class="plusIcon" @click="addPhase(phase)">
|
||||||
<!-- <UIcon name="i-heroicons-plus-circle" />-->
|
|
||||||
|
<UDivider icon="i-heroicons-plus-circle"/>
|
||||||
|
</a>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div v-else-if="item.key === 'password'" class="space-y-3">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</UTabs>
|
||||||
|
<!-- <div id="left">
|
||||||
|
<a
|
||||||
|
v-for="phase in project.attributes.phases"
|
||||||
|
@click="selectedPhase = phase"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="phaseContainer"
|
||||||
|
>
|
||||||
|
<span>{{phase.name}} - {{phase.position}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a class="plusIcon" @click="addPhase(phase)">
|
||||||
|
<!– <UIcon name="i-heroicons-plus-circle" />–>
|
||||||
<UDivider icon="i-heroicons-plus-circle"/>
|
<UDivider icon="i-heroicons-plus-circle"/>
|
||||||
</a>
|
</a>
|
||||||
</a>
|
</a>
|
||||||
@@ -101,7 +131,7 @@ const addPhase = async (phaseBefore) => {
|
|||||||
</UButton>
|
</UButton>
|
||||||
|
|
||||||
{{selectedPhase}}
|
{{selectedPhase}}
|
||||||
</div>
|
</div>-->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -134,6 +164,17 @@ const addPhase = async (phaseBefore) => {
|
|||||||
.phaseContainer:hover {
|
.phaseContainer:hover {
|
||||||
border: 1px solid #69c350;
|
border: 1px solid #69c350;
|
||||||
}
|
}
|
||||||
|
#phaseList {
|
||||||
|
height: 70vh;
|
||||||
|
overflow: auto;
|
||||||
|
-ms-overflow-style: none; /* IE and Edge */
|
||||||
|
scrollbar-width: none; /* Firefox */
|
||||||
|
}
|
||||||
|
|
||||||
|
#phaseList::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.notesTextarea {
|
.notesTextarea {
|
||||||
margin-top: 1em
|
margin-top: 1em
|
||||||
|
|||||||
@@ -4,14 +4,51 @@
|
|||||||
|
|
||||||
<UButton @click="showCreateProject = true">+ Projekt</UButton>
|
<UButton @click="showCreateProject = true">+ Projekt</UButton>
|
||||||
<UModal v-model="showCreateProject">
|
<UModal v-model="showCreateProject">
|
||||||
<UCard :ui="{ ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
|
<UCard>
|
||||||
|
<template #header>
|
||||||
|
Projekt erstellen
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<UFormGroup
|
||||||
|
label="Name:"
|
||||||
|
>
|
||||||
|
<UInput
|
||||||
|
v-model="createProjectData.name"
|
||||||
|
/>
|
||||||
|
</UFormGroup>
|
||||||
|
<UFormGroup
|
||||||
|
label="Kunde:"
|
||||||
|
>
|
||||||
|
<USelectMenu
|
||||||
|
v-model="createProjectData.customer"
|
||||||
|
:options="customers"
|
||||||
|
option-attribute="name"
|
||||||
|
value-attribute="id"
|
||||||
|
searchable
|
||||||
|
:search-attributes="['name']"
|
||||||
|
/>
|
||||||
|
</UFormGroup>
|
||||||
|
<UFormGroup
|
||||||
|
label="Notizen:"
|
||||||
|
>
|
||||||
|
<UTextarea
|
||||||
|
v-model="createProjectData.notes"
|
||||||
|
/>
|
||||||
|
</UFormGroup>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<UButton
|
||||||
|
@click="createProject"
|
||||||
|
>
|
||||||
|
Erstellen
|
||||||
|
</UButton>
|
||||||
|
</template>
|
||||||
</UCard>
|
</UCard>
|
||||||
</UModal>
|
</UModal>
|
||||||
|
|
||||||
<router-link v-for="item in projects" :to="`/projects/${item.id}`">
|
<router-link v-for="item in projects" :to="`/projects/${item.id}`">
|
||||||
<UCard class="listItem">
|
<UCard class="listItem">
|
||||||
<UBadge>{{item.id}}</UBadge> {{item.attributes.name}}
|
<UBadge>{{item.id}}</UBadge> {{item.name}}
|
||||||
</UCard>
|
</UCard>
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
@@ -21,14 +58,14 @@
|
|||||||
{{selectedItem}}
|
{{selectedItem}}
|
||||||
<UCard v-if="selectedItem.id">
|
<UCard v-if="selectedItem.id">
|
||||||
<template #header>
|
<template #header>
|
||||||
<UBadge>{{selectedItem.id}}</UBadge> {{selectedItem.attributes.name}}
|
<UBadge>{{selectedItem.id}}</UBadge> {{selectedItem.name}}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
Kunde:<br>
|
Kunde:<br>
|
||||||
{{selectedItem.attributes.customer.data.attributes.name}}<br>
|
{{selectedItem.customer.data.name}}<br>
|
||||||
|
|
||||||
Notizen: <br>
|
Notizen: <br>
|
||||||
{{selectedItem.attributes.notes}}
|
{{selectedItem.notes}}
|
||||||
|
|
||||||
<!-- Lieferantenrechnungen: <br>
|
<!-- Lieferantenrechnungen: <br>
|
||||||
<UTable :rows="dataStore.getVendorInvoicesByProjectId(selectedItem.id)"></UTable>
|
<UTable :rows="dataStore.getVendorInvoicesByProjectId(selectedItem.id)"></UTable>
|
||||||
@@ -50,11 +87,15 @@ definePageMeta({
|
|||||||
middleware: "auth"
|
middleware: "auth"
|
||||||
})
|
})
|
||||||
|
|
||||||
const {find,create} = useStrapi4()
|
const supabase = useSupabaseClient()
|
||||||
const projects = (await find('projects',{populate: "*"})).data
|
|
||||||
|
const projects = (await supabase.from("projects").select()).data
|
||||||
|
const customers = (await supabase.from("customers").select()).data
|
||||||
|
|
||||||
const showCreateProject = ref(false)
|
const showCreateProject = ref(false)
|
||||||
const projectData = ref({})
|
const createProjectData = ref({
|
||||||
|
phases: []
|
||||||
|
})
|
||||||
|
|
||||||
let selectedItem = ref({})
|
let selectedItem = ref({})
|
||||||
|
|
||||||
@@ -63,6 +104,19 @@ const selectItem = (item) => {
|
|||||||
console.log(item)
|
console.log(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const createProject = async () => {
|
||||||
|
const {data,error} = await supabase
|
||||||
|
.from("projects")
|
||||||
|
.insert([createProjectData.value])
|
||||||
|
.select()
|
||||||
|
|
||||||
|
if(error) console.log(error)
|
||||||
|
|
||||||
|
showCreateProject.value = false
|
||||||
|
createProjectData.value = {phases: []}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -64,12 +64,12 @@
|
|||||||
>
|
>
|
||||||
<UCard>
|
<UCard>
|
||||||
<template #header>
|
<template #header>
|
||||||
{{taskData.attributes.name}}
|
{{taskData.name}}
|
||||||
</template>
|
</template>
|
||||||
<p>{{taskData.attributes.description}}</p>
|
<p>{{taskData.description}}</p>
|
||||||
<p>Erstellt am: {{taskData.attributes.createdAt}}</p>
|
<p>Erstellt am: {{taskData.created_at}}</p>
|
||||||
<UBadge
|
<UBadge
|
||||||
v-for="user in taskData.attributes.users"
|
v-for="user in taskData.users"
|
||||||
class="mr-2"
|
class="mr-2"
|
||||||
>
|
>
|
||||||
{{user}}
|
{{user}}
|
||||||
@@ -114,13 +114,13 @@
|
|||||||
<h3>Neue Aufgaben</h3>
|
<h3>Neue Aufgaben</h3>
|
||||||
<div class="taskScrollList">
|
<div class="taskScrollList">
|
||||||
<a
|
<a
|
||||||
v-for="taskNew in refTasks.filter(task => task.attributes.categorie == 'Neu')"
|
v-for="taskNew in tasks.filter(task => task.categorie == 'Neu')"
|
||||||
@click="inspectTask(taskNew)"
|
@click="inspectTask(taskNew)"
|
||||||
>
|
>
|
||||||
<UCard class="listItem">
|
<UCard class="listItem">
|
||||||
{{taskNew.attributes.name}}
|
{{taskNew.name}}
|
||||||
<UBadge
|
<UBadge
|
||||||
v-for="user in taskNew.attributes.users"
|
v-for="user in taskNew.users"
|
||||||
class="mr-2"
|
class="mr-2"
|
||||||
>
|
>
|
||||||
{{user}}
|
{{user}}
|
||||||
@@ -136,13 +136,13 @@
|
|||||||
<h3>Aufgaben in Bearbeitung</h3>
|
<h3>Aufgaben in Bearbeitung</h3>
|
||||||
<div class="taskScrollList">
|
<div class="taskScrollList">
|
||||||
<a
|
<a
|
||||||
v-for="taskNew in refTasks.filter(task => task.attributes.categorie == 'In Bearbeitung')"
|
v-for="taskNew in tasks.filter(task => task.categorie == 'In Bearbeitung')"
|
||||||
@click="inspectTask(taskNew)"
|
@click="inspectTask(taskNew)"
|
||||||
>
|
>
|
||||||
<UCard class="listItem">
|
<UCard class="listItem">
|
||||||
{{taskNew.attributes.name}}
|
{{taskNew.name}}
|
||||||
<UBadge
|
<UBadge
|
||||||
v-for="user in taskNew.attributes.users"
|
v-for="user in taskNew.users"
|
||||||
class="mr-2"
|
class="mr-2"
|
||||||
>
|
>
|
||||||
{{user}}
|
{{user}}
|
||||||
@@ -156,13 +156,13 @@
|
|||||||
<h3>Dringende Aufgaben</h3>
|
<h3>Dringende Aufgaben</h3>
|
||||||
<div class="taskScrollList">
|
<div class="taskScrollList">
|
||||||
<a
|
<a
|
||||||
v-for="taskNew in refTasks.filter(task => task.attributes.categorie == 'Dringend')"
|
v-for="taskNew in tasks.filter(task => task.categorie == 'Dringend')"
|
||||||
@click="inspectTask(taskNew)"
|
@click="inspectTask(taskNew)"
|
||||||
>
|
>
|
||||||
<UCard class="listItem">
|
<UCard class="listItem">
|
||||||
{{taskNew.attributes.name}}
|
{{taskNew.name}}
|
||||||
<UBadge
|
<UBadge
|
||||||
v-for="user in taskNew.attributes.users"
|
v-for="user in taskNew.users"
|
||||||
class="mr-2"
|
class="mr-2"
|
||||||
>
|
>
|
||||||
{{user}}
|
{{user}}
|
||||||
@@ -182,16 +182,19 @@ definePageMeta({
|
|||||||
middleware: "auth"
|
middleware: "auth"
|
||||||
})
|
})
|
||||||
|
|
||||||
const {find,create, update} = useStrapi4()
|
|
||||||
|
|
||||||
let tasks = (await find('tasks',{populate: "*"})).data
|
const supabase = useSupabaseClient()
|
||||||
|
|
||||||
|
const tasks = (await supabase.from("tasks").select()).data
|
||||||
|
|
||||||
|
|
||||||
let refTasks = ref([])
|
let refTasks = ref([])
|
||||||
|
|
||||||
|
|
||||||
const users = (await find('users',{populate: "*"}))
|
//const users = (await find('users',{populate: "*"}))
|
||||||
|
//const users = (await supabase.from("users").select()).data
|
||||||
let usersForList = []
|
let usersForList = []
|
||||||
users.forEach(user => usersForList.push(user.username))
|
//users.forEach(user => usersForList.push(user.username))
|
||||||
const usersSelected = ref([])
|
const usersSelected = ref([])
|
||||||
usersSelected.value = usersForList
|
usersSelected.value = usersForList
|
||||||
|
|
||||||
@@ -202,21 +205,35 @@ const taskCategories = ["Neu","In Bearbeitung", "Dringend"]
|
|||||||
const createTaskData = ref({
|
const createTaskData = ref({
|
||||||
name: "",
|
name: "",
|
||||||
description: "",
|
description: "",
|
||||||
categorie: "Neu",
|
categorie: "Neu"
|
||||||
users: []
|
/*users: ["86e67794-0ea8-41b0-985a-1072e84f56e9"]*/
|
||||||
})
|
})
|
||||||
|
|
||||||
const taskData = ref({})
|
const taskData = ref({})
|
||||||
const showTaskModal = ref(false)
|
const showTaskModal = ref(false)
|
||||||
|
|
||||||
const createTask = async () => {
|
const createTask = async () => {
|
||||||
await create('tasks', createTaskData.value)
|
//await create('tasks', createTaskData.value)
|
||||||
|
const {data,error} = await supabase
|
||||||
|
.from("tasks")
|
||||||
|
.insert([createTaskData.value])
|
||||||
|
.select()
|
||||||
|
|
||||||
|
console.log(error)
|
||||||
|
|
||||||
showCreateTask.value = false
|
showCreateTask.value = false
|
||||||
createTaskData.value = {}
|
createTaskData.value = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateTask = async () => {
|
const updateTask = async () => {
|
||||||
await update('tasks', taskData.value.id, taskData.value.attributes)
|
//await update('tasks', taskData.value.id, taskData.value)
|
||||||
|
const {data,error} = await supabase
|
||||||
|
.from("tasks")
|
||||||
|
.update([taskData.value])
|
||||||
|
.eq('id',taskData.value.id)
|
||||||
|
.select()
|
||||||
|
|
||||||
|
console.log(error)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,13 +244,14 @@ const inspectTask = (task) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const filterTasks = () => {
|
const filterTasks = () => {
|
||||||
refTasks.value = tasks.filter(task => usersSelected.value.some(user => (task.attributes.users ? (task.attributes.users.includes(user)) : true )))
|
refTasks.value = tasks.filter(task => usersSelected.value.some(user => (task.users ? (task.users.includes(user)) : true )))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const finishTask = () => {
|
const finishTask = () => {
|
||||||
taskData.value.attributes.categorie = "Erledigt"
|
taskData.value.categorie = "Erledigt"
|
||||||
updateTask()
|
updateTask()
|
||||||
|
showTaskModal.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
filterTasks()
|
filterTasks()
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
definePageMeta({
|
definePageMeta({
|
||||||
middleware: "auth"
|
middleware: "auth"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const supabase = useSupabaseClient()
|
||||||
|
|
||||||
|
const times = (await supabase.from("times").select()).data
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -15,6 +19,10 @@ definePageMeta({
|
|||||||
<UButton class="controlButton" disabled>
|
<UButton class="controlButton" disabled>
|
||||||
Pause
|
Pause
|
||||||
</UButton>
|
</UButton>
|
||||||
|
|
||||||
|
|
||||||
|
{{times}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
"info": {
|
"info": {
|
||||||
"singularName": "tenant",
|
"singularName": "tenant",
|
||||||
"pluralName": "tenants",
|
"pluralName": "tenants",
|
||||||
"displayName": "Tenants"
|
"displayName": "Tenants",
|
||||||
|
"description": ""
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"draftAndPublish": true
|
"draftAndPublish": true
|
||||||
@@ -16,6 +17,15 @@
|
|||||||
},
|
},
|
||||||
"short": {
|
"short": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": "oneToMany",
|
||||||
|
"target": "plugin::users-permissions.user",
|
||||||
|
"mappedBy": "tenant"
|
||||||
|
},
|
||||||
|
"modules": {
|
||||||
|
"type": "json"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,7 @@
|
|||||||
"displayName": "User"
|
"displayName": "User"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"draftAndPublish": false,
|
"draftAndPublish": false
|
||||||
"timestamps": true
|
|
||||||
},
|
},
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"username": {
|
"username": {
|
||||||
@@ -65,6 +64,12 @@
|
|||||||
"target": "plugin::users-permissions.role",
|
"target": "plugin::users-permissions.role",
|
||||||
"inversedBy": "users",
|
"inversedBy": "users",
|
||||||
"configurable": false
|
"configurable": false
|
||||||
|
},
|
||||||
|
"tenant": {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": "manyToOne",
|
||||||
|
"target": "api::tenant.tenant",
|
||||||
|
"inversedBy": "users"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
strapi/types/generated/contentTypes.d.ts
vendored
13
strapi/types/generated/contentTypes.d.ts
vendored
@@ -631,7 +631,6 @@ export interface PluginUsersPermissionsUser extends Schema.CollectionType {
|
|||||||
};
|
};
|
||||||
options: {
|
options: {
|
||||||
draftAndPublish: false;
|
draftAndPublish: false;
|
||||||
timestamps: true;
|
|
||||||
};
|
};
|
||||||
attributes: {
|
attributes: {
|
||||||
username: Attribute.String &
|
username: Attribute.String &
|
||||||
@@ -660,6 +659,11 @@ export interface PluginUsersPermissionsUser extends Schema.CollectionType {
|
|||||||
'manyToOne',
|
'manyToOne',
|
||||||
'plugin::users-permissions.role'
|
'plugin::users-permissions.role'
|
||||||
>;
|
>;
|
||||||
|
tenant: Attribute.Relation<
|
||||||
|
'plugin::users-permissions.user',
|
||||||
|
'manyToOne',
|
||||||
|
'api::tenant.tenant'
|
||||||
|
>;
|
||||||
createdAt: Attribute.DateTime;
|
createdAt: Attribute.DateTime;
|
||||||
updatedAt: Attribute.DateTime;
|
updatedAt: Attribute.DateTime;
|
||||||
createdBy: Attribute.Relation<
|
createdBy: Attribute.Relation<
|
||||||
@@ -999,6 +1003,7 @@ export interface ApiTenantTenant extends Schema.CollectionType {
|
|||||||
singularName: 'tenant';
|
singularName: 'tenant';
|
||||||
pluralName: 'tenants';
|
pluralName: 'tenants';
|
||||||
displayName: 'Tenants';
|
displayName: 'Tenants';
|
||||||
|
description: '';
|
||||||
};
|
};
|
||||||
options: {
|
options: {
|
||||||
draftAndPublish: true;
|
draftAndPublish: true;
|
||||||
@@ -1006,6 +1011,12 @@ export interface ApiTenantTenant extends Schema.CollectionType {
|
|||||||
attributes: {
|
attributes: {
|
||||||
name: Attribute.String;
|
name: Attribute.String;
|
||||||
short: Attribute.String;
|
short: Attribute.String;
|
||||||
|
users: Attribute.Relation<
|
||||||
|
'api::tenant.tenant',
|
||||||
|
'oneToMany',
|
||||||
|
'plugin::users-permissions.user'
|
||||||
|
>;
|
||||||
|
modules: Attribute.JSON;
|
||||||
createdAt: Attribute.DateTime;
|
createdAt: Attribute.DateTime;
|
||||||
updatedAt: Attribute.DateTime;
|
updatedAt: Attribute.DateTime;
|
||||||
publishedAt: Attribute.DateTime;
|
publishedAt: Attribute.DateTime;
|
||||||
|
|||||||
Reference in New Issue
Block a user