SPB Git
2.8 KB · 18 lines tsx
1import { sql } from "@/db";2import { requireUserPage } from "@/lib/auth/guard";3import { csrfToken } from "@/lib/auth/session";4import { settingsAction } from "@/lib/admin/actions";5import { Check, Csrf, Field, Notice, PageTitle } from "@/components/admin-ui";6export default async function Settings({ searchParams }: { searchParams: Promise<Record<string, string | undefined>> }) {7  const sp = await searchParams; const u = await requireUserPage(); const rows = await sql`SELECT key, value FROM settings WHERE key NOT LIKE 'private.%'`; const g = (k: string) => (rows.find((r) => r.key === k)?.value ?? {}) as Record<string, any>;8  const attr = g("site.attribution"), inst = g("site.institution"), contact = g("site.contact");9  return (<div><PageTitle title="Settings" /><Notice sp={sp} />10    <form action={settingsAction} className="space-y-6 max-w-4xl"><Csrf token={csrfToken(u)} />11      <section className="card p-4 space-y-3"><h2 className="text-lg">Institutional attribution block</h2><p className="meta">Shown in the footer and on the About page. Keep the distinction between the author's affiliation and an official institutional repository.</p><Field label="Attribution (EN)" name="attribution_en" value={attr.en} rows={4} /><Field label="Attribution (FR)" name="attribution_fr" value={attr.fr} rows={4} />12        <div className="grid sm:grid-cols-2 gap-3"><Field label="Institution name (EN)" name="inst_name_en" value={inst.name_en} /><Field label="Institution name (FR)" name="inst_name_fr" value={inst.name_fr} /><Field label="Department (EN)" name="inst_dept_en" value={inst.department_en} /><Field label="Department (FR)" name="inst_dept_fr" value={inst.department_fr} /><Field label="Institution URL" name="inst_url" value={inst.url} /></div>13        <Check label="Official logo use authorized (confirm permission and visual-identity rules before enabling; the logo file must be added to /public/brand)" name="logo_authorized" checked={inst.logo_authorized} /></section>14      <section className="card p-4 grid sm:grid-cols-3 gap-3"><h2 className="text-lg sm:col-span-3">Contact and home</h2><Field label="Contact e-mail" name="contact_email" value={contact.email} /><Field label="Website" name="contact_website" value={contact.website} /><Field label="Featured papers on home (max)" name="featured_limit" type="number" value={g("home.featured_limit") as unknown as number} /></section>15      <section className="card p-4"><h2 className="text-lg">Ingestion directories</h2><Field label="Additional absolute directories to scan for PDFs (one per line; the storage inbox is always scanned)" name="ingest_dirs" value={((rows.find((r) => r.key === "ingest.extra_dirs")?.value as string[]) ?? []).join("\n")} rows={3} /></section>16      <button className="btn btn-primary">Save settings</button></form></div>);17}18
Files · main
Menu

Theme