Commit Graph
90 Commits
Author SHA1 Message Date
dev ddd49707ae feat(storage): S3-совместимое хранилище файлов (SeaweedFS/MinIO) и миграция uploads
- storage.js: абстракция хранилища с драйверами local и s3 (AWS SDK v3),
  ключи объектов совпадают с текущими путями /uploads/<файл>, поэтому схема БД
  и URL не меняются
- docker-compose.yml: сервис s3 (SeaweedFS, том s3-data, API только на loopback),
  переменные S3_*/STORAGE_*, restart unless-stopped для app и db
- docker-compose.minio.yml: оверрайд S3-сервиса на MinIO (образ из своего зеркала)
- server.js/worker.js: чтение и запись файлов только через storage (отдача
  /uploads/*, миниатюры, share-файлы, zip-отчёты, enhance/apply/rollback,
  photo-worker), автосоздание бакета, глобальная персистенция загрузок multer
- бэкап/восстановление и scripts/backup.sh, restore.sh — через scripts/storage-sync.js
- scripts/migrate-to-s3.js: идемпотентная миграция uploads/ в бакет
  (--dry-run, --verify-only, --delete-local)
- админка: блок «Хранилище» в системной информации
- .env.example, README.md, AGENTS.md: описание драйверов, переменных и перехода на S3
2026-09-26 11:08:53 +03:00
dev 8bf54fb95d feat(trash): deferred purge after configurable days, groups in trash 2026-09-24 13:11:31 +03:00
dev e6c69c8a78 feat(settings): option to show/hide camera button, preview click opens camera 2026-09-24 12:00:20 +03:00
dev e4704c2dc6 fix(index): paste fills only project files, photo stays webcam-only
- pasted images/files always go to "Файлы проекта", never to the entry photo
- drop the photo paste hint and the capturedName plumbing: the entry photo is
  captured from the camera only (submit still requires it)
- keep paste naming ("Вставка <date>.<ext>") and server-mirrored limits
2026-09-24 11:21:58 +03:00
dev a72600af13 feat(index): paste photos and project files from clipboard with Ctrl+V
- handle document paste: images become the entry photo when none is set,
  otherwise they land in "Файлы проекта" along with any other pasted files
- take file names from the clipboard, replace generic ones (image.png, blob)
  with "Вставка <date>.<ext>"; derive extension from MIME when missing
- validate client-side like the server: 10 files, 10 MB per file, 30 MB total,
  reject blocked extensions (*.html, *.js, *.svg, ...)
- share the limit logic between the picker and paste, send the photo under its
  real name so pasted PNG/JPEG keep their extension
- add Ctrl+V hints to the photo and files cards (hidden on touch devices)
2026-09-24 11:18:08 +03:00
dev 2e1d36bc4d chore(deploy): exclude generated version.json from deploy dirty check 2026-09-23 23:02:37 +03:00
dev d943b77f58 chore(deploy): bake commit version into image and add scripts/deploy.sh 2026-09-23 23:01:36 +03:00
dev 69d46a0e5f fix(backup): stream backup download via resumable token link instead of buffering
Формирование и скачивание бэкапа разделены: POST /api/backup собирает архив
на диске и возвращает временную ссылку, GET /api/backup/:token отдаёт его
через res.download (Content-Length, Accept-Ranges, 206 при докачке).

- больше нет fs.readFileSync всего архива и res.send буфера (~550 МБ RAM -> ~60 МБ)
- GET /api/backup сохранён для совместимости, тоже потоковый
- gzip level 1 (архив из JPEG почти не сжимается), чистка /tmp/wido-backups по TTL 30 мин
- settings.html/js: нативное скачивание браузером с прогрессом и докачкой,
  понятные ошибки вместо «Ошибка сети при формировании бэкапа»
2026-09-23 19:03:19 +03:00
dev 16aba3efb0 fix(settings): constrain logo preview size so it does not overflow the card 2026-09-23 16:56:31 +03:00
dev cb3f010cd9 fix(photo): preserve photo_jobs history in backup/restore; paginate photo history on worker page 2026-09-23 16:37:27 +03:00
dev 30cf04b0cf feat(branding): logo and system name on share and report pages, drop logo border-radius 2026-09-23 16:25:13 +03:00
dev f2d465e0c4 feat(branding): system name/logo, horizontal logo on all pages 2026-09-23 15:19:23 +03:00
dev e435b4ad43 feat(ui): show current commit version and date in admin sidebar 2026-09-23 14:14:29 +03:00
dev 4623358f21 feat(students): multi-photo gallery, group photos in export, KIBERone rebrand 2026-09-23 13:32:09 +03:00
dev 5e2533b876 feat(groups): assign tutor to group 2026-09-19 13:17:40 +03:00
dev 1ef81f9d1c wip: student profile/report 2026-09-19 13:06:21 +03:00
dev d7d4cc1133 feat(modules): soft delete with restore and active filter 2026-09-18 20:04:02 +03:00
dev d3dd922e32 feat(modules): batch module import in admin, module usage in journal 2026-09-18 19:36:32 +03:00
dev e6291a0235 feat(modules): module topics for student form, admin CRUD with pagination
- db: modules table (name, lessons_count) + entries.module_id (ON DELETE SET NULL), migration + idempotent startup ensure
- api: GET /api/modules (public, search + limit/offset, entries_count), POST/PUT/DELETE (admin, audit-logged)
- entries: accept/validate module_id on create/update, return module_name, module_id filter
- backup/restore: include modules and entries.module_id
- student form: required module select, hidden while no modules exist
- admin: modules.html + js/modules.js list with pagination, search, create/edit/delete modal
- journal: module filter, module select in edit modal, module badge, CSV column
2026-09-18 18:56:42 +03:00
dev d434732f41 feat(report): student report page with works/gallery/files sections 2026-09-18 17:50:50 +03:00
dev 12c612eccd feat(audit): translate photo job audit actions to Russian 2026-09-17 22:25:17 +03:00
dev 5874e2b619 feat: photo jobs apply/reject flow with applied flag in history
- DB: add photo_jobs.applied column (init + migration + ensure)
- Worker: generate preview only (after_path), no longer mutates entry
- New POST /api/entries/:id/photo/jobs/:jobId/apply — apply done job
  result to entry (backs up current photo, marks applied)
- New POST /api/entries/:id/photo/jobs/:jobId/reject — discard result,
  delete temp file, mark rejected
- saveEnhance: apply AI result directly when sliders are at defaults
- Photo history: '✓ Применить' action for unapplied done AI jobs;
  'rejected' status label
- sweepOrphanedUploads keeps done-not-applied preview files
2026-09-17 18:51:26 +03:00
dev 881b5b4c67 fix: repair photo worker broken code; add pending queue view
- Fix runAiEnhance missing return/closing brace from previous commit
- Remove duplicate code fragments in worker.js
- Add renderPhotoPending() to show pending/processing jobs in worker dashboard
- New pending queue table in worker.html photo section
2026-09-17 17:52:51 +03:00
dev 1145be02f3 feat: persistent photo job queue, worker, history with rollback
- Replace in-memory photoAiJobs Map with DB-backed photo_jobs table
- Background photo worker (worker.js) with retry, backoff, stale reset
  - Handles both AI (Real-ESRGAN) and server-side (sharp) enhancement
  - Controlled via photo_worker_enabled setting
- Photo job history in enhance modal with before/after thumbnails + rollback
- Worker dashboard: photo jobs section with status counts, recent table,
  compare slider for before/after, rollback from worker UI
- New endpoints: /api/photo-jobs/status|wake|enabled|requeue-failed,
  /api/entries/:id/photo/jobs (history), .../rollback
- swapEntryPhotoFiles logs every mutation to photo_jobs table
2026-09-17 17:36:56 +03:00
dev 27a2238082 feat: compare slider UI for photo enhance modal
- Side-by-side before/after comparison with draggable divider
- Zoom (scroll wheel) and pan when zoomed in, double-click to reset
- Sliders moved to sidebar panel, responsive layout
- Original/Result badges on the comparison view
- Helper functions: setEnhanceClip, showEnhanceResult, applyEnhanceTransform
2026-09-17 17:02:35 +03:00
dev dec8790a3a fix: AI photo enhance modal stays open with result preview; fix basicsr build
- Modal no longer auto-closes after Real-ESRGAN completes; result loads into
  canvas so user can review, adjust sliders, and choose to apply or discard
- Backend skips swapEntryPhotoFiles until user confirms via Применить
- New DELETE /api/entries/:id/photo/enhance-ai/preview for temp file cleanup
- photo-ai Dockerfile: patch basicsr via find+sed instead of import (avoids
  torchvision.functional_tensor import crash)
2026-09-17 16:44:44 +03:00
dev 3a345cbefd feat: AI photo enhancement (Real-ESRGAN container) + restore original
- new photo-ai service: FastAPI + Real-ESRGAN x2plus on CPU, internal only
- async job queue in server (POST enhance-ai / GET status), 5min timeout, sequential processing
- keep original photo backup (entries.photo_original_path, uploads/.originals), restore-original endpoint
- UI: AI button and restore-original button in enhance modal
- db: photo_original_path column (init.sql, migration.sql, runtime ensure)
2026-09-17 15:37:49 +03:00
dev c4fd31cd53 feat: hybrid photo enhance engine (server sharp + client canvas), denoise
- enhance endpoint accepts JSON params, processes original on disk via sharp pipeline (median, modulate, linear, sharpen, mozjpeg)
- client fallback renders full-size canvas, keeps multipart path
- engine selection setting: auto/server/client, auto falls back to client on error/timeout
- denoise slider (median filter), noise-aware auto mode, preview capped at 1600px
2026-09-17 15:16:42 +03:00
dev 049df61e55 feat: photo quality improvements
- webcam capture resolution/quality configurable in admin settings (defaults 640x480 / 0.92)
- enhance photo modal in journal: original vs preview with sliders (brightness, contrast, saturation, sharpen) and auto-levels button
- new endpoint PUT /api/entries/:id/photo/enhance replaces photo, cleans old file and thumb
- sharper HEIC conversion (0.92) and webp thumbnails (85)
- worker: fail explicitly on empty AI response
2026-09-17 15:07:43 +03:00
dev 57e48a9d4f fix(ai): adaptive max_tokens per backend (reasoning profiles get 1024+, native llama.cpp stays compact; per-profile max_tokens override); include entry texts in ai_status SSE notify so journal updates live without reload; audit log action filter; links pagination; settings validation & UI improvements 2026-09-17 14:12:36 +03:00
dev a93e37a6b1 fix(settings): prevent aiActiveProfile select from overflowing card-foot (shrinkable label+select, min-width:0 on grid cards) 2026-09-17 12:11:18 +03:00
dev 66f7fdc1a8 refactor(settings): AI profile add/edit moved into a modal dialog (overlay click + Esc to close) 2026-09-17 12:00:19 +03:00
dev d7c793c67a fix(settings): constrain aiActiveProfile select width so it stays inside card-foot 2026-09-17 11:58:34 +03:00
dev efe2a42d1d feat(settings): AI model profiles management — native llama.cpp + custom OpenAI-compatible providers, default model selection, connection test 2026-09-17 11:54:08 +03:00
dev bbfde902a5 feat(journal): live AI status updates in entry cards via Postgres NOTIFY trigger + SSE ai_status events 2026-09-17 11:14:27 +03:00
dev cc9a9e6c2d feat(journal): beautiful entrance animation for entries — cascade fade-up on load, yellow glow pop for newly submitted entries 2026-09-16 20:14:09 +03:00
dev 2784084c68 feat(journal): live updates on new entry via SSE (/api/events) — admin journal auto-refreshes when a student submits 2026-09-16 20:09:06 +03:00
dev e8337c2845 feat(share): group entries by date on public /s/<token> page 2026-09-16 15:06:30 +03:00
dev 2c8beedc4b feat: анти-спам блокировка повторной отправки на главной (cooldown по spam_interval_min)
- index.html/index.js: экран подтверждения отправки с обратным отсчётом
- локальный запрет повторной отправки через localStorage (по настройке spam_interval_min)
- server.js: отдаём spam_interval_min в public-settings (default 30)
- Dockerfile: timeout для apk add, чтобы сборка не зависала на недоступном зеркале
- docker-compose.yml: отключаем cloudflared сервис (закомментирован)
2026-09-13 12:27:35 +03:00
dev fac668567e feat: редизайн страницы отчёта ученика — портфолио-стиль, галерея с листанием и видео
- renderStudentReport: детский учебный дизайн (крупные скругления, sticky-навигация, секции-карточки)

- журнал занятий в две колонки (одна на мобильных)

- единая галерея фото и видео: листание кнопками/стрелками, счётчик

- воспроизведение видео прямо в лайтбоксе

- кнопка закрытия ✕, закрытие по фону и Esc

- модалка экспорта отчёта ученика (период и выбор содержимого)
2026-09-12 23:55:35 +03:00
dev b263a735ac fix: обязательная фотография в форме отправки; модалка редактирования шире и в две колонки; поддержка .jfif в прикреплении 2026-09-12 17:19:53 +03:00
dev 779270fb73 UI: пагинация, вынос пагинатора, быстрые действия 2026-09-12 14:18:15 +03:00
dev 1d706f1356 Dashboard: add Блокировки link to navigation 2026-09-12 12:52:23 +03:00
dev fd753c1318 Add cookie notice with settings, jfif preview support, and share page title from link name 2026-09-12 10:05:02 +03:00
dev 192de5e690 Sidebar: color inactive nav icons by section meaning via data-nav attribute 2026-09-12 01:18:57 +03:00
dev 809b978c4b Bans: confirm unban via alert; audit labels for ip.ban/ip.unban; worker page lucide icons 2026-09-12 01:14:58 +03:00
dev c54a5b180c Settings bans card: unban also requires confirmation 2026-09-12 01:06:24 +03:00
dev e69426882a Bans: unban requires inline confirmation row with yes/cancel 2026-09-12 01:01:59 +03:00
dev 5aee2ce3f5 Bans page: users-style table with badges, client-side pagination, manual ban modal (POST /api/bans with ip/reason/hours), unban row buttons 2026-09-12 00:59:32 +03:00
dev 7dd816cfce Add dedicated Bans page (bans.html) with active IP bans table, unban and refresh; nav item for admins; settings card kept 2026-09-12 00:53:35 +03:00