Add platform settings (Stage 9)
- Settings key-value table in Prisma with migration - getSettings() / getSetting() helpers in lib/settings.ts - Admin UI at /admin/settings with 6 sections: General, Notifications, Student profile, Legal docs, Curator permissions, Code injection - saveSettings() server action with admin-only guard - Maintenance mode: non-admin users redirected to /maintenance page - schoolName propagated to page metadata and all email templates - headCode / bodyCode injected into root layout <head> and <body> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+163
-11
@@ -36,6 +36,15 @@
|
||||
|
||||
---
|
||||
|
||||
**Доработки таблицы пользователей (добавить в рамках Этапа 9):**
|
||||
- [ ] Фильтры: по роли (Ученик / Куратор / Администратор), по статусу email (подтверждён/нет)
|
||||
- [ ] Поиск по имени / email
|
||||
- [ ] Пагинация + выбор кол-ва записей на странице (20/50/100)
|
||||
- [ ] Ховер-попап на строке: список курсов пользователя со сроками доступа + email + телефон
|
||||
- [ ] Быстрые действия в строке: кнопка «Выдать доступ» без перехода на страницу пользователя
|
||||
|
||||
---
|
||||
|
||||
## Этап 1.5 — Расширенное управление доступом ✅ ЗАВЕРШЁН (07.04.2026)
|
||||
|
||||
- [x] Срок доступа: `expiresAt` в `CourseEnrollment`, просроченный подсвечивается красным
|
||||
@@ -80,6 +89,13 @@
|
||||
- [x] Admin: AdminShell на `/curator/*` маршрутах (сайдбар не пропадает)
|
||||
- [x] Admin: реальная статистика на дашборде (студенты, курсы, ДЗ, прогресс)
|
||||
|
||||
**Доработки (добавить в рамках Этапа 9):**
|
||||
- [ ] Фильтры в списке ДЗ: по имени/email ученика, по уроку, по курсу, по статусу
|
||||
- [ ] Поиск по имени/email ученика
|
||||
- [ ] Пагинация + выбор кол-ва записей на странице (20/50/100)
|
||||
- [ ] Расширенные статусы: «Новое» / «Просмотрено» / «Прокомментировано»
|
||||
- [ ] Шаблоны ответов куратора — готовые тексты фидбека, выбираемые из списка
|
||||
|
||||
---
|
||||
|
||||
## Этап 6 — Обсуждения под уроками ✅ ЗАВЕРШЁН (07.04.2026)
|
||||
@@ -90,6 +106,13 @@
|
||||
- [x] Модерация: автор, куратор или admin может удалить комментарий
|
||||
- [x] Счётчик активных комментариев в заголовке секции
|
||||
|
||||
**Не реализовано (добавить в Этап 9 или отдельно):**
|
||||
- [ ] `/admin/comments` — сводная таблица всех комментариев по всем урокам
|
||||
- Колонки: №, Имя ученика, Урок (ссылка), Время, кол-во ответов, превью текста
|
||||
- Удалить комментарий прямо из списка
|
||||
- Пагинация
|
||||
- Ссылка в сайдбаре AdminNav
|
||||
|
||||
---
|
||||
|
||||
## Этап 7 — Email-уведомления ✅ ЗАВЕРШЁН (07.04.2026)
|
||||
@@ -114,31 +137,128 @@
|
||||
|
||||
---
|
||||
|
||||
## Этап 9 — Миграция с emdesell ← СЛЕДУЮЩИЙ
|
||||
**Цель:** все пользователи и контент перенесены в новую LMS.
|
||||
## Этап 9 — Настройки платформы (Admin Settings) ✅ ЗАВЕРШЁН (08.04.2026)
|
||||
**Цель:** администратор управляет ключевыми параметрами платформы без правки кода.
|
||||
|
||||
- [ ] Скрипт импорта пользователей из CSV-экспорта emdesell (email, имя, курсы)
|
||||
- [ ] Создание пользователей без пароля + письмо «установите пароль»
|
||||
- [ ] Назначение доступов к курсам по данным из CSV
|
||||
### Основное
|
||||
- [ ] Название школы (используется в заголовке сайта, подписи писем)
|
||||
- [ ] Описание школы (мета-тег description)
|
||||
- [ ] Ключевые слова (мета-тег keywords)
|
||||
- [ ] Режим тех. работ: вкл/выкл (показывает заглушку всем кроме admin)
|
||||
- [ ] Регистрация учеников: вкл/выкл
|
||||
|
||||
### Оформление
|
||||
- [ ] Логотип школы (загрузка → Object Storage, отображается в шапке)
|
||||
- [ ] Фавикон (загрузка → Object Storage)
|
||||
- [ ] Показывать логотип: да/нет
|
||||
|
||||
### Уведомления
|
||||
- [ ] Email(ы) для системных уведомлений (кому слать письма о ДЗ, вопросах, регистрациях)
|
||||
- [ ] Уведомление куратору/админу о новом ДЗ: вкл/выкл
|
||||
- [ ] Уведомление куратору/админу о новом вопросе ученика: вкл/выкл
|
||||
- [ ] Уведомление админу о новой регистрации: вкл/выкл
|
||||
- [ ] Уведомление ученику при ответе на ДЗ/вопрос: вкл/выкл
|
||||
|
||||
### Данные ученика
|
||||
- [ ] Требовать подтверждение email перед доступом к курсам: да/нет
|
||||
- [ ] Фамилия при регистрации: обязательная / необязательная / выключена
|
||||
- [ ] Телефон при регистрации: обязательный / необязательный / выключен
|
||||
|
||||
### Защита
|
||||
- [ ] Одна активная сессия на аккаунт: вкл/выкл
|
||||
- [ ] CAPTCHA на форме регистрации: вкл/выкл (reCAPTCHA v3)
|
||||
|
||||
### Права куратора
|
||||
- [ ] Куратор видит ДЗ: по всем курсам / только по назначенным курсам
|
||||
- [ ] Куратор может отвечать на вопросы учеников: да/нет
|
||||
- [ ] Куратор видит список всех студентов: да/нет
|
||||
|
||||
### Вставка кода
|
||||
- [ ] Произвольный код в `<head>` (Yandex.Metrika, Google Analytics, пиксели)
|
||||
- [ ] Произвольный код в `<body>` (виджеты, чаты поддержки)
|
||||
|
||||
### Юридические документы
|
||||
- [ ] URL Политики конфиденциальности (ссылка на внешний документ)
|
||||
- [ ] URL Согласия на обработку персональных данных
|
||||
- [ ] URL Договора-оферты
|
||||
- [ ] Показывать чекбокс «Я принимаю условия» при регистрации: да/нет
|
||||
- [ ] Реквизиты организации (текстовое поле, отображается в подвале)
|
||||
|
||||
### Соц. сети
|
||||
- [ ] YouTube: одна ссылка
|
||||
- [ ] VK: несколько ссылок (название + URL), например «Основная группа» и «Канал»
|
||||
- [ ] Telegram: несколько ссылок (название + URL), например «Основной канал» и «Канал курса»
|
||||
(отображаются в подвале личного кабинета ученика; хранятся как JSON-массив в Settings)
|
||||
|
||||
### Вопросы учеников
|
||||
- [ ] Система вопросов глобально: вкл/выкл
|
||||
- [ ] Куратор/админ может написать ученику первым: да/нет
|
||||
- [ ] Вопросы только по курсам ученика: да/нет
|
||||
- [ ] Включать вопросы для новых курсов автоматически: да/нет
|
||||
|
||||
**Хранение:** таблица `Settings` (key-value), доступна через `getSettings()` в server components.
|
||||
**Критерий готовности:** меняю название школы → оно появляется в заголовке. Включаю тех. работы → ученики видят заглушку. Куратор привязан к курсу — видит только его ДЗ.
|
||||
|
||||
---
|
||||
|
||||
## Этап 11 — Импорт/Экспорт учеников и миграция с emdesell
|
||||
**Цель:** все пользователи и контент перенесены в новую LMS. Раздел `/admin/import-export`.
|
||||
|
||||
### Импорт учеников (CSV)
|
||||
- [ ] Скачать файл-шаблон CSV (Email, Имя, Фамилия, Телефон)
|
||||
- [ ] Загрузка CSV, поддержка кодировок Windows-1251 и UTF-8
|
||||
- [ ] Опция: подтверждать email автоматически (да/нет)
|
||||
- [ ] Опция: обновлять уже существующие аккаунты (да/нет)
|
||||
- [ ] Присвоение доступов к курсам при импорте (выбор курса + срок в днях, 0 = бессрочно)
|
||||
- [ ] Опция: отправить письмо-уведомление ученику (со ссылкой для установки пароля)
|
||||
- [ ] Предпросмотр перед применением (таблица: кто создаётся, кто обновляется, кому даётся доступ)
|
||||
- [ ] Применить импорт — создать пользователей, выдать доступы, отправить письма
|
||||
|
||||
### Экспорт учеников (CSV)
|
||||
- [ ] Все ученики или фильтр по конкретному курсу/доступу
|
||||
- [ ] Фильтр по просмотрам уроков (экспортировать только тех кто смотрел)
|
||||
- [ ] Выбор кодировки: Windows-1251 (для Excel) / UTF-8
|
||||
- [ ] Поля: Email, Имя, Фамилия, Телефон, Дата регистрации, Курсы, Прогресс
|
||||
|
||||
### Миграция контента
|
||||
- [ ] Чек-лист ручного переноса контента (уроки, PDF, структура курсов)
|
||||
- [ ] Скрипт проверки целостности: все enrolled пользователи имеют доступ к нужным курсам
|
||||
- [ ] QA: проверить 10 случайных аккаунтов после импорта
|
||||
|
||||
**Критерий готовности:** все ученики из emdesell могут войти в новую LMS и продолжить обучение.
|
||||
**Критерий готовности:** загружаю CSV из emdesell → предпросмотр показывает корректные данные → применяю → ученики получают письма → могут войти и продолжить обучение.
|
||||
|
||||
---
|
||||
|
||||
## Этап 10 — Telegram-бот и аналитика
|
||||
**Цель:** получаю уведомления в Telegram, вижу базовую аналитику.
|
||||
## Этап 12 — Telegram-бот и аналитика
|
||||
**Цель:** уведомления в Telegram для всех участников, базовая аналитика.
|
||||
|
||||
- [ ] Telegram-бот: уведомление куратору/админу о новом ДЗ
|
||||
- [ ] Telegram-бот: уведомление об ошибках (500-е, failed email и т.д.)
|
||||
**Настройки (в разделе Настройки → Telegram):**
|
||||
- Токен бота (вводится в админке, хранится в Settings)
|
||||
- Интеграция вкл/выкл глобально
|
||||
- Показывать кнопку «Подключить Telegram» в кабинете ученика: да/нет
|
||||
|
||||
**Уведомления куратору/админу:**
|
||||
- [ ] Новое ДЗ на проверку
|
||||
- [ ] Новый вопрос от ученика
|
||||
- [ ] Новая регистрация студента
|
||||
- [ ] Ошибки платформы (500-е, failed email и т.д.)
|
||||
|
||||
**Уведомления ученику:**
|
||||
- [ ] Получен фидбек по ДЗ
|
||||
- [ ] Ответ куратора на вопрос
|
||||
- [ ] Открыт доступ к новому курсу
|
||||
|
||||
**Реализация:**
|
||||
- [ ] Ученик привязывает Telegram через `/start` в боте (сохраняется `telegramChatId` в User)
|
||||
- [ ] Кнопка «Подключить Telegram» в личном кабинете ученика
|
||||
- [ ] Админ/куратор вводит свой `chatId` в профиле или через `/start`
|
||||
- [ ] Настройки бота в разделе Настройки → Telegram
|
||||
- [ ] Yandex.Metrika: базовое подключение (pageviews)
|
||||
- [ ] Admin: простая страница аналитики (активные ученики, прогресс по курсам)
|
||||
|
||||
---
|
||||
|
||||
## Этап 11 — Тесты и квизы
|
||||
## Этап 13 — Тесты и квизы
|
||||
**Цель:** можно добавить тест к уроку, ученик проходит и получает результат.
|
||||
|
||||
- [ ] Prisma: Quiz, QuizQuestion, QuizOption, QuizAttempt (схема уже есть)
|
||||
@@ -164,3 +284,35 @@
|
||||
- Kinescope DRM (signed URLs) — при переходе на платный план
|
||||
- Водяные знаки на PDF и картинках
|
||||
- Мобильное приложение
|
||||
- **Вопросы учеников** — система тикетов `/admin/questions` и `/questions` для ученика:
|
||||
- Таблица в админке: №, Имя, Курс, Тема, Статус (Ожидает / Отвечено), Дата
|
||||
- Статусы отсортированы: сначала «Ожидает ответа»
|
||||
- Куратор/Admin может создать обращение первым (написать ученику)
|
||||
- Внутри тикета: история переписки, смена статуса
|
||||
- **База знаний** — FAQ, который ученик видит до отправки вопроса
|
||||
- **Шаблоны ответов** — куратор выбирает готовый ответ из списка
|
||||
- Email + Telegram уведомления обеим сторонам
|
||||
|
||||
- **Главная страница ученика** — кастомизируемый экран после входа:
|
||||
- Приветственный баннер с описанием школы (редактируется в настройках)
|
||||
- Список курсов ученика с прогрессом
|
||||
- Блок бесплатных/открытых материалов (статьи, PDF, видео)
|
||||
- Анонсы ближайших событий и новых курсов
|
||||
|
||||
- **Медиатека (Файлы)** — централизованное файловое хранилище `/admin/files`:
|
||||
- Prisma: `MediaFolder` (id, name, courseId?, createdAt) + `MediaFile` (id, folderId?, name, url, size, mimeType, uploadedById, createdAt)
|
||||
- Папки автоматически создаются по курсам + «Common» для общих файлов
|
||||
- Вид: грид (карточки с иконкой типа) или список — переключатель
|
||||
- Breadcrumb-навигация: Все файлы / Название папки
|
||||
- Загрузка файлов (PDF, изображения, любые) → Object Storage
|
||||
- Создание папки вручную
|
||||
- Клик на файл → диалог: имя (редактируемое), дата загрузки, размер, автор
|
||||
- Действия в диалоге: скопировать ссылку, скачать, удалить
|
||||
- Вставка файлов из медиатеки в урок (вместо повторной загрузки)
|
||||
|
||||
- **Цифровой сад** — публичный раздел платформы для сообщества:
|
||||
- Методические материалы и статьи (PKM, Obsidian, Second Brain)
|
||||
- Рекомендованная литература с аннотациями
|
||||
- Записи открытых встреч и вебинаров
|
||||
- Календарь: предстоящие открытые уроки, запуски курсов, события
|
||||
- Возможно: публичный Obsidian-like граф знаний
|
||||
|
||||
Reference in New Issue
Block a user