Lage en enkel modul
Denne siden viser en liten, fungerende modul fra start til slutt. Eksempelet er
ment for deg som kan litt TypeScript, men ikke kjenner modulsystemet i
inskewl fra før.
Modulen vi lager viser et lite panel nederst til høyre på dashboardet i VIS InSchool. Panelet viser klokkeslettet og har en knapp som skjuler panelet. Eksempelet er enkelt, men bruker samme struktur som de større modulene i prosjektet.
Filstruktur
Lag en ny mappe under src/modules:
src/modules/simple-dashboard-note/
└── simple-dashboard-note.ts
Modulfilen
Opprett src/modules/simple-dashboard-note/simple-dashboard-note.ts:
import type { Injectable } from "../core/Injectable";
import { VismaModule } from "../core/VismaModule";
export class SimpleDashboardNote extends VismaModule {
name = "SimpleDashboardNote";
description = "Shows a small note on the VIS dashboard.";
override shouldLoad(url: string): boolean {
return url.includes("/dashboard");
}
override injectables(): Injectable[] {
let clockTimer: number | undefined;
return [
{
id: "simple-dashboard-note-panel",
target: "body",
placement: "append",
render: () => {
const panel = document.createElement("aside");
panel.setAttribute("aria-label", "inskewl demo");
panel.style.position = "fixed";
panel.style.right = "16px";
panel.style.bottom = "16px";
panel.style.zIndex = "999999";
panel.style.width = "220px";
panel.style.padding = "12px";
panel.style.border = "1px solid #d0d7de";
panel.style.borderRadius = "6px";
panel.style.background = "#ffffff";
panel.style.boxShadow = "0 8px 24px rgba(0, 0, 0, 0.16)";
panel.style.color = "#24292f";
panel.style.fontFamily = "system-ui, sans-serif";
panel.style.fontSize = "14px";
const title = document.createElement("strong");
title.textContent = "inskewl demo";
const text = document.createElement("p");
text.style.margin = "8px 0";
text.textContent = "Denne modulen kjører på dashboardet.";
const clock = document.createElement("p");
clock.style.margin = "0 0 12px";
const updateClock = () => {
clock.textContent = `Klokken er ${new Date().toLocaleTimeString("nb-NO", {
hour: "2-digit",
minute: "2-digit",
})}`;
};
updateClock();
clockTimer = window.setInterval(updateClock, 1000);
const button = document.createElement("button");
button.type = "button";
button.textContent = "Skjul";
button.style.cursor = "pointer";
button.addEventListener("click", () => {
panel.hidden = true;
});
panel.append(title, text, clock, button);
return panel;
},
destroy: () => {
if (clockTimer !== undefined) {
window.clearInterval(clockTimer);
}
},
},
];
}
}
De viktigste delene er:
namebrukes avDomInjectortil å holde styr på hvilke elementer modulen har satt inn.shouldLoad(url)bestemmer hvilke VIS-sider modulen skal være aktiv på.injectables()beskriver hvor UI skal settes inn og hvordan elementet lages.destroyrydder opp når modulen lastes ut. Her stoppes intervallet som oppdaterer klokken.
Registrer modulen
For at modulen skal kjøres, må den legges til i src/main.ts.
Legg til importen:
import { SimpleDashboardNote } from "./modules/simple-dashboard-note/simple-dashboard-note";
Legg deretter modulen inn i listen som sendes til ModuleLoader:
const moduleLoader = new ModuleLoader([
new AttendanceCalculator(),
new TimetableExporter(),
new SimpleDashboardNote(),
]);
Rekkefølgen er bare viktig hvis flere moduler prøver å endre samme del av siden. For denne typen modul er det trygt å legge den sist.
Kjør lokalt
Start watch-builden:
npm run dev
Installer eller oppdater userscriptet fra dist/inskewl.user.js, åpne VIS
InSchool og gå til dashboardet. Når modulen fungerer, vises panelet nederst til
høyre. Hvis du navigerer bort fra dashboardet, fjernes panelet av
ModuleLoader.
Valgfritt: kall et API
Når DOM-modulen fungerer, kan du legge til API-bruk. Dette eksempelet henter aktivt skoleår og skriver det til konsollen når modulen lastes.
API-endepunktene validerer ikke hele svaret fra VIS. I stedet gir hver modul
med sitt eget Zod-schema med akkurat feltene den trenger. Schemaet plukkes
(pick) fra katalog-schemaene i src/api/types, slik at transformeringer
(f.eks. datoer) og feltdokumentasjon følger med.
Lag en schemas.ts i modulmappen:
import { z } from "zod";
import { AcademicYearSchema } from "../../api/types/calendar";
export const MittSkoleaarSchema = z.array(
AcademicYearSchema.pick({
name: true,
currentYear: true,
}),
);
Legg til disse importene øverst i samme modulfil:
import { api } from "../../api/api";
import { MittSkoleaarSchema } from "./schemas";
Legg deretter onLoad inn i SimpleDashboardNote-klassen:
override async onLoad(): Promise<void> {
const academicYear = await api.calendar.getCurrentAcademicYear(
MittSkoleaarSchema,
);
this.logger.info("Aktivt skoleår:", academicYear.name);
}
API-laget bruker Zod til å validere data fra VIS InSchool. Fordelen med å
plukke bare det modulen trenger: hvis VIS endrer eller fjerner et felt modulen
ikke bruker, fortsetter den å fungere. Mangler eller endres et felt modulen
faktisk trenger, kastes en feil umiddelbart — selv om TypeScript-koden
kompilerer. Trenger du et felt som ikke finnes i katalogen ennå, legg det til i
src/api/types først og plukk det deretter.
Vanlige feil
- Panelet vises ikke: sjekk at modulen er registrert i
src/main.ts. - Modulen lastes aldri: logg
urlishouldLoadog kontroller at URL-sjekken matcher siden du tester på. targetfinnes ikke:DomInjectorprøver igjen ved senere DOM-endringer, men en for spesifikk selector kan gjøre at elementet aldri settes inn.- API-kallet feiler: sjekk at du er logget inn i VIS InSchool og at du tester på riktig tenant.