Commit Graph

9 Commits

Author SHA1 Message Date
Maxim Dolgolyov 9bd40c5d1c feat(flashcards): общие колоды — учитель назначает колоду классу/ученику
Учитель делится своей колодой с классом или конкретными учениками; карты общие
(одна копия), а прогресс у каждого свой — flashcard_reviews уже keyed по
user_id+card_id, поэтому ученик копит собственные интервалы на тех же картах.

- миграция 075: flashcard_deck_access (deck_id, type class|user, target_id) —
  зеркало folder_access; индексы по target и deck.
- deckAccess(): владелец/админ (canEdit) либо назначенный напрямую/через класс
  (canRead). listDecks отдаёт свои + назначенные (shared/can_edit/owner_name);
  getCards/getStudySession/submitReview пускают по canRead (ученик учится и
  ставит отзыв), правка карт/колоды — только владелец.
- share API (owner + роль teacher/admin): GET /shares, POST /share, DELETE
  /share?type=&target_id=; цель валидируется (свой класс / свой ученик).
- фронт: общие колоды с бейджем учителя, открываются read-only (CSS .readonly
  прячет ручки/удаление/правку, drag и inline-edit выключены), кнопка
  «Поделиться» с модалкой (вкладки Классы/Ученики, тоггл = add/remove share).
- тест flashcards-share 13/13 (шаринг класс/ученик, видимость, изучение+отзыв,
  правка 404, доступ 404, роль-гейт 403, чужой класс 403, снятие доступа).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 13:30:53 +03:00
Maxim Dolgolyov 5c01a5c7ed feat(flashcards): learning-steps SR — повторный показ «Снова» в сессии, лимит новых карт/день
Tier-1 апгрейд интервального повторения:
- schedule() с состояниями learning/relearning/review вместо плоского sm2():
  новая карта проходит шаги [1,10] мин, «Снова» возвращает на шаг 0 (минуты),
  «Знаю» продвигает шаг → выпуск (1д), «Легко» выпускает сразу (4д); зрелая
  «Снова» = lapse → relearning (ef−0.2, ×0.5).
- study-сессия: динамическая очередь — недоученная карта (graduated=false)
  возвращается через 3 карты и показывается снова в той же сессии.
- лимит новых карт/день (decks.new_per_day, деф.20) в getStudySession и бейдже.
- превью кнопок fcPreview() показывает минуты/дни, зеркало серверной логики.
- миграция 074: state/learning_step/lapses/created_at + new_per_day + индексы.
- тесты SRS 9/9 (шаги, lapse, лимит новых).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 13:10:00 +03:00
Maxim Dolgolyov ad7265d553 feat(flashcards): Anki-стиль интервалов — кнопки различаются
Раньше на новой карте Снова/Трудно/Знаю/Легко все давали 1 день (чистый SM-2:
оценка влияла только на ease factor). Теперь интервал зависит от оценки:
новая карта Легко=4д (остальные 1д), на повторах Трудно ×1.2 / Знаю ×ef /
Легко ×ef×1.3 (easy-бонус). Серверный sm2() и клиентское превью fcNextInterval
синхронны — проверено 0 расхождений на 256 комбинациях.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 23:27:40 +03:00
Maxim Dolgolyov 51e5dc29e1 feat(flashcards): картинки в массовом импорте «Добавить список»
- модалка в 2 шага: текст -> предпросмотр карточек, к каждой стороне
  можно прикрепить картинку перед импортом
- addCardsBulk принимает front_image/back_image (через safeImg) и теперь
  санитизит front/back (stripTags) — раньше bulk пропускал теги
- общий ensureImgPicker() переиспользуется редактором и предпросмотром

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 13:14:13 +03:00
Maxim Dolgolyov 3d627ce782 feat(flashcards): картинки на карточках (загрузка, вставка, рендер)
- Миграция 048: колонки front_image/back_image в flashcard_cards
- Бэкенд: POST /api/flashcards/upload (multer, 5МБ, только изображения),
  валидатор safeImg (только /uploads/flashcards/..., блок XSS/traversal/external),
  картинки в add/update/quick/study/random; статик-маунт /uploads/flashcards
- Редактор: превью+кнопка загрузки+вставка (Ctrl+V) на каждую сторону,
  картинки к ещё не созданной карточке через add-bar
- Режим изучения: рендер изображения над текстом на обеих сторонах
- FAB: вставка картинки в быструю карточку

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 12:58:24 +03:00
Maxim Dolgolyov 29301ff87d feat(flashcards): фаза 1 полировки — хоткеи, поиск, drag-reorder, честные интервалы
- study: хоткеи Space/стрелки=флип, 1-4/←→=оценка
- превью интервалов = точная копия серверного SM-2 (было враньё «<1 мин»)
- поиск/фильтр карточек внутри колоды
- drag-reorder карточек + endpoint PUT /decks/:id/reorder (requireOwnership)
- flashcard_decks добавлен в ALLOWED_TABLES requireOwnership
- эмодзи в empty-state → inline SVG .ic
- deleteCard: нативный confirm() → LS.confirm

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 09:53:03 +03:00
Maxim Dolgolyov 1dcc4cbf6e feat(flashcards): глобальный quick-add FAB + виджет «повтори карточку»
Backend:
- POST /api/flashcards/quick — добавить карточку из любой точки; колода по
  выбору или автоколода «Быстрые карточки» (создаётся при первом обращении)
- GET /api/flashcards/random — случайная карточка из всего пула пользователя

Frontend:
- /js/flashcard-fab.js — плавающая кнопка «запомнить» на всех страницах
  (учебник, лаборатория, симуляция…). Поповер: вопрос/ответ/колода, Ctrl+Enter.
  Гейт по фиче-флагу flashcards; исключены classroom/login/error/сама /flashcards.
  Загружается лениво из sidebar.js (на 45 страницах с шапкой).
- dashboard: виджет #w-flashcard в колонке прогресса — флип-карта (вопрос↔ответ),
  кнопка «Другая», счётчик пула, CTA при пустом пуле; слушает событие
  flashcard:added для авто-обновления.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 09:38:23 +03:00
Maxim Dolgolyov 3a4623a60a fix: полное ревью системы — 15 исправлений безопасности и надёжности
Безопасность:
- tests/🆔 скрыть is_correct и explanation для студентов (P0)
- SQL injection: limit/offset через placeholder вместо template literal
- Stored XSS: stripTags для lesson comments, flashcards, redBook sightings
- profile.html: escape e.message в showMsg (XSS через server error)
- attachment_url: валидация только /uploads/* путей
- requestId: генерировать UUID сервером, не доверять клиенту
- register: скрыть token_version из ответа

Надёжность:
- register: обработка UNIQUE constraint race condition
- pet buyBg: re-check баланса внутри транзакции
- DB errors: скрыть e.message в testController/questionController/courseController
- preferences: лимит 50KB на размер JSON

UX:
- board.html: debounce 250ms на search input

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 10:59:19 +03:00
Maxim Dolgolyov be4d43105e LearnSpace: full-stack educational whiteboard platform
Node.js/Express backend + vanilla JS frontend.
Features: real-time collaborative whiteboard (SSE), multi-page support,
LaTeX formulas, shapes/connectors, coordinate systems, number lines,
compass, zoom/pan, Catmull-Rom pencil smoothing, ruler/protractor with
rotation & resize controls, minimap navigation overlay, auto-measurements,
multi-page thumbnails sidebar, PNG export, page templates.
Student/teacher workflows: classes, assignments, library, dashboard.
Mobile responsive. SQLite (better-sqlite3).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 10:10:37 +03:00