Files
Learn_System/plans/admin-redesign/CONTEXT.md
T

102 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Feature Context: Admin Panel Redesign
## Current State
(будет обновляться после каждой фазы)
- ✅ Phase 1 implemented — `window.AdminRouter` обёртывает старый `switchTab` (hash ↔ tab двусторонне). `switchTab` принимает 2-й аргумент `{ fromRouter: true }` для предотвращения рекурсии. Default = `#stats`. Файлы: `frontend/js/admin/router.js` (новый), `frontend/admin.html` (+1 строка), `frontend/js/admin/admin.js` (модификация `switchTab` + IIFE `initAdminRouter`).
- ✅ Phase 2 implemented (commit 92030b4) — admin.js ужат с ~3591L до 701L. Все 13 plan-tabs живут в `frontend/js/admin/sections/*.js` (IIFE pattern) + `frontend/js/admin/_shared.js` (window.AdminCtx). switchTab() диспетчит в `AdminSections[ROUTE_TO_SECTION[name]].init()`. Lazy-load работает (inited флаг внутри каждой IIFE). System tabs (topics/audit/errors/health/classroom/avatars) остались inline в admin.js — Phase 2 их не extract'ил.
- ⬜ Phase 3-6 not started
## Temporary Workarounds
(пусто — заполняется implementer'ом)
## Cross-Phase Dependencies
- **Phase 2 depends on Phase 1:** sections подписываются на router events, чтобы lazy-init по hashchange
- **Phases 3, 4, 5 depend on Phase 2:** новые модули будут добавляться в `js/admin/sections/` (структура из фазы 2)
- **Phase 6 depends on Phase 2:** deep page для user/session — это новые sections в той же структуре
- **Phase 6 removes** старую `.user-panel` overlay из admin.html — фазы 1-5 НЕ должны её удалять
## Router Contract (Phase 1)
```js
// Subscribe in any future module:
AdminRouter.on('change', ({ route, params, raw }) => { /* ... */ });
// Programmatic deep-link without polluting history:
AdminRouter.navigate('#users/123', { replace: true, silent: true });
```
- Events emitted: `'change'` only (payload: parsed route).
- Late subscribers do NOT receive replay — call `AdminRouter.current()` on init.
- `silent: true` suppresses the synchronous emit but native `hashchange` still fires;
the internal `_navigating` flag in router.js prevents the listener from re-firing.
- `switchTab(btn, { fromRouter: true })` — call from router handlers to skip the
reverse-sync write to `location.hash` (avoids redundant `replaceState`).
## Implementation Notes
### Существующая структура (что менять / что НЕ менять)
**Точки входа в admin.js:**
- `LS.initPage()` — auth + role check
- `switchTab(btn)` — текущий tab-роутер; будет обёрнут router'ом, но не удалён до фазы 6
- Per-tab `*Inited` флаги (`usersInited`, `sessionsInited`, ...) — переедут в section modules
**Backward compat обязателен:**
- `goAddQuestion(slug)` и подобные cross-tab onclick handlers должны работать
- Старые ссылки `<a href="#stats">` (если есть) тоже
### Конвенции вновь создаваемых модулей (Phase 2 закреплено)
Каждая section:
```js
// js/admin/sections/<name>.js
(function () {
'use strict';
let inited = false;
async function load() { /* fetch + render */ }
// Optional onclick handlers used by HTML / dynamic templates:
window.handlerX = handlerX;
window.AdminSections = window.AdminSections || {};
window.AdminSections.<name> = {
init: async () => { if (inited) return; inited = true; await load(); },
reload: load,
// Optional extras for cross-section calls (e.g. questions.openModal):
// openModal: (...) => { ... },
};
})();
```
Shared utilities — на `window.AdminCtx` (см. `_shared.js`):
- `user`, `isTeacher`, `isAdmin` (filled by admin.js)
- `MODES`, `DIFFS`, `DIFF_LABELS`, `TYPE_LABELS`
- `pctClass`, `fmtDate`, `fmtTime`, `fmtDuration`
- `renderMath`, `qTypeBadge`, `qOptsPreview`
- `renderPgnControls`, `ensurePgnStyles`
ROUTE_TO_SECTION map в admin.js — добавлять новые ключи при добавлении секций
(Phase 3 = `overview`, Phase 6 = `user`/`session` deep pages).
Router (фаза 1):
```js
// js/admin/router.js
window.AdminRouter = {
navigate(hash) { /* update hash + dispatch */ },
current() { /* parse current hash */ },
on(event, fn) { /* subscribe */ },
};
```
### Какие onclick handlers есть сейчас (выборка)
Из admin.html / admin.js:
- `onclick="switchTab(this)"` — на каждой admin-nav-item
- `onclick="openUserPanel(event, ${u.id}, '${u.role}')"` — на user row
- `onclick="changeRole(this)"` — на role-select
- `onclick="goAddQuestion('${slug}')"` — cross-tab
Эти должны работать без изменений до фазы 6.