diff --git a/api.smoketest.js b/api.smoketest.js index 2075878..74a8ce3 100644 --- a/api.smoketest.js +++ b/api.smoketest.js @@ -250,6 +250,37 @@ async function main() { plain.status === 201 && plain.data.ai_status === 'none' && plain.data.text_original === null, { status: plain.status, ai_status: plain.data.ai_status }); + const topicName = 'Циклы for и while'; + const withTopic = await api('/api/lesson-reports', { + token, method: 'POST', + body: { group_id: gid, lesson_date: '2019-05-18', lesson_time: '10:00', topic: topicName, text: 'Тема занятия для смоук-теста.', ai_check: false }, + }); + ok('lesson-report: тема занятия сохраняется при создании', + withTopic.status === 201 && withTopic.data.topic === topicName, { status: withTopic.status, topic: withTopic.data.topic }); + + const listed = await api(`/api/lesson-reports?group_id=${gid}&date_from=2019-05-18&date_to=2019-05-18`, { token }); + ok('lesson-report: тема занятия в списке', + listed.status === 200 && (listed.data.items || []).some(i => i.topic === topicName), + { status: listed.status, item: (listed.data.items || [])[0] && (listed.data.items || [])[0].topic }); + + const edited = await api(`/api/lesson-reports/${withTopic.data.id}`, { + token, method: 'PUT', body: { topic: 'Обновлённая тема' }, + }); + ok('lesson-report: тема занятия обновляется при редактировании', + edited.status === 200 && edited.data.topic === 'Обновлённая тема', { status: edited.status, topic: edited.data.topic }); + + const cleared = await api(`/api/lesson-reports/${withTopic.data.id}`, { + token, method: 'PUT', body: { topic: '' }, + }); + ok('lesson-report: тему занятия можно очистить', + cleared.status === 200 && !cleared.data.topic, { status: cleared.status, topic: cleared.data.topic }); + + const tooLong = await api(`/api/lesson-reports/${withTopic.data.id}`, { + token, method: 'PUT', body: { topic: 'я'.repeat(301) }, + }); + ok('lesson-report: слишком длинная тема -> 400', tooLong.status === 400, { status: tooLong.status, error: tooLong.data && tooLong.data.error }); + await api(`/api/lesson-reports/${withTopic.data.id}`, { token, method: 'DELETE' }); + const versions = await api(`/api/lesson-reports/${plain.data.id}/versions`, { token }); ok('lesson-report: история версий содержит исходный текст', versions.status === 200 && Array.isArray(versions.data.items) && versions.data.items.length >= 1 diff --git a/backup-restore.js b/backup-restore.js index 05038c3..309b4a5 100644 --- a/backup-restore.js +++ b/backup-restore.js @@ -1,5 +1,6 @@ const PHOTO_JOB_ACTIONS = new Set(['ai', 'ai_face', 'ai_upscale', 'enhance', 'restore', 'rollback']); const LESSON_REPORT_TEXT_MAX = 5000; +const LESSON_REPORT_TOPIC_MAX = 300; const BACKUP_FORMAT_VERSION = 2; const BACKUP_MIN_FORMAT_VERSION = 1; const BACKUP_TABLES = [ @@ -390,6 +391,7 @@ function normalizeRestoreData(data) { group_id: reqInt(x.group_id), lesson_date: reqDate(x.lesson_date), lesson_time: optTime(x.lesson_time), + topic: optStr(x.topic, LESSON_REPORT_TOPIC_MAX), text: reqStr(x.text, LESSON_REPORT_TEXT_MAX), text_original: optStr(x.text_original, LESSON_REPORT_TEXT_MAX), text_ai: optStr(x.text_ai, LESSON_REPORT_TEXT_MAX), @@ -466,6 +468,7 @@ function normalizeRestoreData(data) { module.exports = { PHOTO_JOB_ACTIONS, LESSON_REPORT_TEXT_MAX, + LESSON_REPORT_TOPIC_MAX, SAFE_NAME, isSafeUploadPath, photoRefKey, diff --git a/db/init.sql b/db/init.sql index 7f2ef8a..4bdf149 100644 --- a/db/init.sql +++ b/db/init.sql @@ -230,6 +230,7 @@ CREATE TABLE IF NOT EXISTS lesson_reports ( group_id INT NOT NULL REFERENCES groups(id) ON DELETE CASCADE, lesson_date DATE NOT NULL, lesson_time TIME, + topic TEXT, text TEXT NOT NULL, text_original TEXT, text_ai TEXT, diff --git a/db/migration.sql b/db/migration.sql index 644b313..a8d1ea9 100644 --- a/db/migration.sql +++ b/db/migration.sql @@ -326,6 +326,7 @@ ALTER TABLE lesson_reports ADD COLUMN IF NOT EXISTS text_ai TEXT; ALTER TABLE lesson_reports ADD COLUMN IF NOT EXISTS ai_status VARCHAR(20) NOT NULL DEFAULT 'none'; ALTER TABLE lesson_reports ADD COLUMN IF NOT EXISTS ai_checked_at TIMESTAMPTZ; ALTER TABLE lesson_reports ADD COLUMN IF NOT EXISTS ai_error TEXT; +ALTER TABLE lesson_reports ADD COLUMN IF NOT EXISTS topic TEXT; CREATE TABLE IF NOT EXISTS lesson_report_versions ( id SERIAL PRIMARY KEY, diff --git a/public/admin.css b/public/admin.css index ba014b2..8375484 100644 --- a/public/admin.css +++ b/public/admin.css @@ -689,6 +689,7 @@ body[data-page=settings] .page-head{align-items:flex-end} .lesson-when i{width:13px;height:13px} .lesson-badge{font-size:.7rem;font-weight:700;padding:2px 9px;border-radius:999px;background:rgba(37,99,235,.1);color:var(--accent)} .lesson-badge.today{background:rgba(16,185,129,.14);color:#059669} +.lesson-topic{font-size:.85rem;font-weight:600;color:var(--accent)} .lesson-text{font-size:.88rem;color:var(--text);white-space:pre-wrap;word-break:break-word;line-height:1.55} .lesson-author{font-size:.75rem;color:var(--muted)} .lesson-actions{display:flex;gap:8px;flex-wrap:wrap;margin-left:auto} diff --git a/public/admin.js b/public/admin.js index 2fdca0f..8fd0127 100644 --- a/public/admin.js +++ b/public/admin.js @@ -534,6 +534,11 @@ function ensureLessonModal() { +
+ + +