Update templates/index.html
Browse files- templates/index.html +190 -18
templates/index.html
CHANGED
@@ -7,6 +7,7 @@
|
|
7 |
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
|
8 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/9.1.6/marked.min.js"></script>
|
9 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert2/11.7.32/sweetalert2.all.min.js"></script>
|
|
|
10 |
<style>
|
11 |
.loader {
|
12 |
width: 48px;
|
@@ -152,6 +153,64 @@
|
|
152 |
background-color: #EF4444;
|
153 |
color: white;
|
154 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
</style>
|
156 |
</head>
|
157 |
<body class="bg-gray-50">
|
@@ -166,7 +225,7 @@
|
|
166 |
<main class="max-w-7xl mx-auto px-4 py-8 sm:px-6 lg:px-8">
|
167 |
<div class="bg-white rounded-lg shadow p-6 mb-8">
|
168 |
<form id="uploadForm" class="space-y-6">
|
169 |
-
|
170 |
<input type="file" id="imageInput" accept="image/*" required
|
171 |
class="hidden" onchange="handleImageSelect()">
|
172 |
<label for="imageInput" class="cursor-pointer">
|
@@ -208,17 +267,34 @@
|
|
208 |
</div>
|
209 |
|
210 |
<div id="results" class="space-y-8 hidden">
|
211 |
-
<div class="
|
212 |
-
<button id="
|
213 |
-
|
214 |
-
|
215 |
-
</button>
|
216 |
</div>
|
217 |
|
218 |
-
<div class="bg-white rounded-lg shadow p-6">
|
219 |
<h2 class="text-2xl font-bold text-gray-900 mb-4">Dissertation</h2>
|
220 |
<div id="dissertationResult" class="prose max-w-none markdown-content">
|
221 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
222 |
</div>
|
223 |
</div>
|
224 |
</main>
|
@@ -226,6 +302,8 @@
|
|
226 |
|
227 |
<script>
|
228 |
let tableauContent = '';
|
|
|
|
|
229 |
|
230 |
function handleImageSelect() {
|
231 |
const input = document.getElementById('imageInput');
|
@@ -288,9 +366,76 @@
|
|
288 |
}
|
289 |
|
290 |
document.getElementById('showTableau').addEventListener('click', () => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
291 |
Swal.fire({
|
292 |
-
|
293 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
294 |
width: '90%',
|
295 |
customClass: {
|
296 |
htmlContainer: 'markdown-content'
|
@@ -298,25 +443,39 @@
|
|
298 |
didRender: () => {
|
299 |
const container = document.querySelector('.markdown-content');
|
300 |
showScrollIndicator(container);
|
301 |
-
|
302 |
-
container.addEventListener('scroll', () => {
|
303 |
-
const maxScroll = container.scrollWidth - container.clientWidth;
|
304 |
-
container.style.boxShadow = container.scrollLeft > 0 ?
|
305 |
-
'inset 10px 0 5px -5px rgba(0,0,0,0.1)' : '';
|
306 |
-
container.style.boxShadow += container.scrollLeft < maxScroll ?
|
307 |
-
', inset -10px 0 5px -5px rgba(0,0,0,0.1)' : '';
|
308 |
-
});
|
309 |
}
|
310 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
311 |
});
|
312 |
|
|
|
|
|
313 |
document.getElementById('uploadForm').addEventListener('submit', async (e) => {
|
314 |
e.preventDefault();
|
315 |
|
316 |
const loading = document.getElementById('loading');
|
317 |
const results = document.getElementById('results');
|
318 |
const dissertationResult = document.getElementById('dissertationResult');
|
319 |
-
|
|
|
320 |
const formData = new FormData();
|
321 |
formData.append('image', document.getElementById('imageInput').files[0]);
|
322 |
|
@@ -332,10 +491,14 @@
|
|
332 |
const data = await response.json();
|
333 |
|
334 |
if (response.ok) {
|
|
|
335 |
tableauContent = data.tableau;
|
|
|
336 |
dissertationResult.innerHTML = marked.parse(data.dissertation);
|
|
|
337 |
results.classList.remove('hidden');
|
338 |
results.classList.add('fade-in');
|
|
|
339 |
} else {
|
340 |
Swal.fire({
|
341 |
icon: 'error',
|
@@ -353,6 +516,15 @@
|
|
353 |
loading.classList.add('hidden');
|
354 |
}
|
355 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
356 |
</script>
|
357 |
</body>
|
358 |
</html>
|
|
|
7 |
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
|
8 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/9.1.6/marked.min.js"></script>
|
9 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert2/11.7.32/sweetalert2.all.min.js"></script>
|
10 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
|
11 |
<style>
|
12 |
.loader {
|
13 |
width: 48px;
|
|
|
153 |
background-color: #EF4444;
|
154 |
color: white;
|
155 |
}
|
156 |
+
|
157 |
+
.tab-buttons {
|
158 |
+
display: flex;
|
159 |
+
justify-content: center;
|
160 |
+
margin-bottom: 1rem;
|
161 |
+
}
|
162 |
+
|
163 |
+
.tab-buttons button {
|
164 |
+
margin: 0 0.5rem;
|
165 |
+
padding: 0.5rem 1rem;
|
166 |
+
border: 1px solid #6366F1;
|
167 |
+
background-color: #EEF2FF;
|
168 |
+
color: #6366F1;
|
169 |
+
border-radius: 0.25rem;
|
170 |
+
cursor: pointer;
|
171 |
+
transition: background-color 0.3s ease;
|
172 |
+
}
|
173 |
+
|
174 |
+
.tab-buttons button.active {
|
175 |
+
background-color: #6366F1;
|
176 |
+
color: white;
|
177 |
+
}
|
178 |
+
|
179 |
+
.tab-content {
|
180 |
+
display: none;
|
181 |
+
}
|
182 |
+
|
183 |
+
.tab-content.active {
|
184 |
+
display: block;
|
185 |
+
}
|
186 |
+
|
187 |
+
#backupList li {
|
188 |
+
margin-bottom: 0.5rem;
|
189 |
+
padding: 0.75rem;
|
190 |
+
border: 1px solid #e5e7eb;
|
191 |
+
border-radius: 0.25rem;
|
192 |
+
background-color: white;
|
193 |
+
cursor: pointer;
|
194 |
+
display: flex;
|
195 |
+
justify-content: space-between;
|
196 |
+
align-items: center;
|
197 |
+
}
|
198 |
+
|
199 |
+
#backupList li:hover {
|
200 |
+
background-color: #f9fafb;
|
201 |
+
}
|
202 |
+
|
203 |
+
#backupList .backup-date {
|
204 |
+
font-size: 0.8rem;
|
205 |
+
color: #9ca3af;
|
206 |
+
}
|
207 |
+
|
208 |
+
#backupList button {
|
209 |
+
padding: 0.25rem 0.5rem;
|
210 |
+
background-color: #EF4444;
|
211 |
+
color: white;
|
212 |
+
border-radius: 0.25rem;
|
213 |
+
}
|
214 |
</style>
|
215 |
</head>
|
216 |
<body class="bg-gray-50">
|
|
|
225 |
<main class="max-w-7xl mx-auto px-4 py-8 sm:px-6 lg:px-8">
|
226 |
<div class="bg-white rounded-lg shadow p-6 mb-8">
|
227 |
<form id="uploadForm" class="space-y-6">
|
228 |
+
<div class="upload-zone rounded-lg p-8 text-center">
|
229 |
<input type="file" id="imageInput" accept="image/*" required
|
230 |
class="hidden" onchange="handleImageSelect()">
|
231 |
<label for="imageInput" class="cursor-pointer">
|
|
|
267 |
</div>
|
268 |
|
269 |
<div id="results" class="space-y-8 hidden">
|
270 |
+
<div class="tab-buttons">
|
271 |
+
<button id="showDissertation" class="active">Dissertation</button>
|
272 |
+
<button id="showTableau">Tableau d'analyse</button>
|
273 |
+
<button id="showBackups">Sauvegardes</button>
|
|
|
274 |
</div>
|
275 |
|
276 |
+
<div id="dissertationTab" class="tab-content active bg-white rounded-lg shadow p-6">
|
277 |
<h2 class="text-2xl font-bold text-gray-900 mb-4">Dissertation</h2>
|
278 |
<div id="dissertationResult" class="prose max-w-none markdown-content">
|
279 |
</div>
|
280 |
+
<button id="saveDissertation" class="mt-4 px-6 py-3 bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors duration-200">
|
281 |
+
Sauvegarder la dissertation
|
282 |
+
</button>
|
283 |
+
</div>
|
284 |
+
|
285 |
+
<div id="tableauTab" class="tab-content bg-white rounded-lg shadow p-6 hidden">
|
286 |
+
<h2 class="text-2xl font-bold text-gray-900 mb-4">Tableau d'analyse</h2>
|
287 |
+
<div id="tableauResult" class="markdown-content">
|
288 |
+
</div>
|
289 |
+
<button id="saveTableau" class="mt-4 px-6 py-3 bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors duration-200">
|
290 |
+
Sauvegarder le tableau
|
291 |
+
</button>
|
292 |
+
</div>
|
293 |
+
|
294 |
+
<div id="backupsTab" class="tab-content bg-white rounded-lg shadow p-6 hidden">
|
295 |
+
<h2 class="text-2xl font-bold text-gray-900 mb-4">Sauvegardes locales</h2>
|
296 |
+
<ul id="backupList" class="space-y-2">
|
297 |
+
</ul>
|
298 |
</div>
|
299 |
</div>
|
300 |
</main>
|
|
|
302 |
|
303 |
<script>
|
304 |
let tableauContent = '';
|
305 |
+
let dissertationContent = '';
|
306 |
+
let backups = loadBackups();
|
307 |
|
308 |
function handleImageSelect() {
|
309 |
const input = document.getElementById('imageInput');
|
|
|
366 |
}
|
367 |
|
368 |
document.getElementById('showTableau').addEventListener('click', () => {
|
369 |
+
showTab('tableau');
|
370 |
+
renderTableauContent();
|
371 |
+
});
|
372 |
+
|
373 |
+
document.getElementById('showDissertation').addEventListener('click', () => {
|
374 |
+
showTab('dissertation');
|
375 |
+
});
|
376 |
+
|
377 |
+
document.getElementById('showBackups').addEventListener('click', () => {
|
378 |
+
showTab('backups');
|
379 |
+
updateBackupList();
|
380 |
+
});
|
381 |
+
|
382 |
+
function showTab(tabName) {
|
383 |
+
document.querySelectorAll('.tab-content').forEach(tab => tab.classList.remove('active'));
|
384 |
+
document.querySelectorAll('.tab-buttons button').forEach(button => button.classList.remove('active'));
|
385 |
+
|
386 |
+
document.getElementById(`${tabName}Tab`).classList.add('active');
|
387 |
+
document.getElementById(`show${tabName.charAt(0).toUpperCase() + tabName.slice(1)}`).classList.add('active');
|
388 |
+
}
|
389 |
+
|
390 |
+
function loadBackups() {
|
391 |
+
try {
|
392 |
+
const storedBackups = localStorage.getItem('mariamAIBackups');
|
393 |
+
return storedBackups ? JSON.parse(storedBackups) : [];
|
394 |
+
} catch (error) {
|
395 |
+
console.error("Erreur lors du chargement des sauvegardes :", error);
|
396 |
+
return [];
|
397 |
+
}
|
398 |
+
}
|
399 |
+
|
400 |
+
function saveBackup(type, content) {
|
401 |
+
const timestamp = moment().format('YYYY-MM-DD HH:mm:ss');
|
402 |
+
backups.push({ timestamp, type, content });
|
403 |
+
localStorage.setItem('mariamAIBackups', JSON.stringify(backups));
|
404 |
+
updateBackupList();
|
405 |
Swal.fire({
|
406 |
+
icon: 'success',
|
407 |
+
title: 'Sauvegarde réussie !});
|
408 |
+
}
|
409 |
+
|
410 |
+
function updateBackupList() {
|
411 |
+
const backupList = document.getElementById('backupList');
|
412 |
+
backupList.innerHTML = '';
|
413 |
+
backups.forEach((backup, index) => {
|
414 |
+
const listItem = document.createElement('li');
|
415 |
+
listItem.innerHTML = `
|
416 |
+
<span class="backup-content">${backup.type === 'dissertation' ? 'Dissertation' : 'Tableau'} - ${backup.timestamp}</span>
|
417 |
+
<div class="flex items-center space-x-2">
|
418 |
+
<button data-index="${index}" class="view-backup bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Voir</button>
|
419 |
+
<button data-index="${index}" class="delete-backup bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">Supprimer</button>
|
420 |
+
</div>
|
421 |
+
`;
|
422 |
+
backupList.appendChild(listItem);
|
423 |
+
});
|
424 |
+
|
425 |
+
document.querySelectorAll('.view-backup').forEach(button => {
|
426 |
+
button.addEventListener('click', viewBackup);
|
427 |
+
});
|
428 |
+
document.querySelectorAll('.delete-backup').forEach(button => {
|
429 |
+
button.addEventListener('click', deleteBackup);
|
430 |
+
});
|
431 |
+
}
|
432 |
+
|
433 |
+
function viewBackup(event) {
|
434 |
+
const index = event.target.dataset.index;
|
435 |
+
const backup = backups[index];
|
436 |
+
Swal.fire({
|
437 |
+
title: backup.type === 'dissertation' ? 'Dissertation sauvegardée' : 'Tableau sauvegardé',
|
438 |
+
html: marked.parse(backup.content),
|
439 |
width: '90%',
|
440 |
customClass: {
|
441 |
htmlContainer: 'markdown-content'
|
|
|
443 |
didRender: () => {
|
444 |
const container = document.querySelector('.markdown-content');
|
445 |
showScrollIndicator(container);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
446 |
}
|
447 |
});
|
448 |
+
}
|
449 |
+
|
450 |
+
function deleteBackup(event) {
|
451 |
+
const index = event.target.dataset.index;
|
452 |
+
backups.splice(index, 1);
|
453 |
+
localStorage.setItem('mariamAIBackups', JSON.stringify(backups));
|
454 |
+
updateBackupList();
|
455 |
+
Swal.fire({
|
456 |
+
icon: 'success',
|
457 |
+
title: 'Suppression réussie!'
|
458 |
+
})
|
459 |
+
}
|
460 |
+
|
461 |
+
document.getElementById('saveDissertation').addEventListener('click', () => {
|
462 |
+
saveBackup('dissertation', dissertationContent);
|
463 |
+
});
|
464 |
+
|
465 |
+
document.getElementById('saveTableau').addEventListener('click', () => {
|
466 |
+
saveBackup('tableau', tableauContent);
|
467 |
});
|
468 |
|
469 |
+
|
470 |
+
|
471 |
document.getElementById('uploadForm').addEventListener('submit', async (e) => {
|
472 |
e.preventDefault();
|
473 |
|
474 |
const loading = document.getElementById('loading');
|
475 |
const results = document.getElementById('results');
|
476 |
const dissertationResult = document.getElementById('dissertationResult');
|
477 |
+
const tableauResult = document.getElementById('tableauResult');
|
478 |
+
|
479 |
const formData = new FormData();
|
480 |
formData.append('image', document.getElementById('imageInput').files[0]);
|
481 |
|
|
|
491 |
const data = await response.json();
|
492 |
|
493 |
if (response.ok) {
|
494 |
+
dissertationContent = data.dissertation;
|
495 |
tableauContent = data.tableau;
|
496 |
+
|
497 |
dissertationResult.innerHTML = marked.parse(data.dissertation);
|
498 |
+
tableauResult.innerHTML = marked.parse(data.tableau);
|
499 |
results.classList.remove('hidden');
|
500 |
results.classList.add('fade-in');
|
501 |
+
showTab('dissertation'); // Afficher l'onglet dissertation par défaut après l'analyse
|
502 |
} else {
|
503 |
Swal.fire({
|
504 |
icon: 'error',
|
|
|
516 |
loading.classList.add('hidden');
|
517 |
}
|
518 |
});
|
519 |
+
|
520 |
+
function renderTableauContent() {
|
521 |
+
const tableauResult = document.getElementById('tableauResult');
|
522 |
+
if (tableauContent) {
|
523 |
+
tableauResult.innerHTML = marked.parse(tableauContent);
|
524 |
+
showScrollIndicator(tableauResult);
|
525 |
+
}
|
526 |
+
}
|
527 |
+
|
528 |
</script>
|
529 |
</body>
|
530 |
</html>
|