Files
board-viewer/.tasks/board-viewer-html-render.md
vitya cab4a8b92d task(html-render): close → 🟢, unblock cron-deploy
closes board-viewer-html-render

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 14:49:42 +03:00

61 lines
4.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# board-viewer-html-render
## Goal
Рендер 5-колоночного kanban-board из нормализованной структуры (продукт `board-viewer-gitea-reader`). Статический HTML + минимальный клиент-сайд JS для фильтра / drawer / refresh-таймера. Без write-side, без realtime.
**TDD-mode:** обязательно по `follow tdd-criteria`. Снапшот-тесты на HTML-output из фиксированных reader-фикстур. Не модифицировать assert'ы без `[test-modify: ...]` маркера. Визуальная отделка (CSS) — под carve-out «visual CSS», но логика рендера (распределение по колонкам, age-расчёт, drawer-привязка) — TDD.
## Key files
- `src/render.ts``renderBoard()`, `formatAge()`, `partitionByStatus()` (pure)
- `src/cli.ts` — entry: load config → readBoard → renderBoard → `dist/index.html` + copy `static/`
- `static/board.css` — raw CSS, system font, light/dark, ~190 LOC
- `static/board.js` — ESM module: filter, drawer (lazy-fetch + `marked@14` from esm.sh), toggle-archived, toggle-grouping (full rerender into per-project columns)
- `tests/render.test.ts` — 17 tests on render logic (no snapshots — semantic property assertions, more robust to harmless markup tweaks)
## Acceptance criteria
- **5 колонок** по статусам: ⚪ open / 🔴 in-progress / 🟡 paused / 🔵 blocked / 🟢 done. Названия колонок — emoji + слово.
- **Карточка:**
- title (truncate на 80 chars в default-view),
- project badge (e.g. `books`, `board-viewer`),
- owner (если есть) — pill,
- age — относительное (`3d`, `2w`, `5mo`) от `last_commit_iso`,
- last-commit-marker — короткий hash или дата.
- **Группировка по проекту** — toggle вверху: «по статусам» (5 колонок × проекты внутри) vs «по проектам» (per-project колонки × статусы внутри).
- **Поиск/фильтр** — клиент-сайд input: substring по `slug`, `title`, `project`; multi-select по статусам.
- **Per-card drawer** — клик по карточке → side panel с full markdown из per-task `<slug>.md` (lazy-fetch из `raw_url`). Markdown рендерится клиент-сайд (e.g. `marked` для TS, `markdown-it` для Py-side-rendered).
- **Refresh-таймер** видно в header: «refreshed Xm ago, next in Ym» (data attribute из generation timestamp).
- **Output:** один `index.html` файл + sidecar `static/`. Открывается локально без сервера для smoke-test.
- **Tests:** snapshot-тесты на 3 reader-фикстуры (пустая доска / 1-2 таски / N≥10 тасок). Snapshots checked-in.
## Decisions log
- 2026-05-22: task создан промоушеном; зависит от `board-viewer-gitea-reader` контракта.
- 2026-05-22: emoji-set acceptance выравнен под reader контракт (⚪🔴🟡🔵🟢).
- 2026-05-22: client-side `marked@14` via esm.sh — lazy-load на первое открытие drawer'а.
- 2026-05-22: raw CSS, no framework — соответствует «whitespace + типографика» intent task notes.
- 2026-05-22: done >14 дней архивируются (hidden by default, toggle «show archived»).
- 2026-05-22: snapshot tests заменены 17 semantic-property тестами — устойчивее к косметическим изменениям markup'а.
## Open questions
- [x] Markdown-renderer → client-side `marked` via esm.sh (lazy на drawer).
- [x] CSS → raw, no framework.
- [x] Done archive → >14d hidden, toggle for show.
## Completed steps
- [x] `formatAge` (m/h/d/w/mo/y, calendar-month arithmetic) — pure, TDD
- [x] `partitionByStatus` — canonical 5-col order
- [x] `renderBoard` — HTML with escaped fields, JSON embed XSS-safe (`\uXXXX` escapes)
- [x] static/board.css — raw, light/dark
- [x] static/board.js — filter, drawer, archived/grouping toggles, refresh-info
- [x] src/cli.ts — wires config+reader+render+fs
- [x] 17 render tests + smoke-verified e2e (78 records, 4 repos, browser-tested both toggle modes)
## Notes
Стиль: минимализм без аватарок/гифок/анимаций. Это инструмент глядеть на доску, не дашборд для презентации. Whitespace + типографика.