Карточка списка на главной теперь даёт краткий обзор «от загрузки до
решения об удалении»: метка «ID:» перед идентификатором, дата добавления
(абсолютная + относительная, всегда), размер раздачи и рейтинг отдачи.
Спойлер контекста убран — контекст смотрят на /download/{id}.
Данные:
- рейтинг и общий размер — из живого снимка воркера (qbt total_size →
worker.Live.TotalSize); размер доступен для любой раздачи в снимке;
- размер-фолбэк, когда торрента нет в qBittorrent (orphaned) — сумма
размеров разложенных файлов: новая колонка file_link.size, layouter
пишет размер при линковке, ридер LayoutSizeByDownload суммирует по
странице одним запросом (дедуп по dst_path);
- дата — source_added_at → фолбэк created_at, показ в TZ сервера.
handleIndex читает снимок для всех карточек (map-lookup), рейтинг/размер
статичны на рендере (без поллинга). Миграция 0007, ER-схема обновлена.
Change download-card-lifecycle-overview влит в спеки и заархивирован.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
80 lines
5.3 KiB
Markdown
80 lines
5.3 KiB
Markdown
# web-ui Specification (delta)
|
||
|
||
## ADDED Requirements
|
||
|
||
### Requirement: Обзор жизненного цикла в карточке списка
|
||
|
||
Карточка загрузки в списке SHALL показывать обзорную мета-строку для решения о
|
||
судьбе раздачи: метку `ID:` перед копируемым идентификатором загрузки, дату
|
||
добавления раздачи (всегда), размер раздачи и рейтинг отдачи. Контекст загрузки
|
||
MUST NOT показываться в карточке списка — он доступен на странице `/download/{id}`.
|
||
|
||
Дата добавления SHALL показываться всегда как абсолютная дата и относительная
|
||
давность (например «`2026-06-30 · 5 дней назад`»); источником SHALL быть время
|
||
добавления раздачи в источник (`source_added_at`, qBittorrent `added_on`) с
|
||
фолбэком на время создания загрузки (`created_at`), согласованным с порядком
|
||
списка.
|
||
|
||
Рейтинг отдачи SHALL браться из живого снимка телеметрии; если торрента нет в
|
||
снимке (источник ушёл из qBittorrent), рейтинг SHALL отображаться прочерком «—».
|
||
|
||
Размер раздачи SHALL браться из живого снимка (общий размер торрента), а при
|
||
отсутствии торрента в снимке — из суммарного размера разложенных файлов загрузки;
|
||
если неизвестно ни то, ни другое — прочерк «—».
|
||
|
||
#### Scenario: Метка идентификатора
|
||
|
||
- **WHEN** рендерится карточка загрузки в списке
|
||
- **THEN** перед значением `download.id` показана метка «ID:», а кнопка
|
||
копирования копирует именно `download.id`
|
||
|
||
#### Scenario: Дата добавления показана всегда
|
||
|
||
- **WHEN** рендерится любая карточка списка
|
||
- **THEN** в ней показана дата добавления раздачи абсолютной датой и
|
||
относительной давностью
|
||
- **AND** если `source_added_at` неизвестно, используется `created_at`
|
||
|
||
#### Scenario: Рейтинг из живого снимка
|
||
|
||
- **WHEN** торрент загрузки присутствует в живом снимке
|
||
- **THEN** в карточке показан его рейтинг отдачи
|
||
- **AND** если торрента в снимке нет, рейтинг показан прочерком «—»
|
||
|
||
#### Scenario: Размер с фолбэком на разложенные файлы
|
||
|
||
- **WHEN** торрент загрузки присутствует в живом снимке
|
||
- **THEN** размер раздачи в карточке берётся из общего размера торрента
|
||
- **AND** если торрента в снимке нет, но у загрузки есть разложенные файлы —
|
||
размер берётся из суммарного размера этих файлов
|
||
|
||
#### Scenario: Контекст не в карточке
|
||
|
||
- **WHEN** у загрузки есть переданный контекст
|
||
- **THEN** он не показывается в карточке списка, но доступен на странице
|
||
`/download/{id}`
|
||
|
||
## MODIFIED Requirements
|
||
|
||
### Requirement: Клиентские взаимодействия без сборки
|
||
|
||
Веб-UI SHALL реализовывать клиентскую логику без шага сборки и без реактивных
|
||
фреймворков: копирование идентификатора загрузки (vanilla JS). Основной
|
||
копируемый идентификатор в карточке списка и в шапке страницы просмотра SHALL
|
||
быть `download.id` (ULID) — тот же ключ, что пишется в логи (`download_id`). Все
|
||
действия над загрузкой SHALL выполняться через формы/htmx (раундтрип на сервер),
|
||
без клиентского пересчёта доменного состояния.
|
||
|
||
#### Scenario: Копирование идентификатора загрузки
|
||
|
||
- **WHEN** пользователь нажимает кнопку копирования рядом с идентификатором
|
||
загрузки (`download.id`) в карточке списка или шапке страницы просмотра
|
||
- **THEN** значение `download.id` копируется в буфер обмена без перезагрузки
|
||
страницы
|
||
|
||
#### Scenario: Действия только через раундтрип
|
||
|
||
- **WHEN** пользователь выполняет действие над загрузкой
|
||
- **THEN** оно исполняется формой/htmx-запросом на сервер, без клиентского
|
||
пересчёта доменного состояния
|