feat: add 'Hide upgrade failures' checkbox to history controls
This commit is contained in:
+19
-3
@@ -9,6 +9,8 @@ const SPLASH_MIN_MS = 1200; // minimum splash display time
|
|||||||
let historyDays = parseInt(localStorage.getItem('sofarr-history-days'), 10) || 7;
|
let historyDays = parseInt(localStorage.getItem('sofarr-history-days'), 10) || 7;
|
||||||
let historyRefreshHandle = null;
|
let historyRefreshHandle = null;
|
||||||
const HISTORY_REFRESH_MS = 5 * 60 * 1000; // auto-refresh history every 5 min
|
const HISTORY_REFRESH_MS = 5 * 60 * 1000; // auto-refresh history every 5 min
|
||||||
|
let ignoreAvailable = localStorage.getItem('sofarr-ignore-available') === 'true';
|
||||||
|
let lastHistoryItems = []; // raw items from last fetch, for re-filtering without a network round-trip
|
||||||
|
|
||||||
// SSE stream state
|
// SSE stream state
|
||||||
let sseSource = null;
|
let sseSource = null;
|
||||||
@@ -869,6 +871,7 @@ function hideLoading() {
|
|||||||
function initHistoryControls() {
|
function initHistoryControls() {
|
||||||
const daysInput = document.getElementById('history-days');
|
const daysInput = document.getElementById('history-days');
|
||||||
const refreshBtn = document.getElementById('history-refresh-btn');
|
const refreshBtn = document.getElementById('history-refresh-btn');
|
||||||
|
const ignoreToggle = document.getElementById('ignore-available-toggle');
|
||||||
if (daysInput) {
|
if (daysInput) {
|
||||||
daysInput.addEventListener('change', () => {
|
daysInput.addEventListener('change', () => {
|
||||||
const v = parseInt(daysInput.value, 10);
|
const v = parseInt(daysInput.value, 10);
|
||||||
@@ -882,6 +885,14 @@ function initHistoryControls() {
|
|||||||
if (refreshBtn) {
|
if (refreshBtn) {
|
||||||
refreshBtn.addEventListener('click', () => loadHistory(true));
|
refreshBtn.addEventListener('click', () => loadHistory(true));
|
||||||
}
|
}
|
||||||
|
if (ignoreToggle) {
|
||||||
|
ignoreToggle.checked = ignoreAvailable;
|
||||||
|
ignoreToggle.addEventListener('change', () => {
|
||||||
|
ignoreAvailable = ignoreToggle.checked;
|
||||||
|
localStorage.setItem('sofarr-ignore-available', ignoreAvailable);
|
||||||
|
renderHistory(lastHistoryItems);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function startHistoryRefresh() {
|
function startHistoryRefresh() {
|
||||||
@@ -897,6 +908,7 @@ function stopHistoryRefresh() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function clearHistory() {
|
function clearHistory() {
|
||||||
|
lastHistoryItems = [];
|
||||||
document.getElementById('history-list').innerHTML = '';
|
document.getElementById('history-list').innerHTML = '';
|
||||||
document.getElementById('no-history').style.display = 'none';
|
document.getElementById('no-history').style.display = 'none';
|
||||||
document.getElementById('history-error').style.display = 'none';
|
document.getElementById('history-error').style.display = 'none';
|
||||||
@@ -920,7 +932,8 @@ async function loadHistory(forceRefresh = false) {
|
|||||||
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
loadingEl.style.display = 'none';
|
loadingEl.style.display = 'none';
|
||||||
renderHistory(data.history || []);
|
lastHistoryItems = data.history || [];
|
||||||
|
renderHistory(lastHistoryItems);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
loadingEl.style.display = 'none';
|
loadingEl.style.display = 'none';
|
||||||
errorEl.textContent = 'Failed to load history.';
|
errorEl.textContent = 'Failed to load history.';
|
||||||
@@ -933,12 +946,15 @@ function renderHistory(items) {
|
|||||||
const listEl = document.getElementById('history-list');
|
const listEl = document.getElementById('history-list');
|
||||||
const noHistoryEl = document.getElementById('no-history');
|
const noHistoryEl = document.getElementById('no-history');
|
||||||
listEl.innerHTML = '';
|
listEl.innerHTML = '';
|
||||||
if (!items.length) {
|
const visible = ignoreAvailable
|
||||||
|
? items.filter(item => !(item.outcome === 'failed' && item.availableForUpgrade))
|
||||||
|
: items;
|
||||||
|
if (!visible.length) {
|
||||||
noHistoryEl.style.display = 'block';
|
noHistoryEl.style.display = 'block';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
noHistoryEl.style.display = 'none';
|
noHistoryEl.style.display = 'none';
|
||||||
items.forEach(item => listEl.appendChild(createHistoryCard(item)));
|
visible.forEach(item => listEl.appendChild(createHistoryCard(item)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function createHistoryCard(item) {
|
function createHistoryCard(item) {
|
||||||
|
|||||||
@@ -98,6 +98,10 @@
|
|||||||
<input type="number" id="history-days" class="history-days-input" value="7" min="1" max="90">
|
<input type="number" id="history-days" class="history-days-input" value="7" min="1" max="90">
|
||||||
<span class="history-days-label">days</span>
|
<span class="history-days-label">days</span>
|
||||||
<button id="history-refresh-btn" class="history-refresh-btn" title="Refresh history">↻</button>
|
<button id="history-refresh-btn" class="history-refresh-btn" title="Refresh history">↻</button>
|
||||||
|
<label class="history-toggle-label" id="ignore-available-label" title="Hide failed downloads where the item is already available on disk (i.e. a failed upgrade attempt)">
|
||||||
|
<input type="checkbox" id="ignore-available-toggle">
|
||||||
|
<span>Hide upgrade failures</span>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="history-loading" class="history-loading" style="display: none;">Loading history...</div>
|
<div id="history-loading" class="history-loading" style="display: none;">Loading history...</div>
|
||||||
|
|||||||
@@ -714,6 +714,22 @@ body {
|
|||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.history-toggle-label {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
font-size: 0.82rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-toggle-label input[type="checkbox"] {
|
||||||
|
cursor: pointer;
|
||||||
|
accent-color: var(--accent, #2980b9);
|
||||||
|
}
|
||||||
|
|
||||||
.history-loading,
|
.history-loading,
|
||||||
.history-error,
|
.history-error,
|
||||||
.no-history {
|
.no-history {
|
||||||
|
|||||||
Reference in New Issue
Block a user