118 lines
7.5 KiB
HTML
118 lines
7.5 KiB
HTML
{{/*
|
|
Admin surface — matches switchboard-prototype-admin.jsx.
|
|
Full-page layout: topbar (with category tabs) + left nav + content area.
|
|
JS (admin-handlers.js, ui-admin.js) populates dynamic sections.
|
|
*/}}
|
|
|
|
{{define "surface-admin"}}
|
|
<div class="surface-admin">
|
|
|
|
{{/* Top Bar */}}
|
|
<div class="admin-topbar">
|
|
<a href="{{.BasePath}}/" class="admin-topbar-back">
|
|
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg>
|
|
Back to Chat
|
|
</a>
|
|
<div class="admin-topbar-sep"></div>
|
|
<span class="admin-topbar-title">🔀 Administration</span>
|
|
|
|
{{/* Category tabs */}}
|
|
<div class="admin-category-tabs" id="adminCategoryTabs">
|
|
{{$section := .Section}}
|
|
{{$base := .BasePath}}
|
|
<a href="{{$base}}/admin/users" class="admin-cat-btn{{if eq $section "users"}} active{{else if eq $section "teams"}} active{{else if eq $section "groups"}} active{{end}}" data-cat="people">
|
|
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/></svg>
|
|
People
|
|
</a>
|
|
<a href="{{$base}}/admin/providers" class="admin-cat-btn{{if eq $section "providers"}} active{{else if eq $section "models"}} active{{else if eq $section "personas"}} active{{else if eq $section "roles"}} active{{else if eq $section "knowledgeBases"}} active{{else if eq $section "memory"}} active{{end}}" data-cat="ai">
|
|
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="4" y="4" width="16" height="16" rx="2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/></svg>
|
|
AI
|
|
</a>
|
|
<a href="{{$base}}/admin/health" class="admin-cat-btn{{if eq $section "health"}} active{{else if eq $section "routing"}} active{{else if eq $section "capabilities"}} active{{end}}" data-cat="routing">
|
|
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
|
|
Routing
|
|
</a>
|
|
<a href="{{$base}}/admin/settings" class="admin-cat-btn{{if eq $section "settings"}} active{{else if eq $section "storage"}} active{{else if eq $section "extensions"}} active{{end}}" data-cat="system">
|
|
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09"/></svg>
|
|
System
|
|
</a>
|
|
<a href="{{$base}}/admin/usage" class="admin-cat-btn{{if eq $section "usage"}} active{{else if eq $section "audit"}} active{{else if eq $section "stats"}} active{{end}}" data-cat="monitoring">
|
|
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>
|
|
Monitoring
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="admin-body">
|
|
{{/* Left Nav */}}
|
|
<div class="admin-nav" id="adminNav">
|
|
{{/* People sections */}}
|
|
{{if eq $section "users"}}<a href="{{$base}}/admin/users" class="admin-nav-link active">Users</a>
|
|
{{else}}<a href="{{$base}}/admin/users" class="admin-nav-link">Users</a>{{end}}
|
|
{{if eq $section "teams"}}<a href="{{$base}}/admin/teams" class="admin-nav-link active">Teams</a>
|
|
{{else}}<a href="{{$base}}/admin/teams" class="admin-nav-link">Teams</a>{{end}}
|
|
{{if eq $section "groups"}}<a href="{{$base}}/admin/groups" class="admin-nav-link active">Groups</a>
|
|
{{else}}<a href="{{$base}}/admin/groups" class="admin-nav-link">Groups</a>{{end}}
|
|
</div>
|
|
|
|
{{/* Content Area */}}
|
|
<div class="admin-content">
|
|
<div class="admin-content-header">
|
|
<h2 id="adminSectionTitle">{{$section}}</h2>
|
|
<div style="flex:1;"></div>
|
|
<div class="admin-search">
|
|
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="color:var(--text-3);flex-shrink:0;"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
|
|
<input id="adminSearch" placeholder="Search…" autocomplete="off">
|
|
</div>
|
|
<button id="adminAddBtn" class="btn-md btn-primary" style="display:none;">
|
|
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
|
|
Add
|
|
</button>
|
|
</div>
|
|
<div class="admin-content-body" id="adminContentBody" data-section="{{$section}}">
|
|
{{/* Populated by admin-handlers.js */}}
|
|
<div class="settings-placeholder" id="adminDynamic">Loading…</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="toastContainer" class="toast-container"></div>
|
|
|
|
{{/* Confirm dialog */}}
|
|
<div id="confirmModal" class="modal-overlay">
|
|
<div class="modal" style="max-width:380px;">
|
|
<div class="modal-header">
|
|
<h2 id="confirmTitle">Confirm</h2>
|
|
<button class="modal-close" onclick="closeModal('confirmModal')">✕</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p id="confirmMessage" style="color:var(--text-2);font-size:14px;line-height:1.65;"></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn-md btn-ghost" onclick="closeModal('confirmModal')">Cancel</button>
|
|
<button id="confirmOkBtn" class="btn-md btn-danger">Confirm</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{/* CSS: loaded via base.html (variables, layout, primitives, modals, chat, panels, surfaces, splash) */}}
|
|
{{define "css-admin"}}{{end}}
|
|
|
|
{{/* Scripts */}}
|
|
{{define "scripts-admin"}}
|
|
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/vendor/marked.min.js"></script>
|
|
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/vendor/purify.min.js"></script>
|
|
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/ui-format.js?v={{.Version}}"></script>
|
|
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/ui-settings.js?v={{.Version}}"></script>
|
|
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/ui-admin.js?v={{.Version}}"></script>
|
|
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/admin-handlers.js?v={{.Version}}"></script>
|
|
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/settings-handlers.js?v={{.Version}}"></script>
|
|
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/knowledge-ui.js?v={{.Version}}"></script>
|
|
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/persona-kb.js?v={{.Version}}"></script>
|
|
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/memory-ui.js?v={{.Version}}"></script>
|
|
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/notifications.js?v={{.Version}}"></script>
|
|
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/admin-scaffold.js?v={{.Version}}"></script>
|
|
{{end}}
|