feat(azure-ai+gpu-ui): per-tenant Azure AI config + GPU health panel
- Per-tenant Azure AI config stored in tenants.tenant_config JSONB
- GET/PUT /api/tenants/{id}/ai-config + POST .../test connection
- api_key never returned to frontend (has_api_key: bool pattern)
- azure_ai.py resolves creds from tenant config when ai_enabled=True
- ai_tasks.py loads tenant config and passes it to validate_thumbnail
- Admin GPU Status section: probe button + status badge + last-checked time
- Notifications: _BELL_CHANNELS filter (notification+alert only in bell)
- Tenants.tsx: per-row Azure AI Config modal with URL auto-parse helper
- Remove duplicate in-memory /gpu-probe endpoints (kept DB-backed /probe/gpu)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -51,30 +51,42 @@ def _visibility_filter(user: User):
|
||||
return and_(AuditLog.notification == True, targeted) # noqa: E712
|
||||
|
||||
|
||||
# Default channels shown in bell dropdown
|
||||
_BELL_CHANNELS = ("notification", "alert")
|
||||
|
||||
|
||||
@router.get("", response_model=NotificationListResponse)
|
||||
async def list_notifications(
|
||||
limit: int = Query(20, ge=1, le=100),
|
||||
offset: int = Query(0, ge=0),
|
||||
unread_only: bool = Query(False),
|
||||
channel: Optional[str] = Query(None, description="Filter by channel: notification, activity, alert. Defaults to notification+alert."),
|
||||
user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
vis = _visibility_filter(user)
|
||||
|
||||
# Channel filter
|
||||
if channel:
|
||||
channel_filter = AuditLog.channel == channel
|
||||
else:
|
||||
channel_filter = AuditLog.channel.in_(_BELL_CHANNELS)
|
||||
|
||||
# Total count
|
||||
total_q = select(func.count(AuditLog.id)).where(vis)
|
||||
total_q = select(func.count(AuditLog.id)).where(vis, channel_filter)
|
||||
if unread_only:
|
||||
total_q = total_q.where(AuditLog.read_at.is_(None))
|
||||
total = (await db.execute(total_q)).scalar() or 0
|
||||
|
||||
# Unread count (always)
|
||||
unread_q = select(func.count(AuditLog.id)).where(vis, AuditLog.read_at.is_(None))
|
||||
# Unread count (always — only for bell channels, not activity)
|
||||
bell_channel_filter = AuditLog.channel.in_(_BELL_CHANNELS)
|
||||
unread_q = select(func.count(AuditLog.id)).where(vis, bell_channel_filter, AuditLog.read_at.is_(None))
|
||||
unread_count = (await db.execute(unread_q)).scalar() or 0
|
||||
|
||||
# Items
|
||||
items_q = (
|
||||
select(AuditLog)
|
||||
.where(vis)
|
||||
.where(vis, channel_filter)
|
||||
.order_by(AuditLog.timestamp.desc())
|
||||
.offset(offset)
|
||||
.limit(limit)
|
||||
@@ -105,7 +117,8 @@ async def unread_count(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
vis = _visibility_filter(user)
|
||||
q = select(func.count(AuditLog.id)).where(vis, AuditLog.read_at.is_(None))
|
||||
bell_channel_filter = AuditLog.channel.in_(_BELL_CHANNELS)
|
||||
q = select(func.count(AuditLog.id)).where(vis, bell_channel_filter, AuditLog.read_at.is_(None))
|
||||
count = (await db.execute(q)).scalar() or 0
|
||||
return UnreadCountResponse(unread_count=count)
|
||||
|
||||
@@ -182,7 +195,9 @@ async def update_my_notification_config(
|
||||
):
|
||||
if channel not in ("in_app", "email"):
|
||||
raise HTTPException(status_code=400, detail="channel must be 'in_app' or 'email'")
|
||||
return await upsert_notification_config(db, current_user.id, event_type, channel, body.enabled)
|
||||
if body.frequency is not None and body.frequency not in ("immediate", "daily", "never"):
|
||||
raise HTTPException(status_code=400, detail="frequency must be 'immediate', 'daily', or 'never'")
|
||||
return await upsert_notification_config(db, current_user.id, event_type, channel, body.enabled, body.frequency)
|
||||
|
||||
|
||||
@router.post("/config/reset", response_model=list[NotificationConfigOut])
|
||||
|
||||
@@ -683,3 +683,4 @@ async def update_worker_config(
|
||||
enabled=cfg.enabled,
|
||||
updated_at=cfg.updated_at.isoformat(),
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user