feat(ui): shared header — Sign in/Sign out and New Chat on every page; hide the Sources nav link from anonymous users
This commit is contained in:
@@ -4,8 +4,16 @@
|
||||
* full-width document table, or the designed empty state when nothing is
|
||||
* indexed yet. Cells are built with DOM APIs (textContent) — never
|
||||
* innerHTML with document-derived data (XSS-safe by construction).
|
||||
*
|
||||
* Phase 19: the page joins the shared header (assets/header.js) — the
|
||||
* whoami gate below runs on the module's cached promise (one request per
|
||||
* page, shared with the header toggling), and the header gains the New
|
||||
* chat button: on a non-chat page "new chat" means going to the chat,
|
||||
* fresh (clear the phase-14 conversation key, then navigate to "/").
|
||||
*/
|
||||
|
||||
import { clearChatStorage, fetchIsAdmin, initSharedHeader } from "/assets/header.js";
|
||||
|
||||
const tbody = document.querySelector("#docs-tbody");
|
||||
const emptyEl = document.querySelector("#sources-empty");
|
||||
const tableWrap = document.querySelector(".table-wrap");
|
||||
@@ -18,13 +26,22 @@ const statLast = document.querySelector("#stat-last");
|
||||
/* Phase 16: whoami BEFORE the docs fetch. Anonymous visitors get the
|
||||
* sign-in gate (stat cards + table hidden) and NO /api/docs call — the
|
||||
* catalog is admin-only. The document viewer itself stays public (the
|
||||
* soft rule), so the gate copy points at what keeps working. */
|
||||
async function isAdmin() {
|
||||
try {
|
||||
const r = await fetch("/api/whoami");
|
||||
if (r.ok) return (await r.json()).authenticated === true;
|
||||
} catch { /* API unreachable: anonymous-safe gate */ }
|
||||
return false;
|
||||
* soft rule), so the gate copy points at what keeps working.
|
||||
* Phase 19: the whoami request is the shared header module's cached
|
||||
* promise — the same single request initSharedHeader() awaited. */
|
||||
function isAdmin() {
|
||||
return fetchIsAdmin();
|
||||
}
|
||||
|
||||
/* Phase 19: New chat on a non-chat page means "go to the chat, fresh":
|
||||
* clear the phase-14 conversation key, then land on the chat page — its
|
||||
* empty state, since the conversation is gone from storage. */
|
||||
const newChatBtn = document.querySelector("#new-chat-btn");
|
||||
if (newChatBtn) {
|
||||
newChatBtn.addEventListener("click", () => {
|
||||
clearChatStorage();
|
||||
window.location.href = "/";
|
||||
});
|
||||
}
|
||||
|
||||
function fmtDate(iso) {
|
||||
@@ -112,6 +129,7 @@ function showEmpty() {
|
||||
}
|
||||
|
||||
(async () => {
|
||||
await initSharedHeader(); // phase 19: Sign in/out + Sources link in the shared bar
|
||||
if (!(await isAdmin())) {
|
||||
// Anonymous: gate in, catalog out, and no /api/docs request at all.
|
||||
if (statCards) statCards.hidden = true;
|
||||
|
||||
Reference in New Issue
Block a user