Slice 7: §14 chrome + settings and admin neighborhoods
§14.1 richer landing, §14.2 /philosophy route (disk-backed), §14.3 persistent About link. /settings/notifications surfaces Slice 6's preferences/quiet-hours/mute/watches endpoints. /admin home base consolidates role management, the §6.2 write-mute, the audit-log viewer, the permission-events log, and the §13.2 graduation queue. Backend: backend/app/philosophy.py, backend/app/api_admin.py (seven admin endpoints + user-search), GET /api/users/me/notification-mutes. Frontend: Landing.jsx (deck), Philosophy.jsx, NotificationSettings.jsx, Admin.jsx, App.jsx routing for the chrome surfaces. Tests: backend/tests/test_chrome_vertical.py — 13 cases. Full suite 75/75 green. Spec corrections: §14.2 (PHILOSOPHY.md source is a deployment-time decision), §17 (admin block extended to name the seven new endpoints + user-search and notification-mutes read). §19.1 rewritten for Slice 8 hardening; §19.2 grew four candidates (owner succession, mute-from-actor, the "Following since <date>" disclosure, audit-log row prose). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -293,6 +293,36 @@ def make_router(config: Config) -> APIRouter:
|
||||
|
||||
# ----- Per-user notification mute (§15.8) -----
|
||||
|
||||
@router.get("/api/users/me/notification-mutes")
|
||||
async def list_user_mutes(request: Request) -> dict[str, Any]:
|
||||
"""Slice 7: the §15.8 mute list the settings surface renders.
|
||||
Joined against users so the settings UI can show @gitea_login and
|
||||
display_name without a second round-trip.
|
||||
"""
|
||||
viewer = auth.require_user(request)
|
||||
rows = db.conn().execute(
|
||||
"""
|
||||
SELECT m.muted_user_id, m.muted_at,
|
||||
u.gitea_login, u.display_name
|
||||
FROM notification_user_mutes m
|
||||
JOIN users u ON u.id = m.muted_user_id
|
||||
WHERE m.muter_user_id = ?
|
||||
ORDER BY m.muted_at DESC
|
||||
""",
|
||||
(viewer.user_id,),
|
||||
).fetchall()
|
||||
return {
|
||||
"items": [
|
||||
{
|
||||
"muted_user_id": r["muted_user_id"],
|
||||
"gitea_login": r["gitea_login"],
|
||||
"display_name": r["display_name"],
|
||||
"muted_at": r["muted_at"],
|
||||
}
|
||||
for r in rows
|
||||
]
|
||||
}
|
||||
|
||||
@router.post("/api/users/{user_id}/notification-mute")
|
||||
async def add_user_mute(user_id: int, request: Request) -> dict[str, Any]:
|
||||
viewer = auth.require_user(request)
|
||||
|
||||
Reference in New Issue
Block a user