Docfile commited on
Commit
79914b8
·
verified ·
1 Parent(s): f71b589

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +286 -97
templates/index.html CHANGED
@@ -1,104 +1,293 @@
1
- {% extends "base.html" %}
2
-
3
- {% block title %}Accueil - Podcasts{% endblock %}
4
-
5
- {% block content %}
6
- <h2>Podcasts Disponibles</h2>
7
-
8
- <div class="search-bar">
9
- <input type="text" id="searchInput" onkeyup="filterPodcasts()" placeholder="Rechercher par nom ou matière...">
10
- </div>
11
-
12
- <div id="podcastList">
13
- {% if podcasts %}
14
- {% for podcast in podcasts %}
15
- <div class="podcast-item" data-name="{{ podcast.name.lower() }}" data-subject="{{ podcast.subject.lower() }}">
16
- <h3>{{ podcast.name }}</h3>
17
- <p><strong>Matière :</strong> {{ podcast.subject }}</p>
18
- <button onclick="playPodcast('{{ podcast.id }}', this)">Écouter</button>
19
- <div id="player-{{ podcast.id }}"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  </div>
21
- {% endfor %}
22
- {% else %}
23
- <p>Aucun podcast disponible. Ajoutez-en depuis la page de <a href="{{ url_for('gestion') }}">gestion</a>.</p>
24
- {% endif %}
 
 
 
 
 
 
 
 
25
  </div>
26
- {% endblock %}
27
-
28
- {% block scripts %}
29
- <script>
30
- function filterPodcasts() {
31
- let input = document.getElementById('searchInput');
32
- let filter = input.value.toLowerCase();
33
- let podcastList = document.getElementById('podcastList');
34
- let items = podcastList.getElementsByClassName('podcast-item');
35
-
36
- for (let i = 0; i < items.length; i++) {
37
- let name = items[i].getAttribute('data-name');
38
- let subject = items[i].getAttribute('data-subject');
39
- if (name.includes(filter) || subject.includes(filter)) {
40
- items[i].style.display = "";
41
- } else {
42
- items[i].style.display = "none";
43
- }
44
- }
45
- }
46
 
