Now that the deep pages (sub-commit 1) work, retire the legacy
.user-panel inline overlay entirely.
* admin.html: removed <div class="user-panel" id="user-panel"> block
inside #tab-users, removed dead .user-panel* CSS (kept .btn-close
for any external use).
* users.js: removed openUserPanel / closeUserPanel / reloadUserPanel
and their closure state (activeTr, activeUserRole). User row onclick
switched from openUserPanel(...) → AdminRouter.navigate('#users/N').
clearUserHistory / toggleBanUser / confirmDeleteUser / openEditUserModal
/ openUserPermsModal / doSet/doReset* all refactored to use the
getActiveUid() helper (reads window.activeUid, set by user-detail.init)
+ reloadDetailAndList() helper (refreshes deep page + list together).
* sessions.js: row click + eye-button switched from toggleDrawer(id)
→ gotoSession(id) → AdminRouter.navigate('#sessions/N'). Removed
toggleDrawer + renderDrawer functions (~60L) and openDrawerId state.
Inline drawer markup removed from the row template.
Verified node --check on all touched JS. ast-index confirms zero
remaining usages of openUserPanel / closeUserPanel / reloadUserPanel /
toggleDrawer across the repo.
This completes Phase 6 and the admin-redesign feature.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
11 KiB
Phase 6: Deep entity pages
Status: ✅ Done (sub-commits: bd30200 + final remove-overlay commit)
Parent plan: PLAN.md
Domain: frontend
Objective
Заменить выезжающую .user-panel overlay на полноценную страницу с URL #users/123. Аналогично для session: #sessions/456 = full detail page. Это самая комплексная фаза — она ломает совместимость с старым overlay UI (удаляет код), потому идёт ПОСЛЕ всех остальных.
Tasks
- User detail page (
frontend/js/admin/sections/user-detail.js):- Реагирует на route
#users/:id - Layout:
- Header: avatar, name, role badge, email, action buttons (ban/edit/perms/delete), back-link to
#users - Tabs (sub-nav в странице):
- Overview — статистика (тестов, средний %, регистрация, посл вход)
- Sessions — таблица последних 20 сессий с pagination
- Classes — список классов где он состоит
- Audit — журнал действий (если есть audit log с user_id)
- Graphs (опционально, можно отдельным таб'ом):
- Простой SVG-чарт: успеваемость по неделям
- Mini-bar chart: avg % по предметам
- Header: avatar, name, role badge, email, action buttons (ban/edit/perms/delete), back-link to
- Реагирует на route
- Session detail page (
frontend/js/admin/sections/session-detail.js):- Реагирует на route
#sessions/:id - Layout: header (user, subject, score, дата) + список вопросов/ответов (правильно/нет, текст), back-link
- Реагирует на route
- Router updates (
frontend/js/admin/router.jsесли ещё не поддерживает): router из Phase 1 уже парсит params — обновлять не пришлось - Admin.js dispatch: добавлена
DEEP_ROUTESmap +activateDeepPane()+activate(route, params) - Удалить overlay-код:
- В
frontend/admin.htmlудалён<div class="user-panel" id="user-panel">блок +.user-panel*CSS - В
sections/users.jsудаленыopenUserPanel,closeUserPanel,reloadUserPanel - В
sections/users.jsonclick переключён наAdminRouter.navigate('#users/${u.id}')
- В
- Replace в Phase 5 quick action "Sessions":
quickOpenUserSessions(uid)→AdminRouter.navigate('#users/' + uid + '/sessions')- Парсить sub-tab из route (выполнено через
params[1]вactivate()) - Открывать user-detail page с активным Sessions tab
- Парсить sub-tab из route (выполнено через
- Глоссарий routes после фазы:
#overview— dashboard (Phase 3)#users— list#users/123— user detail (overview tab default)#users/123/sessions— user detail with sessions sub-tab#sessions— list#sessions/456— session detail- … остальные без params — как было
Files to Modify/Create
frontend/js/admin/sections/user-detail.js— новый, ~400-600Lfrontend/js/admin/sections/session-detail.js— новый, ~200-300Lfrontend/admin.html— удалить.user-paneloverlay, добавить<div id="tab-user-detail">и<div id="tab-session-detail">, добавить<script>тегиfrontend/js/admin/sections/users.js— удалить overlay-функции (~100-150L удаления)frontend/js/admin/router.js— улучшения parsing для sub-routes (если нужно)frontend/js/admin/admin.js— dispatch logic для routes с params
Acceptance Criteria
- Click на user row → URL становится
#users/123, открывается deep page - F5 на
#users/123восстанавливает страницу - Back navigation → возврат на
#userslist - Header содержит все action-кнопки (ban, edit, perms, delete)
- Sub-tabs (overview, sessions, classes, audit) переключаются, URL обновляется
- Старая
.user-paneloverlay полностью удалена из HTML и JS - Click на session id (в любом контексте) →
#sessions/456→ detail page - Нет console errors
- Графики (если делаются) рендерятся корректно
Notes
Backward compat
После Phase 6 старые ссылки/onclick типа openUserPanel(...) УЖЕ НЕ работают. Это intentional — мы их удалили. Но onclick="AdminRouter.navigate('#users/N')" работает везде.
Если есть external links на админку user-panel — они продолжат работать как #users/N через router.
Графики
Можно использовать chart.js (CDN ~50KB), но проще — inline SVG bar/line chart на нескольких десятках строк. У нас уже есть .perf-bar для процентов — можно расширить.
Не обязательно делать графики в этой фазе — можно сделать MVP без них и добавить чартами позже. В acceptance criteria графики помечены опционально.
Audit log
Если в БД есть таблица audit_log с user_id — sub-tab Audit показывает её. Если нет — sub-tab скрывается или показывает empty state "Audit logging не активирован".
Session detail
Сейчас session detail открывается через adminGetSessionDetail → возвращает массив answers. Используем тот же endpoint, рендерим в полноценную страницу вместо modal.
Удаление overlay-кода (опасный шаг)
Делать в КОНЦЕ фазы, после того как deep page работает. Сначала добавить deep page, протестировать, потом удалить overlay. Можно даже сделать отдельным коммитом ("remove overlay").
Что НЕ делать
- Не делать realtime updates (Phase 7+)
- Не делать collaborative cursors
- Не оптимизировать графики до production-grade (chart.js or similar OK)
Review Checklist
- Deep pages работают: F5, back/forward
- Sub-tabs URL-обновляемы
- Old overlay code fully removed
- No regressions: ban/edit/delete user работают из deep page
- Mobile-friendly: tabs scrollable, layout не ломается
- Build passes
- Final smoke test: пройти полный сценарий — открыть админку, найти пользователя через Cmd+K, перейти на deep page, выдать монеты, посмотреть сессии, забанить, разбанить, вернуться в overview
Handoff to Next Phase
Это финальная фаза. Что реализовано в этой фазе:
Done
- Deep page
#users/:idс sub-tabs (overview/sessions/classes/audit) и URL-sync sub-routing - Deep page
#sessions/:idс полным разбором ответов - F5 / browser-back / закладки работают на любом deep-URL
- Overlay
.user-panelполностью удалён (HTML + CSS + JS) - Sessions row-click переключён с inline drawer на deep page navigation (
gotoSession(id)) - Audit sub-tab фильтрует system-wide audit-log по uid client-side
- Inline SVG bar chart для per-subject avg % на Overview sub-tab (no chart.js dep)
- Cmd+K palette user-pick (Phase 4) теперь открывает deep page (ранее был fallback на
#users) - 2 sub-commit разбивка для безопасности:
bd30200(add deep pages, overlay still works) → finale (remove overlay)
Post-merge follow-ups (NOT блокирующие для merge)
- Classes sub-tab — placeholder. Нет backend endpoint
GET /admin/users/:id/classes. Текущий UI показывает empty-state со ссылкой на/classes. После merge добавить endpoint (выбрать изclass_membersпоuser_id). - Audit sub-tab — client-side filter. Фильтрация делается на 500 строк из общего лога — для бóльших инсталляций нужен
GET /admin/audit-log?user_id=N(server-side). Сейчас работает корректно для типичной нагрузки LearnSpace (<10k записей). - Charts — single bar chart only. План включал опциональные графики "успеваемость по неделям" — оставил на post-merge. Использовать тот же inline SVG паттерн (
.ud-bars+.ud-bar-fill). - Mobile. Header кнопки сжимаются на ≤640px (см. CSS
.ud-headerblock в user-detail.js), но при большом количестве действий могут перекрыть. Можно добавить overflow menu (<details>) post-merge если жалобы. .user-panelCSS не полностью удалён — оставлен только.btn-close(используется ещё где-то?). Если нет — можно удалить тоже.window.activeUid— глобальное состояние. Сейчас и user-detail.js, и users.js пишут/читаютwindow.activeUid. Это работает, но в идеале нужно перенести user-only modals (eu-modal, up-modal) в user-detail.js целиком. Не критично, но улучшит изоляцию.
Final smoke checklist (для final-reviewer)
- Открыть
/admin#overview— dashboard - Cmd+K → найти юзера → пик из списка → открыть deep page
- На deep page переключить sub-tabs (URL обновляется)
- F5 на
#users/N/sessions→ page восстановлен - Browser back → возврат на
#userslist - Header action: Изменить → modal → save → header обновлён
- Header action: Бан → toast → header обновлён (метка "Разблокировать")
- Click on session row in Sessions sub-tab →
#sessions/M(deep session page) - Session page: Delete → toast → navigate back to
#sessionslist - No console errors