diff options
Diffstat (limited to 'src/database-prod.ts')
| -rw-r--r-- | src/database-prod.ts | 140 |
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, +}; |
