fix: open #document deep-links on refresh and surface load errors (#631)
Add a hashchange handler for #document-<id> so refresh / URL-bar nav opens the document, and replace the silent console.error in loadDocument with a user-facing toast. Closes #560
This commit is contained in:
@@ -152,6 +152,8 @@ import * as Modals from './modalManager.js';
|
|||||||
addDocToTabs,
|
addDocToTabs,
|
||||||
syncDocIndicator: _syncDocIndicator,
|
syncDocIndicator: _syncDocIndicator,
|
||||||
});
|
});
|
||||||
|
_maybeOpenDocFromHash();
|
||||||
|
window.addEventListener('hashchange', _maybeOpenDocFromHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Update overflow-doc-btn accent indicator, toolbar indicator, and session list icon */
|
/** Update overflow-doc-btn accent indicator, toolbar indicator, and session list icon */
|
||||||
@@ -5811,16 +5813,31 @@ import * as Modals from './modalManager.js';
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`${API_BASE}/api/document/${docId}`);
|
const res = await fetch(`${API_BASE}/api/document/${docId}`);
|
||||||
if (!res.ok) throw new Error('Not found');
|
if (!res.ok) throw new Error(res.status === 404 ? 'Not found' : `HTTP ${res.status}`);
|
||||||
const doc = await res.json();
|
const doc = await res.json();
|
||||||
addDocToTabs(doc, doc.session_id);
|
addDocToTabs(doc, doc.session_id);
|
||||||
_ensureDocPaneMounted();
|
_ensureDocPaneMounted();
|
||||||
switchToDoc(doc.id);
|
switchToDoc(doc.id);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to load document:', e);
|
console.error('Failed to load document:', e);
|
||||||
|
if (uiModule) {
|
||||||
|
const msg = e.message === 'Not found'
|
||||||
|
? 'Document not found — try opening it from the Library.'
|
||||||
|
: 'Could not open document.';
|
||||||
|
uiModule.showError(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deep-link: #document-<id> opens that document on load / URL-bar nav.
|
||||||
|
// Clicks on in-chat document anchors are handled separately (they call
|
||||||
|
// preventDefault, so they don't change the hash); this covers refresh
|
||||||
|
// and pasted/typed document URLs, which previously did nothing.
|
||||||
|
function _maybeOpenDocFromHash() {
|
||||||
|
const m = (window.location.hash || '').match(/^#document-(.+)$/);
|
||||||
|
if (m) loadDocument(m[1]);
|
||||||
|
}
|
||||||
|
|
||||||
/** Open panel and ensure a document exists, creating a session if needed */
|
/** Open panel and ensure a document exists, creating a session if needed */
|
||||||
export async function ensureDocPanel() {
|
export async function ensureDocPanel() {
|
||||||
let sessionId = _lastSessionId
|
let sessionId = _lastSessionId
|
||||||
|
|||||||
33
tests/test_document_deeplink.py
Normal file
33
tests/test_document_deeplink.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
"""Regression guards for in-chat document deep-links (#document-<id>).
|
||||||
|
|
||||||
|
The frontend module is browser-coupled (window/fetch/document) so there's
|
||||||
|
no JS unit harness for it — these pin the source-level invariants that the
|
||||||
|
404-silent-failure fix depends on. See issue #560.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
_REPO = Path(__file__).resolve().parents[1]
|
||||||
|
|
||||||
|
|
||||||
|
def test_chat_document_links_use_the_document_id():
|
||||||
|
"""The list/open tool must anchor to the real document id, not a slug —
|
||||||
|
a slug 404s against the UUID-keyed /api/document/<id> route."""
|
||||||
|
src = (_REPO / "src" / "tool_implementations.py").read_text(encoding="utf-8")
|
||||||
|
assert "(#document-{d.id})" in src
|
||||||
|
assert "(#document-{doc.id})" in src
|
||||||
|
|
||||||
|
|
||||||
|
def test_document_deeplink_handled_on_hashchange_and_load():
|
||||||
|
"""#document-<id> in the URL must open the doc on refresh / URL-bar nav,
|
||||||
|
not just on click."""
|
||||||
|
js = (_REPO / "static" / "js" / "document.js").read_text(encoding="utf-8")
|
||||||
|
assert "addEventListener('hashchange', _maybeOpenDocFromHash)" in js
|
||||||
|
assert "#document-" in js
|
||||||
|
|
||||||
|
|
||||||
|
def test_failed_document_load_surfaces_user_error():
|
||||||
|
"""A missing/failed document must tell the user, not fail silently."""
|
||||||
|
js = (_REPO / "static" / "js" / "document.js").read_text(encoding="utf-8")
|
||||||
|
assert "uiModule.showError" in js
|
||||||
|
assert "Document not found" in js
|
||||||
Reference in New Issue
Block a user