Files
Learn_System/plans/my-materials/PLAN.md
T
Maxim Dolgolyov fd3e5c47e8 feat(materials): Фаза 1 — правка, переименование, создание заметки
- PATCH /api/materials/:id (title, body) с проверкой владельца (@public-by-design) + LS.updateMaterial.
- /my-materials: кнопка «+ Заметка» (личный блокнот с нуля), «Изменить» на карточках
  (заголовок; для заметок — и текст) через LS.modal.
- Добавлен план развития «Мои материалы»: plans/my-materials/PLAN.md (6 фаз).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 11:55:15 +03:00

9.0 KiB

План развития «Мои материалы»

Составлен Opus 2026-06-04. Базис уже есть: student_materials(kind board|note|link|image, title, body, url, source_session_id, source_title, created_at), API /api/materials (GET/POST/DELETE) + LS.listMaterials/saveMaterial/deleteMaterial, страница /my-materials, модуль /js/board-clip.js (сохранение страницы/фрагмента доски), сохранение из my-lessons.html и живого урока classroom.html. См. reference_student_materials.

Следующая миграция: 061. Готчи: новый :id-роут → пометить // @public-by-design (route-auth lint); большие HTML-файлы — только Edit; без эмодзи; коммит поимённо + push; перезапуск сервера при правке backend.


Фаза 1 — Переименование, правка, создание заметки (S, фундамент)

Базовые операции над материалом + личный блокнот.

  • Backend: PATCH /api/materials/:id (поля: title, body, collection_id, tags) с проверкой владельца; пометить @public-by-design. Хелпер LS.updateMaterial(id, data).
  • Frontend /my-materials: инлайн-правка заголовка; модалка правки текста заметки; кнопка «+ Заметка» (создать заметку с нуля → POST kind='note'). Карточкам — меню (правка/удалить).
  • Зависимостей нет. Делается первым.

Фаза 2 — Коллекции (папки) + поиск/фильтры (M, организация)

Решение: коллекции (папки) как основной примитив + свободный поиск + фильтр по типу. Теги — опциональный стретч (поле tags TEXT, чипы), если понадобится.

  • Миграция 061: material_collections(id, user_id, name, color, sort_order, created_at) + ALTER student_materials ADD COLUMN collection_id INTEGER REFERENCES material_collections(id) ON DELETE SET NULL (+ опц. ADD COLUMN tags TEXT).
  • Backend: CRUD коллекций GET/POST/PATCH/DELETE /api/materials/collections; перенос материала — через PATCH /api/materials/:id {collection_id}; список GET /api/materials?collection=ID.
  • Frontend: слева/сверху список коллекций (создать/переименовать/цвет/удалить), «Переместить в…» на карточке, фильтр по коллекции + поиск по тексту + фильтр по типу (клиент, данных немного).
  • Делается после Ф1 (нужна перед «универсальным буфером», иначе всё свалится в одну кучу).

Фаза 3 — Универсальный буфер «Сохранить к себе» (M–L, стратегически)

Кнопка «В мои материалы» по всей платформе. Общий клиентский модуль + поэтапная разводка по источникам.

  • Модуль /js/material-save.js: MaterialSave.note({title,body,...}), .link({title,url}), .image({title,blobOrUrl}), и MaterialSave.button(opts) (готовая кнопка). Поверх LS.saveMaterial. Везде проставлять source_title (откуда сохранено).
  • Источники (по убыванию ценности, разводить инкрементально):
    1. Учебник (/textbook/...): «В мои материалы» на § → kind='link' (/textbook/slug#sec-pN), на рисунок/ выделенный фрагмент → kind='image'/'note'.
    2. Экзамен (exam-prep): сохранить задачу+решение → kind='note' (html в body) или 'link' на задачу.
    3. Лаборатория/симуляция, флешкарты, вложения чата урока → link/image.
  • Kinds: переиспользуем существующие (note/link/image), чтобы не трогать CHECK. Новый kind — только при явной нужде (тогда миграция-пересборка CHECK).
  • Делать: модуль + 2–3 топ-источника (учебник, экзамен, ссылка) в первой итерации; остальное — добивать.

Фаза 4 — Редактирование и аннотации (M, синергия с SVG-рисовалкой)

Рисовать поверх сохранённого изображения и создавать рисунки.

  • /js/svg-draw.js: добавить opts.bgImage (рисунок-подложка) + при экспорте компоновать подложку + вектор в один PNG (offscreen canvas).
  • Frontend /my-materials: на image-карточке «Аннотировать» → модалка SvgDraw(bgImage=url) → сохранить как НОВЫЙ материал (kind='image'). Кнопка «Создать рисунок» (пустой холст → image).
  • Подпись/комментарий к материалу — уже покрывается правкой title/body из Ф1.
  • Зависит от Ф1 (правка) и существующих svg-draw.js/svg-sanitize.js.

Фаза 5 — Учебная интеграция (M)

Превратить материал в инструмент повторения.

  • «В флешкарты»: из заметки создать карточку (front=title, back=body) в выбранной/личной колоде — через существующий API флешкард (decks/cards). Из image — карточка с картинкой.
  • «Учить из материалов»: лёгкий режим перелистывания заметок/карточек.
  • (Полноценный SRS — отдельная инициатива из экзамена; здесь не блокер.)
  • Зависит от API флешкард (проверить контракт).

Фаза 6 — Учитель: своя коллекция + «раздатка» (S + M–L)

  • 6a (S): своя коллекция учителю. Подключить board-clip.js в lesson-history.html (страница учителя) → кнопки «Область»/«К себе» учителю. Раздел «Мои материалы» уже user-agnostic (показать пункт сайдбара и учителю). Быстрый вин, можно сделать рано.
  • 6b (M–L): «Раздатка» — отправить материал ученику/классу.
    • Модель: копия при отправке (проще и согласуется с «у каждого своя копия»): POST /api/materials/:id/share {classId|userId} → вставляет копию в student_materials получателям (source_title='Раздатка: <учитель>'). Без новой таблицы шеринга. (Альтернатива — таблица material_shares со ссылкой; копия проще.)
    • Уведомление получателям через существующую систему (emit/notifications).
    • Frontend: на материале учителя «Раздать» → выбор класса/ученика.

Рекомендованный порядок

1 → 2 → 3 → 6a (быстрый вин) → 4 → 5 → 6b. Ф1 (правка/заметки) и Ф2 (коллекции+поиск) — фундамент; Ф3 (универсальный буфер) — главный стратегический шаг, но после Ф2 (иначе захламит); 6a дешёвый — можно вклинить рано; 4/5 — обогащение; 6b (раздатка) — крупное, в конце.

Сквозные риски / заметки

  • Хранилище: изображения идут в /api/files; универсальный буфер + раздатка-копии множат файлы — заложить (позже) учёт/лимиты/чистку.
  • Route-auth lint: новые :id-роуты (PATCH, share) пометить @public-by-design + проверка владельца.
  • CHECK kind: держимся в note/link/image, чтобы не пересобирать таблицу.
  • Тесты: добавить materials.test.js (CRUD + collections + share-копия + проверка владельца).
  • Разрешения: create-note/правка — любой авторизованный (свои); раздатка — teacher/admin.