47
- function playPodcast(podcastId, buttonElement) {
48
- // Désactiver tous les autres boutons "Écouter" et réinitialiser leur texte
49
- document.querySelectorAll('.podcast-item button').forEach(btn => {
50
- if (btn !== buttonElement) {
51
- btn.disabled = false;
52
- btn.textContent = 'Écouter';
53
- }
54
- });
55
- // Vider les autres lecteurs audio
56
- document.querySelectorAll('div[id^="player-"]').forEach(playerDiv => {
57
- if (playerDiv.id !== `player-${podcastId}`) {
58
- playerDiv.innerHTML = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  });
61
-
62
-
63
- let playerDiv = document.getElementById('player-' + podcastId);
64
 
65
- // Si le lecteur est déjà là, on le supprime (pour "arrêter")
66
- if (playerDiv.querySelector('audio')) {
67
- playerDiv.innerHTML = '';
68
- buttonElement.textContent = 'Écouter';
69
- buttonElement.disabled = false;
70
- return;
71
- }
72
-
73
- // Afficher "Chargement..." et désactiver le bouton
74
- buttonElement.textContent = 'Chargement...';
75
- buttonElement.disabled = true;
76
-
77
- fetch(`/play/${podcastId}`)
78
- .then(response => {
79
- if (!response.ok) {
80
- throw new Error(`Erreur HTTP: ${response.status}`);
81
- }
82
- // Le serveur envoie l'URL du fichier audio mis en cache
83
- return response.json();
84
- })
85
- .then(data => {
86
- if (data.audio_url) {
87
- playerDiv.innerHTML = `<audio controls autoplay src="${data.audio_url}">Votre navigateur ne supporte pas l'élément audio.</audio>`;
88
- buttonElement.textContent = 'Arrêter'; // Ou "Lecture en cours"
89
- buttonElement.disabled = false; // Réactiver pour permettre d'arrêter
90
- } else if (data.error) {
91
- playerDiv.innerHTML = `<p style="color: red;">Erreur: ${data.error}</p>`;
92
- buttonElement.textContent = 'Écouter'; // Réinitialiser
93
- buttonElement.disabled = false;
94
- }
95
- })
96
- .catch(error => {
97
- console.error('Erreur lors de la lecture du podcast:', error);
98
- playerDiv.innerHTML = `<p style="color: red;">Impossible de charger le podcast. Vérifiez la console.</p>`;
99
- buttonElement.textContent = 'Écouter'; // Réinitialiser
100
- buttonElement.disabled = false;
101
  });
102
- }
103
- </script>
104
- {% endblock %}
 
 
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>Résolveur d'Images</title>
7
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js"></script>
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/contrib/auto-render.min.js"></script>
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.css">
10
+ <style>
11
+ body {
12
+ font-family: Arial, sans-serif;
13
+ max-width: 800px;
14
+ margin: 0 auto;
15
+ padding: 20px;
16
+ line-height: 1.6;
17
+ }
18
+ h1 {
19
+ text-align: center;
20
+ color: #333;
21
+ }
22
+ .container {
23
+ display: flex;
24
+ flex-direction: column;
25
+ gap: 20px;
26
+ }
27
+ .upload-section {
28
+ display: flex;
29
+ flex-direction: column;
30
+ align-items: center;
31
+ padding: 20px;
32
+ border: 2px dashed #ccc;
33
+ border-radius: 8px;
34
+ cursor: pointer;
35
+ transition: all 0.3s;
36
+ }
37
+ .upload-section:hover {
38
+ border-color: #888;
39
+ }
40
+ #file-input {
41
+ display: none;
42
+ }
43
+ .preview-container {
44
+ width: 100%;
45
+ text-align: center;
46
+ margin-top: 10px;
47
+ }
48
+ #image-preview {
49
+ max-width: 100%;
50
+ max-height: 300px;
51
+ display: none;
52
+ }
53
+ #solving-container {
54
+ display: none;
55
+ background-color: #f5f5f5;
56
+ padding: 20px;
57
+ border-radius: 8px;
58
+ }
59
+ .response-container {
60
+ margin-top: 20px;
61
+ padding: 20px;
62
+ border: 1px solid #ddd;
63
+ border-radius: 8px;
64
+ background-color: #fff;
65
+ display: none;
66
+ }
67
+ .thinking {
68
+ color: #777;
69
+ font-style: italic;
70
+ }
71
+ .button {
72
+ background-color: #4CAF50;
73
+ color: white;
74
+ border: none;
75
+ padding: 10px 20px;
76
+ text-align: center;
77
+ text-decoration: none;
78
+ display: inline-block;
79
+ font-size: 16px;
80
+ margin: 10px 2px;
81
+ cursor: pointer;
82
+ border-radius: 4px;
83
+ transition: background-color 0.3s;
84
+ }
85
+ .button:hover {
86
+ background-color: #45a049;
87
+ }
88
+ .button:disabled {
89
+ background-color: #cccccc;
90
+ cursor: not-allowed;
91
+ }
92
+ .copy-button {
93
+ background-color: #2196F3;
94
+ }
95
+ .copy-button:hover {
96
+ background-color: #0b7dda;
97
+ }
98
+ .loading {
99
+ text-align: center;
100
+ font-style: italic;
101
+ margin: 10px 0;
102
+ }
103
+ .status {
104
+ text-align: center;
105
+ margin-bottom: 10px;
106
+ font-weight: bold;
107
+ }
108
+ </style>
109
+ </head>
110
+ <body>
111
+ <h1>Résolveur d'Images</h1>
112
+
113
+ <div class="container">
114
+ <div id="upload-section" class="upload-section">
115
+ <p>Cliquez ou glissez-déposez une image ici</p>
116
+ <input type="file" id="file-input" accept="image/*">
117
+ <div class="preview-container">
118
+ <img id="image-preview" src="#" alt="Aperçu de l'image">
119
  </div>
