feat: release v1.8.0 — connections dashboard, VK OAuth, sync config, catalog browser

- 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>
This commit is contained in:
mguschin
2026-03-06 16:08:19 +03:00
parent cfc7229daf
commit 9aeef73b10
20 changed files with 2010 additions and 85 deletions

65
run/read_config.py Normal file
View File

@@ -0,0 +1,65 @@
#!/usr/bin/env python3
"""
Read sync configuration for a user from the database and output JSON.
Usage: python run/read_config.py <user_id>
Output JSON structure:
{
"enabled": true,
"confirmed": true,
"filters": {
"stores": [{"id": "...", "name": "...", "mode": "include"}],
"groups": [{"id": "...", "name": "...", "mode": "include", "parent_store_id": "..."}],
"products": [{"id": "...", "name": "...", "mode": "exclude", "parent_group_id": "..."}]
}
}
"""
import json
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from web.database import SessionLocal
from web.models import SyncConfig, SyncFilter
def read_config(user_id: int) -> dict:
db = SessionLocal()
try:
config = db.query(SyncConfig).filter(SyncConfig.user_id == user_id).first()
if not config:
return {"enabled": False, "confirmed": False, "filters": {"stores": [], "groups": [], "products": []}}
enabled = config.is_enabled
confirmed = config.confirmed_at is not None
stores = []
groups = []
products = []
for f in config.filters:
entry = {"id": f.entity_id, "name": f.entity_name, "mode": f.filter_mode}
if f.entity_type == "store":
stores.append(entry)
elif f.entity_type == "group":
stores.append({**entry, "parent_store_id": f.parent_entity_id})
elif f.entity_type == "product":
products.append({**entry, "parent_group_id": f.parent_entity_id})
return {
"enabled": enabled,
"confirmed": confirmed,
"filters": {"stores": stores, "groups": groups, "products": products},
}
finally:
db.close()
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: read_config.py <user_id>", file=sys.stderr)
sys.exit(1)
user_id = int(sys.argv[1])
print(json.dumps(read_config(user_id), ensure_ascii=False, indent=2))