ernestmindres commited on
Commit
38c8bce
·
verified ·
1 Parent(s): c205b2f

Update templates/static_deploy.html

Browse files
Files changed (1) hide show
  1. templates/static_deploy.html +167 -271
templates/static_deploy.html CHANGED
@@ -12,7 +12,6 @@
12
  /* -------------------------------------- */
13
  /* CSS pour la zone de Glisser-Déposer */
14
  /* -------------------------------------- */
15
- /* ... (styles de dropzone inchangés) ... */
16
  .dropzone {
17
  border: 3px dashed #007bff;
18
  background-color: #f8f9fa;
@@ -119,84 +118,61 @@
119
  <h2 class="text-center mb-4"> Déploiement Statique Instantané</h2>
120
 
121
  <div id="drop-zone" class="dropzone">
122
- <div class="dropzone-icon"></div>
123
- <div class="dropzone-text">Glissez & Déposez vos fichiers ici</div>
124
- <div class="dropzone-hint">ou cliquez pour sélectionner des fichiers (HTML, CSS, JS, Images...)</div>
125
- <div id="upload-status" class="mt-3 text-muted">Prêt pour l'upload.</div>
126
  </div>
127
 
128
- <div id="permanent-url-container" class="mt-4 p-3 border rounded"
129
- style="display: none; background-color: #d1e7dd !important; border-color: #badbcc !important;">
130
- <label class="form-label fw-bold d-block text-success" style="color: #0f5132 !important;">
131
- <span class="material-symbols-rounded align-middle me-1">check_circle</span> Lien de Déploiement Permanent
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  </label>
133
  <div class="input-group mb-2">
134
- <input type="text" id="permanent-url-display" class="form-control" readonly
135
- value="{{ permanent_deployment_url if permanent_deployment_url else '' }}">
136
  <button class="btn btn-outline-secondary" type="button" id="copy-permanent-button" title="Copier le lien permanent">
137
  <span class="material-symbols-rounded">content_copy</span>
138
  </button>
139
  </div>
140
- <small class="text-muted mt-1 d-block">
141
- ✅ Ce lien est sauvegardé sur Hugging Face et est permanent.
142
- </small>
143
  </div>
144
 
145
- <div id="temp-url-container" class="mt-4 p-3 bg-light border rounded"
146
- style="display: none; background-color: #fff3cd !important; border-color: #ffc107 !important;">
147
- <label class="form-label fw-bold d-block text-warning" style="color: #664d03 !important;">
148
- <span class="material-symbols-rounded align-middle me-1">share</span> Lien d'Aperçu Temporaire
149
  </label>
150
  <div class="input-group mb-2">
151
- <input type="text" id="temp-url-display" class="form-control" readonly
152
- value="{{ temp_launch_url if temp_launch_url else '' }}">
153
  <button class="btn btn-outline-secondary" type="button" id="copy-temp-button" title="Copier le lien temporaire">
154
  <span class="material-symbols-rounded">content_copy</span>
155
  </button>
156
  </div>
157
- <small class="text-danger mt-1 d-block">
158
- ⚠️ **Attention:** Ce lien est temporaire. Cliquez sur "Déployer le Site Web" pour le rendre permanent.
159
- </small>
160
- </div>
161
-
162
- <div class="d-grid gap-2 d-md-flex justify-content-md-center mb-4 mt-4">
163
- <button class="btn btn-success btn-lg" id="deploy-button" disabled>
164
- <span class="material-symbols-rounded align-middle me-1">cloud_upload</span> Déployer le Site Web (Permanent)
165
- </button>
166
- <button class="btn btn-primary btn-lg" id="launch-button" disabled>
167
- <span class="material-symbols-rounded align-middle me-1">open_in_new</span> Lancer l'Aperçu
168
- </button>
169
- <button class="btn btn-danger btn-lg" id="clear-button" disabled>
170
- <span class="material-symbols-rounded align-middle me-1">delete</span> Vider le Cache
171
- </button>
172
- </div>
173
-
174
- <div class="card shadow-sm">
175
- <div class="card-header bg-light">
176
- <h5 class="mb-0">Fichiers Actuellement Téléversés (<span id="file-count">{{ files|length }}</span>)</h5>
177
- </div>
178
- <div class="card-body">
179
- {% if files %}
180
- <ul class="file-list" id="uploaded-file-list">
181
- {% for file in files %}
182
- <li>
183
- <span class="file-icon"></span> {{ file }}
184
- {% if file == 'index.html' %}
185
- <span class="badge bg-success" style="background-color: #198754 !important;">PAGE D'ACCUEIL</span>
186
- {% endif %}
187
- </li>
188
- {% endfor %}
189
- </ul>
190
- {% else %}
191
- <p class="text-center text-muted" id="no-files-message">Aucun fichier n'a été téléversé pour le moment.</p>
192
- {% endif %}
193
- </div>
194
  </div>
195
 
196
- {% if deploy_id %}
197
- <small class="text-muted mt-3 d-block text-center">ID de Projet (Cache Local): <code>{{ deploy_id }}</code></small>
198
- {% endif %}
199
-
200
  </div>
201
  </div>
202
  </div>
@@ -205,253 +181,151 @@
205
  // Récupération des éléments du DOM
206
  const dropZone = document.getElementById('drop-zone');
207
  const fileInput = document.getElementById('file-input');
208
- const uploadStatus = document.getElementById('upload-status');
 
 
209
  const launchButton = document.getElementById('launch-button');
210
  const clearButton = document.getElementById('clear-button');
 
211
 
212
- // NOUVEAU
213
- const deployButton = document.getElementById('deploy-button');
214
  const permanentUrlContainer = document.getElementById('permanent-url-container');
215
  const permanentUrlInput = document.getElementById('permanent-url-display');
216
  const copyPermanentButton = document.getElementById('copy-permanent-button');
217
 
218
- // EXISTANT MAIS MODIFIÉ
219
  const tempUrlContainer = document.getElementById('temp-url-container');
220
  const tempUrlInput = document.getElementById('temp-url-display');
221
  const copyTempButton = document.getElementById('copy-temp-button');
222
 
223
- const fileCountSpan = document.getElementById('file-count');
224
- const uploadedFileList = document.getElementById('uploaded-file-list');
225
- const noFilesMessage = document.getElementById('no-files-message');
226
-
227
-
228
- // Récupération de l'URL injectée par Flask
229
- const currentTempUrl = tempUrlInput.value;
230
- const currentPermanentUrl = permanentUrlInput.value;
231
-
232
- /* -------------------------------------- */
233
- /* 0. Initialisation des Boutons/Affichage*/
234
- /* -------------------------------------- */
235
-
236
- const indexFilePresent = {{ index_file_present | tojson }};
237
  const fileCount = {{ files|length }};
238
  const deployId = '{{ deploy_id }}';
239
-
240
-
241
- // 0a. Gestion de l'affichage de l'URL
242
- if (currentPermanentUrl) {
243
- // Si l'URL permanente est là, on affiche le lien permanent et on désactive le bouton de déploiement.
244
- permanentUrlContainer.style.display = 'block';
245
- deployButton.disabled = true;
246
- tempUrlContainer.style.display = 'none';
247
- } else if (currentTempUrl) {
248
- // Si l'URL temporaire est là (avant commit)
249
- tempUrlContainer.style.display = 'block';
250
- deployButton.disabled = false;
251
- permanentUrlContainer.style.display = 'none';
252
- }
253
-
254
-
255
- // 0b. État initial des boutons Lancer et Vider
256
- if (!indexFilePresent || fileCount === 0) {
257
- launchButton.disabled = true;
258
- } else {
259
- launchButton.disabled = false;
260
- }
261
- if (fileCount > 0) {
262
- clearButton.disabled = false;
263
- }
264
-
265
-
266
- // 0c. Gère le lancement de l'aperçu
267
- launchButton.addEventListener('click', () => {
268
- // Utiliser l'URL permanente si disponible, sinon la temporaire
269
- const urlToLaunch = currentPermanentUrl || currentTempUrl;
270
- if (urlToLaunch) {
271
- window.open(urlToLaunch, '_blank');
272
- } else if (deployId && indexFilePresent) {
273
- window.open(`/serve-static/${deployId}/index.html`, '_blank');
274
- }
275
- });
276
-
277
-
278
- /* -------------------------------------- */
279
- /* 1, 2, 3 : Gestion de l'Upload (UI) */
280
- /* -------------------------------------- */
281
-
282
- // ... (Gestion de la Dropzone et du File Input inchangée) ...
283
- dropZone.addEventListener('click', () => { fileInput.click(); });
284
-
285
- ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
286
- dropZone.addEventListener(eventName, preventDefaults, false);
287
- });
288
-
289
- function preventDefaults(e) { e.preventDefault(); e.stopPropagation(); }
290
-
291
- ['dragenter', 'dragover'].forEach(eventName => { dropZone.addEventListener(eventName, highlight, false); });
292
- ['dragleave', 'drop'].forEach(eventName => { dropZone.addEventListener(eventName, unhighlight, false); });
293
-
294
- function highlight() { dropZone.classList.add('dragover'); uploadStatus.textContent = "Relâchez les fichiers pour téléverser..."; }
295
- function unhighlight() { dropZone.classList.remove('dragover'); }
296
-
297
- dropZone.addEventListener('drop', handleDrop, false);
298
-
299
- function handleDrop(e) {
300
- const dt = e.dataTransfer;
301
- fileInput.files = dt.files;
302
- handleFileSelection();
303
- }
304
-
305
- fileInput.addEventListener('change', handleFileSelection);
306
-
307
- function handleFileSelection() {
308
- if (fileInput.files.length > 0) {
309
- uploadFiles(fileInput.files);
310
  }
 
 
 
 
 
 
 
311
  }
