Files
vesti/openspec/changes/candidates-mail-ui/design.md
T

65 lines
4.1 KiB
Markdown
Raw 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.
# design.md — candidates-mail-ui
## Текущая структура (из чтения кода)
- `web/app.py` (FastAPI) — роуты:
- `GET /candidates` — рендер `candidates.html` (список карточек).
- `POST /posts/{id}/approve` — апрув (публикация через publisher).
- `POST /posts/{id}/reject` (или аналогичный) — отклонение.
- GET /media/{filename} — медиа (добавлен в web-media-preview).
- Таблица `posts`: id, source_id (FK), text, direction, lang, views, reactions,
media_path, status (new/published/rejected?), classified, created_at.
- Таблица `classifications`: post_id, direction, relevance, interest, summary, model.
## Архитектура нового UI
### 1. Левая панель: список + группировка + bulk
- Один маршрут `GET /candidates` с query-параметрами:
- `group_by` ∈ {source, date, status} (по умолчанию source)
- `filter` (статус: new/published/rejected/all)
- `q` (поиск по тексту)
- Ответ: тот же HTML (серверный рендер, Jinja2), но layout — две колонки
(Bootstrap 5 grid, уже подключён).
- Список строится из постов (new/rejected), сгруппированных по выбранному
признаку. Группы — сворачиваемые (`<details>`/`<summary>` — без JS).
- Каждый пост имеет чекбокс `<input type="checkbox" name="ids" value="{{ id }}">`.
- Форма bulk: `POST /candidates/bulk` с `ids[]` и `action` (approve/reject/reject-old).
### 2. Правая панель: детальный просмотр + действия
- Выбранный пост: `GET /candidates/{id}` (или та же страница с `?selected=<id>`).
- Секции:
- Кнопки действий: Опубликовать, Отклонить, Переклассифицировать,
Переписать новость (LLM).
- «Мой комментарий»: `<textarea name="comment">` + `POST /posts/{id}/comment`.
- Оригинальный пост: text (markdown), media (`/media/<basename>`), мета
(source @channel, канал, время, views/reactions), direction badge.
### 3. Новые роуты/данные
- `posts.comment TEXT` (nullable) — комментарий пользователя к посту.
- `POST /posts/{id}/comment` — сохранить комментарий.
- `POST /candidates/bulk` — bulk-одобрение/отклонение (транзакция).
- `POST /posts/{id}/reclassify` — перезапуск классификатора (classifier.classify_text
на посте, обновить direction/classifications).
- `POST /posts/{id}/rewrite` — LLM-пересказ (qwen3:8b через Ollama): сгенерировать
черновик текста от себя (без копипасты), сохранить в `posts.rewritten_text`,
вернуть в текстовое поле для редактирования.
### 4. Минимум JS
- Без JS: чекбоксы + `form` с method=post (multi-select через чекбоксы в одной форме).
- Группировка/сворачивание: `<details>`.
- Автоподсветка выбранного: сервер рендерит `class="active"` по `selected` id.
## Реализация (по шагам)
1. Миграция БД: `ALTER TABLE posts ADD COLUMN comment TEXT`.
2. Роуты: GET /candidates (двухпанельный), POST /candidates/bulk,
POST /posts/{id}/comment, POST /posts/{id}/reclassify, POST /posts/{id}/rewrite.
3. Шаблоны: candidates.html переписать (двухколоночная), добавить new/reclassify/
comment/rewrite формы.
4. Bulk-логика + группировка на сервере (Python).
5. Тест: ручной сценарий (создать 2-3 поста, сгруппировать, bulk-отклонить,
коммент, реклассификация).