fix(lessons): живые обновления списка отчётов о занятии

broadcastLessonChanged() был объявлен, но нигде не вызывался —
список отчётов не обновлялся после правки, создания, отката к
версии/оригиналу и удаления. Публикация перенесена в
invalidateLessonReports(), поэтому покрыты все 10 мест вызова,
включая мутации через /api/v1/*.

lessons.js подписан на lessons_changed с дебаунсом 300 мс;
lesson_report_status продолжает слаться сразу для точечного
обновления строки.
This commit is contained in:
dev
2026-10-06 00:12:01 +03:00
parent 9f815e5143
commit 85b737c0aa
2 changed files with 12 additions and 1 deletions
+8
View File
@@ -159,6 +159,7 @@ document.getElementById('searchInput').addEventListener('input', () => {
}); });
let lessonLiveSource = null; let lessonLiveSource = null;
let lessonRefreshTimer = null;
function connectLessonLive() { function connectLessonLive() {
if (lessonLiveSource) { lessonLiveSource.close(); lessonLiveSource = null; } if (lessonLiveSource) { lessonLiveSource.close(); lessonLiveSource = null; }
@@ -166,6 +167,13 @@ function connectLessonLive() {
const t = sessionStorage.getItem('authToken'); const t = sessionStorage.getItem('authToken');
if (!t) return; if (!t) return;
lessonLiveSource = new EventSource(`${API}/api/events?token=${encodeURIComponent(t)}`); lessonLiveSource = new EventSource(`${API}/api/events?token=${encodeURIComponent(t)}`);
lessonLiveSource.addEventListener('lessons_changed', () => {
if (lessonRefreshTimer) return;
lessonRefreshTimer = setTimeout(() => {
lessonRefreshTimer = null;
loadLessons();
}, 300);
});
lessonLiveSource.addEventListener('lesson_report_status', () => loadLessons()); lessonLiveSource.addEventListener('lesson_report_status', () => loadLessons());
lessonLiveSource.onerror = () => { lessonLiveSource.onerror = () => {
if (lessonLiveSource) { lessonLiveSource.close(); lessonLiveSource = null; } if (lessonLiveSource) { lessonLiveSource.close(); lessonLiveSource = null; }
+4 -1
View File
@@ -118,7 +118,10 @@ function invalidateSettings() { cacheDrop('setting:'); cacheDrop('share:payload:
function invalidateStudents() { cacheDrop('students:'); } function invalidateStudents() { cacheDrop('students:'); }
function invalidateGroups() { cacheDrop('groups:'); cacheDrop('students:'); cacheDrop('share:payload:'); } function invalidateGroups() { cacheDrop('groups:'); cacheDrop('students:'); cacheDrop('share:payload:'); }
function invalidateEntries() { cacheDrop('entries:'); cacheDrop('students:'); cacheDrop('share:payload:'); } function invalidateEntries() { cacheDrop('entries:'); cacheDrop('students:'); cacheDrop('share:payload:'); }
function invalidateLessonReports() { cacheDrop('lessons:'); cacheDrop('stats:'); cacheDrop('dashboard:'); } function invalidateLessonReports() {
cacheDrop('lessons:'); cacheDrop('stats:'); cacheDrop('dashboard:');
broadcastLessonChanged();
}
function invalidateSessions() { cacheDrop('session:'); } function invalidateSessions() { cacheDrop('session:'); }
function invalidateApiKeys() { cacheDrop('apikey:'); cacheDrop('rl:apikey'); } function invalidateApiKeys() { cacheDrop('apikey:'); cacheDrop('rl:apikey'); }