47 lines
2.1 KiB
JavaScript
47 lines
2.1 KiB
JavaScript
/* admin.js — shared auth + API helpers for admin pages. */
|
|
export async function api(path, method = 'GET', body) {
|
|
const res = await fetch(path, {
|
|
method,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'x-exhibit-token': localStorage.getItem('exhibitToken') || '',
|
|
},
|
|
body: body === undefined ? undefined : JSON.stringify(body),
|
|
});
|
|
if (res.status === 401) { location.href = '/admin/login.html?next=' + encodeURIComponent(location.pathname); throw new Error('unauthorized'); }
|
|
if (!res.ok) throw new Error((await res.json().catch(() => ({}))).error || res.statusText);
|
|
return res.json();
|
|
}
|
|
|
|
export async function requireAuth() {
|
|
const info = await (await fetch('/api/info')).json();
|
|
if (!info.authRequired) return info;
|
|
// probe a guarded endpoint
|
|
const res = await fetch('/api/client-errors', { headers: { 'x-exhibit-token': localStorage.getItem('exhibitToken') || '' } });
|
|
if (res.status === 401) location.href = '/admin/login.html?next=' + encodeURIComponent(location.pathname);
|
|
return info;
|
|
}
|
|
|
|
export const styles = `
|
|
:root { color-scheme: dark; }
|
|
body { margin:0; background:#0a0d18; color:#e8ecff; font-family:system-ui,sans-serif; }
|
|
header { display:flex; gap:14px; align-items:center; padding:10px 16px; background:#111730; }
|
|
header a { color:#8fb8ff; text-decoration:none; font-size:.9rem; }
|
|
header a.active { color:#51eaf1; }
|
|
h1 { font-size:1.05rem; margin:0 auto 0 0; }
|
|
button { background:#2a3a6e; color:#fff; border:0; border-radius:6px; padding:6px 14px; cursor:pointer; }
|
|
button.primary { background:linear-gradient(135deg,#51eaf1,#529eff); color:#04121a; font-weight:600; }
|
|
button.danger { background:#7a2437; }
|
|
input, select { background:#141a33; color:#fff; border:1px solid #2a3a6e; border-radius:5px; padding:4px 8px; }
|
|
label { font-size:.8rem; opacity:.85; }
|
|
`;
|
|
|
|
export function nav(active) {
|
|
return `<header>
|
|
<h1>Newbury Exhibit — Admin</h1>
|
|
${['layout', 'plan', 'playlist', 'print', 'calibrate', 'errors'].map(p =>
|
|
`<a href="/admin/${p}.html" class="${p === active ? 'active' : ''}">${p}</a>`).join('')}
|
|
<a href="/">viewer ↗</a>
|
|
</header>`;
|
|
}
|