ernestmindres commited on
Commit
f0e5c0b
·
verified ·
1 Parent(s): 9f6bae5

Update templates/api_key.html

Browse files
Files changed (1) hide show
  1. templates/api_key.html +160 -44
templates/api_key.html CHANGED
@@ -1,5 +1,5 @@
1
  <!DOCTYPE html>
2
- <html lang="fr">
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -9,9 +9,89 @@
9
  <link rel="stylesheet"
10
  href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@24,400,0,0" />
11
  <style>
12
- /* Configuration de la police Inter et thème sombre */
13
  body { font-family: 'Inter', sans-serif; }
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  /* Style pour les boutons et cartes carrés (Artboard) */
16
  .btn-square, .card-square {
17
  border-radius: 0; /* Supprime l'arrondi */
@@ -19,14 +99,14 @@
19
 
20
  /* Styles spécifiques pour le chargement/spinner */
21
  .spinner {
22
- border-top-color: var(--spinner-color); /* Utilisation de variable */
23
  animation: spin 1s linear infinite;
24
  }
25
  @keyframes spin {
26
  to { transform: rotate(360deg); }
27
  }
28
 
29
- /* Style pour la Sidebar - FIXE et complète (Correction pour la stabilité) */
30
  .sidebar {
31
  transition: transform 0.3s ease-in-out;
32
  transform: translateX(-100%);
@@ -41,76 +121,80 @@
41
  transform: translateX(0);
42
  }
43
 
44
- /* Sur les grands écrans, la sidebar est statique et toujours visible */
45
  @media (min-width: 1024px) {
46
  .sidebar {
47
  transform: translateX(0) !important;
48
- position: static;
49
- height: auto;
50
  }
51
  }
52
 
53
- /* Conteneur principal pour décaler le contenu sur les grands écrans */
 
54
  @media (min-width: 1024px) {
55
  .main-content {
56
- margin-left: 256px; /* Doit correspondre à la largeur de la sidebar (w-64) */
57
  }
58
  }
59
-
60
  </style>
61
  </head>
62
 
63
- <body class="bg-gray-900 text-gray-100 min-h-screen">
64
 
65
- <aside id="sidebar" class="sidebar w-64 bg-gray-800 border-r border-gray-700 p-6 lg:block">
 
 
 
 
66
  <div class="flex items-center mb-10">
67
  <img src="https://i.imgur.com/7Gn3toV.png" alt="Nexus Pro Logo" class="h-8">
68
- <span class="text-xl font-bold text-white ml-2">Nexus Pro</span>
69
  </div>
70
 
71
  <nav class="space-y-3">
72
- <a href="{{ url_for('user_bp.dashboard') }}" class="flex items-center p-3 text-gray-300 hover:text-white hover:bg-gray-700 rounded-lg transition duration-150">
73
  <span class="material-symbols-rounded">dashboard</span>
74
  <span class="ml-3">Dashboard</span>
75
  </a>
76
- <a href="{{ url_for('user_bp.api_keys') }}" class="flex items-center p-3 bg-gray-700 text-white rounded-lg transition duration-150">
77
  <span class="material-symbols-rounded">key</span>
78
  <span class="ml-3">Clés API</span>
79
  </a>
80
- <a href="{{ url_for('user_bp.api_logs') }}" class="flex items-center p-3 text-gray-300 hover:text-white hover:bg-gray-700 rounded-lg transition duration-150">
81
  <span class="material-symbols-rounded">list_alt</span>
82
  <span class="ml-3">Logs d'API</span>
83
  </a>
84
- <a href="{{ url_for('user_bp.profile') }}" class="flex items-center p-3 text-gray-300 hover:text-white hover:bg-gray-700 rounded-lg transition duration-150">
85
  <span class="material-symbols-rounded">person</span>
86
  <span class="ml-3">Profil</span>
87
  </a>
88
- <a href="{{ url_for('user_bp.deconnexion') }}" id="logout-button-sidebar" class="flex items-center p-3 text-red-400 hover:text-red-300 hover:bg-gray-700 rounded-lg transition duration-150">
89
  <span class="material-symbols-rounded">logout</span>
90
  <span class="ml-3">Déconnexion</span>
91
  </a>
92
  </nav>
93
 
94
- <div class="absolute bottom-6 w-52 text-xs text-gray-400">
95
- <p>Connecté en tant que: <span class="font-semibold text-gray-200">{{ user.email if user else 'Chargement...' }}</span></p>
96
- <p>Plan: <span class="font-semibold text-gray-200">{{ (user.plan | upper) if user else 'Chargement...' }}</span></p>
97
  </div>
98
 
99
  </aside>
100
 
101
- <div id="main-content" class="lg:ml-64 p-8">
102
 
103
  <header class="lg:hidden flex justify-between items-center mb-8">
104
  <div class="flex items-center">
105
  <img src="https://i.imgur.com/7Gn3toV.png" alt="Nexus Pro Logo" class="h-8">
106
- <span class="text-xl font-bold text-white ml-2">Nexus Pro</span>
107
  </div>
108
- <button id="sidebar-toggle" class="p-2 rounded-lg bg-gray-800 hover:bg-gray-700">
109
- <span class="material-symbols-rounded text-white">menu</span>
110
  </button>
111
  </header>
112
 
113
- <h1 class="text-3xl font-bold mb-8 text-white">Gestion des Clés API</h1>
114
 
115
  {% with messages = get_flashed_messages(with_categories=true) %}
116
  {% if messages %}
@@ -122,34 +206,34 @@
122
  {% endif %}
123
  {% endwith %}
124
 
125
- <div class="bg-gray-800 p-6 rounded-lg shadow-xl border border-gray-700">
126
- <h2 class="text-xl font-semibold mb-4 text-white">Votre Clé d'Accès Principale</h2>
127
- <p class="text-gray-400 mb-6">Utilisez cette clé pour authentifier vos requêtes auprès de l'API ErnestMind Nexus.</p>
128
 
129
  <div class="flex items-center space-x-4 mb-6">
130
  <input id="api-key-display"
131
  type="text"
132
  readonly
133
- class="flex-grow bg-gray-900 border border-gray-700 text-green-400 p-3 rounded-lg font-mono text-sm break-all focus:ring-blue-500 focus:border-blue-500"
134
  value="{{ user.api_key if user and user.api_key else 'Clé API non trouvée. Réinitialisez-la.' }}">
135
 
136
- <button id="copy-btn" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-4 rounded-lg transition duration-200 flex items-center btn-square">
137
  <span class="material-symbols-rounded">content_copy</span>
138
  <span class="ml-2 hidden sm:inline">Copier</span>
139
  </button>
140
  </div>
141
 
142
- <div class="flex items-center justify-between border-t border-gray-700 pt-4">
143
- <button id="regenerate-btn" class="text-sm text-red-400 hover:text-red-300 transition duration-200 flex items-center font-medium">
144
  <span class="material-symbols-rounded text-lg mr-1">refresh</span>
145
  Régénérer la Clé
146
- <div id="spinner" class="spinner w-4 h-4 border-2 border-gray-500 rounded-full ml-2 hidden" style="--spinner-color: #ffffff;"></div>
147
  </button>
148
- <p id="status-message" class="text-sm text-green-400 font-medium"></p>
149
  </div>
150
  </div>
151
 
152
- <div class="mt-8 p-4 bg-yellow-900/50 border border-yellow-800 rounded-lg text-yellow-300">
153
  <h3 class="font-bold flex items-center">
154
  <span class="material-symbols-rounded mr-2">warning</span>
155
  Attention Sécurité
@@ -160,6 +244,44 @@
160
  </div>
161
 
162
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  // Logique pour la copie de la clé API
164
  const copyBtn = document.getElementById('copy-btn');
165
  const apiKeyDisplay = document.getElementById('api-key-display');
@@ -167,9 +289,6 @@
167
  const regenerateBtn = document.getElementById('regenerate-btn');
168
  const spinner = document.getElementById('spinner');
169
 
170
- // Styles pour le spinner (Assurer que la couleur de la bordure est blanche)
171
- document.documentElement.style.setProperty('--spinner-color', '#ffffff');
172
-
173
  // 1. Fonctionnalité de Copie
174
  copyBtn.addEventListener('click', () => {
175
  apiKeyDisplay.select();
@@ -191,10 +310,7 @@
191
  sidebar.classList.toggle('open');
192
  });
193
 
194
- // 3. Logique de REGÉNÉRATION (Laisser la structure pour la Phase 2/3)
195
- // NOTE: La logique de régénération AJAX est retirée pour l'instant.
196
- // Elle sera réintégrée dans la phase suivante si nécessaire.
197
- // Pour l'instant, le bouton ne fait rien d'autre qu'afficher un message.
198
  regenerateBtn.addEventListener('click', (e) => {
199
  e.preventDefault();
200
  // Simuler une action pour l'utilisateur
@@ -208,7 +324,7 @@
208
  const logoutHandler = async (e) => {
209
  e.preventDefault();
210
  // La déconnexion est maintenant gérée par la route Flask directe
211
- window.location.href = regenerateBtn.parentElement.querySelector('#logout-button-sidebar').href;
212
  };
213
  // On attache l'événement à la déconnexion dans la sidebar.
214
  document.getElementById('logout-button-sidebar').addEventListener('click', logoutHandler);
 
1
  <!DOCTYPE html>
2
+ <html lang="fr" class="dark">
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
 
9
  <link rel="stylesheet"
10
  href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@24,400,0,0" />
11
  <style>
12
+ /* Configuration de la police Inter */
13
  body { font-family: 'Inter', sans-serif; }
14
 
15
+ /* Transition pour un effet doux des couleurs */
16
+ .transition-colors-theme { transition: background-color 0.3s, color 0.3s, border-color 0.3s; }
17
+
18
+ /* Style et positionnement du bouton de Thème */
19
+ .theme-switch {
20
+ background: none;
21
+ border: none;
22
+ cursor: pointer;
23
+ font-size: 24px;
24
+ transition: color 0.2s;
25
+ position: fixed; /* Reste fixe même si le reste défile */
26
+ top: 1rem;
27
+ right: 1rem;
28
+ z-index: 50; /* Doit être au-dessus de tout */
29
+ }
30
+
31
+ /* Définir les Variables de Thème */
32
+ /* Mode Sombre (Défaut) */
33
+ :root, .dark {
34
+ --bg-page: #121212;
35
+ --bg-card: #1E1E1E;
36
+ --bg-sidebar: #1E1E1E; /* Sidebar aussi foncée que les cartes */
37
+ --bg-sidebar-active: #2C2C2C;
38
+ --border-sidebar: #383838;
39
+ --text-color: #FFFFFF;
40
+ --text-secondary: #D1D5DB;
41
+ --text-link: #3B82F6;
42
+ --text-link-hover: #60A5FA;
43
+ --input-bg: #2C2C2C;
44
+ --input-border: #4B5563;
45
+ --input-text-key: #6EE7B7; /* Vert clair pour la clé */
46
+ --primary-color: #3B82F6;
47
+ --primary-hover: #2563EB;
48
+ --warning-bg: #451A03; /* Orange très sombre */
49
+ --warning-border: #78350F;
50
+ --warning-text: #FBBF24;
51
+ }
52
+ /* Mode Clair */
53
+ .light {
54
+ --bg-page: #F5F5F5;
55
+ --bg-card: #FFFFFF;
56
+ --bg-sidebar: #FFFFFF;
57
+ --bg-sidebar-active: #F3F4F6;
58
+ --border-sidebar: #D1D5DB;
59
+ --text-color: #000000;
60
+ --text-secondary: #4B5563;
61
+ --text-link: #1D4ED8;
62
+ --text-link-hover: #3B82F6;
63
+ --input-bg: #FFFFFF;
64
+ --input-border: #D1D5DB;
65
+ --input-text-key: #059669; /* Vert foncé pour la clé */
66
+ --primary-color: #3B82F6;
67
+ --primary-hover: #2563EB;
68
+ --warning-bg: #FEF3C7; /* Jaune très clair */
69
+ --warning-border: #FBBF24;
70
+ --warning-text: #92400E;
71
+ }
72
+
73
+ /* Appliquer les variables au body et aux éléments */
74
+ .bg-page-var { background-color: var(--bg-page); }
75
+ .bg-card-var { background-color: var(--bg-card); }
76
+ .bg-sidebar-var { background-color: var(--bg-sidebar); }
77
+ .border-sidebar-var { border-color: var(--border-sidebar); }
78
+ .text-color-var { color: var(--text-color); }
79
+ .text-secondary-var { color: var(--text-secondary); }
80
+ .text-link-var { color: var(--text-link); }
81
+ .hover\:text-link-hover-var:hover { color: var(--text-link-hover); }
82
+ .bg-input-var { background-color: var(--input-bg); }
83
+ .border-input-var { border-color: var(--input-border); }
84
+ .text-input-key-var { color: var(--input-text-key); }
85
+ .bg-primary-color-var { background-color: var(--primary-color); }
86
+ .hover\:bg-primary-hover-var:hover { background-color: var(--primary-hover); }
87
+ .focus\:ring-primary-color-var:focus { --tw-ring-color: var(--primary-color); }
88
+ .focus\:border-primary-color-var:focus { border-color: var(--primary-color); }
89
+ .bg-sidebar-active-var { background-color: var(--bg-sidebar-active); }
90
+ .bg-warning-var { background-color: var(--warning-bg); }
91
+ .border-warning-var { border-color: var(--warning-border); }
92
+ .text-warning-var { color: var(--warning-text); }
93
+
94
+
95
  /* Style pour les boutons et cartes carrés (Artboard) */
96
  .btn-square, .card-square {
97
  border-radius: 0; /* Supprime l'arrondi */
 
99
 
100
  /* Styles spécifiques pour le chargement/spinner */
101
  .spinner {
102
+ border-top-color: var(--primary-color); /* Utiliser la couleur primaire pour le spinner */
103
  animation: spin 1s linear infinite;
104
  }
105
  @keyframes spin {
106
  to { transform: rotate(360deg); }
107
  }
108
 
109
+ /* Style pour la Sidebar - FIXE et complète */
110
  .sidebar {
111
  transition: transform 0.3s ease-in-out;
112
  transform: translateX(-100%);
 
121
  transform: translateX(0);
122
  }
123
 
124
+ /* Sur les grands écrans (lg), la sidebar est statique et toujours visible */
125
  @media (min-width: 1024px) {
126
  .sidebar {
127
  transform: translateX(0) !important;
128
+ position: fixed; /* Changement : Rendre la sidebar fixe sur grand écran */
129
+ height: 100vh;
130
  }
131
  }
132
 
133
+ /* Conteneur principal pour décaler le contenu sur les grands écrans (lg) */
134
+ /* La marge doit correspondre à la largeur de la sidebar (w-64) */
135
  @media (min-width: 1024px) {
136
  .main-content {
137
+ margin-left: 256px;
138
  }
139
  }
 
140
  </style>
141
  </head>
142
 
143
+ <body class="bg-page-var text-color-var min-h-screen transition-colors-theme">
144
 
145
+ <button id="theme-toggle" class="theme-switch text-color-var hover:text-link-hover-var transition-colors-theme">
146
+ <span class="material-symbols-rounded">dark_mode</span>
147
+ </button>
148
+
149
+ <aside id="sidebar" class="sidebar w-64 bg-sidebar-var border-r border-sidebar-var p-6 lg:block transition-colors-theme">
150
  <div class="flex items-center mb-10">
151
  <img src="https://i.imgur.com/7Gn3toV.png" alt="Nexus Pro Logo" class="h-8">
152
+ <span class="text-xl font-bold text-color-var ml-2 transition-colors-theme">Nexus Pro</span>
153
  </div>
154
 
155
  <nav class="space-y-3">
156
+ <a href="{{ url_for('user_bp.dashboard') }}" class="flex items-center p-3 text-secondary-var hover:text-color-var hover:bg-sidebar-active-var rounded-lg transition duration-150 transition-colors-theme">
157
  <span class="material-symbols-rounded">dashboard</span>
158
  <span class="ml-3">Dashboard</span>
159
  </a>
160
+ <a href="{{ url_for('user_bp.api_keys') }}" class="flex items-center p-3 bg-sidebar-active-var text-color-var rounded-lg transition duration-150 transition-colors-theme">
161
  <span class="material-symbols-rounded">key</span>
162
  <span class="ml-3">Clés API</span>
163
  </a>
164
+ <a href="{{ url_for('user_bp.api_logs') }}" class="flex items-center p-3 text-secondary-var hover:text-color-var hover:bg-sidebar-active-var rounded-lg transition duration-150 transition-colors-theme">
165
  <span class="material-symbols-rounded">list_alt</span>
166
  <span class="ml-3">Logs d'API</span>
167
  </a>
168
+ <a href="{{ url_for('user_bp.profile') }}" class="flex items-center p-3 text-secondary-var hover:text-color-var hover:bg-sidebar-active-var rounded-lg transition duration-150 transition-colors-theme">
169
  <span class="material-symbols-rounded">person</span>
170
  <span class="ml-3">Profil</span>
171
  </a>
172
+ <a href="{{ url_for('user_bp.deconnexion') }}" id="logout-button-sidebar" class="flex items-center p-3 text-red-500 hover:text-red-400 hover:bg-sidebar-active-var rounded-lg transition duration-150 transition-colors-theme">
173
  <span class="material-symbols-rounded">logout</span>
174
  <span class="ml-3">Déconnexion</span>
175
  </a>
176
  </nav>
177
 
178
+ <div class="absolute bottom-6 w-52 text-xs text-secondary-var transition-colors-theme">
179
+ <p>Connecté en tant que: <span class="font-semibold text-color-var transition-colors-theme">{{ user.email if user else 'Chargement...' }}</span></p>
180
+ <p>Plan: <span class="font-semibold text-color-var transition-colors-theme">{{ (user.plan | upper) if user else 'Chargement...' }}</span></p>
181
  </div>
182
 
183
  </aside>
184
 
185
+ <div id="main-content" class="main-content p-8 transition-colors-theme">
186
 
187
  <header class="lg:hidden flex justify-between items-center mb-8">
188
  <div class="flex items-center">
189
  <img src="https://i.imgur.com/7Gn3toV.png" alt="Nexus Pro Logo" class="h-8">
190
+ <span class="text-xl font-bold text-color-var ml-2 transition-colors-theme">Nexus Pro</span>
191
  </div>
192
+ <button id="sidebar-toggle" class="p-2 rounded-lg bg-sidebar-active-var hover:bg-sidebar-active-var/80 transition-colors-theme">
193
+ <span class="material-symbols-rounded text-color-var">menu</span>
194
  </button>
195
  </header>
196
 
197
+ <h1 class="text-3xl font-bold mb-8 text-color-var transition-colors-theme">Gestion des Clés API</h1>
198
 
199
  {% with messages = get_flashed_messages(with_categories=true) %}
200
  {% if messages %}
 
206
  {% endif %}
207
  {% endwith %}
208
 
209
+ <div class="bg-card-var p-6 rounded-lg shadow-xl border border-sidebar-var transition-colors-theme">
210
+ <h2 class="text-xl font-semibold mb-4 text-color-var transition-colors-theme">Votre Clé d'Accès Principale</h2>
211
+ <p class="text-secondary-var mb-6 transition-colors-theme">Utilisez cette clé pour authentifier vos requêtes auprès de l'API ErnestMind Nexus.</p>
212
 
213
  <div class="flex items-center space-x-4 mb-6">
214
  <input id="api-key-display"
215
  type="text"
216
  readonly
217
+ class="flex-grow bg-input-var border border-input-var text-input-key-var p-3 rounded-lg font-mono text-sm break-all focus:outline-none focus:ring-2 focus:ring-primary-color-var focus:border-primary-color-var transition-colors-theme"
218
  value="{{ user.api_key if user and user.api_key else 'Clé API non trouvée. Réinitialisez-la.' }}">
219
 
220
+ <button id="copy-btn" class="bg-primary-color-var hover:bg-primary-hover-var text-white font-bold py-3 px-4 rounded-lg transition duration-200 flex items-center btn-square transition-colors-theme">
221
  <span class="material-symbols-rounded">content_copy</span>
222
  <span class="ml-2 hidden sm:inline">Copier</span>
223
  </button>
224
  </div>
225
 
226
+ <div class="flex items-center justify-between border-t border-sidebar-var pt-4 transition-colors-theme">
227
+ <button id="regenerate-btn" class="text-sm text-red-500 hover:text-red-400 transition duration-200 flex items-center font-medium transition-colors-theme">
228
  <span class="material-symbols-rounded text-lg mr-1">refresh</span>
229
  Régénérer la Clé
230
+ <div id="spinner" class="spinner w-4 h-4 border-2 rounded-full ml-2 hidden" style="border-bottom-color: transparent;"></div>
231
  </button>
232
+ <p id="status-message" class="text-sm text-input-key-var font-medium transition-colors-theme"></p>
233
  </div>
234
  </div>
235
 
236
+ <div class="mt-8 p-4 bg-warning-var border border-warning-border-var rounded-lg text-warning-text-var transition-colors-theme">
237
  <h3 class="font-bold flex items-center">
238
  <span class="material-symbols-rounded mr-2">warning</span>
239
  Attention Sécurité
 
244
  </div>
245
 
246
  <script>
247
+ // Logique du thème (copiée de inscription.html)
248
+ const themeToggle = document.getElementById('theme-toggle');
249
+ const html = document.documentElement;
250
+
251
+ const updateIcon = () => {
252
+ const icon = themeToggle.querySelector('.material-symbols-rounded');
253
+ if (html.classList.contains('light')) {
254
+ icon.textContent = 'light_mode';
255
+ } else {
256
+ icon.textContent = 'dark_mode';
257
+ }
258
+ };
259
+
260
+ const savedTheme = localStorage.getItem('theme');
261
+ if (savedTheme === 'light') {
262
+ html.classList.remove('dark');
263
+ html.classList.add('light');
264
+ } else {
265
+ // Par défaut, nous nous assurons que 'dark' est appliqué s'il n'y a pas de thème enregistré
266
+ html.classList.add('dark');
267
+ html.classList.remove('light');
268
+ }
269
+ updateIcon();
270
+
271
+ themeToggle.addEventListener('click', () => {
272
+ if (html.classList.contains('dark')) {
273
+ html.classList.remove('dark');
274
+ html.classList.add('light');
275
+ localStorage.setItem('theme', 'light');
276
+ } else {
277
+ html.classList.remove('light');
278
+ html.classList.add('dark');
279
+ localStorage.setItem('theme', 'dark');
280
+ }
281
+ updateIcon();
282
+ });
283
+
284
+
285
  // Logique pour la copie de la clé API
286
  const copyBtn = document.getElementById('copy-btn');
287
  const apiKeyDisplay = document.getElementById('api-key-display');
 
289
  const regenerateBtn = document.getElementById('regenerate-btn');
290
  const spinner = document.getElementById('spinner');
291
 
 
 
 
292
  // 1. Fonctionnalité de Copie
293
  copyBtn.addEventListener('click', () => {
294
  apiKeyDisplay.select();
 
310
  sidebar.classList.toggle('open');
311
  });
312
 
313
+ // 3. Logique de REGÉNÉRATION (Message de démo)
 
 
 
314
  regenerateBtn.addEventListener('click', (e) => {
315
  e.preventDefault();
316
  // Simuler une action pour l'utilisateur
 
324
  const logoutHandler = async (e) => {
325
  e.preventDefault();
326
  // La déconnexion est maintenant gérée par la route Flask directe
327
+ window.location.href = document.getElementById('logout-button-sidebar').href;
328
  };
329
  // On attache l'événement à la déconnexion dans la sidebar.
330
  document.getElementById('logout-button-sidebar').addEventListener('click', logoutHandler);