fix: api/keys endpoint + logout button
This commit is contained in:
parent
314f8603aa
commit
9e7a974538
Binary file not shown.
|
|
@ -1,251 +1,44 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="fr" class="dark">
|
<html lang="fr">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>{% block title %}context-hub | Nyora Infrastructure{% endblock %}</title>
|
<title>{% block title %}CONCEPT | Nyora{% endblock %}</title>
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
|
||||||
<script>
|
|
||||||
tailwind.config = {
|
|
||||||
darkMode: "class",
|
|
||||||
theme: { extend: { colors: { nyora: "#d4a01a", "nyora-dark": "#a07810" } } }
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
body { font-family: "Inter", sans-serif; }
|
* { box-sizing: border-box; }
|
||||||
|
html, body { margin: 0; padding: 0; height: 100%; }
|
||||||
|
body { font-family: 'Inter', system-ui, sans-serif; background: #0d0d0d; color: #e8e6e3; -webkit-font-smoothing: antialiased; overflow: hidden; }
|
||||||
|
::-webkit-scrollbar { width: 10px; height: 10px; }
|
||||||
|
::-webkit-scrollbar-thumb { background: #262626; border-radius: 6px; border: 2px solid #0d0d0d; }
|
||||||
|
::-webkit-scrollbar-track { background: transparent; }
|
||||||
|
input, select, button, textarea { font-family: inherit; outline: none; }
|
||||||
|
@keyframes toastIn { from { opacity:0; transform:translateY(10px); } to { opacity:1; transform:translateY(0); } }
|
||||||
|
@keyframes pulse { 0%,100% { opacity:1; } 50% { opacity:.35; } }
|
||||||
|
|
||||||
/* ── BACKGROUNDS ── */
|
.hover-bg-17:hover { background: #171717 !important; color: #e8e6e3 !important; }
|
||||||
.bg-app {
|
.hover-bg-10:hover { background: #101010 !important; }
|
||||||
background: #0a0e1a;
|
.hover-border-3a:hover { border-color: #3a3a3a !important; color: #e8e6e3 !important; }
|
||||||
background-image:
|
.hover-border-5a:hover { border-color: #5a352f !important; color: #c47a6e !important; }
|
||||||
radial-gradient(ellipse at 15% 40%, rgba(29,78,216,0.12) 0%, transparent 55%),
|
.hover-card:hover { background: #151515 !important; border-color: #2c2c2c !important; }
|
||||||
radial-gradient(ellipse at 85% 15%, rgba(212,160,26,0.08) 0%, transparent 50%),
|
.hover-btn-add:hover { background: #e08864 !important; }
|
||||||
radial-gradient(ellipse at 55% 85%, rgba(109,40,217,0.08) 0%, transparent 50%);
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
/* HF Storage light mode : fond blanc pur + ticker + sections */
|
|
||||||
html:not(.dark) body {
|
|
||||||
background: #ffffff;
|
|
||||||
}
|
|
||||||
html:not(.dark) body::before {
|
|
||||||
content: '';
|
|
||||||
position: fixed; inset: 0; pointer-events: none; z-index: -1;
|
|
||||||
background: #f8fafc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── GLASS ── */
|
/* NYORA FOOTER */
|
||||||
.glass-dark {
|
.nyora-footer { text-align: center; padding: 1.5rem 1rem 1rem 1rem; width: 100%; margin-top: auto; }
|
||||||
background: rgba(15,22,46,0.72);
|
.nyora-line-top { height: 1px; background: linear-gradient(90deg, transparent, #d4a01a, transparent); margin-bottom: 1rem; opacity: 0.5; }
|
||||||
backdrop-filter: blur(20px) saturate(180%);
|
.nyora-brand { display: flex; align-items: center; justify-content: center; gap: 0.4rem; margin-bottom: 0.2rem; }
|
||||||
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
.nyora-dot { width: 4px; height: 4px; background: #d4a01a; border-radius: 50%; }
|
||||||
border: 1px solid rgba(255,255,255,0.07);
|
.nyora-name { font-size: 0.75rem; font-weight: 800; letter-spacing: 0.3em; color: #d4a01a; font-family: Georgia, serif; }
|
||||||
box-shadow: 0 8px 32px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.05);
|
.nyora-tag { font-size: 0.65rem; color: #6a6863; letter-spacing: 0.05em; font-style: italic; }
|
||||||
}
|
|
||||||
.glass-light {
|
|
||||||
background: #ffffff;
|
|
||||||
border: 1px solid #e2e8f0;
|
|
||||||
box-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 4px 16px rgba(0,0,0,0.04);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── CARD 4D ── */
|
/* Dr Nexum Progress */
|
||||||
.card-4d {
|
.progress-bar-bg { background: #1c1c1c; height: 6px; border-radius: 3px; overflow: hidden; margin-top: 6px; }
|
||||||
border-radius: 1rem;
|
.progress-bar-fg { height: 100%; border-radius: 3px; transition: width 0.3s; }
|
||||||
overflow: hidden;
|
|
||||||
transition: all 0.35s cubic-bezier(0.4,0,0.2,1);
|
|
||||||
transform-style: preserve-3d;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.card-4d::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
border-radius: inherit;
|
|
||||||
background: linear-gradient(135deg, rgba(255,255,255,0.04) 0%, transparent 60%);
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.card-4d:hover {
|
|
||||||
transform: translateY(-5px) perspective(800px) rotateX(1.5deg) rotateY(-0.5deg);
|
|
||||||
}
|
|
||||||
.dark .card-4d:hover {
|
|
||||||
box-shadow: 0 24px 64px rgba(0,0,0,0.5), 0 0 0 1px rgba(212,160,26,0.2);
|
|
||||||
}
|
|
||||||
.light .card-4d:hover, html:not(.dark) .card-4d:hover {
|
|
||||||
box-shadow: 0 24px 64px rgba(99,102,241,0.15), 0 0 0 1px rgba(212,160,26,0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── NAV ── */
|
|
||||||
.nav-bar {
|
|
||||||
position: sticky; top: 0; z-index: 100;
|
|
||||||
backdrop-filter: blur(24px) saturate(200%);
|
|
||||||
-webkit-backdrop-filter: blur(24px) saturate(200%);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── TOGGLE THEME ── */
|
|
||||||
.theme-btn {
|
|
||||||
display: flex; align-items: center; gap: 6px;
|
|
||||||
padding: 6px 14px;
|
|
||||||
border-radius: 999px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 0.78rem;
|
|
||||||
font-weight: 600;
|
|
||||||
letter-spacing: 0.03em;
|
|
||||||
border: 1.5px solid rgba(212,160,26,0.6);
|
|
||||||
color: #d4a01a;
|
|
||||||
background: rgba(212,160,26,0.1);
|
|
||||||
transition: all 0.2s;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
.theme-btn:hover { background: rgba(212,160,26,0.2); border-color: #d4a01a; transform: scale(1.04); }
|
|
||||||
.theme-btn .icon { font-size: 0.9rem; }
|
|
||||||
|
|
||||||
/* ── NYORA FOOTER ── */
|
|
||||||
.nyora-footer { text-align: center; position: relative; padding: 0; }
|
|
||||||
.nyora-line-top {
|
|
||||||
height: 1px;
|
|
||||||
background: linear-gradient(90deg, transparent, rgba(212,160,26,0.4), #d4a01a, rgba(212,160,26,0.4), transparent);
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
.nyora-brand { display: flex; align-items: center; justify-content: center; gap: 0.6rem; margin-bottom: 0.35rem; }
|
|
||||||
.nyora-dot { width: 5px; height: 5px; background: #d4a01a; border-radius: 50%; }
|
|
||||||
.nyora-name { font-size: 0.82rem; font-weight: 800; letter-spacing: 0.4em; color: #d4a01a; font-family: Georgia, serif; }
|
|
||||||
.nyora-tag { font-size: 0.7rem; letter-spacing: 0.08em; font-style: italic; margin-bottom: 0.2rem; }
|
|
||||||
.nyora-year { font-size: 0.65rem; letter-spacing: 0.05em; }
|
|
||||||
|
|
||||||
/* ── HF TICKER ── */
|
|
||||||
.hf-ticker {
|
|
||||||
display: none;
|
|
||||||
overflow: hidden;
|
|
||||||
background: #1a1a2e;
|
|
||||||
color: rgba(255,255,255,0.35);
|
|
||||||
font-family: monospace;
|
|
||||||
font-size: 0.72rem;
|
|
||||||
letter-spacing: 0.08em;
|
|
||||||
padding: 7px 0;
|
|
||||||
white-space: nowrap;
|
|
||||||
border-bottom: 1px solid rgba(255,255,255,0.05);
|
|
||||||
}
|
|
||||||
html:not(.dark) .hf-ticker { display: block; }
|
|
||||||
.hf-ticker-inner {
|
|
||||||
display: inline-block;
|
|
||||||
animation: ticker 28s linear infinite;
|
|
||||||
}
|
|
||||||
@keyframes ticker {
|
|
||||||
0% { transform: translateX(0); }
|
|
||||||
100% { transform: translateX(-50%); }
|
|
||||||
}
|
|
||||||
/* nav clair HF */
|
|
||||||
html:not(.dark) nav.nav-bar {
|
|
||||||
box-shadow: 0 1px 3px rgba(0,0,0,0.04);
|
|
||||||
}
|
|
||||||
html:not(.dark) body {
|
|
||||||
background: #f8fafc;
|
|
||||||
color: #0f172a;
|
|
||||||
}
|
|
||||||
/* section headers colorés style HF en mode clair */
|
|
||||||
html:not(.dark) .hf-header {
|
|
||||||
}
|
|
||||||
html:not(.dark) .hf-tag {
|
|
||||||
filter: brightness(0.85) saturate(1.2);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
<link rel="stylesheet" href="/static/style.css">
|
|
||||||
|
|
||||||
<script>
|
|
||||||
(function(){
|
|
||||||
var t = localStorage.getItem("ctx-theme") || "dark";
|
|
||||||
if(t === "light") document.documentElement.classList.remove("dark");
|
|
||||||
else document.documentElement.classList.add("dark");
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
<body id="app-body" class="bg-app min-h-screen flex flex-col transition-all duration-300">
|
<body>
|
||||||
|
{% block content %}{% endblock %}
|
||||||
< HF-style ticker (mode clair uniquement) -->
|
|
||||||
<div class="hf-ticker" aria-hidden="true">
|
|
||||||
<span class="hf-ticker-inner">
|
|
||||||
+ = · ( ~ @ · # % · & * ? · / : · ; < > · [ ] · { }
|
|
||||||
context-hub · NYORA INFRASTRUCTURE ·
|
|
||||||
infra · llm · nyora · perso · tt ·
|
|
||||||
+ = · ( ~ @ · # % · & * ? · / : · ; < > · [ ] · { }
|
|
||||||
context-hub · NYORA INFRASTRUCTURE ·
|
|
||||||
infra · llm · nyora · perso · tt ·
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if request.url.path != "/login" %}
|
|
||||||
<nav class="nav-bar dark:bg-gray-950/90 bg-white/90 dark:border-white/5 border-gray-200/80 border-b">
|
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
||||||
<div class="flex items-center justify-between h-14">
|
|
||||||
<div class="flex items-center gap-8">
|
|
||||||
<a href="/dashboard" class="flex items-center gap-2 no-underline group">
|
|
||||||
<div class="w-7 h-7 rounded-lg flex items-center justify-center"
|
|
||||||
style="background:linear-gradient(135deg,#d4a01a,#f0b429)">
|
|
||||||
<span class="text-xs font-black text-gray-900">C</span>
|
|
||||||
</div>
|
|
||||||
<span class="font-black text-sm tracking-widest dark:text-white text-gray-900">CONTEXT<span class="text-nyora">-HUB</span></span>
|
|
||||||
</a>
|
|
||||||
<div class="hidden md:flex items-center gap-1">
|
|
||||||
<a href="/dashboard" class="px-3 py-1.5 rounded-lg text-xs font-medium dark:text-gray-400 text-gray-600 dark:hover:text-white hover:text-gray-900 dark:hover:bg-white/5 hover:bg-gray-100 transition-all">Dashboard</a>
|
|
||||||
<a href="/audit" class="px-3 py-1.5 rounded-lg text-xs font-medium dark:text-gray-400 text-gray-600 dark:hover:text-white hover:text-gray-900 dark:hover:bg-white/5 hover:bg-gray-100 transition-all">Audit</a>
|
|
||||||
<a href="/keys" class="px-3 py-1.5 rounded-lg text-xs font-medium dark:text-gray-400 text-gray-600 dark:hover:text-white hover:text-gray-900 dark:hover:bg-white/5 hover:bg-gray-100 transition-all">API Keys</a>
|
|
||||||
<a href="/docs" class="px-3 py-1.5 rounded-lg text-xs font-medium dark:text-gray-400 text-gray-600 dark:hover:text-white hover:text-gray-900 dark:hover:bg-white/5 hover:bg-gray-100 transition-all">Docs</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center gap-3">
|
|
||||||
<button class="theme-btn" onclick="toggleTheme()" id="theme-btn">
|
|
||||||
<span class="icon" id="theme-icon">☀️</span>
|
|
||||||
<span id="theme-label">Clair</span>
|
|
||||||
</button>
|
|
||||||
<a href="/auth/logout" class="px-3 py-1.5 rounded-lg text-xs font-medium dark:text-gray-400 text-gray-600 dark:hover:text-red-400 hover:text-red-500 transition-all">Déconnexion</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<main class="flex-grow w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
||||||
{% block content %}{% endblock %}
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer class="nyora-footer mt-12">
|
|
||||||
<div class="nyora-line-top"></div>
|
|
||||||
<div class="pb-8">
|
|
||||||
<div class="nyora-brand">
|
|
||||||
<span class="nyora-dot"></span>
|
|
||||||
<span class="nyora-name">NYORA</span>
|
|
||||||
<span class="nyora-dot"></span>
|
|
||||||
</div>
|
|
||||||
<div class="nyora-tag dark:text-gray-500 text-gray-400">Crafted with precision · Built for excellence</div>
|
|
||||||
<div class="nyora-year dark:text-gray-600 text-gray-400">© 2026</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function updateThemeUI(isDark) {
|
|
||||||
var icon = document.getElementById("theme-icon");
|
|
||||||
var label = document.getElementById("theme-label");
|
|
||||||
if (!icon) return;
|
|
||||||
if (isDark) { icon.textContent = "☀️"; label.textContent = "Clair"; }
|
|
||||||
else { icon.textContent = "🌙"; label.textContent = "Sombre"; }
|
|
||||||
}
|
|
||||||
function toggleTheme() {
|
|
||||||
var html = document.documentElement;
|
|
||||||
var isDark = html.classList.contains("dark");
|
|
||||||
if (isDark) {
|
|
||||||
html.classList.remove("dark");
|
|
||||||
localStorage.setItem("ctx-theme","light");
|
|
||||||
updateThemeUI(false);
|
|
||||||
} else {
|
|
||||||
html.classList.add("dark");
|
|
||||||
localStorage.setItem("ctx-theme","dark");
|
|
||||||
updateThemeUI(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
document.addEventListener("DOMContentLoaded", function(){
|
|
||||||
updateThemeUI(document.documentElement.classList.contains("dark"));
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue