feat: show the active queue filter count
Add a fixed filter summary that counts sidebar, filename, host, and status constraints, highlighting nonzero counts without changing the toolbar geometry.
This commit is contained in:
+13
-2
@@ -3933,13 +3933,24 @@ function applyQueueDetailFilters() {
|
||||
}
|
||||
|
||||
function _hasActiveQueueFilters() {
|
||||
return uploadSidebarFilter !== 'all' || Boolean(queueSearchQuery || queueHosterFilter || queueStatusFilter);
|
||||
return _activeQueueFilterCount() > 0;
|
||||
}
|
||||
|
||||
function _activeQueueFilterCount() {
|
||||
return Number(uploadSidebarFilter !== 'all') + Number(Boolean(queueSearchQuery)) + Number(Boolean(queueHosterFilter)) + Number(Boolean(queueStatusFilter));
|
||||
}
|
||||
|
||||
function syncQueueFilterResetAction() {
|
||||
const button = document.getElementById('queueFilterResetBtn');
|
||||
const count = document.getElementById('queueActiveFilterCount');
|
||||
const activeCount = _activeQueueFilterCount();
|
||||
const active = activeCount > 0;
|
||||
if (count) {
|
||||
count.textContent = String(activeCount);
|
||||
count.setAttribute('aria-label', String(activeCount));
|
||||
count.classList.toggle('is-active', active);
|
||||
}
|
||||
if (!button) return;
|
||||
const active = _hasActiveQueueFilters();
|
||||
button.disabled = !active;
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
['Bereit zum Download', 'Ready to download'],
|
||||
['Abbrechen', 'Cancel'],
|
||||
['Filter zurücksetzen', 'Reset filters'],
|
||||
['Filter', 'Filters'],
|
||||
['Jetzt installieren', 'Install now'],
|
||||
['Jetzt updaten', 'Install now'],
|
||||
['Alle Dateien', 'All files'],
|
||||
|
||||
@@ -290,6 +290,11 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16"><path d="M8 7l-4-5h8z" fill="#4caf50"/><path d="M8 11l-4-5h8z" fill="#4caf50"/><rect x="4" y="13" width="8" height="2" rx="0.5" fill="#4caf50"/></svg>
|
||||
</button>
|
||||
<div class="queue-filter-bar" aria-label="Warteschlange filtern">
|
||||
<div class="queue-filter-summary">
|
||||
<span>Filter</span>
|
||||
<strong id="queueActiveFilterCount" aria-label="0">0</strong>
|
||||
</div>
|
||||
<span class="queue-filter-divider" aria-hidden="true"></span>
|
||||
<input class="key-input" id="queueSearchInput" type="search" placeholder="Dateiname suchen" aria-label="Dateiname suchen" style="max-width:260px">
|
||||
<select class="hs-input" id="queueHosterFilter" aria-label="Nach Hoster filtern" style="width:auto;min-width:150px"><option value="">Alle Hoster</option></select>
|
||||
<select class="hs-input" id="queueStatusFilter" aria-label="Nach Status filtern" style="width:auto;min-width:150px">
|
||||
|
||||
@@ -425,6 +425,42 @@ body {
|
||||
.queue-filter-bar .hs-input {
|
||||
height: 30px;
|
||||
}
|
||||
.queue-filter-summary {
|
||||
min-width: 72px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 7px;
|
||||
padding: 0 6px;
|
||||
color: var(--text-dim);
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
letter-spacing: .05em;
|
||||
text-transform: uppercase;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#queueActiveFilterCount {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 999px;
|
||||
background: var(--bg-raised);
|
||||
color: var(--text-muted);
|
||||
font-size: 11px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
transition: background-color .16s ease, color .16s ease;
|
||||
}
|
||||
#queueActiveFilterCount.is-active {
|
||||
background: var(--success);
|
||||
color: #000;
|
||||
}
|
||||
.queue-filter-divider {
|
||||
width: 1px;
|
||||
height: 22px;
|
||||
background: var(--border);
|
||||
}
|
||||
.queue-container {
|
||||
flex: 1 1 0;
|
||||
min-height: 0;
|
||||
|
||||
@@ -30,6 +30,7 @@ test('translations cover static labels and interpolated status text in both lang
|
||||
assert.equal(translateText('Update v2.1.0 available', 'de'), 'Update v2.1.0 verfügbar');
|
||||
assert.equal(translateText('Alle Status', 'en'), 'Any status');
|
||||
assert.equal(translateText('Any status', 'de'), 'Alle Status');
|
||||
assert.equal(translateText('Filter', 'en'), 'Filters');
|
||||
});
|
||||
|
||||
test('sidebar hierarchy uses distinct English and German kicker labels', () => {
|
||||
|
||||
@@ -178,6 +178,7 @@ test('header occupies its final geometry before asynchronous initialization', ()
|
||||
assert.match(css, /\.update-release-notes\s*\{[^}]*height:\s*min\(264px,\s*48vh\);/su);
|
||||
assert.match(html, /class="update-progress-footer"[\s\S]*id="updateProgressDetails"[\s\S]*id="updateProgressSize"[\s\S]*id="updateProgressSpeed"[\s\S]*id="updateProgressEta"[\s\S]*id="updateProgressText"/u);
|
||||
assert.match(html, /id="queueFilterResetBtn"[^>]*disabled[^>]*>Filter zurücksetzen</u);
|
||||
assert.match(html, /class="queue-filter-summary"[\s\S]*id="queueActiveFilterCount"[^>]*>0</u);
|
||||
assert.doesNotMatch(html, /<\/div>\s*<div class="queue-filter-bar"/u);
|
||||
assert.match(css, /\.queue-filter-bar\s*\{[^}]*display:\s*flex;[^}]*margin-left:\s*auto;[^}]*border:\s*1px solid var\(--border\);[^}]*border-radius:\s*7px;/su);
|
||||
assert.match(css, /#updateProgressDetails\s*\{[^}]*display:\s*grid;[^}]*grid-template-columns:\s*19ch 2ch 11ch 2ch 10ch;[^}]*column-gap:\s*0;[^}]*font-variant-numeric:\s*tabular-nums;/su);
|
||||
|
||||
+5
-2
@@ -737,11 +737,14 @@ setTimeout(async () => {
|
||||
document.getElementById('queueStatusFilter').value = 'active';
|
||||
applyQueueDetailFilters();
|
||||
const button = document.getElementById('queueFilterResetBtn');
|
||||
const before = { hidden: button.hidden, disabled: button.disabled };
|
||||
const count = document.getElementById('queueActiveFilterCount');
|
||||
const before = { hidden: button.hidden, disabled: button.disabled, count: count.textContent, active: count.classList.contains('is-active') };
|
||||
button.click();
|
||||
const after = {
|
||||
hidden: button.hidden,
|
||||
disabled: button.disabled,
|
||||
count: count.textContent,
|
||||
active: count.classList.contains('is-active'),
|
||||
sidebar: uploadSidebarFilter,
|
||||
search: document.getElementById('queueSearchInput').value,
|
||||
hoster: document.getElementById('queueHosterFilter').value,
|
||||
@@ -754,7 +757,7 @@ setTimeout(async () => {
|
||||
renderQueueTable();
|
||||
return { before, after };
|
||||
})()\`);
|
||||
check('Queue filter reset clears every filter without shifting its stable action', queueFilterReset.before.hidden === false && queueFilterReset.before.disabled === false && queueFilterReset.after.hidden === false && queueFilterReset.after.disabled === true && queueFilterReset.after.sidebar === 'all' && queueFilterReset.after.search === '' && queueFilterReset.after.hoster === '' && queueFilterReset.after.status === '' && queueFilterReset.after.allPressed === 'true' && queueFilterReset.after.visible === 'filter-a|filter-b');
|
||||
check('Queue filter reset clears every filter and updates the stable active count', queueFilterReset.before.hidden === false && queueFilterReset.before.disabled === false && queueFilterReset.before.count === '4' && queueFilterReset.before.active === true && queueFilterReset.after.hidden === false && queueFilterReset.after.disabled === true && queueFilterReset.after.count === '0' && queueFilterReset.after.active === false && queueFilterReset.after.sidebar === 'all' && queueFilterReset.after.search === '' && queueFilterReset.after.hoster === '' && queueFilterReset.after.status === '' && queueFilterReset.after.allPressed === 'true' && queueFilterReset.after.visible === 'filter-a|filter-b');
|
||||
|
||||
const queueSelectionAnchor = await wc.executeJavaScript(\`(() => {
|
||||
queueJobs = ['a', 'b', 'c', 'd'].map(id => ({ id: 'anchor-' + id, file: 'C:/ui/anchor-' + id + '.bin', fileName: 'anchor-' + id + '.bin', hoster: 'byse.sx', status: 'queued', bytesUploaded: 0, bytesTotal: 100, progress: 0 }));
|
||||
|
||||
Reference in New Issue
Block a user