fix(candidates): после Отклонить остаёмся на кандидатах, кнопки действий над комментарием

- reject/reject-old (single + bulk): редирект на /candidates с текущей
  группировкой вместо /candidates?status=rejected — не прерываем отбор.
  Отклонённые доступны через фильтр статуса.
- candidates.html: Обработать/Переписать/Отклонить — один ряд над полем
  комментария (после переноса Опубликовать в approve-форму кнопки съехали).

changes: candidates-buttons-order, reject-stay-candidates (skip_specs, валидны).
This commit is contained in:
kpa39l
2026-09-15 16:30:19 +00:00
parent ee2f8ac61a
commit 562d787f1b
11 changed files with 551 additions and 29 deletions
@@ -0,0 +1,57 @@
## Design
Файл: `/opt/vesti/web/app.py`.
### 1. `reject()` — строка 582
Сейчас:
```python
return RedirectResponse(url=_cand_back(group_by, direction, own, q, status="rejected"), status_code=302)
```
Стало:
```python
return RedirectResponse(url=_cand_back(group_by, direction, own, q), status_code=302)
```
`_cand_back` без `status` строит `/candidates` с сохранением
`group_by/direction/own/q` — очереди кандидатов (`status=new` по умолчанию).
### 2. `candidates_bulk()` — строки 345, 358
Сейчас:
```python
if action == "reject":
...
return RedirectResponse(url=back + "&status=rejected", status_code=302)
...
if action == "reject-old":
...
return RedirectResponse(url=back + "&status=rejected", status_code=302)
```
Стало: редирект на `back` (уже содержит `group_by` + фильтры), без
`&status=rejected`.
```python
if action == "reject":
...
return RedirectResponse(url=back, status_code=302)
...
if action == "reject-old":
...
return RedirectResponse(url=back, status_code=302)
```
## Верификация
- `openspec validate reject-stay-candidates` — чисто.
- Юнит (TestClient): login → POST `/posts/{id}/reject` с `group_by=date`
→ ожидаем `Location: /candidates?group_by=date` (БЕЗ `status=rejected`).
- Перезапуск: `sudo systemctl restart vesti-web`.
- Ручная проверка: отклонить пост из правой панели → остаёмся на
«Кандидатах» в той же группировке, пост пропал из списка; список
отклонённых доступен через фильтр «🗑 Отклонённые».