Private
Public Access
1
0

Phase 6: Activity log and notifications

Add activity logging to all write API routes, notification system with
real-time delivery via Socket.IO, @mention parsing in comments, activity
feed sidebar on board page, per-card activity in card modal, and
notification bell with unread badge in the navbar.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Catherine Renelle
2026-02-26 00:26:15 -05:00
parent e61c549ddb
commit e5f2c64e14
32 changed files with 930 additions and 23 deletions
@@ -6,6 +6,7 @@ import { canViewBoard } from '$lib/server/permissions.js';
import { readFile, unlink } from 'fs/promises';
import { json } from '@sveltejs/kit';
import { broadcast } from '$lib/server/realtime.js';
import { logActivity } from '$lib/server/activity.js';
export const GET: RequestHandler = async ({ params, locals }) => {
const tenant = locals.tenant;
@@ -78,6 +79,14 @@ export const DELETE: RequestHandler = async ({ params, request, locals }) => {
throw error(403, 'Access denied');
}
await logActivity(tx, {
boardId: att.card.column.board.id,
userId: locals.user!.id,
action: 'attachment.deleted',
cardId: att.cardId,
metadata: { filename: att.filename }
});
await tx.attachment.delete({ where: { id: params.attachmentId } });
try {
@@ -91,6 +100,7 @@ export const DELETE: RequestHandler = async ({ params, request, locals }) => {
const socketId = request.headers.get('X-Socket-ID');
broadcast(deleted.boardId, 'card:updated', { cardId: deleted.cardId, columnId: deleted.columnId, socketId });
broadcast(deleted.boardId, 'activity:new', { boardId: deleted.boardId, cardId: deleted.cardId, socketId });
return json({ ok: true });
};