mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-16 08:27:07 +00:00
141 lines
3.9 KiB
TypeScript
141 lines
3.9 KiB
TypeScript
import type { Plugin } from "../../core/types";
|
|
import { waitForElm } from "@/seqta/utils/waitForElm";
|
|
import { getAssessmentsData } from "./api";
|
|
import { renderErrorState, renderGrid, renderSkeletonLoader } from "./ui";
|
|
import styles from "./styles.css?inline";
|
|
import { delay } from "@/seqta/utils/delay";
|
|
import { isSeqtaEngageExperience } from "@/seqta/utils/isSeqtaEngage";
|
|
import {
|
|
isEngageAssessmentOverviewRoute,
|
|
} from "@/seqta/utils/engageAssessmentStudent";
|
|
import { resolveEngageStudentId } from "./engageApi";
|
|
|
|
const OVERVIEW_MENU_CLASS = "betterseqta-assessments-overview-item";
|
|
|
|
function ensureOverviewMenuPosition(
|
|
menu: HTMLElement,
|
|
gridItem: HTMLElement,
|
|
) {
|
|
if (menu.firstElementChild !== gridItem) {
|
|
menu.insertBefore(gridItem, menu.firstChild);
|
|
}
|
|
}
|
|
|
|
function isOverviewRoute() {
|
|
if (isSeqtaEngageExperience()) {
|
|
return isEngageAssessmentOverviewRoute();
|
|
}
|
|
return window.location.hash.includes("/assessments/overview");
|
|
}
|
|
|
|
async function waitForAssessmentsSubmenu(): Promise<HTMLElement> {
|
|
if (!isSeqtaEngageExperience()) {
|
|
return (await waitForElm(
|
|
'[data-key="assessments"] > .sub > ul',
|
|
true,
|
|
100,
|
|
60,
|
|
)) as HTMLElement;
|
|
}
|
|
|
|
return (await waitForElm(
|
|
'[data-key="assessments"] .sub ul, [data-key="assessments"] ul',
|
|
true,
|
|
100,
|
|
350,
|
|
)) as HTMLElement;
|
|
}
|
|
|
|
const assessmentsOverviewPlugin: Plugin<{}> = {
|
|
id: "assessments-overview",
|
|
name: "Assessments Overview",
|
|
description:
|
|
"Adds an overview option to the assessments page that organizes assessments by status",
|
|
version: "1.0.0",
|
|
settings: {},
|
|
disableToggle: false,
|
|
styles,
|
|
|
|
run: async () => {
|
|
const menu = await waitForAssessmentsSubmenu();
|
|
const gridItem = document.createElement("li");
|
|
gridItem.className = "item";
|
|
gridItem.classList.add(OVERVIEW_MENU_CLASS);
|
|
const label = document.createElement("label");
|
|
label.textContent = "Overview";
|
|
gridItem.appendChild(label);
|
|
menu.insertBefore(gridItem, menu.firstChild);
|
|
|
|
const menuObserver = new MutationObserver(() => {
|
|
ensureOverviewMenuPosition(menu, gridItem);
|
|
});
|
|
menuObserver.observe(menu, { childList: true });
|
|
|
|
if (isOverviewRoute()) {
|
|
void loadGridView();
|
|
}
|
|
|
|
const clickHandler = (e: Event) => {
|
|
e.preventDefault();
|
|
void loadGridView();
|
|
};
|
|
gridItem.addEventListener("click", clickHandler);
|
|
|
|
async function loadGridView() {
|
|
await delay(1);
|
|
|
|
if (isSeqtaEngageExperience()) {
|
|
const studentId = await resolveEngageStudentId();
|
|
window.history.pushState(
|
|
{},
|
|
"",
|
|
`/#?page=/assessments/${studentId}/overview`,
|
|
);
|
|
document.title = "Overview ― SEQTA Engage";
|
|
} else {
|
|
window.history.pushState({}, "", "/#?page=/assessments/overview");
|
|
document.title = "Overview ― SEQTA Learn";
|
|
}
|
|
|
|
const main = document.getElementById("main");
|
|
if (!main) return;
|
|
|
|
document
|
|
.querySelectorAll('[data-key="assessments"] .item')
|
|
.forEach((item) => {
|
|
item.classList.remove("active");
|
|
});
|
|
gridItem.classList.add("active");
|
|
document
|
|
.querySelector('[data-key="assessments"]')
|
|
?.classList.add("active");
|
|
|
|
main.innerHTML = '<div id="grid-view-container" class="bsplus-overview-host"></div>';
|
|
const container = document.getElementById(
|
|
"grid-view-container",
|
|
) as HTMLElement;
|
|
|
|
renderSkeletonLoader(container);
|
|
|
|
try {
|
|
const data = await getAssessmentsData();
|
|
renderGrid(container, data);
|
|
} catch (err) {
|
|
console.error("Failed to load assessments:", err);
|
|
renderErrorState(
|
|
container,
|
|
err instanceof Error ? err.message : "Unknown error",
|
|
);
|
|
}
|
|
}
|
|
|
|
return () => {
|
|
menuObserver.disconnect();
|
|
gridItem.removeEventListener("click", clickHandler);
|
|
gridItem.remove();
|
|
};
|
|
},
|
|
};
|
|
|
|
export default assessmentsOverviewPlugin;
|