312
 
313
-
314
- /* -------------------------------------- */
315
- /* 4. Logique de l'Upload (AJAX TEMPORAIRE)*/
316
- /* -------------------------------------- */
317
- function uploadFiles(files) {
318
- const url = "{{ url_for('web_bp.upload_static_files') }}";
319
- const formData = new FormData();
320
-
321
- for (let i = 0; i < files.length; i++) {
322
- formData.append('file-' + i, files[i]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
  }
324
-
325
- uploadStatus.className = 'mt-3 text-info';
326
- uploadStatus.textContent = `Téléversement de ${files.length} fichiers en cours...`;
327
 
328
- // Désactiver tous les boutons pendant l'upload
329
- launchButton.disabled = true;
330
- clearButton.disabled = true;
331
- deployButton.disabled = true;
332
-
333
- fetch(url, {
334
- method: 'POST',
335
- body: formData,
336
- })
337
- .then(response => {
338
- if (!response.ok) {
339
- return response.json().then(err => { throw new Error(err.message || 'Erreur serveur inconnu'); });
340
- }
341
- return response.json();
342
- })
343
- .then(data => {
344
- if (data.status === 'success') {
345
- uploadStatus.className = 'mt-3 text-success';
346
- uploadStatus.textContent = data.message;
347
-
348
- // Mise à jour de l'URL temporaire et affichage du conteneur temporaire
349
- tempUrlInput.value = data.launch_url;
350
- tempUrlContainer.style.display = 'block';
351
- permanentUrlContainer.style.display = 'none'; // Cacher l'ancien permanent
352
-
353
- // Réactiver les boutons selon l'état
354
- launchButton.disabled = !data.index_present;
355
- clearButton.disabled = false;
356
- deployButton.disabled = !data.index_present; // On ne peut déployer que s'il y a un index.html
357
-
358
- // Mise à jour de la liste des fichiers (rechargement pour la simplicité)
359
- setTimeout(() => {
360
- window.location.href = "{{ url_for('web_bp.static_deploy_page') }}";
361
- }, 500);
362
-
363
- // Si la liste était mise à jour côté client (sans rechargement):
364
- // updateFileList(data.uploaded_files_list, data.index_present, data.file_count);
365
-
366
- } else {
367
- uploadStatus.className = 'mt-3 text-danger';
368
- uploadStatus.textContent = `Échec du téléversement: ${data.message}`;
369
- // Réactiver les boutons de base si l'upload a échoué
370
- clearButton.disabled = fileCount === 0;
371
- }
372
- })
373
- .catch(error => {
374
- console.error('Erreur AJAX Upload:', error);
375
- uploadStatus.className = 'mt-3 text-danger';
376
- uploadStatus.textContent = `Erreur critique lors de l'upload: ${error.message}`;
377
- clearButton.disabled = false;
378
- });
379
  }
380
 
 
 
 
381
 
382
- /* -------------------------------------- */
383
- /* 5. Logique du Déploiement (AJAX PERMANENT) */
384
- /* -------------------------------------- */
385
- deployButton.addEventListener('click', commitDeployment);
386
-
387
- function commitDeployment() {
388
- const url = "{{ url_for('web_bp.deploy_to_hf') }}";
389
-
390
- // 1. Démarrer l'animation de chargement
391
  deployButton.disabled = true;
392
- launchButton.disabled = true;
393
- clearButton.disabled = true;
394
- deployButton.innerHTML = '<span class="spinner-border text-light me-2"></span> Déploiement en cours...';
395
 
396
- uploadStatus.className = 'mt-3 text-info';
397
- uploadStatus.textContent = `Déploiement permanent sur Hugging Face en cours... (Cela peut prendre quelques instants)`;
398
-
399
- // 2. Envoyer la requête AJAX
400
- fetch(url, {
401
- method: 'POST',
402
- })
403
- .then(response => {
404
- // Tente de lire l'erreur JSON pour un statut HTTP 4xx/5xx
405
- if (!response.ok) {
406
- return response.json().then(err => { throw new Error(err.message || 'Erreur serveur inconnu'); });
407
- }
408
- return response.json();
409
- })
410
- .then(data => {
411
- // 3. Mettre à jour l'interface en cas de succès
412
  if (data.success) {
413
- uploadStatus.className = 'mt-3 text-success';
414
- uploadStatus.textContent = data.message + " Redirection en cours...";
 
415
 
416
- // Mise à jour de l'URL permanente et de l'affichage
417
  permanentUrlInput.value = data.url;
418
  permanentUrlContainer.style.display = 'block';
419
  tempUrlContainer.style.display = 'none';
420
-
421
- // Recharger pour que Flask mette à jour l'interface JINJA2 pour un état permanent
422
- setTimeout(() => {
423
- window.location.href = "{{ url_for('web_bp.static_deploy_page') }}";
424
- }, 500);
 
 
 
425
 
426
  } else {
427
- // 4. Mettre à jour l'interface en cas d'échec
428
- uploadStatus.className = 'mt-3 text-danger';
429
  uploadStatus.textContent = `Échec du déploiement: ${data.message}`;
430
-
431
- // Rétablir les boutons à l'état "temporaire"
432
  deployButton.innerHTML = '<span class="material-symbols-rounded align-middle me-1">cloud_upload</span> Déployer le Site Web (Permanent)';
433
- deployButton.disabled = false;
434
- launchButton.disabled = !indexFilePresent;
435
- clearButton.disabled = false;
 
 
 
436
  }
437
- })
438
- .catch(error => {
439
- console.error('Erreur AJAX Déploiement:', error);
440
- uploadStatus.className = 'mt-3 text-danger';
441
- uploadStatus.textContent = `Erreur critique lors du déploiement: ${error.message}`;
442
 
443
- // Rétablir les boutons à l'état "temporaire"
444
  deployButton.innerHTML = '<span class="material-symbols-rounded align-middle me-1">cloud_upload</span> Déployer le Site Web (Permanent)';
445
- deployButton.disabled = false;
446
- launchButton.disabled = !indexFilePresent;
447
- clearButton.disabled = false;
448
- });
449
- }
450
 
451
 
452
- /* -------------------------------------- */
453
- /* 6. Gestion des Boutons de Copie */
454
- /* -------------------------------------- */
455
 
456
  function setupCopyButton(button, input) {
457
  button.addEventListener('click', () => {
@@ -480,12 +354,34 @@ function setupCopyButton(button, input) {
480
  setupCopyButton(copyTempButton, tempUrlInput);
481
  setupCopyButton(copyPermanentButton, permanentUrlInput);
482
 
 
 
 
 
 
 
 
483
 
484
  // Gère le bouton Vider (doit être implémenté au backend pour la suppression du dossier)
485
  clearButton.addEventListener('click', () => {
 
486
  alert("Fonction Vider: Une route de suppression doit être implémentée au backend pour supprimer le dossier temporaire et vider la session.");
487
  });
488
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
489
  </script>
490
 
491
  </body>
 
12
  /* -------------------------------------- */
13
  /* CSS pour la zone de Glisser-Déposer */
14
  /* -------------------------------------- */
 
15
  .dropzone {
16
  border: 3px dashed #007bff;
17
  background-color: #f8f9fa;
 
118
  <h2 class="text-center mb-4"> Déploiement Statique Instantané</h2>
119
 
120
  <div id="drop-zone" class="dropzone">
121
+ <span class="material-symbols-rounded dropzone-icon">cloud_upload</span>
122
+ <p class="dropzone-text">Glissez et déposez vos fichiers ici (HTML, CSS, JS, Images)</p>
123
+ <p class="dropzone-hint">Ou cliquez pour sélectionner des fichiers. Un fichier index.html est requis.</p>
124
+ <button id="select-files-button" class="btn btn-outline-primary mt-3">Sélectionner des Fichiers</button>
125
  </div>
126
 
127
+ <div id="file-upload-status" class="mt-3 text-muted">
128
+ Aucun fichier téléversé.
129
+ </div>
130
+
131
+ <ul id="uploaded-file-list" class="file-list p-3 border rounded shadow-sm bg-white" style="display: none;">
132
+ </ul>
133
+
134
+ <div id="action-zone" class="mt-4 p-4 border rounded shadow-sm bg-white">
135
+ <div class="d-flex justify-content-between align-items-center">
136
+ <button id="launch-button" class="btn btn-info me-2" disabled>
137
+ <span class="material-symbols-rounded align-middle me-1">open_in_new</span> Lancer l'Aperçu (Temp)
138
+ </button>
139
+
140
+ <button id="deploy-button" class="btn btn-success me-2" disabled>
141
+ <span class="material-symbols-rounded align-middle me-1">cloud_upload</span> Déployer le Site Web (Permanent)
142
+ </button>
143
+
144
+ <button id="clear-button" class="btn btn-danger" disabled>
145
+ <span class="material-symbols-rounded align-middle me-1">delete_forever</span> Vider
146
+ </button>
147
+ </div>
148
+ </div>
149
+
150
+ <div id="permanent-url-container" class="mt-4 p-3 bg-success-light border rounded" style="display: none; background-color: #d1e7dd !important; border-color: #badbcc !important;">
151
+ <label class="form-label fw-bold d-block text-success" style="color: #0f5132 !important;">
152
+ <span class="material-symbols-rounded align-middle me-1">link</span> Lien Permanent du Site
153
  </label>
154
  <div class="input-group mb-2">
155
+ <input type="text" id="permanent-url-display" class="form-control" readonly value="">
 
156
  <button class="btn btn-outline-secondary" type="button" id="copy-permanent-button" title="Copier le lien permanent">
157
  <span class="material-symbols-rounded">content_copy</span>
158
  </button>
159
  </div>
160
+ <small class="text-muted mt-1 d-block" style="color: #0f5132 !important;"> ✅ Ce lien est sauvegardé sur Hugging Face et est permanent. </small>
 
 
161
  </div>
162
 
163
+ <div id="temp-url-container" class="mt-4 p-3 bg-light border rounded" style="display: none; background-color: #fff3cd !important; border-color: #ffc107 !important;">
164
+ <label class="form-label fw-bold d-block text-warning" style="color: #664d03 !important;">
165
+ <span class="material-symbols-rounded align-middle me-1">share</span> Lien d'Aperçu Temporaire
 
166
  </label>
167
  <div class="input-group mb-2">
168
+ <input type="text" id="temp-url-display" class="form-control" readonly value="{{ temp_launch_url if temp_launch_url else '' }}">
 
169
  <button class="btn btn-outline-secondary" type="button" id="copy-temp-button" title="Copier le lien temporaire">
170
  <span class="material-symbols-rounded">content_copy</span>
171
  </button>
172
  </div>
173
+ <small class="text-muted mt-1 d-block"> ⚠️ Ce lien est temporaire. Cliquez sur "Déployer le Site Web" pour le rendre permanent. </small>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  </div>
175
 
 
 
 
 
176
  </div>
177
  </div>
178
  </div>
 
181
  // Récupération des éléments du DOM
182
  const dropZone = document.getElementById('drop-zone');
183
  const fileInput = document.getElementById('file-input');
184
+ const selectFilesButton = document.getElementById('select-files-button');
185
+ const uploadStatus = document.getElementById('file-upload-status');
186
+ const uploadedFileList = document.getElementById('uploaded-file-list');
187
  const launchButton = document.getElementById('launch-button');
188
  const clearButton = document.getElementById('clear-button');
189
+ const deployButton = document.getElementById('deploy-button'); // Le bouton Commit Change
190
 
 
 
191
  const permanentUrlContainer = document.getElementById('permanent-url-container');
192
  const permanentUrlInput = document.getElementById('permanent-url-display');
193
  const copyPermanentButton = document.getElementById('copy-permanent-button');
194
 
 
195
  const tempUrlContainer = document.getElementById('temp-url-container');
196
  const tempUrlInput = document.getElementById('temp-url-display');
197
  const copyTempButton = document.getElementById('copy-temp-button');
198
 
199
+ // Données injectées par Flask (Assurez-vous que votre route Flask passe ces variables)
200
+ const currentTempUrl = '{{ temp_launch_url if temp_launch_url else "" }}';
201
+ const currentPermanentUrl = '{{ permanent_deployment_url if permanent_deployment_url else "" }}';
202
+ const indexFilePresent = {{ 'true' if 'index.html' in files else 'false' }};
 
 
 
 
 
 
 
 
 
 
203
  const fileCount = {{ files|length }};
204
  const deployId = '{{ deploy_id }}';
205
+ const files = JSON.parse('{{ files | tojson | safe }}'); // Liste des fichiers pour l'affichage initial
206
+
207
+ // -------------------------------------------------------------
208
+ // --- Fonctions d'Utilitaires et de Mise à Jour de l'Interface ---
209
+ // -------------------------------------------------------------
210
+
211
+ /** Affiche la liste des fichiers téléversés */
212
+ function renderFileList(fileList) {
213
+ uploadedFileList.innerHTML = '';
214
+ if (fileList.length === 0) {
215
+ uploadedFileList.style.display = 'none';
216
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
  }
218
+
219
+ fileList.forEach(filename => {
220
+ const li = document.createElement('li');
221
+ li.innerHTML = `<span class="material-symbols-rounded file-icon">file_present</span> ${filename}`;
222
+ uploadedFileList.appendChild(li);
223
+ });
224
+ uploadedFileList.style.display = 'block';
225
  }
226
 
227
+ /** Met à jour l'état initial des éléments au chargement de la page */
228
+ function updateInitialState() {
229
+ renderFileList(files);
230
+
231
+ if (currentPermanentUrl) {
232
+ // État final: URL permanente
233
+ permanentUrlInput.value = currentPermanentUrl;
234
+ permanentUrlContainer.style.display = 'block';
235
+ deployButton.disabled = true;
236
+ deployButton.innerHTML = '<span class="material-symbols-rounded align-middle me-1">cloud_done</span> Déployé !';
237
+ deployButton.classList.remove('btn-success');
238
+ deployButton.classList.add('btn-secondary');
239
+ launchButton.disabled = false;
240
+ tempUrlContainer.style.display = 'none';
241
+ } else if (currentTempUrl && indexFilePresent) {
242
+ // État temporaire: prêt à être déployé
243
+ tempUrlInput.value = currentTempUrl; // Assurer que l'input a la valeur
244
+ tempUrlContainer.style.display = 'block';
245
+ deployButton.disabled = false;
246
+ launchButton.disabled = false;
247
+ permanentUrlContainer.style.display = 'none';
248
+ } else {
249
+ // Aucun fichier ou index.html manquant
250
+ deployButton.disabled = true;
251
+ launchButton.disabled = true;
252
+ tempUrlContainer.style.display = 'none';
253
+ permanentUrlContainer.style.display = 'none';
254
  }
 
 
 
255
 
256
+ clearButton.disabled = fileCount === 0;
257
+ uploadStatus.textContent = fileCount > 0
258
+ ? `Fichiers téléversés temporairement (${fileCount} fichiers. Index.html: ${indexFilePresent ? 'Oui' : 'Non'}).`
259
+ : "Aucun fichier téléversé.";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  }
261
 
262
+ // -------------------------------------------------------------
263
+ // --- Logique du Bouton de Déploiement Permanent (Commit) ---
264
+ // -------------------------------------------------------------
265
 
266
+ deployButton.addEventListener('click', async () => {
267
+ // 1. Préparer l'animation et désactiver le bouton
 
 
 
 
 
 
 
268
  deployButton.disabled = true;
269
+ deployButton.innerHTML = '<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span> Déploiement en cours...';
270
+ uploadStatus.className = 'mt-3 text-info fw-bold';
271
+ uploadStatus.textContent = 'Téléversement des fichiers sur Hugging Face en cours... (Cela peut prendre quelques instants)';
272
 
273
+ // 2. Appel AJAX à la route de commit
274
+ try {
275
+ const response = await fetch('/commit_static_deployment', {
276
+ method: 'POST',
277
+ });
278
+
279
+ const data = await response.json();
280
+
281
+ // 3. Traiter la réponse
 
 
 
 
 
 
 
282
  if (data.success) {
283
+ // SUCCÈS
284
+ uploadStatus.className = 'mt-3 text-success fw-bold';
285
+ uploadStatus.textContent = data.message;
286
 
287
+ // Mise à jour des URLs
288
  permanentUrlInput.value = data.url;
289
  permanentUrlContainer.style.display = 'block';
290
  tempUrlContainer.style.display = 'none';
291
+
292
+ // Mise à jour du bouton (Succès, non réactivable)
293
+ deployButton.innerHTML = '<span class="material-symbols-rounded align-middle me-1">cloud_done</span> Déployé !';
294
+ deployButton.classList.remove('btn-success');
295
+ deployButton.classList.add('btn-secondary');
296
+ deployButton.disabled = true;
297
+
298
+ launchButton.disabled = false; // Lancer le site déployé
299
 
300
  } else {
301
+ // ERREUR
302
+ uploadStatus.className = 'mt-3 text-danger fw-bold';
303
  uploadStatus.textContent = `Échec du déploiement: ${data.message}`;
304
+
305
+ // Rétablir les boutons à l'état "temporaire" (si l'échec n'est pas critique)
306
  deployButton.innerHTML = '<span class="material-symbols-rounded align-middle me-1">cloud_upload</span> Déployer le Site Web (Permanent)';
307
+ deployButton.disabled = !indexFilePresent; // Réactiver si un index.html est présent
308
+
309
+ // L'URL temporaire doit rester affichée
310
+ if (currentTempUrl && indexFilePresent) {
311
+ tempUrlContainer.style.display = 'block';
312
+ }
313
  }
314
+ } catch (error) {
315
+ console.error('Erreur réseau/inattendue:', error);
316
+ uploadStatus.className = 'mt-3 text-danger fw-bold';
317
+ uploadStatus.textContent = `Erreur réseau ou inattendue lors du déploiement: ${error.message}`;
 
318
 
319
+ // Rétablir les boutons
320
  deployButton.innerHTML = '<span class="material-symbols-rounded align-middle me-1">cloud_upload</span> Déployer le Site Web (Permanent)';
321
+ deployButton.disabled = !indexFilePresent;
322
+ }
323
+ });
 
 
324
 
325
 
326
+ // -------------------------------------------------------------
327
+ // --- Logique de Copie d'URL et Initialisation ---
328
+ // -------------------------------------------------------------
329
 
330
  function setupCopyButton(button, input) {
331
  button.addEventListener('click', () => {
 
354
  setupCopyButton(copyTempButton, tempUrlInput);
355
  setupCopyButton(copyPermanentButton, permanentUrlInput);
356
 
357
+ // Gère l'action du bouton Lancer (Ouvre l'URL temporaire ou permanente)
358
+ launchButton.addEventListener('click', () => {
359
+ const url = permanentUrlInput.value || tempUrlInput.value;
360
+ if (url) {
361
+ window.open(url, '_blank');
362
+ }
363
+ });
364
 
365
  // Gère le bouton Vider (doit être implémenté au backend pour la suppression du dossier)
366
  clearButton.addEventListener('click', () => {
367
+ // NOTE: La route /clear_deployment n'est pas implémentée, ceci est un rappel pour le développeur.
368
  alert("Fonction Vider: Une route de suppression doit être implémentée au backend pour supprimer le dossier temporaire et vider la session.");
369
  });
370
 
371
+
372
+ // -------------------------------------------------------------
373
+ // --- Logique de Glisser-Déposer (Inchagée, doit être là pour fonctionner) ---
374
+ // -------------------------------------------------------------
375
+
376
+ // NOTE: Les handlers pour Drag/Drop et la sélection de fichiers
377
+ // et le téléversement initial (appelant /upload_static_files)
378
+ // doivent être implémentés ici ou ailleurs dans votre structure.
379
+ // Comme vous n'avez pas fourni ces fonctions, elles sont omises,
380
+ // mais updateInitialState se base sur les variables Flask injectées.
381
+
382
+ // Initialise l'état au chargement de la page
383
+ window.onload = updateInitialState;
384
+
385
  </script>
386
 
387
  </body>