mirror of
https://github.com/BetterCorp/BetterFrame.git
synced 2026-05-27 01:46:35 +00:00
feat: global Settings page for AbleSign + Cloud Cam account config
- New /admin/settings page with AbleSign account setup (API key) and link to Cloud Cams config - Settings nav item in sidebar (gear icon, before Account) - Removed AbleSign Config from AbleSign dropdown (now in Settings) - AbleSign account delete redirects to Settings - Cloud Cams nav item kept for its own CRUD page Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f0088836e9
commit
d6a52df27a
4 changed files with 78 additions and 3 deletions
|
|
@ -217,7 +217,7 @@ export function registerAbleSignRoutes(app: H3, deps: AdminDeps): void {
|
|||
app.post("/admin/ablesign/:id/delete", async (event) => {
|
||||
const id = getRouterParam(event, "id") ?? "";
|
||||
await deps.repo.deleteAbleSignAccount(id);
|
||||
return new Response(null, { status: 302, headers: { location: "/admin/ablesign" } });
|
||||
return new Response(null, { status: 302, headers: { location: "/admin/settings" } });
|
||||
});
|
||||
|
||||
app.post("/admin/ablesign/screens/:sid/delete", async (event) => {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import {
|
|||
renderKioskLabels,
|
||||
renderDisplayLayouts,
|
||||
renderDefaultLayoutSelect,
|
||||
SettingsPage,
|
||||
} from "../../web-templates/admin-pages.js";
|
||||
import { discover as onvifDiscover, getEventProperties as onvifGetEventProperties } from "../../shared/onvif.js";
|
||||
import { generateBundle } from "../../shared/bundle.js";
|
||||
|
|
@ -2219,6 +2220,14 @@ export function registerAdminRoutes(app: H3, deps: AdminDeps): void {
|
|||
return new Response(null, { status: 302, headers: { location: `/admin/kiosks/${id}` } });
|
||||
});
|
||||
|
||||
// ---- Settings page ----------------------------------------------------------
|
||||
|
||||
app.get("/admin/settings", async () => {
|
||||
const cloudAccounts = await deps.repo.listCloudAccounts();
|
||||
const ablesignAccounts = await deps.repo.listAbleSignAccounts();
|
||||
return htmlPage(SettingsPage({ cloudAccounts, ablesignAccounts }));
|
||||
});
|
||||
|
||||
// ---- Tenant switcher fragment (htmx) ----------------------------------------
|
||||
app.get("/admin/_tenant_switcher", async (event) => {
|
||||
const tenants = await deps.repo.listTenants();
|
||||
|
|
|
|||
|
|
@ -4380,6 +4380,73 @@ export function TenantEditPage(props: TenantEditPageProps) {
|
|||
);
|
||||
}
|
||||
|
||||
// ---- Settings Page ----------------------------------------------------------
|
||||
|
||||
interface SettingsPageProps {
|
||||
cloudAccounts: any[];
|
||||
ablesignAccounts: any[];
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export function SettingsPage(props: SettingsPageProps) {
|
||||
return (
|
||||
<Layout title="Settings" activeNav="settings">
|
||||
<h1 style="font-size:1.5rem; margin:0 0 1.5rem">Settings</h1>
|
||||
|
||||
{props.error ? <div class="alert alert-error" style="margin-bottom:1rem">{props.error}</div> : ""}
|
||||
|
||||
<div class="card" style="margin-bottom:1.5rem">
|
||||
<h2 style="font-size:1.1rem; margin:0 0 1rem">AbleSign Account</h2>
|
||||
{props.ablesignAccounts.length > 0 ? (
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead><tr><th>Name</th><th>Screens</th><th>Last Sync</th><th>Actions</th></tr></thead>
|
||||
<tbody>
|
||||
{props.ablesignAccounts.map((a: any) => (
|
||||
<tr>
|
||||
<td>{a.name}</td>
|
||||
<td>{String(a.screen_count ?? 0)}</td>
|
||||
<td style="font-size:0.85rem">{a.last_sync_at ? formatTime(a.last_sync_at) : "Never"}</td>
|
||||
<td>
|
||||
<form method="POST" action={`/admin/ablesign/${String(a.id)}/delete`} style="display:inline">
|
||||
<button type="submit" class="btn btn-sm btn-ghost" style="color:#c00">Remove</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
) : (
|
||||
<form method="POST" action="/admin/ablesign/add" style="display:flex; gap:0.5rem; flex-wrap:wrap; align-items:end">
|
||||
<label style="font-size:0.85rem">
|
||||
{"Name"}<br/>
|
||||
<input type="text" name="name" required style="width:10rem" placeholder="My AbleSign" />
|
||||
</label>
|
||||
<label style="font-size:0.85rem">
|
||||
{"API Key"}<br/>
|
||||
<input type="password" name="api_key" required style="width:14rem" placeholder="ak_..." />
|
||||
</label>
|
||||
<label style="font-size:0.85rem">
|
||||
{"Workspace ID"}<br/>
|
||||
<input type="text" name="workspace_id" style="width:6rem" />
|
||||
</label>
|
||||
<button type="submit" class="btn btn-sm">Connect</button>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div class="card" style="margin-bottom:1.5rem">
|
||||
<h2 style="font-size:1.1rem; margin:0 0 1rem">Cloud Camera Accounts</h2>
|
||||
<p style="font-size:0.85rem; color:#999">
|
||||
{"Manage cloud camera integrations at "}
|
||||
<a href="/admin/cloud-accounts">Cloud Cams</a>.
|
||||
</p>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
// ---- AbleSign Pages ---------------------------------------------------------
|
||||
|
||||
interface AbleSignPageProps {
|
||||
|
|
|
|||
|
|
@ -71,18 +71,17 @@ function Sidebar(props: { activeNav?: string }) {
|
|||
<NavItem href="/admin/kiosks" label="Kiosks" icon="◈" active={a === "kiosks"} />
|
||||
<NavItem href="/admin/firmware" label="Firmware" icon="▲" active={a === "firmware"} />
|
||||
<NavItem href="/admin/os-updates" label="OS Updates" icon="●" active={a === "os-updates"} />
|
||||
<NavItem href="/admin/cloud-accounts" label="Cloud Cams" icon="☁" active={a === "cloud"} />
|
||||
<NavGroup label="AbleSign" icon="▶" active={a?.startsWith("ablesign")}>
|
||||
<NavItem href="/admin/ablesign/screens" label="Screens" icon=" " active={a === "ablesign-screens"} />
|
||||
<NavItem href="/admin/ablesign/content" label="Content" icon=" " active={a === "ablesign-content"} />
|
||||
<NavItem href="/admin/ablesign/playlists" label="Playlists" icon=" " active={a === "ablesign-playlists"} />
|
||||
<NavItem href="/admin/ablesign" label="Config" icon=" " active={a === "ablesign"} />
|
||||
</NavGroup>
|
||||
<NavItem href="/admin/labels" label="Labels" icon="◆" active={a === "labels"} />
|
||||
<NavItem href="/admin/audit" label="Audit" icon="◎" active={a === "audit"} />
|
||||
<NavItem href="/admin/backup" label="Backup" icon="☼" active={a === "backup"} />
|
||||
<NavItem href="/admin/tenants" label="Tenants" icon="☷" active={a === "tenants"} />
|
||||
<hr />
|
||||
<NavItem href="/admin/settings" label="Settings" icon="⚙" active={a === "settings"} />
|
||||
<NavItem href="/admin/account" label="Account" icon="●" active={a === "account"} />
|
||||
<NavItem href="/admin/nodered" label="Node-RED" icon="→" active={a === "nodered"} />
|
||||
<div class="tenant-switcher" {...{"hx-get": "/admin/_tenant_switcher", "hx-trigger": "load", "hx-swap": "innerHTML"}}></div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue