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);
|
).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 ─────────────────────────────────────────────────────────────
|
// ─── helpers ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
private UUID createPerson(String firstName, String lastName) {
|
private UUID createPerson(String firstName, String lastName) {
|
||||||
@@ -326,4 +377,63 @@ class MigrationIntegrationTest {
|
|||||||
em.flush();
|
em.flush();
|
||||||
return doc.getId();
|
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