fix: robust HTML delivery for downloads section
- Decoupled downloads container from main template to prevent static rendering errors - Forced HTMX polling to use html=1 parameter - Added server-side debug logging for request format detection - Fixed Jinja2 loop error by ensuring tasks are provided via HTMX
This commit is contained in:
@@ -27,14 +27,15 @@ async def get_downloads(
|
|||||||
"""Get list of all download tasks. Returns HTML for HTMX."""
|
"""Get list of all download tasks. Returns HTML for HTMX."""
|
||||||
tasks = download_manager.get_all_tasks()
|
tasks = download_manager.get_all_tasks()
|
||||||
|
|
||||||
# Check for HTMX or explicit HTML request
|
# Force HTML if requested or via HTMX
|
||||||
if html or request.headers.get("HX-Request"):
|
if html or request.headers.get("HX-Request"):
|
||||||
print(f"[DOWNLOADS] Returning HTML list for {len(tasks)} tasks")
|
print(f"[DOWNLOADS] HTMX Request detected. Returning HTML for {len(tasks)} tasks.")
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
"components/downloads_list.html",
|
"components/downloads_list.html",
|
||||||
{"request": request, "tasks": tasks}
|
{"request": request, "tasks": tasks}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
print(f"[DOWNLOADS] API Request detected. Returning JSON.")
|
||||||
return {"downloads": tasks}
|
return {"downloads": tasks}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
<div class="downloads-grid"
|
{% if tasks %}
|
||||||
hx-get="/api/downloads?html=1"
|
<div class="downloads-grid">
|
||||||
hx-trigger="every 2s"
|
|
||||||
hx-swap="innerHTML">
|
|
||||||
{% if tasks %}
|
|
||||||
{% for task in tasks %}
|
{% for task in tasks %}
|
||||||
<div class="download-item task-{{ task.status }}">
|
<div class="download-item task-{{ task.status }}">
|
||||||
<div class="download-info">
|
<div class="download-info">
|
||||||
@@ -46,9 +43,54 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
</div>
|
||||||
<div class="empty-state">
|
{% else %}
|
||||||
<p>Aucun téléchargement en cours</p>
|
<div class="empty-state">
|
||||||
</div>
|
<p>Aucun téléchargement en cours</p>
|
||||||
{% endif %}
|
</div>
|
||||||
</div>
|
{% endif %}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.downloads-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
.download-item {
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 15px;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
.progress-container {
|
||||||
|
height: 8px;
|
||||||
|
background: rgba(0, 0, 0, 0.3);
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 10px 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.progress-bar {
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, #00d9ff, #00ff88);
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
}
|
||||||
|
.download-info { display: flex; justify-content: space-between; align-items: center; margin-bottom: 5px; }
|
||||||
|
.download-name { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 70%; }
|
||||||
|
.download-meta { display: flex; justify-content: space-between; font-size: 0.8rem; color: #aaa; }
|
||||||
|
.download-actions { display: flex; gap: 10px; margin-top: 10px; justify-content: flex-end; }
|
||||||
|
.btn-icon {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 6px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.badge-completed { color: #00ff88; }
|
||||||
|
.badge-failed { color: #ff4444; }
|
||||||
|
.badge-downloading { color: #00d9ff; }
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -5,77 +5,24 @@
|
|||||||
<button class="btn btn-sm btn-secondary"
|
<button class="btn btn-sm btn-secondary"
|
||||||
hx-post="/api/downloads/cleanup"
|
hx-post="/api/downloads/cleanup"
|
||||||
hx-swap="none"
|
hx-swap="none"
|
||||||
title="Supprimer les téléchargements terminés de la liste">
|
hx-on::after-request="htmx.trigger('#downloads-container-inner', 'refresh')">
|
||||||
Nettoyer terminés
|
Nettoyer terminés
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="downloads-container">
|
<!-- Container that loads content via HTMX -->
|
||||||
{% include "components/downloads_list.html" %}
|
<div id="downloads-container-inner"
|
||||||
|
hx-get="/api/downloads?html=1"
|
||||||
|
hx-trigger="load, refresh, every 3s"
|
||||||
|
hx-swap="innerHTML">
|
||||||
|
<div class="loading-placeholder">
|
||||||
|
<div class="spinner"></div> Chargement des téléchargements...
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.section-container { margin-bottom: 40px; }
|
.section-container { margin-bottom: 40px; }
|
||||||
.download-item {
|
/* Styles already defined or moved to downloads_list.html */
|
||||||
background: rgba(255, 255, 255, 0.05);
|
|
||||||
border-radius: 10px;
|
|
||||||
padding: 15px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
|
||||||
.progress-container {
|
|
||||||
height: 8px;
|
|
||||||
background: rgba(0, 0, 0, 0.3);
|
|
||||||
border-radius: 4px;
|
|
||||||
margin: 10px 0;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.progress-bar {
|
|
||||||
height: 100%;
|
|
||||||
background: linear-gradient(90deg, #00d9ff, #00ff88);
|
|
||||||
transition: width 0.3s ease;
|
|
||||||
}
|
|
||||||
.download-info {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
.download-name {
|
|
||||||
font-weight: 500;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
max-width: 70%;
|
|
||||||
}
|
|
||||||
.download-meta {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
color: #aaa;
|
|
||||||
}
|
|
||||||
.download-actions {
|
|
||||||
display: flex;
|
|
||||||
gap: 10px;
|
|
||||||
margin-top: 10px;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
.btn-icon {
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
border: none;
|
|
||||||
color: white;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
border-radius: 6px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
.btn-icon:hover { background: rgba(0, 217, 255, 0.2); color: #00d9ff; }
|
|
||||||
.btn-icon.danger:hover { background: rgba(244, 67, 54, 0.2); color: #f44336; }
|
|
||||||
.btn-icon.success:hover { background: rgba(76, 175, 80, 0.2); color: #4caf50; }
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user