Skip to content

Chat basics: one chat per Project, live updates, unread badge (#92) - #99

Merged
Oceandek merged 1 commit into
mainfrom
feat/chat-basics
Oct 22, 2026
Merged

Oceandek merged 1 commit into
mainfrom
feat/chat-basics

Conversation

@Oceandek

Copy link
Copy Markdown
Collaborator

Closes #92 (spec #91).

What's new

  • One chat per Project. Its Chat people are the Members and the Product Owner. Every Teacher and the Superuser can also read and write in every chat. Other Students get 403, and a removed or moved Member loses access at once; a new Member sees the full history.
  • Messages: text up to 4000 characters, web links clickable (escaped HTML, new tab). Your own messages sit on the right on sand, others' on the left. Enter sends, Shift+Enter starts a new line.
  • Live: an open chat polls GET …/chat/messages?after=<last id> every 2 s, so others' messages appear within ~2 s without reloading (ADR 0008: polling instead of push, frontend → backend stays plain REST).
  • Unread: chat_reads keeps each person's last read message. Opening a chat reads it. A red badge on Chat (Students) / Chats (Teachers, Superuser) shows the Unread count of your own chats, refreshed every 10 s; for staff only Projects where they are the Product Owner count. A Student without a Project doesn't see the Chat item.
  • Screens: /chat (Student's chat), /chats (staff: every Active Project's chat with its Unread count), /chats/{project_id}, and a Chat button next to the title on a Project's page.
  • Archived Project: the chat is read-only (sending gives 409).
  • Migration 0014 (chat_messages, chat_reads); CONTEXT.md: Chat, Chat people, Unread; changelog row.

API

GET /api/projects/{id}/chat, GET/POST /api/projects/{id}/chat/messages, POST /api/projects/{id}/chat/read, GET /api/chats, GET /api/chats/unread.

Test infrastructure fix

Pages now poll the backend, and the frontend tests run the backend in-process. A request cancelled at the end of a test left its database transaction open ("idle in transaction"), and the next test's TRUNCATE waited forever (seen locally: the suite hung). FinishingTransport in frontend/tests/conftest.py lets every request finish, the fixture waits for them, and each test's engine is disposed. Four existing tests clicked before their page had loaded; they now wait for it like their neighbours.

Tests

Backend 329 passed (new test_chat.py: access, ordering, after, Unread, length, archived). Frontend 98 passed (new test_chat.py: Student sends and receives live, Teacher badge + Chats screen + opening reads, Chat button, no Chat item without a Project, link escaping).

Not yet: Guests (#93), files (#94), edit/delete/reply (#95), reactions/mentions (#96), typing/seen/search (#97), 6-month cleanup (#98).

🤖 Generated with Claude Code

One group chat per Project for its Members and Product Owner; every Teacher
and the Superuser can read and write in every chat. Text messages (4000
characters, clickable links), new messages within ~2 s by polling (ADR 0008),
Unread counts per User with a badge on the Chat / Chats navigation item, a
Chats screen for staff and a Chat button on a Project's page. An Archived
Project's chat is read-only. Migration 0014.

Frontend tests: backend requests made in-process now always finish (a request
cancelled at the end of a test left its transaction open and blocked the next
test's reset), engines are disposed, and four tests wait for their page before
clicking.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Oceandek
Oceandek merged commit d1869d7 into main Oct 22, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Chat basics: one chat per Project, text messages, live updates, unread badge

1 participant