UI/UX списка и карточки загрузки: серверные фильтр/поиск/пагинация, матч-ссылка, имя раздачи (web-ui-list-detail)
- Список: серверные фильтр по группе состояний, поиск и пагинация (GET
f/q/page/all, по 25), сортировка по времени добавления в qBittorrent
(added_on) с фолбеком на created_at и tie-break по id.
- Заголовок загрузки = имя раздачи (display_name) → распознанное название →
усечённый источник; сырой magnet вынесен в блок «Информация о торренте».
- Матч метабазы показан ссылкой на запись (страница загрузки и ревью);
URL берётся у выбранного кандидата либо строится по provider+id и типу.
- Полировка вёрстки; клиентская JS-фильтрация убрана (всё серверное, без JS).
- Миграция 0005 (display_name, source_added_at); воркер однократно
фиксирует source_added_at при поллинге/усыновлении; ER-схема обновлена.
- OpenSpec: дельты влиты в specs/{web-ui,ingest}, change заархивирован.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+2
-33
@@ -40,36 +40,5 @@ function flashCopy(btn, ok) {
|
||||
setTimeout(() => { btn.textContent = old; btn.classList.remove('copied'); }, 1400);
|
||||
}
|
||||
|
||||
// --- Фильтр/поиск по списку загрузок (по уже отрисованным карточкам) ---
|
||||
|
||||
let activeFilter = 'all';
|
||||
|
||||
function setFilter(el) {
|
||||
document.querySelectorAll('#chips .chip').forEach((c) => c.classList.remove('active'));
|
||||
el.classList.add('active');
|
||||
activeFilter = el.dataset.f;
|
||||
applyFilters();
|
||||
}
|
||||
|
||||
function applyFilters() {
|
||||
const searchEl = document.querySelector('#list-toolbar input[type=search]');
|
||||
const q = (searchEl ? searchEl.value : '').toLowerCase().trim();
|
||||
const showAllEl = document.getElementById('showAll');
|
||||
const showAll = showAllEl ? showAllEl.checked : false;
|
||||
let visible = 0;
|
||||
document.querySelectorAll('#list .card').forEach((card) => {
|
||||
const grp = card.dataset.group;
|
||||
const isDeleted = card.dataset.deleted === '1';
|
||||
let ok = true;
|
||||
if (isDeleted && !showAll) ok = false;
|
||||
if (ok && activeFilter !== 'all' && grp !== activeFilter) ok = false;
|
||||
if (ok && q && !(card.dataset.text || '').includes(q)) ok = false;
|
||||
card.style.display = ok ? '' : 'none';
|
||||
if (ok) visible += 1;
|
||||
});
|
||||
const empty = document.getElementById('empty');
|
||||
if (empty) empty.style.display = visible ? 'none' : '';
|
||||
}
|
||||
|
||||
// Применить начальный фильтр (скрыть удалённые) после загрузки.
|
||||
document.addEventListener('DOMContentLoaded', applyFilters);
|
||||
// Фильтр, поиск и пагинация списка — серверные (GET-параметры f/q/page/all),
|
||||
// работают без JS. Здесь клиентской фильтрации нет намеренно.
|
||||
|
||||
Reference in New Issue
Block a user