2. Zwischenstand
All checks were successful
Build and Push Docker Images / build-backend (push) Successful in 15s
Build and Push Docker Images / build-frontend (push) Successful in 2m43s

This commit is contained in:
2026-03-21 22:56:56 +01:00
parent 68b2cbb0ee
commit 03bcc1a939
56 changed files with 1289 additions and 1302 deletions

View File

@@ -51,7 +51,7 @@ const savingUser = ref(false)
const savingTenant = ref(false)
const creatingUser = ref(false)
const creatingTenant = ref(false)
const activeTab = ref(0)
const activeTab = ref("0")
const createUserModalOpen = ref(false)
const createTenantModalOpen = ref(false)
const createdUserPassword = ref("")
@@ -472,7 +472,7 @@ onMounted(async () => {
:items="tabItems"
class="admin-tabs h-full"
>
<template #item="{ item }">
<template #content="{ item }">
<div v-if="item.label === 'Benutzer'" class="admin-grid mt-5 grid grid-cols-1 xl:grid-cols-3 gap-5">
<UCard class="admin-card xl:col-span-1">
<div class="flex items-center justify-between mb-4">
@@ -494,7 +494,7 @@ onMounted(async () => {
v-if="!loading"
:data="userTableRows"
:columns="normalizedUserTableColumns"
@select="selectUser"
:on-select="selectUser"
/>
<USkeleton v-else class="h-80" />
@@ -519,49 +519,49 @@ onMounted(async () => {
</div>
<UForm :state="userForm" class="grid grid-cols-1 md:grid-cols-2 gap-6">
<UFormGroup label="E-Mail">
<UFormField label="E-Mail">
<UInput v-model="userForm.email" />
</UFormGroup>
</UFormField>
<UFormGroup label="Profil Vorname">
<UFormField label="Profil Vorname">
<UInput v-model="userForm.profile_defaults.first_name" />
</UFormGroup>
</UFormField>
<UFormGroup label="Profil Nachname">
<UFormField label="Profil Nachname">
<UInput v-model="userForm.profile_defaults.last_name" />
</UFormGroup>
</UFormField>
<UFormGroup label="Tenants">
<UFormField label="Tenants">
<USelectMenu
:model-value="userForm.tenant_ids"
:options="tenantOptions"
value-attribute="value"
option-attribute="label"
:items="tenantOptions"
value-key="value"
label-key="label"
multiple
@update:model-value="updateUserTenants"
/>
</UFormGroup>
</UFormField>
<UFormGroup label="Administrative Freigabe">
<UFormField label="Administrative Freigabe">
<div class="flex items-center gap-3 h-10">
<UToggle v-model="userForm.is_admin" />
<USwitch v-model="userForm.is_admin" />
<span class="text-sm text-gray-600">Darf Administrationsseite und Admin-API nutzen</span>
</div>
</UFormGroup>
</UFormField>
<UFormGroup label="Multi-Tenant">
<UFormField label="Multi-Tenant">
<div class="flex items-center gap-3 h-10">
<UToggle v-model="userForm.multiTenant" />
<USwitch v-model="userForm.multiTenant" />
<span class="text-sm text-gray-600">Benutzer darf mehreren Tenants zugeordnet sein</span>
</div>
</UFormGroup>
</UFormField>
<UFormGroup label="Passwortwechsel erzwingen">
<UFormField label="Passwortwechsel erzwingen">
<div class="flex items-center gap-3 h-10">
<UToggle v-model="userForm.must_change_password" />
<USwitch v-model="userForm.must_change_password" />
<span class="text-sm text-gray-600">Beim nächsten Login muss das Passwort geändert werden</span>
</div>
</UFormGroup>
</UFormField>
</UForm>
<div>
@@ -586,33 +586,33 @@ onMounted(async () => {
</div>
</div>
<UFormGroup label="Rolle">
<UFormField label="Rolle">
<USelectMenu
:model-value="getRoleForTenant(tenantId)"
:options="getRoleOptionsForTenant(tenantId)"
value-attribute="value"
option-attribute="label"
:items="getRoleOptionsForTenant(tenantId)"
value-key="value"
label-key="label"
placeholder="Rolle auswählen"
@update:model-value="(value) => setRoleForTenant(tenantId, value)"
/>
</UFormGroup>
</UFormField>
<UFormGroup label="Freies Profil">
<UFormField label="Freies Profil">
<USelectMenu
:model-value="getProfileAssignmentForTenant(tenantId)"
:options="[
:items="[
{ label: 'Neues Profil erzeugen', value: null },
...getFreeProfilesForTenant(tenantId).map((profile) => ({
label: profile.full_name || `${profile.first_name} ${profile.last_name}`,
value: profile.id,
}))
]"
value-attribute="value"
option-attribute="label"
value-key="value"
label-key="label"
placeholder="Profil auswählen"
@update:model-value="(value) => setProfileAssignmentForTenant(tenantId, value)"
/>
</UFormGroup>
</UFormField>
</div>
</UCard>
</div>
@@ -676,7 +676,7 @@ onMounted(async () => {
v-if="!loading"
:data="tenantTableRows"
:columns="normalizedTenantTableColumns"
@select="selectTenant"
:on-select="selectTenant"
/>
<USkeleton v-else class="h-80" />
@@ -701,13 +701,13 @@ onMounted(async () => {
</div>
<UForm :state="tenantForm" class="grid grid-cols-1 md:grid-cols-2 gap-6">
<UFormGroup label="Name">
<UFormField label="Name">
<UInput v-model="tenantForm.name" />
</UFormGroup>
</UFormField>
<UFormGroup label="Kürzel">
<UFormField label="Kürzel">
<UInput v-model="tenantForm.short" />
</UFormGroup>
</UFormField>
</UForm>
<div>
@@ -743,49 +743,50 @@ onMounted(async () => {
</UDashboardPanelContent>
<UModal v-model:open="createUserModalOpen">
<UCard>
<template #header>
<div class="text-lg font-semibold">Benutzer anlegen</div>
</template>
<template #content>
<UCard>
<template #header>
<div class="text-lg font-semibold">Benutzer anlegen</div>
</template>
<UForm
:state="createUserForm"
class="space-y-4"
@submit.prevent="createUser"
>
<UFormGroup label="E-Mail">
<UFormField label="E-Mail">
<UInput v-model="createUserForm.email" type="email" />
</UFormGroup>
</UFormField>
<UFormGroup label="Initialpasswort">
<UFormField label="Initialpasswort">
<UInput
v-model="createUserForm.password"
type="text"
placeholder="Leer lassen für automatisches Passwort"
/>
</UFormGroup>
</UFormField>
<UFormGroup label="Vorname für neues Profil">
<UFormField label="Vorname für neues Profil">
<UInput v-model="createUserForm.first_name" />
</UFormGroup>
</UFormField>
<UFormGroup label="Nachname für neues Profil">
<UFormField label="Nachname für neues Profil">
<UInput v-model="createUserForm.last_name" />
</UFormGroup>
</UFormField>
<UFormGroup label="Administrative Freigabe">
<UFormField label="Administrative Freigabe">
<div class="flex items-center gap-3 h-10">
<UToggle v-model="createUserForm.is_admin" />
<USwitch v-model="createUserForm.is_admin" />
<span class="text-sm text-gray-600">Benutzer darf die Administration öffnen</span>
</div>
</UFormGroup>
</UFormField>
<UFormGroup label="Multi-Tenant">
<UFormField label="Multi-Tenant">
<div class="flex items-center gap-3 h-10">
<UToggle v-model="createUserForm.multiTenant" />
<USwitch v-model="createUserForm.multiTenant" />
<span class="text-sm text-gray-600">Mehrere Tenant-Zuordnungen erlauben</span>
</div>
</UFormGroup>
</UFormField>
<div class="flex justify-end gap-3 pt-2">
<UButton color="gray" variant="soft" @click="createUserModalOpen = false">
@@ -795,28 +796,30 @@ onMounted(async () => {
Benutzer anlegen
</UButton>
</div>
</UForm>
</UCard>
</UForm>
</UCard>
</template>
</UModal>
<UModal v-model:open="createTenantModalOpen">
<UCard>
<template #header>
<div class="text-lg font-semibold">Tenant anlegen</div>
</template>
<template #content>
<UCard>
<template #header>
<div class="text-lg font-semibold">Tenant anlegen</div>
</template>
<UForm
:state="createTenantForm"
class="space-y-4"
@submit.prevent="createTenant"
>
<UFormGroup label="Name">
<UFormField label="Name">
<UInput v-model="createTenantForm.name" />
</UFormGroup>
</UFormField>
<UFormGroup label="Kürzel">
<UFormField label="Kürzel">
<UInput v-model="createTenantForm.short" />
</UFormGroup>
</UFormField>
<UAlert
title="Seed-Daten"
@@ -833,8 +836,9 @@ onMounted(async () => {
Tenant anlegen
</UButton>
</div>
</UForm>
</UCard>
</UForm>
</UCard>
</template>
</UModal>
<div class="mx-5 mb-5">