PLAN.md + 6 subplans + CONTEXT.md Strategy: Incremental | Mode: Automated | Execution: Orchestrator Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8.4 KiB
Phase 2: Split admin.html → per-section modules
Status: ⬜ Not Started Parent plan: PLAN.md Domain: frontend
Objective
Разделить монолит admin.js (3500L) на per-section модули в frontend/js/admin/sections/*.js. После фазы admin.js становится оркестратором (~500-800L): он только подключает router, инициализирует общие виджеты (notif, sidebar) и делегирует загрузку section-данных в соответствующий модуль.
Tasks
- Создать
frontend/js/admin/sections/директорию - Определить единый паттерн модуля:
// js/admin/sections/<name>.js (function () { 'use strict'; let inited = false; const ctx = { user: null, isAdmin: false }; // прокидываем из admin.js async function load() { /* существующий loadX код */ } window.AdminSections = window.AdminSections || {}; window.AdminSections.<name> = { init: async (sharedCtx) => { Object.assign(ctx, sharedCtx); if (inited) return; inited = true; await load(); }, reload: load, }; })(); - Извлечь 13 секций (в порядке риска — от меньшего к большему):
stats.js—loadStats+ связанные функции (small, ~50L)sublog.js— submission log (medium)sims.js,games.js,tpl.js— admin-only (small каждая)subjects.js— настройка доступных тестовpermissions.jsshop.js— items + purchases + award coinsgam.js— gamification stats + award xpassignments.jstests.jsquestions.js— самая большая, ~800L (включая Q-modal)users.js— users-table + pagination + user-panel (overlay остаётся!)sessions.js— sessions-table + session detail
- Модифицировать
admin.js:- Удалить функции, перенесённые в sections
- Заменить inline вызовы (
loadUsers()→AdminSections.users.init(ctx)) - Добавить генератор route→section маппинга:
const ROUTE_TO_SECTION = { stats: 'stats', users: 'users', sessions: 'sessions', questions: 'questions', tests: 'tests', assignments: 'assignments', subjects: 'subjects', permissions: 'permissions', shop: 'shop', gam: 'gam', tpl: 'tpl', sims: 'sims', games: 'games', sublog: 'sublog', }; AdminRouter.on('change', ({ route }) => { const sec = ROUTE_TO_SECTION[route]; if (sec && AdminSections[sec]) AdminSections[sec].init(sharedCtx); });
- Все 13
<script>тегов добавить вadmin.html(после router.js, перед admin.js) - Глобальные функции, которые используются из onclick HTML, остаются доступными через
window.X:changeRole,openUserPanel,goAddQuestion,confirmDeleteUser, etc.- Каждый section module экспортирует свои onclick-handler'ы через
window.X = Xили через делегацию из admin.js
- Удалить per-tab
*Initedфлаги из admin.js — они переехали внутрь section modules
Files to Modify/Create
frontend/js/admin/sections/stats.js— новыйfrontend/js/admin/sections/users.js— новый, ~400-500Lfrontend/js/admin/sections/sessions.js— новыйfrontend/js/admin/sections/questions.js— новый, ~800Lfrontend/js/admin/sections/tests.js— новыйfrontend/js/admin/sections/assignments.js— новыйfrontend/js/admin/sections/subjects.js— новыйfrontend/js/admin/sections/permissions.js— новыйfrontend/js/admin/sections/shop.js— новыйfrontend/js/admin/sections/gam.js— новыйfrontend/js/admin/sections/tpl.js— новыйfrontend/js/admin/sections/sims.js— новыйfrontend/js/admin/sections/games.js— новыйfrontend/js/admin/sections/sublog.js— новыйfrontend/js/admin/admin.js— сильно ужать (с 3500L до ~500-800L)frontend/admin.html— добавить 13<script>тегов
Acceptance Criteria
admin.js≤ 800L (от 3500L)- Каждый section-файл ≤ 900L (questions.js самый большой)
- Все 13 табов работают идентично текущему поведению (no regressions)
- Cross-tab handlers (
goAddQuestion,confirmDelete*) работают - Lazy-load работает: при первом открытии tab делается fetch, при повторном — нет
- F5 на любом
#Xкорректно ленево-грузит секцию (через router из Phase 1) - Browser back/forward работают
- Никаких console errors в Devtools
Notes
Стратегия извлечения
Один section за раз, мелкими безопасными шагами:
- Скопировать функции
loadX, openXModal, deleteX, ...в новый файл sections/.js, обернуть в IIFE - Экспортировать через
window.AdminSections.X - Подключить
<script>в admin.html - В admin.js заменить вызовы (
loadX()→AdminSections.X.init(ctx)) - Удалить дубликаты в admin.js
- Тест: открыть tab — работает?
- Перейти к следующей секции
Что НЕ переезжает в sections
LS.initPage()+ auth check — остаётся в admin.jsswitchTab(helper) — остаётсяpctClass,fmtDate,fmtTime— общие утилиты, остаются (или переезжают вadmin/_shared.js)- Sidebar / notif init — остаётся
- Router setup — остаётся
Глобальные функции из onclick
Сейчас многие функции вызываются из HTML onclick (onclick="openUserPanel(...)"). Чтобы не переписывать HTML на этой фазе, в каждом section module экспортируем нужные функции через window.X = X внутри IIFE. Phase 5/6 могут заменить onclick на event delegation, но Phase 2 этого не делает (incremental).
Тестирование каждой секции
После каждой выделенной секции:
- Открыть
/admin→ переключиться на этот tab → данные загрузились - Все кнопки/модалки секции работают
- Cross-tab navigation (если есть) работает
- F5 на
#<route>корректно открывает tab
Если регрессия — откатить эту итерацию, разобраться, починить.
Совет implementer'у
Если фаза становится огромной — можно сделать несколько коммитов внутри phase branch. Это inscope. Не нужно делать один гигантский коммит на 14 файлов.
Review Checklist
- Все 13 секций имеют одинаковую структуру (init/reload)
- admin.js ≤ 800L, в нём нет дублирования с sections
- Все window.X экспорты есть для onclick handlers
- Lazy-init работает (профилировка: при открытии tab → fetch, при повторе → нет)
- F5 на каждом из 13 routes восстанавливает секцию
- Build passes: server starts, no errors