feat(materials): серверные миниатюры (sharp) + пагинация рендера списка
Миниатюры: uploadPersonalFile генерирует webp ≤480px (sharp), возвращает {url, thumbUrl}; колонка thumb_url (мигр.074); грид рисует <img> на миниатюре, просмотр/скачивание/аннотация — полный url. Ссылочная чистка матчит url И thumb_url; share копирует thumb; квота учитывает файл+миниатюру. Сейверы board-clip/material-save/textbook-clip/draw пробрасывают thumbUrl.
Пагинация: клиент рендерит PAGE_SIZE=60 карточек + «Показать ещё» (сброс на смену фильтра), сохраняя клиентский поиск/сортировку над полным списком.
Тесты: materials.test.js 16→19. План V2 выполнен.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,12 +27,17 @@
|
||||
4. **`backend/tests/materials.test.js`** — CRUD, владелец (403/404), коллекции, share-копия + роль/owner,
|
||||
валидация URL, лимит числа, ссылочная чистка (прямой вызов хелпера на временном файле).
|
||||
|
||||
## Фаза 2 — Производительность ✅ (частично)
|
||||
## Фаза 2 — Производительность ✅
|
||||
- ✅ `GET /api/materials` отдаёт **обрезанный** `body` (первые 1000 симв.) + флаг `body_trunc`; полный текст —
|
||||
ленивый `GET /api/materials/:id` (`getOne`, owner-only). Клиент `ensureFullBody()` подгружает перед
|
||||
просмотром/правкой/флешкартой (иначе правка сохранила бы усечённый текст).
|
||||
- ⬜ Пагинация/keyset — отложено (клиент пока фильтрует в памяти; включить при росте объёмов).
|
||||
- ⬜ Серверные миниатюры `board/image` — отложено (нужна обработка картинок; пока `loading=lazy`).
|
||||
- ✅ Пагинация рендера: клиент держит весь список (поиск/фильтр/сортировка в памяти), но в DOM рисует
|
||||
`PAGE_SIZE=60` карточек + «Показать ещё»; `_shown` сбрасывается на смену фильтра. Снимает стоимость
|
||||
рендера тысяч узлов, не ломая клиентский поиск (keyset на сервере не нужен на текущих объёмах).
|
||||
- ✅ Серверные миниатюры `board/image`: `uploadPersonalFile` (sharp → webp ≤480px) возвращает `{url, thumbUrl}`;
|
||||
колонка `thumb_url` (мигр. **074**); грид рисует `<img src=thumb_url||url>`, просмотр/скачивание/аннотация —
|
||||
полный `url`. Чистится по ссылкам (releaseFileForUrl теперь матчит url **и** thumb_url); share копирует thumb;
|
||||
квота считает файл+миниатюру. Клиентские сейверы (board-clip/material-save/textbook-clip/draw) пробрасывают `thumbUrl`.
|
||||
|
||||
## Фаза 3 — Доводка заложенных фич ✅
|
||||
- ✅ UI тегов: ввод в модалках создания/правки + чипы на карточке (клик → фильтр) + пилюля активного фильтра.
|
||||
@@ -45,10 +50,11 @@
|
||||
- ✅ Множественный выбор (чекбокс на карточке) + панель массовых действий (переместить/удалить, reuse per-item API).
|
||||
- ✅ Живое превью KaTeX в редакторе заметки (oninput → `mmPreview` → `mathHtml`).
|
||||
|
||||
### Статус
|
||||
Сделано и проверено: **Ф1 целиком** (16 backend-тестов), **Ф2/Ф3/Ф4 ✅** (headless-смоук `my-materials.html`:
|
||||
синтаксис + рендер карточек с deep-link/тегами/чекбоксом + фильтр по тегу + bulk-bar + тинт папки).
|
||||
Осталось ⬜ (инфра, отложено): пагинация/keyset списка, серверные миниатюры board/image.
|
||||
### Статус — ПЛАН V2 ВЫПОЛНЕН
|
||||
**Ф1–Ф4 ✅.** Backend: 19 тестов `materials.test.js` (CRUD/владелец/коллекции/share/URL-allowlist/квота/
|
||||
ссылочная чистка url+thumb/round-trip thumb_url). Frontend: headless-смоук `my-materials.html` (синтаксис +
|
||||
deep-link/теги/чекбокс/bulk/тинт папки + `<img>` на thumb_url + пагинация «Показать ещё»). sharp-пайплайн и
|
||||
client-сейверы (board-clip/material-save/textbook-clip) проверены. Открытого из плана не осталось.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user