Files
Learn_System/plans/admin-redesign/phase-2-split-sections.md
T
Maxim Dolgolyov 76e376ee04 chore(plan): admin-redesign 6-phase plan
PLAN.md + 6 subplans + CONTEXT.md

Strategy: Incremental | Mode: Automated | Execution: Orchestrator

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 21:47:55 +03:00

8.4 KiB
Raw Blame History

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.jsloadStats + связанные функции (small, ~50L)
    • sublog.js — submission log (medium)
    • sims.js, games.js, tpl.js — admin-only (small каждая)
    • subjects.js — настройка доступных тестов
    • permissions.js
    • shop.js — items + purchases + award coins
    • gam.js — gamification stats + award xp
    • assignments.js
    • tests.js
    • questions.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-500L
  • frontend/js/admin/sections/sessions.js — новый
  • frontend/js/admin/sections/questions.js — новый, ~800L
  • frontend/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 за раз, мелкими безопасными шагами:

  1. Скопировать функции loadX, openXModal, deleteX, ... в новый файл sections/.js, обернуть в IIFE
  2. Экспортировать через window.AdminSections.X
  3. Подключить <script> в admin.html
  4. В admin.js заменить вызовы (loadX()AdminSections.X.init(ctx))
  5. Удалить дубликаты в admin.js
  6. Тест: открыть tab — работает?
  7. Перейти к следующей секции

Что НЕ переезжает в sections

  • LS.initPage() + auth check — остаётся в admin.js
  • switchTab (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

Handoff to Next Phase