Add CPR cross-referencing (related documents)
Clicking any flagged card that contains CPR hits now shows a "Related documents" section in the preview panel, listing other items from the same scan session that share at least one CPR number. Items are ordered by number of shared CPRs; clicking any entry opens it in the preview panel. Works in both live mode and scan history mode. Implementation - GDPRDb.get_related_items() — SQL self-join on the existing cpr_index table using the same symmetric 300 s session window as get_session_items. No new data collection needed. - GET /api/db/related/<item_id>?ref=N — new endpoint in routes/database.py, consistent with the ?ref convention used by /api/db/flagged. - #previewRelated div injected between the metadata block and disposition row in the preview panel. - _loadRelated(f) in results.js fetches and renders the list; window._openRelated() resolves items from the live grid or falls back to the API response for history-mode items. Also - Added keyword/FTS5 search as a deferred idea in SUGGESTIONS.md - Updated CHANGELOG.md, README.md, and CLAUDE.md
This commit is contained in:
1 parent
8b55e9d933
commit
d84e57239a
8 files changed
+118
-1
No files matched your search
+31
@@ -523,6 +523,37 @@ class ScanDB:
|
||||
result.append(d)
|
||||
return result
|
||||
|
||||
def get_related_items(self, item_id: str, ref_scan_id: int | None = None,
|
||||
window_seconds: int = 300) -> list[dict]:
|
||||
"""Return flagged items from the same session that share at least one CPR
|
||||
hash with *item_id*, ordered by number of shared CPRs descending."""
|
||||
if ref_scan_id:
|
||||
row = self._connect().execute(
|
||||
"SELECT started_at FROM scans WHERE id=?", (ref_scan_id,)
|
||||
).fetchone()
|
||||
else:
|
||||
row = self._connect().execute(
|
||||
"SELECT started_at FROM scans WHERE finished_at IS NOT NULL ORDER BY id DESC LIMIT 1"
|
||||
).fetchone()
|
||||
if not row:
|
||||
return []
|
||||
latest_start = row[0]
|
||||
rows = self._connect().execute(
|
||||
"""SELECT fi.*, COUNT(DISTINCT ci2.cpr_hash) AS shared_cprs
|
||||
FROM cpr_index ci1
|
||||
JOIN cpr_index ci2 ON ci2.cpr_hash = ci1.cpr_hash
|
||||
JOIN flagged_items fi ON fi.id = ci2.item_id
|
||||
JOIN scans s ON fi.scan_id = s.id
|
||||
WHERE ci1.item_id = ?
|
||||
AND fi.id != ?
|
||||
AND s.started_at BETWEEN ? AND ?
|
||||
AND s.finished_at IS NOT NULL
|
||||
GROUP BY fi.id
|
||||
ORDER BY shared_cprs DESC, fi.cpr_count DESC""",
|
||||
(item_id, item_id, latest_start - window_seconds, latest_start + window_seconds),
|
||||
).fetchall()
|
||||
return [dict(r) for r in rows]
|
||||
|
||||
def get_session_sources(self, window_seconds: int = 300) -> set:
|
||||
"""Return the union of all source keys scanned in the current session.
|
||||
|
||||
|
||||
Reference in new issue
Block a user