45 lines
3.7 KiB
HTML
45 lines
3.7 KiB
HTML
<!doctype html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>{% block title %}Onyscribe Admin{% endblock %}</title>
|
||
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='14' fill='%231a1a1a'/%3E%3Cpath d='M20 22l14 10-14 10' fill='none' stroke='%2300cccc' stroke-width='7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E">
|
||
<link rel="stylesheet" href="/static/admin.css?v={{ static_v('admin.css') }}">
|
||
</head>
|
||
<body>
|
||
<aside class="side">
|
||
<div class="brand"><b>onyva</b><span>Scribe Admin</span></div>
|
||
<nav class="nav">
|
||
<a href="/" class="{{ 'on' if nav=='dashboard' }}"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></svg><span>Tenants</span></a>
|
||
<a href="/deployments" class="{{ 'on' if nav=='deployments' }}"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v12m0 0l-4-4m4 4l4-4M4 19h16"/></svg><span>Deployments</span></a>
|
||
<a href="/core" class="{{ 'on' if nav=='core' }}"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2l9 5v10l-9 5-9-5V7z"/><path d="M12 22V12M3 7l9 5 9-5"/></svg><span>Core</span></a>
|
||
<a href="/settings" class="{{ 'on' if nav=='settings' }}"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="3"/><path d="M12 2v3m0 14v3M2 12h3m14 0h3M5 5l2 2m10 10l2 2M19 5l-2 2M7 17l-2 2"/></svg><span>Einstellungen</span></a>
|
||
<a href="/audit" class="{{ 'on' if nav=='audit' }}"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 6h11M9 12h11M9 18h11M4 6h.01M4 12h.01M4 18h.01"/></svg><span>Audit-Log</span></a>
|
||
</nav>
|
||
<div class="side-foot">
|
||
<span class="pill {{ 'live' if deploy_live() else 'lock' }}" title="Env DEPLOY_LIVE der Admin-Plattform">Deploy: {{ 'live' if deploy_live() else 'gesperrt · Dry-Run' }}</span>
|
||
{% set u = request.state.user if request is defined else None %}
|
||
{% if u and u.email and u.email != 'dev@local' %}<span>{{ u.email }}<br><a href="/auth/logout">Abmelden</a></span>{% else %}<span class="pill live" title="AUTH_ENABLED ist nicht true: jeder mit der URL hat vollen Zugriff. Live-Aktionen sind gesperrt.">Login aus – offen!</span>{% endif %}
|
||
</div>
|
||
</aside>
|
||
<div class="main">{% block body %}{% endblock %}</div>
|
||
<div id="toast"></div>
|
||
<script>
|
||
function toast(msg, err){const t=document.getElementById('toast');t.textContent=msg;t.className=err?'err':'';t.style.display='block';clearTimeout(window._tt);window._tt=setTimeout(()=>t.style.display='none',3200)}
|
||
async function api(method, url, body){
|
||
const o={method,headers:{}};
|
||
if(body!==undefined){o.headers['Content-Type']='application/json';o.body=JSON.stringify(body)}
|
||
const r=await fetch(url,o);
|
||
let d=null;try{d=await r.json()}catch(e){}
|
||
if(!r.ok){throw new Error((d&&(d.detail||d.message))||('Fehler '+r.status))}
|
||
return d;
|
||
}
|
||
const esc=s=>String(s??'').replace(/[&<>"]/g,c=>({'&':'&','<':'<','>':'>','"':'"'}[c]));
|
||
function modal(id,on){document.getElementById(id).classList.toggle('on',on)}
|
||
function fmt(d){return d?new Date(d).toLocaleString('de-DE',{day:'2-digit',month:'2-digit',year:'numeric',hour:'2-digit',minute:'2-digit'}):'–'}
|
||
</script>
|
||
{% block scripts %}{% endblock %}
|
||
</body>
|
||
</html>
|