aboutsummaryrefslogtreecommitdiff
path: root/src/database-prod.ts
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2026-08-05 11:51:51 +0200
committerFlorian Fischer <florian.fischer@muhq.space>2026-08-05 11:51:51 +0200
commit582df8885a3573a728394b473b826616f8969316 (patch)
tree9c21db03f4fbfd9956ee398e0d9194ebfa5b3234 /src/database-prod.ts
parent46ac53e11b49a7f9cdb92c3559b05f41ce90122f (diff)
downloadbycs-sol-582df8885a3573a728394b473b826616f8969316.tar.gz
bycs-sol-582df8885a3573a728394b473b826616f8969316.zip
convert a lot of js to typescript and use a single graduation DB
Diffstat (limited to 'src/database-prod.ts')
-rw-r--r--src/database-prod.ts140
1 files changed, 140 insertions, 0 deletions
diff --git a/src/database-prod.ts b/src/database-prod.ts
new file mode 100644
index 0000000..6a55f25
--- /dev/null
+++ b/src/database-prod.ts
@@ -0,0 +1,140 @@
+import { getCourseId } from "./utils-ENV.js";
+
+const DB_TEMPLATE_LIST_HEADER = `
+<table class="table table-striped">
+ <thead>
+ <tr>
+ <th>Json</th>
+ </tr>
+ </thead>
+ <tbody>
+`;
+const DB_TEMPLATE_LIST_ENTRY = `
+<tr class="db-row">
+ <td class="db-cell" data-key="date">##timeadded##</td>
+ <td class="db-cell" data-key="coach">##user##</td>
+ <td class="db-cell" data-key="json">[[Json]]</td>
+</tr>
+`;
+const DB_TEMPLATE_LIST_FOOTER = `
+ </tbody>
+</table>
+`;
+
+let graduationDb = findGraduationDb();
+
+const ID_QUERY_PARAM_REGEX = /[?&]id=(\d+)/
+
+async function findGraduationDb() {
+ let graduationDbId = localStorage.getItem("gruaduationDbId");
+ if (graduationDbId !== null) {
+ return new DB(Number(graduationDbId));
+ }
+
+ const courseUrl = `https://lernplattform.bycs.de/course/view.php?id=${getCourseId()}`;
+ const courseRes = await fetch(courseUrl);
+ const courseDoc = new DOMParser().parseFromString(await courseRes.text(), 'text/html');
+
+ for (const a of courseDoc.querySelectorAll("div.activityname a.aalink")) {
+ if (a.textContent.trim() === "Graduation Datenbank") {
+ const anchor = (a as HTMLAnchorElement);
+ const match = anchor.href.match(ID_QUERY_PARAM_REGEX);
+ if (match === null) continue;
+ const dbId = match[1];
+ localStorage.setItem("graduationDbId", dbId);
+ return new DB(Number(dbId))
+ }
+ }
+ console.assert(false, "Graduation DB not found");
+}
+
+interface DatabaseParams {
+ [key: string]: string;
+}
+
+interface DatabaseEntry {
+ [key: string]: string;
+}
+
+class DB {
+ id: number;
+
+ constructor(id: number) {
+ this.id = id;
+ }
+
+ async fetchEntries(params?: DatabaseParams) {
+ return loadFromDatabaseActivity(this.id, params)
+ }
+
+ async saveEntry(json: string) {
+ return addEntryToDatabaseActivity(this.id, json);
+ }
+
+}
+
+async function loadFromDatabaseActivity(id: string | number, params?: DatabaseParams) {
+ let dbUrl = `${window.location.origin}/mod/data/view.php?id=${id}&mode=list&perpage=1000`;
+ // TODO(muhq): Why does this not include entries?
+ if (typeof params !== "undefined") {
+ dbUrl += "&filter=1&advanced=1";
+ for (const param in params) {
+ dbUrl += `&${param}=${encodeURIComponent(params[param])}`
+ }
+ }
+
+ const dbRes = await fetch(encodeURI(dbUrl));
+ const dbDoc = new DOMParser().parseFromString(await dbRes.text(), 'text/html');
+ let data: any[] = [];
+ dbDoc.querySelectorAll('.db-row').forEach(row => {
+ let entry: DatabaseEntry = {};
+ row.querySelectorAll<HTMLElement>('.db-cell').forEach(field => {
+ const key = field.dataset.key!;
+ let value;
+ // Moodle includes the full date in the title attribute of the included span
+ if (key === "date") {
+ value = field.querySelector("span")?.title;
+ } else {
+ value = field.innerText.trim();
+ }
+ entry[key] = value!;
+ });
+ data.push(entry);
+ });
+ return data;
+}
+
+async function getGraduationDb() {
+ return (await graduationDb)!;
+}
+
+async function addEntryToDatabaseActivity(id: number, json: string) {
+ // TODO(muhq): do not fetch the form
+ const url = `/mod/data/edit.php?id=${id}`;
+ const editRes = await fetch(url);
+ const editDoc = new DOMParser().parseFromString(await editRes.text(), 'text/html');
+ const form = editDoc.querySelector<HTMLFormElement>('div[role="main"] > form');
+
+ const formData = new FormData(form!);
+
+ for (const key of formData.keys()) {
+ if (key.startsWith("field_")) {
+ formData.set(key, json);
+ // We found our json key
+ break;
+ }
+ }
+ formData.set("saveandview", "Speichern");
+
+ return await fetch("/mod/data/edit.php", {
+ method: "POST",
+ // Set the FormData instance as the request body
+ body: formData,
+ });
+}
+
+export {
+ DB,
+ DatabaseEntry, DatabaseParams,
+ getGraduationDb,
+};