Files
lms-sb/ROADMAP.md
T
admins c647b29712 Add Markdown import from Obsidian (Stage 8)
- md-to-tiptap.ts: remark-based converter (headings, lists, blockquotes,
  code blocks, bold/italic/strike, links, images, hr)
- Obsidian ![[wikilink]] stripped, [[link|alias]] → plain text
- POST /api/admin/import-md: parses frontmatter (gray-matter) + converts content
- LessonEditor: "Импорт .md" button populates editor without auto-save
- ROADMAP: marked Stages 2, 3, 5, 6, 7, 8 as complete, fixed numbering

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 15:44:42 +05:00

167 lines
11 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.
# ROADMAP — LMS Second Brain
**Стек:** Next.js 16.2.2 · React 19 · PostgreSQL 16 · Prisma 7 · Better Auth 1.6 · Tailwind v4 · shadcn/ui · TipTap · Kinescope · Resend · Hetzner Object Storage
**Принцип:** один этап — одна рабочая фича. Не переходим к следующему, пока текущий не работает end-to-end.
---
## Этап 0 — Каркас, auth, роли ✅ ЗАВЕРШЁН (07.04.2026)
- [x] Next.js 16.2.2 (App Router, TypeScript, Tailwind v4)
- [x] Docker Compose: PostgreSQL 16 (прод на Hetzner)
- [x] Prisma 7: схема User, Session, Account + полная LMS-модель
- [x] Better Auth: вход по email/password, роли student/curator/admin
- [x] Middleware: защита маршрутов по сессии
- [x] Дашборды для трёх ролей
- [x] Страница входа, регистрации, подтверждения email
- [x] Seed: admin/curator/student (пароль: Password123!)
- [x] Dockerfile multi-stage + docker-compose.prod.yml
- [x] Caddy: school.second-brain.ru → порт 3010
---
## Этап 1 — Курсы → Модули → Уроки (CRUD в админке) ✅ ЗАВЕРШЁН (07.04.2026)
- [x] Prisma-схема: Course, Module, Lesson (с порядком, статусом published)
- [x] Admin: список курсов, создать / редактировать / удалить курс
- [x] Admin: список модулей внутри курса, drag-and-drop сортировка
- [x] Admin: список уроков внутри модуля, drag-and-drop сортировка
- [x] Admin: редактор урока с TipTap (заголовки, списки, цитаты, код, картинки, ссылки)
- [x] Загрузка картинок в уроке → Hetzner Object Storage
- [x] Поле для Kinescope ID в уроке
- [x] Публикация/скрытие курса и урока (черновик / опубликован)
- [x] Управление доступом: выдать / забрать доступ к курсу для пользователя
- [x] Дизайн: Fira Mono, #F5F5F0, Aubade-карточки
- [x] Admin: таблица пользователей (/admin/users)
---
## Этап 1.5 — Расширенное управление доступом ✅ ЗАВЕРШЁН (07.04.2026)
- [x] Срок доступа: `expiresAt` в `CourseEnrollment`, просроченный подсвечивается красным
- [x] Категории курсов: таблица `Category`, `/admin/categories`, привязка к курсу
- [x] Расширенный энролл: `/admin/users/[userId]` — выбор нескольких курсов + срок одной операцией
- [x] История доступа: `AccessLog` — каждая операция логируется (кто, когда, метод, примечание)
---
## Этап 2 — Интеграция Kinescope, рендер уроков для ученика ✅ ЗАВЕРШЁН (07.04.2026)
- [x] Компонент `KinescopePlayer` — обёртка над `@kinescope/react-kinescope-player`
- [x] Рендер урока для ученика: видео (если есть Kinescope ID) + текст + файлы
- [x] Загрузка PDF/файлов к уроку (Object Storage), список для скачивания
- [x] Страница курса для ученика: список модулей и уроков, статус прохождения
- [x] Навигация по урокам: предыдущий / следующий
- [x] Блокировка доступа к курсу без enrollment (layout server component)
- [x] Страница «Мои курсы» в личном кабинете ученика (dashboard)
- [x] Кнопки Сохранить / Просмотр в редакторе урока
- [x] Иконка-статус уроков в боковой панели курса (✓ пройден)
---
## Этап 3 — Прогресс ✅ ЗАВЕРШЁН (07.04.2026)
- [x] Prisma: таблица `LessonProgress` (userId, lessonId, completedAt)
- [x] Кнопка «Урок завершён» — создаёт/удаляет запись в LessonProgress
- [x] Прогресс-бар по курсу в боковой панели (% завершённых уроков)
- [x] Прогресс-бар по курсу на дашборде студента
- [x] Admin bypass: администратор видит все уроки без отметок о прогрессе
---
## Этап 5 — Домашние задания и обратная связь куратора ✅ ЗАВЕРШЁН (07.04.2026)
- [x] Prisma: Homework, HomeworkSubmission, HomeworkFeedback
- [x] Admin: добавить / редактировать / удалить блок ДЗ к уроку (HomeworkEditor)
- [x] Ученик: форма отправки ДЗ (текст + файлы → Object Storage)
- [x] Ученик: видит статус ДЗ и фидбек куратора в карточке урока
- [x] Куратор / Admin: список ДЗ на проверку (`/curator/homework`)
- [x] Куратор / Admin: просмотр работы, текстовый комментарий с обратной связью
- [x] Admin: AdminShell на `/curator/*` маршрутах (сайдбар не пропадает)
- [x] Admin: реальная статистика на дашборде (студенты, курсы, ДЗ, прогресс)
---
## Этап 6 — Обсуждения под уроками ✅ ЗАВЕРШЁН (07.04.2026)
- [x] Prisma: LessonComment (soft-delete через поле `deleted`)
- [x] Рендер списка комментариев под уроком (server-fetched, client-rendered)
- [x] Форма отправки комментария (только для enrolled учеников и admin)
- [x] Модерация: автор, куратор или admin может удалить комментарий
- [x] Счётчик активных комментариев в заголовке секции
---
## Этап 7 — Email-уведомления ✅ ЗАВЕРШЁН (07.04.2026)
- [x] Базовый HTML email-шаблон (фирменный стиль Second Brain)
- [x] Приветственное письмо при регистрации (`databaseHooks.user.create.after`)
- [x] Письмо ученику об открытии доступа к курсу
- [x] Куратор / Admin: уведомление о новом ДЗ на проверку
- [x] Ученик: уведомление о полученном фидбеке
- [x] Resend domain: mailsend.second-brain.ru (verified)
---
## Этап 8 — Импорт уроков из Markdown (Obsidian) ✅ ЗАВЕРШЁН (07.04.2026)
- [x] API: `POST /api/admin/import-md` — принимает .md-файл
- [x] Парсинг frontmatter (title, kinescopeId, order, published) через `gray-matter`
- [x] Конвертация Markdown → TipTap JSON через `unified` + `remark-parse`
- [x] Поддержка: заголовки, параграфы, жирный/курсив/зачёркнутый, инлайн-код, блоки кода, цитаты, списки, ссылки, изображения (HTTP), горизонтальные разделители
- [x] Очистка Obsidian-синтаксиса: `![[image]]` удаляется, `[[link|alias]]` → текст
- [x] UI: кнопка «Импорт .md» в редакторе урока — заполняет форму без автосохранения
---
## Этап 9 — Миграция с emdesell ← СЛЕДУЮЩИЙ
**Цель:** все пользователи и контент перенесены в новую LMS.
- [ ] Скрипт импорта пользователей из CSV-экспорта emdesell (email, имя, курсы)
- [ ] Создание пользователей без пароля + письмо «установите пароль»
- [ ] Назначение доступов к курсам по данным из CSV
- [ ] Чек-лист ручного переноса контента (уроки, PDF, структура курсов)
- [ ] Скрипт проверки целостности: все enrolled пользователи имеют доступ к нужным курсам
- [ ] QA: проверить 10 случайных аккаунтов после импорта
**Критерий готовности:** все ученики из emdesell могут войти в новую LMS и продолжить обучение.
---
## Этап 10 — Telegram-бот и аналитика
**Цель:** получаю уведомления в Telegram, вижу базовую аналитику.
- [ ] Telegram-бот: уведомление куратору/админу о новом ДЗ
- [ ] Telegram-бот: уведомление об ошибках (500-е, failed email и т.д.)
- [ ] Yandex.Metrika: базовое подключение (pageviews)
- [ ] Admin: простая страница аналитики (активные ученики, прогресс по курсам)
---
## Этап 11 — Тесты и квизы
**Цель:** можно добавить тест к уроку, ученик проходит и получает результат.
- [ ] Prisma: Quiz, QuizQuestion, QuizOption, QuizAttempt (схема уже есть)
- [ ] Admin: создание теста к уроку (вопрос → варианты → отметить правильный)
- [ ] Типы вопросов: одиночный выбор, множественный выбор, короткий текст
- [ ] Рендер теста в уроке для ученика
- [ ] Авто-проверка (single/multiple choice), результат сразу
- [ ] Настройка: показывать правильные ответы после прохождения (да/нет)
- [ ] Интеграция с прогрессом: урок с тестом засчитан только после прохождения теста
**Критерий готовности:** добавляю тест из 3 вопросов к уроку, ученик проходит, видит результат, урок засчитывается.
---
## Бэклог (после MVP)
- Резервное копирование PostgreSQL (cron → Object Storage)
- GitHub Actions: CI/CD pipeline (lint → build → push Docker image → deploy)
- Сертификаты по окончании курса
- Геймификация (баллы, бейджи, рейтинги)
- Промокоды и интеграция с платёжными системами
- Дедлайны и расписания
- Kinescope DRM (signed URLs) — при переходе на платный план
- Водяные знаки на PDF и картинках
- Мобильное приложение