fix(#145): deep-link notifications; show createdAt in recent docs

- Notification widget builds full link with ?commentId= and
  &annotationId= params, matching the bell notification behaviour
- Recent docs widget shows createdAt (upload date) instead of
  documentDate (the date on the original document)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-03-29 10:03:36 +02:00
parent c8da2224f8
commit 7734ce7bae
4 changed files with 31 additions and 17 deletions

View File

@@ -5,6 +5,8 @@ type NotificationDTO = {
id: string;
type: 'REPLY' | 'MENTION';
documentId?: string;
referenceId?: string;
annotationId?: string;
read: boolean;
createdAt: string;
actorName?: string;
@@ -26,7 +28,9 @@ let { mentions }: Props = $props();
<div class="flex items-center gap-3 border-b border-line py-2 last:border-0">
{#if mention.documentId}
<a
href="/documents/{mention.documentId}"
href={mention.annotationId
? `/documents/${mention.documentId}?commentId=${mention.referenceId}&annotationId=${mention.annotationId}`
: `/documents/${mention.documentId}?commentId=${mention.referenceId}`}
class="font-serif text-sm text-ink hover:text-ink-2"
>
{mention.actorName ?? ''}

View File

@@ -10,6 +10,8 @@ type NotificationDTO = {
id: string;
type: 'REPLY' | 'MENTION';
documentId?: string;
referenceId?: string;
annotationId?: string;
read: boolean;
createdAt: string;
actorName?: string;
@@ -20,6 +22,7 @@ function makeMention(overrides: Partial<NotificationDTO> = {}): NotificationDTO
id: 'notif-1',
type: 'MENTION',
documentId: 'doc-abc',
referenceId: 'comment-xyz',
read: false,
createdAt: '2026-01-15T10:00:00Z',
actorName: 'Anna Schmidt',
@@ -40,15 +43,22 @@ describe('DashboardMentions', () => {
await expect.element(widget).toBeInTheDocument();
});
it('renders one row per mention with link to document', async () => {
const mentions = [
makeMention({ id: 'n1', documentId: 'doc-1', actorName: 'Anna' }),
makeMention({ id: 'n2', documentId: 'doc-2', actorName: 'Bob' })
];
render(DashboardMentions, { mentions });
const links = page.getByRole('link');
await expect.element(links.nth(0)).toHaveAttribute('href', '/documents/doc-1');
await expect.element(links.nth(1)).toHaveAttribute('href', '/documents/doc-2');
it('builds link with commentId param when no annotationId', async () => {
render(DashboardMentions, {
mentions: [makeMention({ documentId: 'doc-1', referenceId: 'cmt-1' })]
});
const link = page.getByRole('link');
await expect.element(link).toHaveAttribute('href', '/documents/doc-1?commentId=cmt-1');
});
it('builds link with commentId and annotationId when annotationId is present', async () => {
render(DashboardMentions, {
mentions: [makeMention({ documentId: 'doc-2', referenceId: 'cmt-2', annotationId: 'ann-9' })]
});
const link = page.getByRole('link');
await expect
.element(link)
.toHaveAttribute('href', '/documents/doc-2?commentId=cmt-2&annotationId=ann-9');
});
it('shows actor name in each row', async () => {

View File

@@ -5,7 +5,7 @@ import { getLocale } from '$lib/paraglide/runtime.js';
type Document = {
id: string;
title: string;
documentDate?: string;
createdAt?: string;
sender?: { id: string; firstName: string; lastName: string };
};
@@ -20,7 +20,7 @@ function formatDate(dateStr: string): string {
day: 'numeric',
month: 'long',
year: 'numeric'
}).format(new Date(dateStr + 'T12:00:00'));
}).format(new Date(dateStr));
}
</script>
@@ -37,12 +37,12 @@ function formatDate(dateStr: string): string {
>
{doc.title}
</a>
{#if doc.documentDate}
{#if doc.createdAt}
<span
data-testid="doc-date-{doc.id}"
class="ml-2 shrink-0 font-sans text-xs text-gray-400"
>
{formatDate(doc.documentDate)}
{formatDate(doc.createdAt)}
</span>
{/if}
</div>

View File

@@ -9,12 +9,12 @@ afterEach(cleanup);
type Document = {
id: string;
title: string;
documentDate?: string;
createdAt?: string;
sender?: { id: string; firstName: string; lastName: string };
};
function makeDoc(id: string, title: string, date?: string): Document {
return { id, title, documentDate: date };
function makeDoc(id: string, title: string, createdAt?: string): Document {
return { id, title, createdAt };
}
describe('DashboardRecentDocuments', () => {