feat(admin): тумблер вкл/выкл для экзамен-модулей (exam-prep)
Не было UI для управления exam_tracks.enabled (только флаг в БД, ставился
миграцией). Добавлена админ-секция «Экзамен-модули»:
- backend exam-prep.js: GET /admin/tracks (все треки, вкл. выключенные, + число
заданий) и PATCH /admin/track (exam_key, enabled), обе requireRole('admin').
Пути без :examKey, чтобы не задеть гейт content_access.
- frontend: секция sections/exams.js (список треков + переключатель enabled),
вкладка в admin.html (admin-only через ADMIN_ONLY_TABS, locked для не-админов),
регистрация в admin.js (ROUTE_TO_SECTION).
Выключенный трек скрыт у учеников и пропадает из каталога прав доступа (тот
берёт exam_tracks WHERE enabled=1). Доступ ученикам по-прежнему в «Доступ · контент».
Требует перезапуска бэкенда + Ctrl+F5.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
const router = require('express').Router();
|
||||
const db = require('../db/db');
|
||||
const { authMiddleware } = require('../middleware/auth');
|
||||
const { authMiddleware, requireRole } = require('../middleware/auth');
|
||||
const access = require('../services/contentAccess');
|
||||
|
||||
router.use(authMiddleware);
|
||||
@@ -416,6 +416,28 @@ router.get('/tracks', (req, res) => {
|
||||
res.json({ tracks });
|
||||
});
|
||||
|
||||
/* ── Админ: управление экзамен-модулями (вкл/выкл) ──
|
||||
Отдельные пути (без :examKey, чтобы не задеть гейт content_access). */
|
||||
router.get('/admin/tracks', requireRole('admin'), (_req, res) => {
|
||||
const tracks = db.prepare(`
|
||||
SELECT exam_key, title, subject_slug, grade, enabled, variants_count, sort_order,
|
||||
(SELECT COUNT(*) FROM exam_tasks t WHERE t.exam_key = exam_tracks.exam_key) AS task_count
|
||||
FROM exam_tracks
|
||||
ORDER BY sort_order, exam_key
|
||||
`).all();
|
||||
res.json({ tracks });
|
||||
});
|
||||
|
||||
router.patch('/admin/track', requireRole('admin'), (req, res) => {
|
||||
const key = String(req.body && req.body.exam_key || '').trim();
|
||||
if (!key) return res.status(400).json({ error: 'exam_key required' });
|
||||
if (!db.prepare('SELECT 1 FROM exam_tracks WHERE exam_key = ?').get(key))
|
||||
return res.status(404).json({ error: 'Unknown exam track' });
|
||||
const enabled = req.body && req.body.enabled ? 1 : 0;
|
||||
db.prepare('UPDATE exam_tracks SET enabled = ? WHERE exam_key = ?').run(enabled, key);
|
||||
res.json({ ok: true, exam_key: key, enabled });
|
||||
});
|
||||
|
||||
/* ── GET /api/exam-prep/:examKey/info ──
|
||||
Track metadata + global counts + this user's aggregate progress. */
|
||||
// @public-by-design: router-level authMiddleware (line 6) covers this route
|
||||
|
||||
Reference in New Issue
Block a user