chore: merge main and release 3.7.3 bugfix bundle

Resolve conflicts with deep-reform (PR #452) while keeping bugfix branch
changes: sidebar visibility, verbose logging, device login name, and
notification archive. Bump to 3.7.3 with What's New release notes.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-26 20:12:58 +09:30
93 changed files with 2628 additions and 1368 deletions
@@ -268,7 +268,7 @@
xScale={scaleBand().padding(distribution().modeUsed === "letter" ? 0.22 : 0.28)}
yScale={yScale()}
yScale={yScale}
x="grade"
@@ -310,8 +310,6 @@
y: { type: "tween", duration: 600, easing: cubicInOut },
height: { type: "tween", duration: 600, easing: cubicInOut },
},
},
@@ -35,6 +35,15 @@
),
);
$effect(() => {
sortedData.length;
itemsPerPage;
const maxPage = Math.max(0, pageCount - 1);
if (currentPage > maxPage) {
currentPage = maxPage;
}
});
function toggleSort(column: keyof Assessment) {
if (sortColumn === column) {
sortDirection = sortDirection === "asc" ? "desc" : "asc";
@@ -53,8 +53,9 @@
const [minG, maxG] = gradeRange;
return analyticsData.filter((a) => {
if (filterSubjects.length && !filterSubjects.includes(a.subject)) return false;
const grade = a.finalGrade ?? -1;
if (grade < minG || grade > maxG) return false;
if (a.finalGrade !== undefined) {
if (a.finalGrade < minG || a.finalGrade > maxG) return false;
}
if (
filterSearch &&
!a.title.toLowerCase().includes(filterSearch.toLowerCase()) &&
+15 -3
View File
@@ -24,6 +24,9 @@ async function fetchJSON(url: string, body: Record<string, unknown>) {
headers: { "Content-Type": "application/json; charset=utf-8" },
body: JSON.stringify(body),
});
if (!res.ok) {
throw new Error(`HTTP ${res.status} for ${url}`);
}
return res.json();
}
@@ -254,10 +257,19 @@ async function loadAllPast(
const results: Record<string, unknown>[][] = [];
for (let i = 0; i < subjects.length; i += PAST_FETCH_CONCURRENCY) {
const batch = subjects.slice(i, i + PAST_FETCH_CONCURRENCY);
const batchResults = await Promise.all(
const batchResults = await Promise.allSettled(
batch.map((s) => loadPastForSubject(studentId, s)),
);
results.push(...batchResults);
for (const result of batchResults) {
if (result.status === "fulfilled") {
results.push(result.value);
} else {
console.error(
"[BetterSEQTA+] Past assessments fetch failed:",
result.reason,
);
}
}
}
return results.flat();
}
@@ -295,7 +307,7 @@ function mergeRawAssessments(
}
export async function getStudentId(): Promise<number> {
const info = await getUserInfo();
const info = await getUserInfo({ validateSession: true });
const id = Number(info?.id);
if (!id || isNaN(id)) throw new Error("Could not resolve student ID");
return id;