feat: add notifications and project shares features
- Backend: notifications + shares routes, DB tables, SqliteAdapter methods - Frontend: NotificationPanel (bell icon + dropdown), ShareDialog, Dashboard integration - Styles: notification + share dialog CSS
This commit is contained in:
@@ -9,6 +9,7 @@ import { randomUUID } from 'crypto';
|
||||
import type {
|
||||
DatabaseInterface, DBProject, DBDrawing, DBLayer,
|
||||
DBElement, DBBlock, DBSetting, DBUser, DBSession,
|
||||
DBNotification, DBProjectShare,
|
||||
} from './DatabaseInterface.js';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
@@ -265,4 +266,43 @@ export class SqliteAdapter implements DatabaseInterface {
|
||||
deleteExpiredSessions(): void {
|
||||
this.db.prepare('DELETE FROM sessions WHERE expires_at < ?').run(Date.now());
|
||||
}
|
||||
|
||||
// ─── Notifications ──────────────────────────────────
|
||||
listNotifications(userId: string): DBNotification[] {
|
||||
return this.db.prepare('SELECT * FROM notifications WHERE user_id = ? ORDER BY created_at DESC').all(userId) as DBNotification[];
|
||||
}
|
||||
|
||||
createNotification(data: Partial<DBNotification>): DBNotification {
|
||||
const id = data.id ?? `notif-${Date.now()}`;
|
||||
this.db.prepare(
|
||||
'INSERT INTO notifications (id, user_id, type, title, message, read) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
).run(id, data.user_id!, data.type ?? 'info', data.title!, data.message!, data.read ?? 0);
|
||||
return this.db.prepare('SELECT * FROM notifications WHERE id = ?').get(id) as DBNotification;
|
||||
}
|
||||
|
||||
markNotificationRead(id: string): boolean {
|
||||
return this.db.prepare('UPDATE notifications SET read = 1 WHERE id = ?').run(id).changes > 0;
|
||||
}
|
||||
|
||||
deleteNotification(id: string): boolean {
|
||||
return this.db.prepare('DELETE FROM notifications WHERE id = ?').run(id).changes > 0;
|
||||
}
|
||||
|
||||
// ─── Project Shares ─────────────────────────────────
|
||||
listProjectShares(projectId: string): DBProjectShare[] {
|
||||
return this.db.prepare('SELECT * FROM project_shares WHERE project_id = ? ORDER BY created_at DESC').all(projectId) as DBProjectShare[];
|
||||
}
|
||||
|
||||
createProjectShare(data: Partial<DBProjectShare>): DBProjectShare {
|
||||
const id = data.id ?? `share-${Date.now()}`;
|
||||
const shareToken = data.share_token ?? randomUUID();
|
||||
this.db.prepare(
|
||||
'INSERT INTO project_shares (id, project_id, shared_with_email, shared_by, permission, share_token) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
).run(id, data.project_id!, data.shared_with_email!, data.shared_by!, data.permission ?? 'view', shareToken);
|
||||
return this.db.prepare('SELECT * FROM project_shares WHERE id = ?').get(id) as DBProjectShare;
|
||||
}
|
||||
|
||||
deleteProjectShare(id: string): boolean {
|
||||
return this.db.prepare('DELETE FROM project_shares WHERE id = ?').run(id).changes > 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user