120
+ </div>
121
+
122
+ <button id="solve-button" class="button" disabled>Résoudre</button>
123
+
124
+ <div id="solving-container">
125
+ <div class="status" id="status">En attente de résolution...</div>
126
+ <div class="loading" id="loading-text">Traitement en cours...</div>
127
+ <div class="response-container" id="response-container">
128
+ <div id="response"></div>
129
+ <button id="copy-button" class="button copy-button">Copier la réponse</button>
130
+ </div>
131
+ </div>
132
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
+ <script>
135
+ document.addEventListener('DOMContentLoaded', function() {
136
+ const uploadSection = document.getElementById('upload-section');
137
+ const fileInput = document.getElementById('file-input');
138
+ const imagePreview = document.getElementById('image-preview');
139
+ const solveButton = document.getElementById('solve-button');
140
+ const solvingContainer = document.getElementById('solving-container');
141
+ const responseContainer = document.getElementById('response-container');
142
+ const response = document.getElementById('response');
143
+ const copyButton = document.getElementById('copy-button');
144
+ const statusElement = document.getElementById('status');
145
+ const loadingText = document.getElementById('loading-text');
146
+
147
+ let selectedFile = null;
148
+
149
+ // Événements pour l'upload d'image
150
+ uploadSection.addEventListener('click', () => fileInput.click());
151
+
152
+ uploadSection.addEventListener('dragover', (e) => {
153
+ e.preventDefault();
154
+ uploadSection.style.borderColor = '#2196F3';
155
+ });
156
+
157
+ uploadSection.addEventListener('dragleave', () => {
158
+ uploadSection.style.borderColor = '#ccc';
159
+ });
160
+
161
+ uploadSection.addEventListener('drop', (e) => {
162
+ e.preventDefault();
163
+ uploadSection.style.borderColor = '#ccc';
164
+
165
+ if (e.dataTransfer.files.length) {
166
+ handleFileSelection(e.dataTransfer.files[0]);
167
+ }
168
+ });
169
+
170
+ fileInput.addEventListener('change', (e) => {
171
+ if (e.target.files.length) {
172
+ handleFileSelection(e.target.files[0]);
173
+ }
174
+ });
175
+
176
+ function handleFileSelection(file) {
177
+ if (!file.type.startsWith('image/')) {
178
+ alert('Veuillez sélectionner une image valide');
179
+ return;
180
+ }
181
+
182
+ selectedFile = file;
183
+ solveButton.disabled = false;
184
+
185
+ const reader = new FileReader();
186
+ reader.onload = (e) => {
187
+ imagePreview.src = e.target.result;
188
+ imagePreview.style.display = 'block';
189
+ };
190
+ reader.readAsDataURL(file);
191
  }
192
+
193
+ // Événement pour résoudre l'image
194
+ solveButton.addEventListener('click', () => {
195
+ if (!selectedFile) return;
196
+
197
+ solveButton.disabled = true;
198
+ solvingContainer.style.display = 'block';
199
+ responseContainer.style.display = 'none';
200
+ statusElement.textContent = 'En attente de résolution...';
201
+ loadingText.style.display = 'block';
202
+ response.innerHTML = '';
203
+
204
+ const formData = new FormData();
205
+ formData.append('image', selectedFile);
206
+
207
+ // Création d'une connexion SSE pour recevoir la réponse en streaming
208
+ const eventSource = new EventSource('/solve?' + new URLSearchParams({
209
+ t: new Date().getTime()
210
+ }));
211
+
212
+ fetch('/solve', {
213
+ method: 'POST',
214
+ body: formData
215
+ }).then(response => {
216
+ if (!response.ok) {
217
+ throw new Error('Erreur lors de la résolution');
218
+ }
219
+
220
+ // Gestion du SSE
221
+ const eventSource = new EventSource('/solve');
222
+ let fullResponse = '';
223
+
224
+ eventSource.onmessage = function(event) {
225
+ const data = JSON.parse(event.data);
226
+
227
+ if (data.mode === 'thinking') {
228
+ statusElement.textContent = 'Gemini réfléchit...';
229
+ response.className = 'thinking';
230
+ } else if (data.mode === 'answering') {
231
+ statusElement.textContent = 'Réponse:';
232
+ response.className = '';
233
+ responseContainer.style.display = 'block';
234
+ loadingText.style.display = 'none';
235
+ }
236
+
237
+ if (data.content) {
238
+ fullResponse += data.content;
239
+ response.innerHTML = fullResponse;
240
+ renderMathInElement(response);
241
+ }
242
+
243
+ if (data.error) {
244
+ statusElement.textContent = 'Erreur:';
245
+ response.innerHTML = data.error;
246
+ eventSource.close();
247
+ solveButton.disabled = false;
248
+ }
249
+ };
250
+
251
+ eventSource.onerror = function() {
252
+ eventSource.close();
253
+ solveButton.disabled = false;
254
+ };
255
+ }).catch(error => {
256
+ statusElement.textContent = 'Erreur:';
257
+ response.innerHTML = 'Une erreur est survenue lors de la communication avec le serveur.';
258
+ responseContainer.style.display = 'block';
259
+ loadingText.style.display = 'none';
260
+ solveButton.disabled = false;
261
+ });
262
+ });
263
+
264
+ // Événement pour copier la réponse
265
+ copyButton.addEventListener('click', () => {
266
+ const range = document.createRange();
267
+ range.selectNode(response);
268
+ window.getSelection().removeAllRanges();
269
+ window.getSelection().addRange(range);
270
+ document.execCommand('copy');
271
+ window.getSelection().removeAllRanges();
272
+
273
+ copyButton.textContent = 'Copié!';
274
+ setTimeout(() => {
275
+ copyButton.textContent = 'Copier la réponse';
276
+ }, 2000);
277
+ });
278
  });
 
 
 
279
 
280
+ // Rendu des formules LaTeX
281
+ document.addEventListener('DOMContentLoaded', function() {
282
+ renderMathInElement(document.body, {
283
+ delimiters: [
284
+ {left: '$$', right: '$$', display: true},
285
+ {left: '$', right: '$', display: false},
286
+ {left: '\\(', right: '\\)', display: false},
287
+ {left: '\\[', right: '\\]', display: true}
288
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  });
290
+ });
291
+ </script>
292
+ </body>
293
+ </html>