Docfile commited on
Commit
003c135
·
verified ·
1 Parent(s): 789b21f

Create templates/generale.html

Browse files
Files changed (1) hide show
  1. templates/generale.html +382 -0
templates/generale.html ADDED
@@ -0,0 +1,382 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>Question Générale</title>
7
+ <!-- Style de secours pour masquer les éléments dès le début -->
8
+ <style>
9
+ .hidden { display: none !important; }
10
+ </style>
11
+ <!-- Tailwind CSS -->
12
+ <script src="https://cdn.tailwindcss.com"></script>
13
+ <!-- Marked (Markdown) -->
14
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/4.0.2/marked.min.js" defer></script>
15
+ <!-- Font Awesome -->
16
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" />
17
+ <!-- SweetAlert2 -->
18
+ <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11" defer></script>
19
+ <!-- Polyfill -->
20
+ <script src="https://polyfill.io/v3/polyfill.min.js?features=es6" defer></script>
21
+ <!-- Anime.js -->
22
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js" defer></script>
23
+ <!-- Configuration de MathJax -->
24
+ <script>
25
+ window.MathJax = {
26
+ tex: {
27
+ inlineMath: [['$', '$'], ['\\(', '\\)']],
28
+ displayMath: [['$$', '$$'], ['\\[', '\\]']],
29
+ processEscapes: true
30
+ },
31
+ options: {
32
+ skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre']
33
+ },
34
+ startup: {
35
+ pageReady: () => {
36
+ return MathJax.startup.defaultPageReady().then(() => {
37
+ console.log('MathJax initial typesetting complete');
38
+ });
39
+ }
40
+ }
41
+ };
42
+ </script>
43
+ <!-- MathJax -->
44
+ <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" defer></script>
45
+ <style>
46
+ :root {
47
+ --primary-color: #008cba;
48
+ --background-color: #f0f8ff;
49
+ --animation-timing: 0.3s;
50
+ }
51
+
52
+ body {
53
+ margin: 0;
54
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
55
+ background-color: var(--background-color);
56
+ min-height: 100vh;
57
+ padding: 20px;
58
+ box-sizing: border-box;
59
+ overflow-x: hidden;
60
+ }
61
+
62
+ .navbar {
63
+ background-color: var(--primary-color);
64
+ color: white;
65
+ padding: 15px;
66
+ width: 100%;
67
+ text-align: center;
68
+ font-size: 24px;
69
+ font-weight: bold;
70
+ position: fixed;
71
+ top: 0;
72
+ left: 0;
73
+ z-index: 1000;
74
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
75
+ animation: slideDown 0.5s ease-out;
76
+ }
77
+
78
+ .container {
79
+ margin-top: 80px;
80
+ max-width: 800px;
81
+ background-color: white;
82
+ border-radius: 8px;
83
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
84
+ padding: 20px;
85
+ animation: fadeInScale 0.5s forwards;
86
+ }
87
+
88
+ .button {
89
+ background-color: var(--primary-color);
90
+ color: white;
91
+ padding: 15px;
92
+ border: none;
93
+ border-radius: 8px;
94
+ font-size: 16px;
95
+ text-align: center;
96
+ cursor: pointer;
97
+ position: relative;
98
+ overflow: hidden;
99
+ transform: translateZ(0);
100
+ will-change: transform;
101
+ transition: all var(--animation-timing) ease;
102
+ }
103
+
104
+ .button:hover {
105
+ transform: scale(1.05) translateY(-2px);
106
+ box-shadow: 0 10px 20px rgba(0,0,0,0.2);
107
+ }
108
+
109
+ .button i {
110
+ margin-right: 10px;
111
+ transition: transform var(--animation-timing) ease;
112
+ }
113
+
114
+ .input-field {
115
+ width: 100%;
116
+ padding: 12px;
117
+ border: 2px solid var(--primary-color);
118
+ border-radius: 8px;
119
+ margin-bottom: 15px;
120
+ transition: all var(--animation-timing) ease;
121
+ }
122
+
123
+ .input-field:focus {
124
+ outline: none;
125
+ box-shadow: 0 0 0 3px rgba(0,140,186,0.2);
126
+ }
127
+
128
+ #response {
129
+ background-color: #f8f9fa;
130
+ border-radius: 8px;
131
+ padding: 15px;
132
+ margin-top: 20px;
133
+ animation: fadeIn 0.5s ease-out;
134
+ }
135
+
136
+ #loader {
137
+ display: flex;
138
+ justify-content: center;
139
+ align-items: center;
140
+ margin: 20px 0;
141
+ }
142
+
143
+ @keyframes fadeInScale {
144
+ 0% {
145
+ opacity: 0;
146
+ transform: scale(0.5);
147
+ }
148
+ 100% {
149
+ opacity: 1;
150
+ transform: scale(1);
151
+ }
152
+ }
153
+
154
+ @keyframes slideDown {
155
+ from { transform: translateY(-100%); }
156
+ to { transform: translateY(0); }
157
+ }
158
+
159
+ @keyframes fadeIn {
160
+ from { opacity: 0; }
161
+ to { opacity: 1; }
162
+ }
163
+
164
+ .url-item {
165
+ background-color: #f0f8ff;
166
+ padding: 10px;
167
+ border-radius: 6px;
168
+ margin-bottom: 8px;
169
+ display: flex;
170
+ align-items: center;
171
+ animation: fadeIn 0.3s ease-out;
172
+ }
173
+ </style>
174
+ </head>
175
+ <body>
176
+ <div class="navbar">Mariam AI</div>
177
+
178
+ <div class="container mx-auto">
179
+ <!-- En-tête -->
180
+ <div class="flex flex-col md:flex-row md:justify-between items-start md:items-center mb-6 space-y-4 md:space-y-0">
181
+ <h1 class="text-3xl font-bold text-gray-800">Poser une question générale</h1>
182
+ <button onclick="showInfo()" class="button">
183
+ <i class="fas fa-info-circle"></i> Info
184
+ </button>
185
+ </div>
186
+
187
+ <!-- Zone de question -->
188
+ <div class="mb-6">
189
+ <label for="questionInput" class="block mb-2 text-lg font-medium text-gray-700">Votre question :</label>
190
+ <textarea id="questionInput" class="input-field" rows="4" placeholder="Entrez votre question ici..."></textarea>
191
+ </div>
192
+
193
+ <!-- Zone d'ajout d'URLs -->
194
+ <div class="mb-6">
195
+ <label for="urlInput" class="block mb-2 text-lg font-medium text-gray-700">URLs (optionnel) :</label>
196
+ <div class="flex">
197
+ <input type="text" id="urlInput" class="input-field" placeholder="Entrez une URL" />
198
+ <button onclick="addUrl()" class="button ml-2">
199
+ <i class="fas fa-plus"></i> Ajouter
200
+ </button>
201
+ </div>
202
+ <div id="urlList" class="mt-2 space-y-2"></div>
203
+ </div>
204
+
205
+ <!-- Zone d'ajout de fichiers -->
206
+ <div class="mb-6">
207
+ <label for="fileUpload" class="block mb-2 text-lg font-medium text-gray-700">Fichiers (optionnel) :</label>
208
+ <input type="file" id="fileUpload" class="input-field" multiple />
209
+ </div>
210
+
211
+ <!-- Bouton de soumission -->
212
+ <button onclick="submitQuestion()" class="button w-full">
213
+ <i class="fas fa-paper-plane"></i> Soumettre
214
+ </button>
215
+
216
+ <!-- Loader -->
217
+ <div id="loader" class="hidden">
218
+ <div class="animate-spin rounded-full h-12 w-12 border-t-4 border-b-4 border-blue-500"></div>
219
+ <p class="ml-2 text-gray-600">Chargement en cours...</p>
220
+ </div>
221
+
222
+ <!-- Affichage de la réponse -->
223
+ <div id="response" class="hidden"></div>
224
+
225
+ <!-- Bouton pour copier la réponse -->
226
+ <div id="copyResponseContainer" class="hidden mt-4">
227
+ <button onclick="copyResponse()" class="button w-full">
228
+ <i class="fas fa-copy"></i> Copier la réponse
229
+ </button>
230
+ </div>
231
+ </div>
232
+
233
+ <script>
234
+ function showInfo() {
235
+ Swal.fire({
236
+ title: 'Information',
237
+ html: `
238
+ <p class="mb-2">Ce formulaire vous permet de poser des questions générales.</p>
239
+ <p class="mb-2">Vous pouvez également ajouter des URLs et des fichiers pour fournir plus de contexte à votre question.</p>
240
+ <p class="mb-2">La réponse sera formatée en Markdown et peut inclure des équations LaTeX.</p>
241
+ <p>Si vous souhaitez résoudre vos exercices de mathématiques ici, signalez-le à Mariam pour une réponse en LaTeX.</p>
242
+ `,
243
+ icon: 'info',
244
+ confirmButtonText: 'Compris'
245
+ });
246
+ }
247
+
248
+ function addUrl() {
249
+ const urlInput = document.getElementById('urlInput');
250
+ const urlList = document.getElementById('urlList');
251
+ const url = urlInput.value.trim();
252
+ if (url) {
253
+ const urlItem = document.createElement('div');
254
+ urlItem.className = 'url-item flex items-center bg-gray-200 p-2 rounded-lg shadow-sm';
255
+ urlItem.innerHTML = `
256
+ <span class="flex-grow truncate">${url}</span>
257
+ <button onclick="removeUrl(this)" class="ml-2 text-red-500 hover:text-red-700">
258
+ <i class="fas fa-times"></i>
259
+ </button>
260
+ `;
261
+ urlList.appendChild(urlItem);
262
+ urlInput.value = '';
263
+ }
264
+ }
265
+
266
+ function removeUrl(button) {
267
+ const urlItem = button.closest('.url-item');
268
+ if(urlItem) urlItem.remove();
269
+ }
270
+
271
+ async function submitQuestion() {
272
+ const question = document.getElementById('questionInput').value.trim();
273
+ if (!question) return;
274
+
275
+ const loader = document.getElementById('loader');
276
+ const responseDiv = document.getElementById('response');
277
+ const copyResponseContainer = document.getElementById('copyResponseContainer');
278
+
279
+ // Afficher le loader et réinitialiser la zone de réponse
280
+ loader.classList.remove('hidden');
281
+ responseDiv.classList.remove('hidden');
282
+ responseDiv.innerHTML = '';
283
+ responseDiv.classList.add('opacity-0');
284
+ copyResponseContainer.classList.add('hidden');
285
+
286
+ const formData = new FormData();
287
+ formData.append('question', question);
288
+
289
+ // Récupération des URLs
290
+ document.querySelectorAll('#urlList .url-item').forEach(item => {
291
+ formData.append('urls', item.querySelector('span').textContent);
292
+ });
293
+
294
+ // Récupération des fichiers
295
+ Array.from(document.getElementById('fileUpload').files).forEach(file => {
296
+ formData.append('files', file);
297
+ });
298
+
299
+ try {
300
+ const response = await fetch('/submit', {
301
+ method: 'POST',
302
+ body: formData
303
+ });
304
+ const data = await response.json();
305
+
306
+ loader.classList.add('hidden');
307
+ responseDiv.classList.remove('opacity-0');
308
+
309
+ if (data.error) {
310
+ responseDiv.innerHTML = `<p class="text-red-600">Erreur : ${data.error}</p>`;
311
+ } else {
312
+ const htmlContent = marked.parse(data.response);
313
+ responseDiv.innerHTML = htmlContent;
314
+ copyResponseContainer.classList.remove('hidden');
315
+
316
+ // Rendu de LaTeX avec MathJax
317
+ await MathJax.typesetPromise([responseDiv]);
318
+ console.log('LaTeX rendu avec succès');
319
+ }
320
+ } catch (error) {
321
+ loader.classList.add('hidden');
322
+ responseDiv.innerHTML = `<p class="text-red-600">Erreur : ${error.message}</p>`;
323
+ responseDiv.classList.remove('opacity-0');
324
+ }
325
+ }
326
+
327
+ function copyResponse() {
328
+ const responseDiv = document.getElementById('response');
329
+ const text = responseDiv.innerText;
330
+
331
+ if (navigator.clipboard && navigator.clipboard.writeText) {
332
+ navigator.clipboard.writeText(text)
333
+ .then(() => {
334
+ Swal.fire({
335
+ icon: 'success',
336
+ title: 'Copié !',
337
+ text: 'La réponse a été copiée dans le presse-papiers.',
338
+ showConfirmButton: false,
339
+ timer: 1500
340
+ });
341
+ })
342
+ .catch(err => {
343
+ console.error('Erreur lors de la copie avec Clipboard API:', err);
344
+ fallbackCopyTextToClipboard(text);
345
+ });
346
+ } else {
347
+ fallbackCopyTextToClipboard(text);
348
+ }
349
+ }
350
+
351
+ function fallbackCopyTextToClipboard(text) {
352
+ const textArea = document.createElement("textarea");
353
+ textArea.value = text;
354
+ // Éviter le scroll et positionner en dehors de l'écran
355
+ textArea.style.top = "0";
356
+ textArea.style.left = "0";
357
+ textArea.style.position = "fixed";
358
+ document.body.appendChild(textArea);
359
+ textArea.focus();
360
+ textArea.select();
361
+
362
+ try {
363
+ const successful = document.execCommand('copy');
364
+ if (successful) {
365
+ Swal.fire({
366
+ icon: 'success',
367
+ title: 'Copié !',
368
+ text: 'La réponse a été copiée dans le presse-papiers.',
369
+ showConfirmButton: false,
370
+ timer: 1500
371
+ });
372
+ } else {
373
+ console.error('Erreur lors de la copie avec execCommand');
374
+ }
375
+ } catch (err) {
376
+ console.error('Erreur lors de la copie:', err);
377
+ }
378
+ document.body.removeChild(textArea);
379
+ }
380
+ </script>
381
+ </body>
382
+ </html>