feat(m8): SSE hub + realtime chat with mentions, tests, e2e
- SseHub (project-scoped client mgmt + broadcast, implements SseBroadcaster) with SSE-formatted payload; singleton getSseHub - ChatRepository (message CRUD, soft-delete, search, pagination, project isolation) + ChatService (membership permission, send/edit/delete, @email mention -> mention notification, SSE broadcast of created/updated/deleted) - SSE stream endpoint (ReadableStream + heartbeat + abort cleanup, membership) - Chat message API routes (history/send/edit/delete) - ChatWindow client (EventSource auto-reconnect, history fetch, realtime append/update/delete), chat page, ProjectNav チャット link - SseEvent type now carries ChatMessage for chat events - Unit (SseHub, ChatRepository, ChatService) + integration chat-sse-broadcast + e2e chat-sse (two contexts realtime)
This commit is contained in:
@ -2,6 +2,7 @@ const NAV_ITEMS = [
|
||||
{ href: '', label: '概要' },
|
||||
{ href: '/board', label: '掲示板' },
|
||||
{ href: '/notes', label: 'メモ' },
|
||||
{ href: '/chat', label: 'チャット' },
|
||||
{ href: '/members', label: 'メンバー' },
|
||||
{ href: '/activity', label: 'アクティビティ' },
|
||||
{ href: '/settings', label: '設定' },
|
||||
@ -16,12 +17,20 @@ export function ProjectNav({
|
||||
active,
|
||||
}: {
|
||||
projectId: number;
|
||||
active: 'overview' | 'board' | 'notes' | 'members' | 'activity' | 'settings';
|
||||
active:
|
||||
| 'overview'
|
||||
| 'board'
|
||||
| 'notes'
|
||||
| 'chat'
|
||||
| 'members'
|
||||
| 'activity'
|
||||
| 'settings';
|
||||
}) {
|
||||
const activeMap: Record<string, boolean> = {
|
||||
overview: active === 'overview',
|
||||
board: active === 'board',
|
||||
notes: active === 'notes',
|
||||
chat: active === 'chat',
|
||||
members: active === 'members',
|
||||
activity: active === 'activity',
|
||||
settings: active === 'settings',
|
||||
|
||||
Reference in New Issue
Block a user