2026-03-06 15:26:49 +03:00
# Connections Dashboard with Background Health Checks
## Context
2026-03-06 16:08:19 +03:00
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.
2026-03-06 15:26:49 +03:00
2026-03-06 16:08:19 +03:00
Supported connection types: **Evotor ** , **VK ** (one per type per user).
2026-03-06 15:26:49 +03:00
2026-03-06 16:08:19 +03:00
## 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.
2026-03-06 15:26:49 +03:00
2026-03-06 16:08:19 +03:00
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:
2026-03-06 15:26:49 +03:00
- `is_online` (Boolean, default=False, server_default="0")
- `last_checked_at` (DateTime, nullable)
2026-03-06 16:08:19 +03:00
## Plan
### 1. Model Changes — `web/models.py`
Add `is_online` and `last_checked_at` to both `EvotorConnection` and `VkConnection` .
2026-03-06 15:26:49 +03:00
### 2. Alembic Migration
2026-03-06 16:08:19 +03:00
Add health check fields to both connection tables.
2026-03-06 15:26:49 +03:00
### 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)
2026-03-06 16:08:19 +03:00
- `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`
2026-03-06 15:26:49 +03:00
### 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
2026-03-06 16:08:19 +03:00
- Register connections router
2026-03-06 15:26:49 +03:00
### 6. Connections Route — `web/routes/connections.py` (new)
2026-03-06 16:08:19 +03:00
**`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:
2026-03-06 15:26:49 +03:00
```python
2026-03-06 16:08:19 +03:00
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:
2026-03-06 15:26:49 +03:00
```
2026-03-06 16:08:19 +03:00
┌─────────────────────────────────────────────────┐
│ Подключения [+ Добавить] │
├─────────────────────────────────────────────────┤
│ │
│ ┌─ 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
2026-03-06 15:26:49 +03:00
2026-03-06 16:08:19 +03:00
Empty state: message prompting user to add their first connection.
2026-03-06 15:26:49 +03:00
2026-03-06 16:08:19 +03:00
**`web/templates/connections_add.html` ** — Add connection page:
```
┌─────────────────────────────────────────────────┐
│ Добавить подключение │
├─────────────────────────────────────────────────┤
│ │
│ ┌─ Card ─────────────────────────────────────┐ │
│ │ 🏪 Эвотор │ │
│ │ Подключите кассу Эвотор для синхронизации │ │
│ │ каталога товаров. │ │
│ │ [Подключить →] │ │
│ └────────────────────────────────────────────┘ │
│ │
│ ┌─ Card ─────────────────────────────────────┐ │
│ │ 💬 ВКонтакте │ │
│ │ Подключите аккаунт ВКонтакте для │ │
│ │ публикации товаров в вашу группу. │ │
│ │ [Подключить →] │ │
│ └────────────────────────────────────────────┘ │
│ │
│ ← Вернуться к подключениям │
│ │
└─────────────────────────────────────────────────┘
```
2026-03-06 15:26:49 +03:00
### 8. Navbar Update — `web/templates/base.html`
Replace "Эвотор" link with "Подключения" → `/connections` .
2026-03-06 16:08:19 +03:00
### 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
2026-03-06 15:26:49 +03:00
2026-03-06 16:08:19 +03:00
Change back links on `/evotor` and `/vk` pages: "Вернуться к подключениям" → `/connections` .
2026-03-06 15:26:49 +03:00
2026-03-06 16:08:19 +03:00
### 11. Delete Confirmation
2026-03-06 15:26:49 +03:00
2026-03-06 16:08:19 +03:00
The "Отключить" button on the dashboard uses a simple JS `confirm()` dialog: "Вы уверены, что хотите отключить {service name}?" before submitting the POST form.
2026-03-06 15:26:49 +03:00
## Files Summary
| File | Action |
|------|--------|
2026-03-06 16:08:19 +03:00
| `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 |
2026-03-06 15:26:49 +03:00
| Alembic migration | Create |
## Verification
2026-03-06 16:08:19 +03:00
1. Run `alembic upgrade head`
2026-03-06 15:26:49 +03:00
2. Start the app, verify background task logs appear
2026-03-06 16:08:19 +03:00
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