KI-AGENT: Chaträume sortieren und Matrix-Setup verschieben

This commit is contained in:
2026-05-19 08:31:40 +02:00
parent 5b3445c2dc
commit 0fb469c9b0
2 changed files with 88 additions and 69 deletions

View File

@@ -80,11 +80,6 @@ const links = computed(() => {
to: "/communication/chat",
icon: "i-heroicons-chat-bubble-left-right"
},
{
label: "Matrix-Setup",
to: "/communication",
icon: "i-heroicons-cog-6-tooth"
},
featureEnabled("helpdesk") ? {
label: "Helpdesk",
to: "/helpdesk",
@@ -332,6 +327,11 @@ const links = computed(() => {
to: "/settings/tenant",
icon: "i-heroicons-building-office",
} : null,
{
label: "Matrix-Setup",
to: "/communication",
icon: "i-heroicons-chat-bubble-left-right",
},
featureEnabled("export") ? {
label: "Export",
to: "/export",

View File

@@ -112,6 +112,10 @@ const roomCreateKeyPreview = computed(() =>
normalizeRoomKey(roomCreateForm.value.key || roomCreateForm.value.name)
)
const sortRoomsByName = (roomList) => [...roomList].sort((first, second) =>
String(first.name || "").localeCompare(String(second.name || ""), "de", { sensitivity: "base" })
)
const rooms = computed(() => {
const baseRooms = matrixRooms.value
.filter((room) => !["project", "direct"].includes(room.type))
@@ -138,9 +142,31 @@ const rooms = computed(() => {
provisionEndpoint: `/api/communication/matrix/direct-rooms/${encodeURIComponent(room.userId)}/provision`
}))
return [...baseRooms, ...projectRooms, ...directRooms]
return [
...sortRoomsByName(baseRooms),
...sortRoomsByName(projectRooms),
...sortRoomsByName(directRooms)
]
})
const groupedRooms = computed(() => [
{
key: "rooms",
label: "Räume",
rooms: rooms.value.filter((room) => room.group === "Räume")
},
{
key: "projects",
label: "Projekte",
rooms: rooms.value.filter((room) => room.group === "Projekte")
},
{
key: "direct",
label: "Direktnachrichten",
rooms: rooms.value.filter((room) => room.group === "Direkt")
}
].filter((group) => group.rooms.length > 0))
const normalizeRoomKey = (value) => {
const normalized = String(value || "")
.toLowerCase()
@@ -919,63 +945,63 @@ onBeforeUnmount(() => {
</form>
</div>
<div class="flex-1 overflow-y-auto p-3">
<button
v-for="room in rooms"
:key="room.key"
type="button"
class="mb-1 flex w-full items-center gap-3 rounded-md px-3 py-2 text-left transition"
:class="[
room.disabled ? 'cursor-not-allowed opacity-50' : 'text-highlighted hover:bg-muted',
room.key === activeRoomKey ? 'bg-muted ring-1 ring-primary/20' : ''
]"
:disabled="room.disabled"
@click="setActiveRoom(room)"
<div class="flex-1 space-y-4 overflow-y-auto p-3">
<section
v-for="group in groupedRooms"
:key="group.key"
class="space-y-1"
>
<span class="flex size-9 shrink-0 items-center justify-center rounded-md bg-primary/10 text-primary">
<UIcon :name="room.icon || 'i-heroicons-chat-bubble-left-right'" class="size-5" />
</span>
<span class="min-w-0 flex-1">
<span class="block truncate text-sm font-medium">{{ room.name }}</span>
<span class="block truncate text-xs text-muted">{{ room.description }}</span>
</span>
<UBadge
v-if="roomProvisioningKey === room.key"
color="primary"
variant="soft"
size="xs"
<div class="flex items-center justify-between px-2">
<p class="text-[11px] font-semibold uppercase tracking-wide text-muted">
{{ group.label }}
</p>
<span class="text-[11px] text-muted">{{ group.rooms.length }}</span>
</div>
<button
v-for="room in group.rooms"
:key="room.key"
type="button"
class="flex w-full items-center gap-3 rounded-md px-3 py-2 text-left transition"
:class="[
room.disabled ? 'cursor-not-allowed opacity-50' : 'text-highlighted hover:bg-muted',
room.key === activeRoomKey ? 'bg-muted ring-1 ring-primary/20' : ''
]"
:disabled="room.disabled"
@click="setActiveRoom(room)"
>
lädt
</UBadge>
<UBadge
v-else-if="room.exists"
color="success"
variant="soft"
size="xs"
>
aktiv
</UBadge>
<UBadge
v-else-if="!room.disabled"
color="neutral"
variant="soft"
size="xs"
>
offen
</UBadge>
</button>
</div>
<div class="border-t border-default p-3">
<UButton
to="/communication"
icon="i-heroicons-cog-6-tooth"
color="neutral"
variant="outline"
block
>
Matrix-Setup
</UButton>
<span class="flex size-9 shrink-0 items-center justify-center rounded-md bg-primary/10 text-primary">
<UIcon :name="room.icon || 'i-heroicons-chat-bubble-left-right'" class="size-5" />
</span>
<span class="min-w-0 flex-1">
<span class="block truncate text-sm font-medium">{{ room.name }}</span>
<span class="block truncate text-xs text-muted">{{ room.description }}</span>
</span>
<UBadge
v-if="roomProvisioningKey === room.key"
color="primary"
variant="soft"
size="xs"
>
lädt
</UBadge>
<UBadge
v-else-if="room.exists"
color="success"
variant="soft"
size="xs"
>
aktiv
</UBadge>
<UBadge
v-else-if="!room.disabled"
color="neutral"
variant="soft"
size="xs"
>
offen
</UBadge>
</button>
</section>
</div>
</aside>
@@ -1020,13 +1046,6 @@ onBeforeUnmount(() => {
:disabled="!canStartMatrixCall"
@click="openMatrixCall('video')"
/>
<UButton
class="lg:hidden"
to="/communication"
icon="i-heroicons-cog-6-tooth"
color="neutral"
variant="outline"
/>
<UButton
class="lg:hidden"
icon="i-heroicons-plus"
@@ -1050,7 +1069,7 @@ onBeforeUnmount(() => {
<div class="border-b border-default bg-default p-3 lg:hidden">
<div class="flex gap-2 overflow-x-auto pb-1">
<button
<button
v-for="room in rooms"
:key="room.key"
type="button"