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."""
|
||||
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"):
|
||||
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(
|
||||
"components/downloads_list.html",
|
||||
{"request": request, "tasks": tasks}
|
||||
)
|
||||
|
||||
print(f"[DOWNLOADS] API Request detected. Returning JSON.")
|
||||
return {"downloads": tasks}
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
<div class="downloads-grid"
|
||||
hx-get="/api/downloads?html=1"
|
||||
hx-trigger="every 2s"
|
||||
hx-swap="innerHTML">
|
||||
{% if tasks %}
|
||||
{% if tasks %}
|
||||
<div class="downloads-grid">
|
||||
{% for task in tasks %}
|
||||
<div class="download-item task-{{ task.status }}">
|
||||
<div class="download-info">
|
||||
@@ -46,9 +43,54 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<div class="empty-state">
|
||||
<p>Aucun téléchargement en cours</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="empty-state">
|
||||
<p>Aucun téléchargement en cours</p>
|
||||
</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"
|
||||
hx-post="/api/downloads/cleanup"
|
||||
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
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="downloads-container">
|
||||
{% include "components/downloads_list.html" %}
|
||||
<!-- Container that loads content via HTMX -->
|
||||
<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>
|
||||
|
||||
<style>
|
||||
.section-container { margin-bottom: 40px; }
|
||||
.download-item {
|
||||
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; }
|
||||
/* Styles already defined or moved to downloads_list.html */
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user