refactor(assignments): единый модуль assignment-utils.js (тип/«сдано»/срочность)
Логика классификации типа задания и статуса «сдано» дублировалась в трёх местах (dashboard.html, homework.html, assignmentController.js) и начала расходиться. Вынес в один UMD-модуль frontend/js/assignment-utils.js (грузится и в браузере, и в Node через require — как svg-sanitize.js): type(a), isDone(a, sub, opts), urgencyScore(a). Нюанс «сдано» для upload/file параметризован: вид ученика (acceptedOnly) — закрыто только при принятой сдаче; учитель/обзор долгов — любая сдача не на доработке. Поведение всех трёх поверхностей сохранено 1:1. - homework.html: asgnType/asgnDone/urgencyScore → тонкие делегаты в AssignmentUtils. - dashboard.html: urgencyScore делегирует; classify и upload-ветка buildAssignCard через AssignmentUtils.type/isDone (заодно корректнее: учебник-ДЗ больше не путается с upload). - assignmentController: classOutstanding/_assignTypeOf → AssignmentUtils. Verified: AU-контракт 25/25 (типы, isDone teacher vs acceptedOnly, порядок urgency); интеграция 8/8 (classOutstanding те же 14 уч./42 просрочено; homework делегирует). node --check всех файлов + инлайна обоих HTML. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+16
-18
@@ -1889,6 +1889,7 @@
|
||||
<!-- Join modal -->
|
||||
<!-- Quick-start test modal -->
|
||||
<script src="/js/api.js"></script>
|
||||
<script src="/js/assignment-utils.js"></script>
|
||||
<script src="/js/sound.js"></script>
|
||||
<script src="/js/sidebar.js"></script>
|
||||
<script src="/js/notifications.js"></script>
|
||||
@@ -2381,15 +2382,8 @@
|
||||
body.classList.toggle('collapsed');
|
||||
}
|
||||
|
||||
/* ── Urgency sort score (lower = shown first) ── */
|
||||
function urgencyScore(a) {
|
||||
if (a.session_status === 'in_progress') return -4; // in progress <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> top
|
||||
const dlMs = a.deadline ? new Date(a.deadline) - Date.now() : Infinity;
|
||||
if (dlMs < 0) return -3; // overdue
|
||||
if (dlMs < 24 * 3600 * 1000) return -2; // urgent <24h
|
||||
if (dlMs < Infinity) return dlMs; // sorted by deadline
|
||||
return 1e12; // no deadline <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> last
|
||||
}
|
||||
/* ── Urgency sort score (lower = shown first) — общий модуль ── */
|
||||
function urgencyScore(a) { return AssignmentUtils.urgencyScore(a); }
|
||||
|
||||
/* ── Is assignment urgent for teacher (within 48h) ── */
|
||||
function isTeacherUrgent(a) {
|
||||
@@ -2457,7 +2451,7 @@
|
||||
}
|
||||
|
||||
/* ── Upload-only homework (no test, no file) ── */
|
||||
if (a.is_homework && !a.file_id && !a.session_id && a.count <= 1 && (!a.subject_slug || a.subject_slug === 'other')) {
|
||||
if (AssignmentUtils.type(a) === 'upload') {
|
||||
const over = a.deadline && new Date(a.deadline) < new Date();
|
||||
const sub = _mySubmissions.get(a.id);
|
||||
const metaParts = [classStr, dl ? `до ${dl}` : null,
|
||||
@@ -2694,18 +2688,22 @@
|
||||
reIcons(); return;
|
||||
}
|
||||
|
||||
// Classify
|
||||
// Classify (active/overdue/done) — тип и «сдано» из общего модуля AssignmentUtils.
|
||||
function classify(a) {
|
||||
const maxAtt = a.max_attempts || 0;
|
||||
const usedAtt = a.attempts_used ?? 0;
|
||||
if (a.textbook_id) {
|
||||
if (a.completed_at || a.textbook_all_read) return 'done';
|
||||
const t = AssignmentUtils.type(a);
|
||||
if (t === 'textbook') {
|
||||
if (AssignmentUtils.isDone(a)) return 'done';
|
||||
if (a.deadline && new Date(a.deadline) < now) return 'overdue';
|
||||
return 'active';
|
||||
}
|
||||
if (maxAtt > 0 && usedAtt >= maxAtt) return 'done';
|
||||
if (a.session_status === 'completed' && a.mode !== 'repeat') return 'done';
|
||||
if (!a.file_id && a.deadline && new Date(a.deadline) < now && a.session_status !== 'in_progress') return 'overdue';
|
||||
if (t === 'test') {
|
||||
if (AssignmentUtils.isDone(a)) return 'done';
|
||||
if (a.deadline && new Date(a.deadline) < now && a.session_status !== 'in_progress') return 'overdue';
|
||||
return 'active';
|
||||
}
|
||||
// upload / file: «сдано» по сабмишену здесь не считаем (как и раньше — статус
|
||||
// показывает чип сдачи в карточке); upload просрочивается по дедлайну, file — всегда активен.
|
||||
if (t === 'upload' && a.deadline && new Date(a.deadline) < now) return 'overdue';
|
||||
return 'active';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user