From efa6ea90a21a5f07f6a9ed036607c03135cb6aec Mon Sep 17 00:00:00 2001 From: flfeders Date: Sat, 3 Oct 2026 14:38:39 +0200 Subject: [PATCH] fix(communication): display project chat state and refresh room visibility --- backend/tests/chatVisibility.test.ts | 12 +++- .../columnRenderings/projectChatEnabled.vue | 9 +++ frontend/pages/communication/chat.vue | 13 +++- frontend/stores/data.js | 3 +- frontend/tests/chat-collaboration.test.cjs | 35 ++++++++++- frontend/tests/project-chat-setting.test.cjs | 62 +++++++++++++++++++ 6 files changed, 127 insertions(+), 7 deletions(-) create mode 100644 frontend/components/columnRenderings/projectChatEnabled.vue create mode 100644 frontend/tests/project-chat-setting.test.cjs diff --git a/backend/tests/chatVisibility.test.ts b/backend/tests/chatVisibility.test.ts index 360761a9..f2da55d3 100644 --- a/backend/tests/chatVisibility.test.ts +++ b/backend/tests/chatVisibility.test.ts @@ -81,7 +81,17 @@ test("disabling in the project form blocks list, provision, reads and writes unt }) await app.register(communicationRoutes) await app.register(resourceRoutes) - const update = (chatEnabled: unknown, headers = { "x-manager": "true" }) => app.inject({ method: "PUT", url: "/resource/projects/1", headers, payload: { chatEnabled } }) + // The project editor loads the complete record and sends it back, including dates and other fields. + const update = async (chatEnabled: unknown, headers = { "x-manager": "true" }) => { + const loaded = await app.inject("/resource/projects/1/true") + assert.equal(loaded.statusCode, 200, loaded.body) + const result = await app.inject({ method: "PUT", url: "/resource/projects/1", headers, payload: { ...loaded.json(), chatEnabled } }) + if (result.statusCode === 200) { + assert.equal(result.json().chatEnabled, chatEnabled) + assert.equal((await app.inject("/resource/projects/1/true")).json().chatEnabled, chatEnabled) + } + return result + } const provision = await app.inject({ method: "POST", url: "/communication/chat/project-rooms/1/provision" }) assert.equal(provision.statusCode, 200, provision.body) const roomId = provision.json().id diff --git a/frontend/components/columnRenderings/projectChatEnabled.vue b/frontend/components/columnRenderings/projectChatEnabled.vue new file mode 100644 index 00000000..bcf7901a --- /dev/null +++ b/frontend/components/columnRenderings/projectChatEnabled.vue @@ -0,0 +1,9 @@ + + + diff --git a/frontend/pages/communication/chat.vue b/frontend/pages/communication/chat.vue index dd3e69d1..e3109bde 100644 --- a/frontend/pages/communication/chat.vue +++ b/frontend/pages/communication/chat.vue @@ -99,6 +99,9 @@ async function refreshLists() { const scope = scopeVersion await Promise.all([loadRoomLists(scope), loadUnread(scope), loadCollaboration(scope)]) } +function refreshVisibleLists() { + if (!disposed && !document.hidden && !loading.value && hasSession.value) void refreshLists() +} async function loadRoomPreferences(scope = scopeVersion) { if (!hasSession.value || !currentScope(scope)) return @@ -260,9 +263,15 @@ watch(() => route.query.room, () => { onMounted(() => { mounted = true; void initialize() pollTimer = window.setInterval(pollMessages, 2500) - listTimer = window.setInterval(() => { if (!document.hidden && !loading.value) void refreshLists() }, 15000) + listTimer = window.setInterval(refreshVisibleLists, 15000) + window.addEventListener('focus', refreshVisibleLists) + document.addEventListener('visibilitychange', refreshVisibleLists) +}) +onBeforeUnmount(() => { + disposed = true; ++scopeVersion; ++roomVersion; clearInterval(pollTimer); clearInterval(listTimer) + window.removeEventListener('focus', refreshVisibleLists) + document.removeEventListener('visibilitychange', refreshVisibleLists) }) -onBeforeUnmount(() => { disposed = true; ++scopeVersion; ++roomVersion; clearInterval(pollTimer); clearInterval(listTimer) })