Docfile commited on
Commit
57ee656
·
verified ·
1 Parent(s): 42a564e

Delete templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +0 -459
templates/index.html DELETED
@@ -1,459 +0,0 @@
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">
6
- <title>Mariam AI - Analyse d'Image</title>
7
- <!-- Tailwind CSS -->
8
- <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
9
- <!-- Marked -->
10
- <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
11
- <!-- SweetAlert2 -->
12
- <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
13
- <!-- Moment.js -->
14
- <script src="https://cdn.jsdelivr.net/npm/[email protected]/moment.min.js"></script>
15
- <style>
16
- /* Loader et animations */
17
- .loader {
18
- width: 48px;
19
- height: 48px;
20
- border: 5px solid #FFF;
21
- border-bottom-color: #6366F1;
22
- border-radius: 50%;
23
- animation: rotation 1s linear infinite;
24
- }
25
- @keyframes rotation {
26
- from { transform: rotate(0deg); }
27
- to { transform: rotate(360deg); }
28
- }
29
- .fade-in {
30
- animation: fadeIn 0.5s ease-in;
31
- }
32
- @keyframes fadeIn {
33
- from { opacity: 0; }
34
- to { opacity: 1; }
35
- }
36
-
37
- /* Zone de drop d'image */
38
- .upload-zone {
39
- border: 2px dashed #6366F1;
40
- transition: background-color 0.3s ease, border-color 0.3s ease;
41
- }
42
- .upload-zone:hover {
43
- border-color: #4F46E5;
44
- background-color: #EEF2FF;
45
- }
46
-
47
- /* Contenu Markdown */
48
- .markdown-content {
49
- overflow-x: auto;
50
- padding-bottom: 1rem;
51
- }
52
- .markdown-content table {
53
- border-collapse: collapse;
54
- width: 100%;
55
- margin: 1rem 0;
56
- }
57
- .markdown-content th,
58
- .markdown-content td {
59
- border: 1px solid #e5e7eb;
60
- padding: 0.75rem;
61
- text-align: left;
62
- white-space: nowrap;
63
- min-width: 150px;
64
- }
65
- .markdown-content th {
66
- background-color: #f9fafb;
67
- position: sticky;
68
- top: 0;
69
- z-index: 10;
70
- }
71
- /* Pour conserver les espaces et retours à la ligne dans le Markdown */
72
- .markdown-content p,
73
- .markdown-content pre,
74
- .markdown-content code {
75
- white-space: pre-wrap;
76
- word-wrap: break-word;
77
- }
78
-
79
- /* Scroll horizontal */
80
- .scroll-indicator {
81
- position: absolute;
82
- bottom: 20px;
83
- right: 20px;
84
- background: rgba(99, 102, 241, 0.9);
85
- color: white;
86
- padding: 8px 12px;
87
- border-radius: 4px;
88
- font-size: 0.875rem;
89
- opacity: 0;
90
- transition: opacity 0.3s ease;
91
- pointer-events: none;
92
- }
93
- .scroll-indicator.visible { opacity: 1; }
94
-
95
- /* Prévisualisation de l'image */
96
- .image-preview-container {
97
- position: relative;
98
- max-width: 100%;
99
- margin: 1rem auto;
100
- border-radius: 0.5rem;
101
- overflow: hidden;
102
- box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -1px rgba(0,0,0,0.06);
103
- }
104
- .image-preview-container img {
105
- display: block;
106
- width: 100%;
107
- height: auto;
108
- max-height: 400px;
109
- object-fit: contain;
110
- }
111
- .remove-image {
112
- position: absolute;
113
- top: 0.5rem;
114
- right: 0.5rem;
115
- background-color: rgba(255,255,255,0.9);
116
- border-radius: 50%;
117
- padding: 0.5rem;
118
- cursor: pointer;
119
- transition: background-color 0.2s ease;
120
- }
121
- .remove-image:hover {
122
- background-color: #EF4444;
123
- color: white;
124
- }
125
-
126
- /* Boutons d'onglets */
127
- .tab-buttons button {
128
- margin: 0 0.5rem;
129
- padding: 0.5rem 1rem;
130
- border: 1px solid #6366F1;
131
- background-color: #EEF2FF;
132
- color: #6366F1;
133
- border-radius: 0.25rem;
134
- transition: background-color 0.3s ease;
135
- }
136
- .tab-buttons button.active {
137
- background-color: #6366F1;
138
- color: white;
139
- }
140
-
141
- /* Liste des sauvegardes */
142
- #backupList li {
143
- margin-bottom: 0.5rem;
144
- padding: 0.75rem;
145
- border: 1px solid #e5e7eb;
146
- border-radius: 0.25rem;
147
- background-color: #fff;
148
- cursor: pointer;
149
- display: flex;
150
- justify-content: space-between;
151
- align-items: center;
152
- }
153
- #backupList li:hover { background-color: #f9fafb; }
154
- #backupList .backup-date { font-size: 0.8rem; color: #9ca3af; }
155
- #backupList button {
156
- padding: 0.25rem 0.5rem;
157
- border-radius: 0.25rem;
158
- }
159
-
160
- /* Ajustement SweetAlert2 */
161
- .swal2-popup {
162
- width: 90% !important;
163
- max-width: 1200px !important;
164
- }
165
- .swal2-html-container {
166
- max-height: 80vh !important;
167
- overflow-y: auto !important;
168
- }
169
- </style>
170
- </head>
171
- <body class="bg-gray-50">
172
- <div class="min-h-screen flex flex-col">
173
- <!-- Header -->
174
- <header class="bg-white shadow">
175
- <div class="max-w-7xl mx-auto px-4 py-4 sm:px-6 lg:px-8">
176
- <h1 class="text-3xl font-bold text-indigo-600">Mariam AI</h1>
177
- <p class="mt-1 text-sm text-gray-500">Assistant pour commentaire composé.</p>
178
- </div>
179
- </header>
180
-
181
- <!-- Contenu principal -->
182
- <main class="flex-grow max-w-7xl mx-auto px-4 py-8 sm:px-6 lg:px-8">
183
- <!-- Formulaire d'upload -->
184
- <div class="bg-white rounded-lg shadow p-6 mb-8">
185
- <form id="uploadForm" class="space-y-6">
186
- <div class="upload-zone rounded-lg p-8 text-center cursor-pointer">
187
- <input type="file" id="imageInput" accept="image/*" required class="hidden" onchange="handleImageSelect()">
188
- <label for="imageInput" class="block">
189
- <div class="space-y-2">
190
- <svg class="mx-auto h-12 w-12 text-indigo-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
191
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
192
- d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
193
- </svg>
194
- <div id="fileName" class="text-sm text-gray-500">Cliquez ou glissez une image ici</div>
195
- </div>
196
- </label>
197
- </div>
198
-
199
- <!-- Prévisualisation de l'image -->
200
- <div id="imagePreview" class="hidden image-preview-container">
201
- <img id="preview" src="#" alt="Prévisualisation">
202
- <button type="button" class="remove-image" onclick="removeImage()">
203
- <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
204
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
205
- d="M6 18L18 6M6 6l12 12" />
206
- </svg>
207
- </button>
208
- </div>
209
-
210
- <div class="flex justify-center">
211
- <button type="submit"
212
- class="inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors">
213
- Analyser l'image
214
- </button>
215
- </div>
216
- </form>
217
- </div>
218
-
219
- <!-- Loader -->
220
- <div id="loading" class="hidden">
221
- <div class="flex flex-col items-center justify-center space-y-4">
222
- <span class="loader"></span>
223
- <p class="text-gray-500">Analyse en cours, veuillez patienter...</p>
224
- </div>
225
- </div>
226
-
227
- <!-- Résultats -->
228
- <div id="results" class="space-y-8 hidden">
229
- <div class="tab-buttons flex flex-wrap justify-center mb-4">
230
- <button id="showDissertation" class="active">Dissertation</button>
231
- <button id="showTableau">Tableau d'analyse</button>
232
- <button id="showBackups">Sauvegardes</button>
233
- </div>
234
-
235
- <!-- Onglet Dissertation -->
236
- <div id="dissertationTab" class="tab-content active bg-white rounded-lg shadow p-6">
237
- <h2 class="text-2xl font-bold text-gray-900 mb-4">Dissertation</h2>
238
- <div id="dissertationResult" class="prose max-w-none markdown-content"></div>
239
- <button id="saveDissertation" class="mt-4 px-6 py-3 bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors">
240
- Sauvegarder la dissertation
241
- </button>
242
- </div>
243
-
244
- <!-- Onglet Tableau d'analyse -->
245
- <div id="tableauTab" class="tab-content bg-white rounded-lg shadow p-6 hidden">
246
- <h2 class="text-2xl font-bold text-gray-900 mb-4">Tableau d'analyse</h2>
247
- <div id="tableauResult" class="markdown-content"></div>
248
- <button id="saveTableau" class="mt-4 px-6 py-3 bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors">
249
- Sauvegarder le tableau
250
- </button>
251
- </div>
252
-
253
- <!-- Onglet Sauvegardes -->
254
- <div id="backupsTab" class="tab-content bg-white rounded-lg shadow p-6 hidden">
255
- <h2 class="text-2xl font-bold text-gray-900 mb-4">Sauvegardes locales</h2>
256
- <ul id="backupList" class="space-y-2"></ul>
257
- </div>
258
- </div>
259
- </main>
260
- </div>
261
-
262
- <!-- JavaScript -->
263
- <script>
264
- let tableauContent = '';
265
- let dissertationContent = '';
266
- let backups = loadBackups();
267
-
268
- function handleImageSelect() {
269
- const input = document.getElementById('imageInput');
270
- const preview = document.getElementById('preview');
271
- const previewContainer = document.getElementById('imagePreview');
272
- const fileName = document.getElementById('fileName');
273
-
274
- if (input.files && input.files[0]) {
275
- const reader = new FileReader();
276
- reader.onload = e => {
277
- preview.src = e.target.result;
278
- previewContainer.classList.remove('hidden');
279
- previewContainer.classList.add('fade-in');
280
- };
281
- reader.readAsDataURL(input.files[0]);
282
- fileName.textContent = input.files[0].name;
283
- } else {
284
- removeImage();
285
- }
286
- }
287
-
288
- function removeImage() {
289
- const input = document.getElementById('imageInput');
290
- const preview = document.getElementById('preview');
291
- const previewContainer = document.getElementById('imagePreview');
292
- const fileName = document.getElementById('fileName');
293
-
294
- input.value = '';
295
- preview.src = '#';
296
- previewContainer.classList.add('hidden');
297
- fileName.textContent = 'Cliquez ou glissez une image ici';
298
- }
299
-
300
- function showScrollIndicator(container) {
301
- if (container.scrollWidth > container.clientWidth) {
302
- const indicator = document.createElement('div');
303
- indicator.className = 'scroll-indicator visible';
304
- indicator.textContent = '← Faites défiler →';
305
- container.parentElement.appendChild(indicator);
306
-
307
- setTimeout(() => indicator.classList.remove('visible'), 3000);
308
- container.addEventListener('scroll', () => {
309
- clearTimeout(container.scrollTimeout);
310
- indicator.classList.toggle('visible', container.scrollLeft > 0);
311
- container.scrollTimeout = setTimeout(() => indicator.classList.remove('visible'), 1000);
312
- });
313
- }
314
- }
315
-
316
- // Gestion des onglets
317
- document.getElementById('showTableau').addEventListener('click', () => {
318
- showTab('tableau');
319
- renderTableauContent();
320
- });
321
- document.getElementById('showDissertation').addEventListener('click', () => showTab('dissertation'));
322
- document.getElementById('showBackups').addEventListener('click', () => {
323
- showTab('backups');
324
- updateBackupList();
325
- });
326
- function showTab(tabName) {
327
- document.querySelectorAll('.tab-content').forEach(tab => tab.classList.remove('active'));
328
- document.querySelectorAll('.tab-buttons button').forEach(btn => btn.classList.remove('active'));
329
- document.getElementById(`${tabName}Tab`).classList.add('active');
330
- document.getElementById(`show${tabName.charAt(0).toUpperCase() + tabName.slice(1)}`).classList.add('active');
331
- }
332
-
333
- function loadBackups() {
334
- try {
335
- const stored = localStorage.getItem('mariamAIBackups');
336
- return stored ? JSON.parse(stored) : [];
337
- } catch (error) {
338
- console.error("Erreur lors du chargement des sauvegardes :", error);
339
- return [];
340
- }
341
- }
342
-
343
- function saveBackup(type, content) {
344
- const timestamp = moment().format('YYYY-MM-DD HH:mm:ss');
345
- backups.push({ timestamp, type, content });
346
- localStorage.setItem('mariamAIBackups', JSON.stringify(backups));
347
- updateBackupList();
348
- Swal.fire({ icon: 'success', title: 'Sauvegarde réussie!' });
349
- }
350
-
351
- function updateBackupList() {
352
- const backupList = document.getElementById('backupList');
353
- backupList.innerHTML = '';
354
- backups.forEach((backup, index) => {
355
- const li = document.createElement('li');
356
- li.innerHTML = `
357
- <span>${backup.type === 'dissertation' ? 'Dissertation' : 'Tableau'} - ${backup.timestamp}</span>
358
- <div>
359
- <button data-index="${index}" class="view-backup bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 rounded text-xs">Voir</button>
360
- <button data-index="${index}" class="delete-backup bg-red-500 hover:bg-red-700 text-white font-bold py-1 px-2 rounded text-xs">Supprimer</button>
361
- </div>
362
- `;
363
- backupList.appendChild(li);
364
- li.querySelector('.view-backup').addEventListener('click', viewBackup);
365
- li.querySelector('.delete-backup').addEventListener('click', deleteBackup);
366
- });
367
- }
368
-
369
- function viewBackup(e) {
370
- const index = e.target.dataset.index;
371
- const backup = backups[index];
372
- Swal.fire({
373
- title: backup.type === 'dissertation' ? 'Dissertation sauvegardée' : 'Tableau sauvegardé',
374
- html: marked.parse(backup.content),
375
- width: '90%',
376
- customClass: { htmlContainer: 'markdown-content' },
377
- didRender: () => {
378
- const container = document.querySelector('.markdown-content');
379
- showScrollIndicator(container);
380
- }
381
- });
382
- }
383
-
384
- function deleteBackup(e) {
385
- const index = e.target.dataset.index;
386
- Swal.fire({
387
- title: 'Êtes-vous sûr ?',
388
- text: "Vous ne pourrez pas revenir en arrière !",
389
- icon: 'warning',
390
- showCancelButton: true,
391
- confirmButtonColor: '#3085d6',
392
- cancelButtonColor: '#d33',
393
- confirmButtonText: 'Oui, supprimer!'
394
- }).then((result) => {
395
- if (result.isConfirmed) {
396
- backups.splice(index, 1);
397
- localStorage.setItem('mariamAIBackups', JSON.stringify(backups));
398
- updateBackupList();
399
- Swal.fire('Supprimé!', 'Votre fichier a été supprimé.', 'success');
400
- }
401
- });
402
- }
403
-
404
- document.getElementById('saveDissertation').addEventListener('click', () => saveBackup('dissertation', dissertationContent));
405
- document.getElementById('saveTableau').addEventListener('click', () => saveBackup('tableau', tableauContent));
406
-
407
- document.getElementById('uploadForm').addEventListener('submit', async (e) => {
408
- e.preventDefault();
409
- const imageInput = document.getElementById('imageInput');
410
- if (!imageInput.files || !imageInput.files[0]) {
411
- return Swal.fire({
412
- icon: 'error',
413
- title: 'Aucune image sélectionnée',
414
- text: 'Veuillez sélectionner une image à analyser.'
415
- });
416
- }
417
- const loading = document.getElementById('loading');
418
- const results = document.getElementById('results');
419
- const dissertationResult = document.getElementById('dissertationResult');
420
- const formData = new FormData();
421
- formData.append('image', imageInput.files[0]);
422
-
423
- loading.classList.remove('hidden');
424
- results.classList.add('hidden');
425
- try {
426
- const response = await fetch('/analyze', { method: 'POST', body: formData });
427
- if (!response.ok) {
428
- const errorData = await response.json();
429
- throw new Error(errorData.error || `Erreur serveur ${response.status}`);
430
- }
431
- const data = await response.json();
432
- dissertationContent = data.dissertation;
433
- tableauContent = data.tableau;
434
- dissertationResult.innerHTML = marked.parse(data.dissertation);
435
- results.classList.remove('hidden');
436
- results.classList.add('fade-in');
437
- showTab('dissertation');
438
- } catch (error) {
439
- console.error("Erreur lors de l'analyse :", error);
440
- Swal.fire({
441
- icon: 'error',
442
- title: 'Erreur',
443
- text: error.message || 'Une erreur est survenue lors de la communication avec le serveur.'
444
- });
445
- } finally {
446
- loading.classList.add('hidden');
447
- }
448
- });
449
-
450
- function renderTableauContent() {
451
- const tableauResult = document.getElementById('tableauResult');
452
- if (tableauContent) {
453
- tableauResult.innerHTML = marked.parse(tableauContent);
454
- showScrollIndicator(tableauResult);
455
- }
456
- }
457
- </script>
458
- </body>
459
- </html>