mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-05 19:24:39 +00:00
fix @SethBurkart123 's comments
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
import { settingsState } from "@/seqta/utils/listeners/SettingsState";
|
import { settingsState } from "@/seqta/utils/listeners/SettingsState";
|
||||||
import { loadHomePage } from "@/seqta/utils/Loaders/LoadHomePage";
|
import { loadHomePage } from "@/seqta/utils/Loaders/LoadHomePage";
|
||||||
import { waitForElm } from "@/seqta/utils/waitForElm";
|
import { waitForElm } from "@/seqta/utils/waitForElm";
|
||||||
import { getCurrentStudentId } from "../indexing/api";
|
|
||||||
|
|
||||||
export interface BaseCommandItem {
|
export interface BaseCommandItem {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -24,11 +23,6 @@ async function getCurrentLesson() {
|
|||||||
const todayFormatted = formatDate(date);
|
const todayFormatted = formatDate(date);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const student = await getCurrentStudentId();
|
|
||||||
if (typeof student !== "number") {
|
|
||||||
alert("Could not determine the active SEQTA student.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const response = await fetch(`${location.origin}/seqta/student/load/timetable?`, {
|
const response = await fetch(`${location.origin}/seqta/student/load/timetable?`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
@@ -36,7 +30,6 @@ async function getCurrentLesson() {
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
from: todayFormatted,
|
from: todayFormatted,
|
||||||
until: todayFormatted,
|
until: todayFormatted,
|
||||||
student,
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,67 +1,41 @@
|
|||||||
import type { IndexItem, Job } from "../types";
|
import type { IndexItem, Job } from "../types";
|
||||||
import { getCurrentStudentId, seqtaFetchPayload } from "../api";
|
|
||||||
import { getUserInfo } from "@/seqta/ui/AddBetterSEQTAElements";
|
|
||||||
|
|
||||||
/**
|
const fetchJSON = async (url: string, body: any) => {
|
||||||
* Resolves the active student id from whatever source is available.
|
const res = await fetch(`${location.origin}${url}`, {
|
||||||
*
|
method: "POST",
|
||||||
* The shared `getCurrentStudentId()` calls `/seqta/student/login` with a
|
credentials: "include",
|
||||||
* specific body shape; on some SEQTA installs that endpoint can return a
|
headers: { "Content-Type": "application/json; charset=utf-8" },
|
||||||
* response that confuses the helper (no `id`, or a non-"200" envelope).
|
body: JSON.stringify(body),
|
||||||
* To make sure we never silently skip the entire assignments pass, we
|
});
|
||||||
* also fall back to `getUserInfo()` from `AddBetterSEQTAElements.ts` —
|
return res.json();
|
||||||
* it's the same handshake the host page uses to render the avatar, so
|
};
|
||||||
* if the user is logged in at all this path resolves.
|
|
||||||
*/
|
const fetchUpcomingAssessments = async (student: number = 69) => {
|
||||||
async function resolveStudentId(): Promise<number | undefined> {
|
|
||||||
try {
|
try {
|
||||||
const direct = await getCurrentStudentId();
|
const res = await fetchJSON("/seqta/student/assessment/list/upcoming?", {
|
||||||
if (typeof direct === "number" && Number.isFinite(direct)) return direct;
|
student,
|
||||||
|
});
|
||||||
|
// Match analytics.rs: payload is an array, return empty array if not found
|
||||||
|
return Array.isArray(res.payload) ? res.payload : [];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn(
|
console.error("[Assignments job] Failed to fetch upcoming assessments:", e);
|
||||||
"[Assignments job] getCurrentStudentId() threw, falling back to getUserInfo()",
|
return [];
|
||||||
e,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
const info = (await getUserInfo()) as { id?: unknown } | null;
|
|
||||||
const id = info?.id;
|
|
||||||
if (typeof id === "number" && Number.isFinite(id)) return id;
|
|
||||||
if (typeof id === "string" && id && Number.isFinite(Number(id))) {
|
|
||||||
return Number(id);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.warn("[Assignments job] getUserInfo() fallback failed:", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fetchUpcomingAssessments = async (student: number) => {
|
|
||||||
const payload = await seqtaFetchPayload<any[]>(
|
|
||||||
"/seqta/student/assessment/list/upcoming",
|
|
||||||
{ student },
|
|
||||||
);
|
|
||||||
return Array.isArray(payload) ? payload : [];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchSubjects = async () => {
|
const fetchSubjects = async () => {
|
||||||
// SEQTA accepts both `{}` and `{ mode: "list" }` here; the latter is the
|
try {
|
||||||
// shape every BetterSEQTA-Plus path uses elsewhere and is the more
|
const res = await fetchJSON("/seqta/student/load/subjects?", {});
|
||||||
// reliable response format on schools that customize the `student/load`
|
return res.payload
|
||||||
// endpoint.
|
?.filter((s: any) => s.active === 1)
|
||||||
const payload = await seqtaFetchPayload<any[]>(
|
?.flatMap((s: any) => s.subjects) || [];
|
||||||
"/seqta/student/load/subjects",
|
} catch (e) {
|
||||||
{ mode: "list" },
|
console.error("[Assignments job] Failed to fetch subjects:", e);
|
||||||
);
|
return [];
|
||||||
if (!Array.isArray(payload)) return [];
|
}
|
||||||
return payload
|
|
||||||
.filter((s: any) => s && s.active === 1)
|
|
||||||
.flatMap((s: any) => (Array.isArray(s.subjects) ? s.subjects : []));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchPastAssessments = async (student: number, subjects: any[]) => {
|
const fetchPastAssessments = async (student: number = 69, subjects: any[]) => {
|
||||||
const map: Record<number, any> = {};
|
const map: Record<number, any> = {};
|
||||||
|
|
||||||
// Fetch past assessments for all subjects in parallel (like assessmentsOverview does)
|
// Fetch past assessments for all subjects in parallel (like assessmentsOverview does)
|
||||||
@@ -69,16 +43,12 @@ const fetchPastAssessments = async (student: number, subjects: any[]) => {
|
|||||||
await Promise.all(
|
await Promise.all(
|
||||||
subjects.map(async (subject) => {
|
subjects.map(async (subject) => {
|
||||||
try {
|
try {
|
||||||
const payload = await seqtaFetchPayload<any>(
|
// Match analytics.rs exactly: parameter order is programme, metaclass, student
|
||||||
"/seqta/student/assessment/list/past",
|
const res = await fetchJSON("/seqta/student/assessment/list/past?", {
|
||||||
{
|
programme: subject.programme,
|
||||||
programme: subject.programme,
|
metaclass: subject.metaclass,
|
||||||
metaclass: subject.metaclass,
|
student,
|
||||||
student,
|
});
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!payload) return;
|
|
||||||
|
|
||||||
// Past assessments API can return data in payload.tasks OR payload.pending (or both)
|
// Past assessments API can return data in payload.tasks OR payload.pending (or both)
|
||||||
// Based on analytics.rs fetch_past_assessments, we need to check both arrays
|
// Based on analytics.rs fetch_past_assessments, we need to check both arrays
|
||||||
@@ -98,13 +68,13 @@ const fetchPastAssessments = async (student: number, subjects: any[]) => {
|
|||||||
|
|
||||||
// Match analytics.rs: Check both pending and tasks arrays
|
// Match analytics.rs: Check both pending and tasks arrays
|
||||||
// Check for pending array first (matching Rust code order)
|
// Check for pending array first (matching Rust code order)
|
||||||
if (payload?.pending && Array.isArray(payload.pending)) {
|
if (res.payload?.pending && Array.isArray(res.payload.pending)) {
|
||||||
payload.pending.forEach(processAssessment);
|
res.payload.pending.forEach(processAssessment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for tasks array
|
// Check for tasks array
|
||||||
if (payload?.tasks && Array.isArray(payload.tasks)) {
|
if (res.payload?.tasks && Array.isArray(res.payload.tasks)) {
|
||||||
payload.tasks.forEach(processAssessment);
|
res.payload.tasks.forEach(processAssessment);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn(`[Assignments job] Failed to fetch past assessments for subject ${subject.code || subject.subject || 'unknown'}:`, e);
|
console.warn(`[Assignments job] Failed to fetch past assessments for subject ${subject.code || subject.subject || 'unknown'}:`, e);
|
||||||
@@ -156,27 +126,9 @@ export const assignmentsJob: Job = {
|
|||||||
const existingItems = await ctx.getStoredItems("assignments");
|
const existingItems = await ctx.getStoredItems("assignments");
|
||||||
const existingIds = new Set(existingItems.map((i) => i.id));
|
const existingIds = new Set(existingItems.map((i) => i.id));
|
||||||
|
|
||||||
// Resolve the active student id from the live SEQTA session. Historically
|
const student = 69; // TODO: Get from context if available
|
||||||
// this was hard-coded to 69, which only happens to be correct on a few
|
|
||||||
// local dev instances; the shared helper now reuses the same `login`
|
|
||||||
// handshake that the host page performs so every install gets the right
|
|
||||||
// value without configuration.
|
|
||||||
//
|
|
||||||
// We *throw* instead of returning [] when resolution fails, so the
|
|
||||||
// indexer's "lastRun" meta is NOT updated. Otherwise the job would be
|
|
||||||
// marked complete (with zero items) and `shouldRun` would skip it for
|
|
||||||
// the entire 24h frequency window — meaning a single bad page load
|
|
||||||
// could leave the user without any assessment results until tomorrow.
|
|
||||||
const student = await resolveStudentId();
|
|
||||||
if (typeof student !== "number") {
|
|
||||||
throw new Error(
|
|
||||||
"[Assignments job] Could not resolve current student id from /seqta/student/login. The job will retry on the next page load.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.debug(
|
console.debug("[Assignments job] Starting indexing - fetching all assessments (upcoming and past)...");
|
||||||
`[Assignments job] Starting indexing for student=${student} - fetching all assessments (upcoming and past)...`,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Fetch data in parallel
|
// Fetch data in parallel
|
||||||
const [upcoming, subjects] = await Promise.all([
|
const [upcoming, subjects] = await Promise.all([
|
||||||
|
|||||||
Reference in New Issue
Block a user