- Connections dashboard with add/remove flow and background health checks - VK OAuth connection with profile info and health monitoring - Sync configuration page with master toggle and filter summary - Catalog browser with store/group/product tables, filter management, CSV export - Alembic migrations for all new tables - run/read_config.py for shell sync script DB integration - CHANGELOG.md updated for v1.8.0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
193 lines
10 KiB
Markdown
193 lines
10 KiB
Markdown
# Connections Dashboard with Background Health Checks
|
||
|
||
## Context
|
||
|
||
Users currently access Evotor connection via a dedicated `/evotor` page linked from the navbar. As more integrations are planned, we need a unified **Connections** page where users can manage all their connections: add new ones, view status, edit, and delete. The dashboard starts empty — users explicitly add each connection they need.
|
||
|
||
Supported connection types: **Evotor**, **VK** (one per type per user).
|
||
|
||
## Data Design
|
||
|
||
### Current state (separate models)
|
||
|
||
`EvotorConnection` and `VkConnection` remain as-is — they hold service-specific fields (store_id/store_name for Evotor, vk_user_id/first_name/last_name for VK). The connections dashboard reads from both tables.
|
||
|
||
No new unified "connection" table needed. The dashboard builds a virtual list by querying both tables. The "add" flow is just a gateway to the existing per-service OAuth pages.
|
||
|
||
### Model additions (both `EvotorConnection` and `VkConnection`)
|
||
|
||
Already planned:
|
||
- `is_online` (Boolean, default=False, server_default="0")
|
||
- `last_checked_at` (DateTime, nullable)
|
||
|
||
## Plan
|
||
|
||
### 1. Model Changes — `web/models.py`
|
||
|
||
Add `is_online` and `last_checked_at` to both `EvotorConnection` and `VkConnection`.
|
||
|
||
### 2. Alembic Migration
|
||
|
||
Add health check fields to both connection tables.
|
||
|
||
### 3. Config Addition — `web/config.py`
|
||
|
||
Add `HEALTH_CHECK_INTERVAL_SECONDS: int = 600` (10 minutes default).
|
||
|
||
### 4. Background Health Checker — `web/health_checker.py` (new)
|
||
|
||
- `check_evotor_connection(access_token) -> bool` — async, `GET https://api.evotor.ru/stores` with Bearer token
|
||
- `check_vk_connection(access_token) -> bool` — async, `GET https://api.vk.com/method/users.get` with token
|
||
- `run_health_checks()` — queries all connection rows, checks each, updates `is_online` and `last_checked_at`
|
||
- `health_check_loop(interval)` — infinite loop with `asyncio.sleep`
|
||
|
||
### 5. Wire Background Task — `web/main.py`
|
||
|
||
Add FastAPI lifespan context manager:
|
||
- On startup: `asyncio.create_task(health_check_loop(...))`
|
||
- On shutdown: cancel the task
|
||
- Register connections router
|
||
|
||
### 6. Connections Route — `web/routes/connections.py` (new)
|
||
|
||
**`GET /connections`** — Main dashboard. Requires auth.
|
||
|
||
Queries both `EvotorConnection` and `VkConnection` for the current user. Builds a list of available service types and their connection state:
|
||
|
||
```python
|
||
SERVICE_TYPES = [
|
||
{"type": "evotor", "name": "Эвотор", "icon": "bi-shop", "connect_url": "/evotor", "disconnect_url": "/evotor/disconnect"},
|
||
{"type": "vk", "name": "ВКонтакте", "icon": "bi-chat-dots", "connect_url": "/vk", "disconnect_url": "/vk/disconnect"},
|
||
]
|
||
```
|
||
|
||
For each type, attach the connection record (or None). Template renders based on state.
|
||
|
||
**`GET /connections/add`** — "Add connection" page.
|
||
|
||
Shows only service types the user has NOT yet connected:
|
||
- Card per available type with service name, icon, short description
|
||
- "Подключить" button linking to the service's OAuth page (`/evotor` or `/vk`)
|
||
- If all types already connected — message "Все доступные сервисы подключены"
|
||
- Back link to `/connections`
|
||
|
||
**`POST /connections/delete?type=evotor|vk`** — Delete a connection.
|
||
|
||
Same as existing disconnect endpoints but accessed from the dashboard. Deletes the connection record, redirects to `/connections`.
|
||
|
||
(The existing `/evotor/disconnect` and `/vk/disconnect` routes remain as aliases.)
|
||
|
||
### 7. Templates
|
||
|
||
**`web/templates/connections.html`** — Dashboard:
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────┐
|
||
│ Подключения [+ Добавить] │
|
||
├─────────────────────────────────────────────────┤
|
||
│ │
|
||
│ ┌─ Card ─────────────────────────────────────┐ │
|
||
│ │ 🏪 Эвотор ● (green) │ │
|
||
│ │ Магазин "Чайная" │ │
|
||
│ │ Последняя проверка: 06.03.2026 14:30 │ │
|
||
│ │ │ │
|
||
│ │ [Настроить] [Отключить] │ │
|
||
│ └────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ ┌─ Card ─────────────────────────────────────┐ │
|
||
│ │ 💬 ВКонтакте ● (green) │ │
|
||
│ │ Иван Иванов │ │
|
||
│ │ Последняя проверка: 06.03.2026 14:30 │ │
|
||
│ │ │ │
|
||
│ │ [Настроить] [Отключить] │ │
|
||
│ └────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ (Нет подключений — нажмите «Добавить») │
|
||
│ │
|
||
└─────────────────────────────────────────────────┘
|
||
```
|
||
|
||
Each connection card:
|
||
- Icon + service name + status indicator (green/red/grey)
|
||
- Details line (store name for Evotor, profile name for VK)
|
||
- Last checked timestamp in card footer
|
||
- "Настроить" button → links to service page (`/evotor` or `/vk`) for reconnect/details
|
||
- "Отключить" button → POST to `/connections/delete?type=...` with confirmation
|
||
|
||
Empty state: message prompting user to add their first connection.
|
||
|
||
**`web/templates/connections_add.html`** — Add connection page:
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────┐
|
||
│ Добавить подключение │
|
||
├─────────────────────────────────────────────────┤
|
||
│ │
|
||
│ ┌─ Card ─────────────────────────────────────┐ │
|
||
│ │ 🏪 Эвотор │ │
|
||
│ │ Подключите кассу Эвотор для синхронизации │ │
|
||
│ │ каталога товаров. │ │
|
||
│ │ [Подключить →] │ │
|
||
│ └────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ ┌─ Card ─────────────────────────────────────┐ │
|
||
│ │ 💬 ВКонтакте │ │
|
||
│ │ Подключите аккаунт ВКонтакте для │ │
|
||
│ │ публикации товаров в вашу группу. │ │
|
||
│ │ [Подключить →] │ │
|
||
│ └────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ ← Вернуться к подключениям │
|
||
│ │
|
||
└─────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 8. Navbar Update — `web/templates/base.html`
|
||
|
||
Replace "Эвотор" link with "Подключения" → `/connections`.
|
||
|
||
### 9. Evotor/VK Callback Updates
|
||
|
||
On successful OAuth callback in both `/evotor/callback` and `/vk/callback`:
|
||
- Set `is_online=True` and `last_checked_at=now()`
|
||
- Redirect to `/connections` (already done for Evotor)
|
||
|
||
### 10. Evotor/VK Template Back Links
|
||
|
||
Change back links on `/evotor` and `/vk` pages: "Вернуться к подключениям" → `/connections`.
|
||
|
||
### 11. Delete Confirmation
|
||
|
||
The "Отключить" button on the dashboard uses a simple JS `confirm()` dialog: "Вы уверены, что хотите отключить {service name}?" before submitting the POST form.
|
||
|
||
## Files Summary
|
||
|
||
| File | Action |
|
||
|------|--------|
|
||
| `web/models.py` | Modify — add `is_online`, `last_checked_at` to both connection models |
|
||
| `web/config.py` | Modify — add `HEALTH_CHECK_INTERVAL_SECONDS` |
|
||
| `web/main.py` | Modify — lifespan + register connections router |
|
||
| `web/routes/evotor.py` | Modify — set online on callback, redirect to /connections |
|
||
| `web/routes/vk.py` | Modify — set online on callback, redirect to /connections |
|
||
| `web/routes/connections.py` | Create — dashboard, add page, delete endpoint |
|
||
| `web/health_checker.py` | Create — background checks for both Evotor and VK |
|
||
| `web/templates/connections.html` | Create — dashboard with cards |
|
||
| `web/templates/connections_add.html` | Create — add connection page |
|
||
| `web/templates/base.html` | Modify — navbar link |
|
||
| `web/templates/evotor.html` | Modify — back link to /connections |
|
||
| `web/templates/vk.html` | Modify — back link to /connections |
|
||
| Alembic migration | Create |
|
||
|
||
## Verification
|
||
|
||
1. Run `alembic upgrade head`
|
||
2. Start the app, verify background task logs appear
|
||
3. Visit `/connections` — empty state, "Добавить" button visible
|
||
4. Click "Добавить" → shows Evotor and VK as available services
|
||
5. Add Evotor → goes through OAuth → returns to `/connections` with green status card
|
||
6. Add VK → same flow → both connections visible
|
||
7. Click "Добавить" again → shows "Все доступные сервисы подключены"
|
||
8. Click "Отключить" on Evotor → confirmation dialog → connection removed → card disappears
|
||
9. Click "Добавить" → Evotor is available again
|
||
10. Wait for health check cycle → verify `is_online` and `last_checked_at` update on remaining connections
|