bug: notification deep-link does not scroll to comment on document detail page #299
@@ -0,0 +1,24 @@
|
||||
-- Backfill annotation_id on block comments and their notifications.
|
||||
--
|
||||
-- Before the upstream fix, CommentService.postBlockComment did not set
|
||||
-- DocumentComment.annotationId, so block comments were stored with
|
||||
-- annotation_id = NULL and every notification built from them inherited
|
||||
-- that NULL (see NotificationService.notifyMentions/notifyReply).
|
||||
--
|
||||
-- The frontend deep-link flow needs annotationId in the URL query string
|
||||
-- to open the correct annotation panel and scroll to the comment.
|
||||
-- Without this backfill, previously issued notifications would still
|
||||
-- carry annotation_id = NULL even after the code fix lands.
|
||||
|
||||
UPDATE document_comments dc
|
||||
SET annotation_id = tb.annotation_id
|
||||
FROM transcription_blocks tb
|
||||
WHERE dc.block_id = tb.id
|
||||
AND dc.annotation_id IS NULL;
|
||||
|
||||
UPDATE notifications n
|
||||
SET annotation_id = dc.annotation_id
|
||||
FROM document_comments dc
|
||||
WHERE n.reference_id = dc.id
|
||||
AND n.annotation_id IS NULL
|
||||
AND dc.annotation_id IS NOT NULL;
|
||||
@@ -302,6 +302,57 @@ class MigrationIntegrationTest {
|
||||
).isInstanceOf(DataIntegrityViolationException.class);
|
||||
}
|
||||
|
||||
// ─── V51: backfill annotation_id on block comments and notifications ─────
|
||||
|
||||
@Test
|
||||
void v51_backfillsAnnotationIdOnBlockCommentsFromTheirBlocks() {
|
||||
UUID docId = createDocument();
|
||||
UUID annotationId = insertAnnotation(docId);
|
||||
UUID blockId = insertBlock(docId, annotationId);
|
||||
UUID commentId = insertBlockCommentWithNullAnnotationId(docId, blockId);
|
||||
|
||||
jdbc.update(V51_BACKFILL_COMMENTS_SQL);
|
||||
|
||||
UUID stored = jdbc.queryForObject(
|
||||
"SELECT annotation_id FROM document_comments WHERE id = ?",
|
||||
UUID.class, commentId);
|
||||
assertThat(stored).isEqualTo(annotationId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void v51_backfillsAnnotationIdOnNotificationsFromTheirReferencedComment() {
|
||||
UUID docId = createDocument();
|
||||
UUID userId = insertUser("recipient-" + UUID.randomUUID() + "@example.com");
|
||||
UUID annotationId = insertAnnotation(docId);
|
||||
UUID blockId = insertBlock(docId, annotationId);
|
||||
UUID commentId = insertBlockCommentWithAnnotationId(docId, blockId, annotationId);
|
||||
UUID notificationId = insertNotificationWithNullAnnotationId(docId, commentId, userId);
|
||||
|
||||
jdbc.update(V51_BACKFILL_NOTIFICATIONS_SQL);
|
||||
|
||||
UUID stored = jdbc.queryForObject(
|
||||
"SELECT annotation_id FROM notifications WHERE id = ?",
|
||||
UUID.class, notificationId);
|
||||
assertThat(stored).isEqualTo(annotationId);
|
||||
}
|
||||
|
||||
private static final String V51_BACKFILL_COMMENTS_SQL = """
|
||||
UPDATE document_comments dc
|
||||
SET annotation_id = tb.annotation_id
|
||||
FROM transcription_blocks tb
|
||||
WHERE dc.block_id = tb.id
|
||||
AND dc.annotation_id IS NULL
|
||||
""";
|
||||
|
||||
private static final String V51_BACKFILL_NOTIFICATIONS_SQL = """
|
||||
UPDATE notifications n
|
||||
SET annotation_id = dc.annotation_id
|
||||
FROM document_comments dc
|
||||
WHERE n.reference_id = dc.id
|
||||
AND n.annotation_id IS NULL
|
||||
AND dc.annotation_id IS NOT NULL
|
||||
""";
|
||||
|
||||
// ─── helpers ─────────────────────────────────────────────────────────────
|
||||
|
||||
private UUID createPerson(String firstName, String lastName) {
|
||||
@@ -326,4 +377,63 @@ class MigrationIntegrationTest {
|
||||
em.flush();
|
||||
return doc.getId();
|
||||
}
|
||||
|
||||
private UUID insertAnnotation(UUID docId) {
|
||||
UUID id = UUID.randomUUID();
|
||||
jdbc.update("""
|
||||
INSERT INTO document_annotations
|
||||
(id, document_id, page_number, x, y, width, height, color)
|
||||
VALUES (?, ?, 1, 0.1, 0.1, 0.3, 0.1, '#00C7B1')
|
||||
""", id, docId);
|
||||
return id;
|
||||
}
|
||||
|
||||
private UUID insertBlock(UUID docId, UUID annotationId) {
|
||||
UUID id = UUID.randomUUID();
|
||||
jdbc.update("""
|
||||
INSERT INTO transcription_blocks
|
||||
(id, annotation_id, document_id, text, sort_order)
|
||||
VALUES (?, ?, ?, '', 0)
|
||||
""", id, annotationId, docId);
|
||||
return id;
|
||||
}
|
||||
|
||||
private UUID insertUser(String email) {
|
||||
UUID id = UUID.randomUUID();
|
||||
jdbc.update("""
|
||||
INSERT INTO users (id, email, password, enabled, notify_on_reply, notify_on_mention)
|
||||
VALUES (?, ?, 'hash', true, false, false)
|
||||
""", id, email);
|
||||
return id;
|
||||
}
|
||||
|
||||
private UUID insertBlockCommentWithNullAnnotationId(UUID docId, UUID blockId) {
|
||||
UUID id = UUID.randomUUID();
|
||||
jdbc.update("""
|
||||
INSERT INTO document_comments
|
||||
(id, document_id, block_id, annotation_id, author_name, content)
|
||||
VALUES (?, ?, ?, NULL, 'Tester', 'Hi')
|
||||
""", id, docId, blockId);
|
||||
return id;
|
||||
}
|
||||
|
||||
private UUID insertBlockCommentWithAnnotationId(UUID docId, UUID blockId, UUID annotationId) {
|
||||
UUID id = UUID.randomUUID();
|
||||
jdbc.update("""
|
||||
INSERT INTO document_comments
|
||||
(id, document_id, block_id, annotation_id, author_name, content)
|
||||
VALUES (?, ?, ?, ?, 'Tester', 'Hi')
|
||||
""", id, docId, blockId, annotationId);
|
||||
return id;
|
||||
}
|
||||
|
||||
private UUID insertNotificationWithNullAnnotationId(UUID docId, UUID commentId, UUID recipientId) {
|
||||
UUID id = UUID.randomUUID();
|
||||
jdbc.update("""
|
||||
INSERT INTO notifications
|
||||
(id, recipient_id, type, document_id, reference_id, annotation_id, read, actor_name)
|
||||
VALUES (?, ?, 'MENTION', ?, ?, NULL, false, 'Tester')
|
||||
""", id, recipientId, docId, commentId);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user