From 6ff9971ff9e7b751c5650b38c3bc558fb42ae660 Mon Sep 17 00:00:00 2001 From: flfeders Date: Fri, 2 Oct 2026 18:03:11 +0200 Subject: [PATCH 1/3] fix(push-admin): show test push delivery errors --- push-server/apps/admin/pages/instances/[id].vue | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/push-server/apps/admin/pages/instances/[id].vue b/push-server/apps/admin/pages/instances/[id].vue index f4817a71..45f80cda 100644 --- a/push-server/apps/admin/pages/instances/[id].vue +++ b/push-server/apps/admin/pages/instances/[id].vue @@ -82,14 +82,14 @@ async function sendTestPush() { }); await Promise.all([refreshInstance(), refreshJobs(), refreshDevices()]); toast.add({ - title: "Test-Push gesendet", - description: `${result.sent ?? 0} gesendet, ${result.failed ?? 0} fehlgeschlagen`, - color: result.failed ? "warning" : "success", + title: result.failed ? (result.sent ? "Test-Push teilweise fehlgeschlagen" : "Test-Push fehlgeschlagen") : "Test-Push gesendet", + description: [`${result.sent ?? 0} gesendet, ${result.failed ?? 0} fehlgeschlagen`, result.lastErrorCode, result.lastErrorMessage].filter(Boolean).join(" · "), + color: result.failed ? (result.sent ? "warning" : "error") : "success", }); } catch (error: any) { toast.add({ title: "Test-Push fehlgeschlagen", - description: error?.data?.message || error?.message || "Die Testnachricht konnte nicht gesendet werden.", + description: error?.data?.message || error?.data?.error || error?.message || "Die Testnachricht konnte nicht gesendet werden.", color: "error", }); } finally { @@ -246,6 +246,7 @@ async function sendTestPush() { Angenommen Gesendet Fehler + Letzter Fehler Erstellt @@ -256,6 +257,10 @@ async function sendTestPush() { {{ job.acceptedCount }} {{ job.sentCount }} {{ job.failedCount }} + +
{{ job.lastErrorCode || "-" }}
+
{{ job.lastErrorMessage }}
+ {{ new Date(job.createdAt).toLocaleString() }} -- 2.49.1 From 0887863981e069d45aaf52dff32e32333d1bf3b3 Mon Sep 17 00:00:00 2001 From: flfeders Date: Fri, 2 Oct 2026 18:12:03 +0200 Subject: [PATCH 2/3] feat(communication): integrate collaboration rooms into normal chat --- docs/chat-foederation-konzept.md | 2 + frontend/components/CollaborationRoom.vue | 8 +- frontend/pages/communication/chat.vue | 390 ++++++++++-------- .../pages/communication/collaboration.vue | 8 +- frontend/tests/chat-collaboration.test.cjs | 239 +++++++++++ 5 files changed, 462 insertions(+), 185 deletions(-) create mode 100644 frontend/tests/chat-collaboration.test.cjs diff --git a/docs/chat-foederation-konzept.md b/docs/chat-foederation-konzept.md index 61602b55..fa7f7008 100644 --- a/docs/chat-foederation-konzept.md +++ b/docs/chat-foederation-konzept.md @@ -285,6 +285,8 @@ Als erster nutzbarer Meilenstein wird **ein abgegrenzter Projekt-Unterraum mit e Unter **Kommunikation → Zusammenarbeit** können interne Teilnehmer ihre eigenen Unterräume und Einladungen öffnen. Projektverantwortliche mit `organisation.projects.write` beziehungsweise Administratoren können Unterräume verwalten und freie Partnerchats anlegen. Der Projektkopf verlinkt ebenfalls auf die Zusammenarbeit. Die Verwaltung eines Raums berechtigt weiterhin nicht zum Lesen seiner Nachrichten; nur der Ersteller wird bei der Anlage automatisch Teilnehmer. +Unter **Kommunikation → Chat** erscheinen diese Unterräume ebenfalls in der Raumgruppe **Zusammenarbeit**, einschließlich instanzübergreifender Räume und Ungelesen-Zähler. Einladungen lassen sich dort direkt annehmen oder ablehnen; nach der Annahme öffnet sich der Raum. Nachrichten, Teilnehmer und ausdrücklich freigegebene Projektinformationen werden direkt im normalen Chat angezeigt. **Details und Freigaben** öffnet die bestehende Verwaltungsansicht für den ausgewählten Raum; **Im Chat öffnen** führt zurück. Sichtbar sind ausschließlich Räume mit eigener Teilnahme, keine lediglich verwaltbaren Räume. Interne Chaträume und Unterräume behalten ihre getrennten Berechtigungsprüfungen. + Einladungen unterstützen eigene Mitarbeiter, persönliche FEDEO-Kontaktadressen und Gäste ohne FEDEO-Konto. Eine Kontaktadresse bezeichnet immer genau einen Benutzer in einem Heimatmandanten. Sie lässt sich in der Zusammenarbeit kopieren. Kontakte anderer Mandanten derselben Instanz benötigen keinen Server-Server-Transport. Fremde Instanzen müssen auf beiden Seiten im jeweiligen Mandanten unter **Partnerinstanzen** freigegeben sein. Beim Empfänger erscheint ein Angebot, das ausdrücklich angenommen oder abgelehnt wird. Gäste erhalten ausschließlich einen Projekt-Unterraum. Der Link öffnet `/guest`; ein achtstelliger, zehn Minuten gültiger Einmalcode wird an die eingeladene Adresse geschickt. Nach fünf falschen Versuchen ist der Code gesperrt. Die eigene Gastsitzung gilt zwölf Stunden und wird nicht als reguläres FEDEO-Token akzeptiert. Für spätere Anmeldungen bietet die Gastoberfläche eine als Lesezeichen speicherbare Adresse mit öffentlicher Workspace-ID an. Ohne gewähltes Ablaufdatum gilt die Teilnahme eines Gasts 30 Tage. Der Einladungslink allein erlaubt keinen Inhaltszugriff. diff --git a/frontend/components/CollaborationRoom.vue b/frontend/components/CollaborationRoom.vue index effbb3bd..9884e2b5 100644 --- a/frontend/components/CollaborationRoom.vue +++ b/frontend/components/CollaborationRoom.vue @@ -1,5 +1,5 @@