Session 2026-09-13: unify directions (canon+LLM-fallback, 966/1019), publisher dry_run fix, git repo, archive 8 changes, candidates-mail-ui WIP, docs

This commit is contained in:
kpa39l
2026-09-13 17:48:06 +00:00
parent c3f59f7b7a
commit 71fd48aa06
40 changed files with 305 additions and 7 deletions
@@ -0,0 +1,65 @@
# 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-отклонить,
коммент, реклассификация).