44 Commits
Author SHA1 Message Date
dev 2363d099d2 feat(lesson-ai): новый шаблон промпта + предупреждение о дубле отчёта
- заменён дефолтный промпт редактуры отчёта о занятии на формат
  «сообщение тьютора»: связный текст от 3-го лица, 1 абзац 2–4
  предложения, начало «На занятии ребята …», практика «В конце занятия …»,
  без группы/даты/времени и markdown, обращение на «вы» убрано, «они» → «каждый»
- синхронизированы три копии промпта: LESSON_AI_DEFAULT_PROMPT в server.js
  и сид lesson_ai_prompt в db/init.sql и db/migration.sql; добавлен пример
  «плохо → хорошо» с запретом переносить факты примера
- дубль отчёта в модалке создания больше не автозаполняет форму: показывается
  баннер #lessonDup с кнопкой перехода к существующему отчёту
- проверка на дубль срабатывает и при смене даты (#lessonDate), защищена
  счётчиком поколений lessonDupSeq от гонки при быстрой смене группы/даты
- стили .lesson-dup в public/admin.css, уточнена подсказка в карточке
  шаблона отчёта на public/settings.html
- DDL не менялся: ни таблиц, ни колонок, ни индексов
2026-10-04 00:54:23 +03:00
dev b931c0a760 feat(lesson-ai): проверка отчёта о занятии по шаблону + история версий
Галочка «Проверить по шаблону» в окне отчёта отправляет текст модели:
совпал с шаблоном — остаётся как есть (skipped), не совпал — переписывается
в деловом виде (done). Обработка идёт в фоне, HTTP-запрос не ждёт модель,
оригинал тьютора сохраняется в text_original.

- схема: text_original/text_ai/ai_status/ai_checked_at/ai_error в
  lesson_reports, таблица lesson_report_versions, ensureLessonReportsTable()
- настройки lesson_ai_enabled и lesson_ai_prompt (раздел sec-lesson-ai),
  значения только 'true'/'false'
- worker.js: createLessonReportChecker (FOR UPDATE OF lr SKIP LOCKED,
  до 3 попыток), хук назовён notifyEvent — notify в createPhotoEnhanceWorker
  уже занят будильником
- server.js: wakeLessonAiWorker, onLessonAiDone (версия, аудит с diff,
  уведомление lesson.ai.formatted, SSE lesson_report_status), маршруты
  /versions, /versions/:id/restore и /ai/revert
- aiComplete вместо aiCorrectText: общий вызов модели с таймаутом
- бэкап/восстановление: lesson_reports и lesson_report_versions в payload
- фронтенд: openLessonVersions/restoreLessonVersion в admin.js, бейджи
  статусов в lessons.js, лейблы аудита, renderAuditPager
- docs: раздел 3d в AGENTS.md и Agent Workflow, пункт в README
- тесты: контракт lesson-report и настройки уведомления в api.smoketest.js
2026-10-04 00:12:24 +03:00
dev a84f33307e feat(lessons): отчёты о занятиях — таблица, CRUD, страница и блок на дашборде
Добавлена сущность «что прошли на занятии»:
- lesson_reports (init.sql + migration.sql + ensureLessonReportsTable)
- GET/POST /api/lesson-reports, PUT/DELETE /api/lesson-reports/:id
  с branchScope, уникальностью (group_id, lesson_date) и лимитом текста
- уведомление lesson.report (NOTIFY_TYPES + настройка + иконка)
- кэш-префикс lessons: + инвалидация stats:/dashboard:
- восстановление lesson_reports в normalizeRestoreData
- блок recent_lessons в /api/dashboard

Фронтенд:
- public/lessons.html + public/js/lessons.js — список с фильтрами и правкой
- openLessonModal в admin.js — общая модалка из журнала и дашборда
- кнопки в журнале и быстрые действия дашборда

Также исправлен сдвиг индексов параметров в notificationsScope —
$1 уходил повторно в список филиалов из-за params.push без смещения.
2026-10-03 23:33:45 +03:00
dev 2377707297 feat(students): аватары в списке студентов с превью и лайтбоксом
Круглый аватар слева от поля имени: миниатюра главного фото через thumbSrc, иначе инициалы. Клик по фото открывает imgModal с полным размером, клик по пустому — карточку профиля для загрузки. Аватар синхронизируется после загрузки, смены и удаления фото.
2026-10-03 21:33:25 +03:00
dev 70b0c7ae9b feat: env-driven upload limits + request timeout, inline video playback, range requests
- Add UPLOAD_FILE_LIMIT_MB/UPLOAD_TOTAL_LIMIT_MB env (defaults 50/200), compute request timeout from total limit or UPLOAD_REQUEST_TIMEOUT_MS
- Expose upload limits via /api/public-settings and sync in frontend (remove hardcoded 50MB assumption)
- Add byte-range support in storage (getRange/streamRangeTo) and serve Content-Range/Accept-Ranges for S3/local
- Implement inline playable video delivery for browser formats (mp4/m4v/webm/ogv) with ?play=1, range requests, proper 206/416
- Add video modal in journal UI with player and download fallback
- Update docs (AGENTS.md/PRD.md/README.md), styles for video modal, add instructions/TODO.md and screenshots
- Extend MIME types for media
2026-10-03 12:00:48 +03:00
dev 31542de33b feat(photos): раздел «Фото» — единая галерея всех загруженных фотографий
Новый read-only раздел для просмотра всех фотографий системы:
GET /api/photos собирает через UNION ALL пять источников — главное фото
записи, фото записи (entry_photos), фотохронику групп, фото учеников и фото
тем модулей. Фильтры search/student_name/group_id/date_from/date_to и
пагинация limit/offset, ответ { photos, total }. Не-admin ограничен
своими филиалами (branch_id), чужой group_id отдаёт 403.

Фронтенд: public/photos.html + public/js/photos.js — сетка превью
(/uploads/thumb/...), бейдж источника, описание, ученик/группа, дата,
ссылка на источник, lightbox по клику, поиск с debounce и пагинация.
Навигация: пункт «Фото» в сайдбаре и плитка в быстрых действиях дашборда.
2026-09-28 00:15:32 +03:00
dev 2afe676969 feat(notifications): центр уведомлений о системных событиях
Добавлена система уведомлений о системных и фоновых событиях (новые записи
журнала, обработка фото, авто-проверка текста, блокировки IP, бэкапы).

- backend (server.js, worker.js):
  - каталог NOTIFY_TYPES с метаданными и уровнями
  - таблицы notifications и notification_reads в db/init.sql и db/migration.sql
  - SSE-стрим GET /api/notifications/stream через Redis pub/sub с in-memory fallback
  - REST API: список, счётчик непрочитанных, отметка о прочтении, удаление, очистка
  - настройки уведомлений в settings (notify_enabled, notify_retention_days, notify_<тип>)
  - автоматическая очистка старых уведомлений по расписанию
- frontend:
  - колокольчик со счётчиком непрочитанных в шапке (admin.js)
  - страница списка уведомлений public/notifications.html и public/js/notifications.js
  - секция настроек уведомлений в public/settings.html и public/js/settings.js
  - стили для уведомлений в public/admin.css
- тесты и документация:
  - добавлены проверки в api.smoketest.js
  - обновлены README.md и AGENTS.md
2026-09-27 23:34:47 +03:00
dev f31b8deea2 feat(settings): блок «Статус стека» — на чём всё крутится
На странице Настроек появился блок с состоянием стека системы: версии
компонентов, состояние сервисов и нагрузка. Рендерится из нового блока
stack в ответе GET /api/system-info, в том же стиле, что и соседний
блок системной информации (sys-card / sys-item / sys-bar, точки
worker-dot, полосы загрузки и памяти с порогами 70 % и 90 %).

Карточки: Приложение (версия и коммит, Node.js, PID и RSS, аптайм,
куча, сворачиваемый список библиотек), Сервер (ОС, ядро, архитектура и
число ядер, модель CPU, loadavg, память, аптайм, контейнер), База
данных (PostgreSQL и версия, хост, состояние пула), Кэш (драйвер,
версия Redis, ключи, память, попадания и промахи, операций в памяти) и
Хранилище (драйвер, endpoint, бакет или каталог).

- server.js: getStackInfo() — версии из package.json, node_modules и
  public/version.json, ОС из /etc/os-release, определение Docker,
  SHOW server_version, счётчики пула pg, состояние Redis. Считается вне
  cacheWrap, чтобы версии и нагрузка не отдавались из 30-секундного
  кэша; хосты только через URL.hostname, без учётных данных URL
- settings.html: карточка sec-stack и пункт «Стек» в навигации
- settings.js: renderStackInfo(), форматирование аптаймов с
  русскими склонениями, degrade-состояние «нет связи — в памяти»;
  кнопка обновления перезагружает оба блока одним запросом
- admin.css: .sys-inline для точки статуса рядом с текстом
- api.smoketest.js: контракт блока stack и проверка, что в ответе нет
  учётных данных из DATABASE_URL/REDIS_URL
2026-09-27 12:47:04 +03:00
dev 54cf5bbfa4 feat(audit): показывать изменения текста записи по шагам
При сохранении записи журнала (PUT /api/entries/:id) сравнивается
состояние до и после, и в audit_log пишется не только факт правки,
но и сами изменения: пословный дифф текста, статистика добавленных
и удалённых слов, а также смена ФИО, группы и темы модуля.

- diff.js: пословный LCS-дифф без зависимостей, обрезка больших
  текстов, сборка изменений по полям записи, облегчённый target
  для списка аудита
- source правки: manual / ai / ai_manual / ai_revert; журнал шлёт
  edit_source, сервер доверяет явному значению и определяет источник
  по description_ai как запасной вариант
- те же диффы пишутся для автопроверки ИИ (entry.ai.auto-check)
  и отката к оригиналу (entry.ai.revert)
- GET /api/audit отдаёт список без diff, GET /api/audit/:id — полный
  target, чтобы не грузить килобайты текста на каждую строку
- Аудит: колонка «Кто», сводка в таблице, модалка с подсветкой
  удалённого и добавленного текста, «было/стало» для полей
- auth.login теперь пишет user_id, иначе колонка «Кто» показывала
  «система»
- diff.selftest.js: 16 тестов диффа; README и AGENTS обновлены
2026-09-27 11:29:17 +03:00
dev 8bf54fb95d feat(trash): deferred purge after configurable days, groups in trash 2026-09-24 13:11:31 +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 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 d3dd922e32 feat(modules): batch module import in admin, module usage in journal 2026-09-18 19:36:32 +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 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 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 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 2bebfc071c Replace emoji icons with lucide icons on settings page 2026-09-12 00:04:55 +03:00
dev 4db02d75bc Add AI-check details modal on worker page and raise backup upload limit 2026-09-11 16:26:30 +03:00
dev ee19da7fa0 Add audit details modal and translate remaining action labels
- Make Детали cell clickable to open a modal with the full details text\n- Translate missing audit action keys (auth.login, user.*, branch.*, group.photo.*, entry.photo.*)
2026-09-11 14:45:07 +03:00
dev 7044505915 Fix AI status badge sizing on worker page
Restore .ai-badge as a text pill and scope the compact icon circle to .ai-badge-ic (used by journal); worker page text badges now render at correct size
2026-09-11 14:38:46 +03:00
dev ad81adfe71 Migrate UI to Lucide icons, reorder sidebar, and polish journal/groups UX
- Replace emoji icons with Lucide across admin pages; add vendor/lucide.min.js and renderIcons() helper\n- Reorder sidebar logically (Dashboard, Journal, Students, Groups, Files, Links, Trash + admin sections)\n- Groups: open photo chronology only via the Фото button; covers no longer clickable\n- Journal: show group badge over card photo, compact AI-status icon beside description, and date range in empty-state message\n- Update README (AI worker, Lucide, worker.js)
2026-09-11 14:33:41 +03:00
dev 275ed46dfb Add HF model auto-download with configurable AI env, and share link visibility toggles 2026-09-11 13:12:13 +03:00
dev b7e798b867 Add AI auto-check worker, share link message/link fields, and update journal/settings UI 2026-09-11 10:29:49 +03:00
dev 3850fe35e4 Update project files 2026-09-10 11:26:51 +03:00
dev 89152295ea Add AI text correction button to journal edit modal 2026-09-10 00:06:38 +03:00
dev d6e589d2f5 feat: add branches feature, security audit, and multi-branch support 2026-09-09 09:41:07 +03:00
dev 7a003e5df6 Add system info dashboard to settings
- New /api/system-info endpoint returning DB size, table sizes, photo/file counts, uploads stats, disk usage
- System info cards in settings page (responsive grid)
- Replaced inline onclick handlers with data attributes + event delegation in groups.html
2026-09-09 01:08:48 +03:00
dev e0cec0f943 add admin audit log (11), hide stacktraces via NODE_ENV=production (13), validate spam_interval_min>=1 (16) 2026-09-08 12:12:29 +03:00
dev f13031e9b3 add detach files feature, utf8 filename fix, and error pages 2026-09-07 09:42:28 +03:00
dev 84fed96097 add full dashboard: activity chart, recent entries, group photos, quick actions, active groups, top students 2026-09-06 15:08:39 +03:00
dev 65e5651be2 redesign settings page UX/UI: structured cards, consistent fields, sticky save bar, backup stats and loading states 2026-09-06 14:56:06 +03:00
dev 621c3c3b5c add soft delete with trash page and group photo chronology with styling 2026-09-06 13:51:47 +03:00
dev a117184a2a make project file tokens public; keep name links with image preview and file download 2026-09-06 11:35:40 +03:00
dev ac8621c5aa serve project files by token hash, preview images inline and download other files 2026-09-06 11:33:33 +03:00
dev c5fdf006f5 add project file upload to student form, project_files table with backup/restore, download in journal, and crash-proof entries endpoint 2026-09-06 11:29:34 +03:00
dev c2c5f2ed42 add photo placeholder, mirrored camera capture, configurable footer, and student .url zip export 2026-09-06 11:22:00 +03:00
dev 94ea5606ff style student filter inputs (#studentFilter, #linkStudent) to match admin design 2026-09-05 20:30:36 +03:00
dev 6dc54e49b8 batch add students: add optional group selection in batch modal 2026-09-05 18:31:28 +03:00