Docfile commited on
Commit
a6bd134
·
verified ·
1 Parent(s): 5028228

Delete templates/index.html

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