157 lines
6.8 KiB
HTML
157 lines
6.8 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Warteschlange - AniWorld Downloader{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h2><i class="bi bi-list-check"></i> Download-Warteschlange</h2>
|
|
<button class="btn btn-outline-secondary" id="refreshQueueBtn">
|
|
<i class="bi bi-arrow-clockwise"></i> Aktualisieren
|
|
</button>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th>Titel</th>
|
|
<th>S/E</th>
|
|
<th>Provider</th>
|
|
<th>Sprache</th>
|
|
<th>Status</th>
|
|
<th>Fortschritt</th>
|
|
<th>Erstellt</th>
|
|
<th>Aktionen</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="downloadTable">
|
|
{% for download in downloads %}
|
|
<tr data-download-id="{{ download.id }}">
|
|
<td>{{ download.title }}</td>
|
|
<td>
|
|
{% if download.season %}
|
|
S{{ download.season }}E{{ download.episode }}
|
|
{% else %}
|
|
Film {{ download.episode }}
|
|
{% endif %}
|
|
</td>
|
|
<td>{{ download.provider }}</td>
|
|
<td>{{ download.language }}</td>
|
|
<td>
|
|
<span class="badge bg-{% if download.status == 'completed' %}success{% elif download.status == 'downloading' %}primary{% elif download.status == 'failed' %}danger{% elif download.status == 'cancelled' %}warning{% else %}secondary{% endif %}">
|
|
{{ download.status.title() }}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<div class="progress" style="width: 100px; height: 10px;">
|
|
<div class="progress-bar {% if download.status == 'failed' %}bg-danger{% elif download.status == 'cancelled' %}bg-warning{% endif %}"
|
|
style="width: {{ download.progress }}%"
|
|
aria-valuenow="{{ download.progress }}"
|
|
aria-valuemin="0" aria-valuemax="100">
|
|
</div>
|
|
</div>
|
|
<small class="text-muted">{{ download.progress|round(1) }}%</small>
|
|
</td>
|
|
<td>{{ download.created_at.strftime('%d.%m.%Y %H:%M') }}</td>
|
|
<td>
|
|
{% if download.status in ['queued', 'downloading'] %}
|
|
<button class="btn btn-sm btn-outline-danger cancel-btn"
|
|
data-download-id="{{ download.id }}">
|
|
<i class="bi bi-x-circle"></i>
|
|
</button>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
{% if not downloads %}
|
|
<div class="text-center py-5 text-muted">
|
|
<i class="bi bi-inbox display-4"></i>
|
|
<p class="mt-3">Keine Downloads in der Warteschlange</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_scripts %}
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Refresh button
|
|
document.getElementById('refreshQueueBtn').addEventListener('click', function() {
|
|
location.reload();
|
|
});
|
|
|
|
// Cancel buttons
|
|
document.querySelectorAll('.cancel-btn').forEach(button => {
|
|
button.addEventListener('click', async function() {
|
|
const downloadId = this.getAttribute('data-download-id');
|
|
if (confirm('Download wirklich abbrechen?')) {
|
|
try {
|
|
const response = await fetch(`/api/download/${downloadId}/cancel`, {
|
|
method: 'POST'
|
|
});
|
|
|
|
if (response.ok) {
|
|
const result = await response.json();
|
|
if (result.success) {
|
|
// Update status in table
|
|
const row = document.querySelector(`tr[data-download-id="${downloadId}"]`);
|
|
const statusCell = row.querySelector('td:nth-child(5) span');
|
|
statusCell.className = 'badge bg-warning';
|
|
statusCell.textContent = 'Cancelled';
|
|
|
|
// Remove cancel button
|
|
row.querySelector('td:last-child button').remove();
|
|
}
|
|
} else {
|
|
alert('Fehler beim Abbrechen des Downloads');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error:', error);
|
|
alert('Fehler beim Abbrechen des Downloads');
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
// Auto-update progress for downloading items
|
|
setInterval(async function() {
|
|
const downloadingRows = document.querySelectorAll('tr[data-download-id] td:nth-child(5) span.badge.bg-primary');
|
|
|
|
for (const statusBadge of downloadingRows) {
|
|
const row = statusBadge.closest('tr');
|
|
const downloadId = row.getAttribute('data-download-id');
|
|
|
|
try {
|
|
const response = await fetch(`/api/download/${downloadId}/status`);
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
|
|
// Update progress bar
|
|
const progressBar = row.querySelector('.progress-bar');
|
|
progressBar.style.width = `${data.progress}%`;
|
|
progressBar.setAttribute('aria-valuenow', data.progress);
|
|
|
|
// Update progress text
|
|
row.querySelector('td:nth-child(6) small').textContent = `${data.progress.toFixed(1)}%`;
|
|
|
|
// Update status if changed
|
|
if (data.status !== 'downloading') {
|
|
// Reload the page to show updated status
|
|
location.reload();
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error(`Error updating download ${downloadId}:`, error);
|
|
}
|
|
}
|
|
}, 3000);
|
|
});
|
|
</script>
|
|
{% endblock %} |