diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2026-08-03 14:31:25 +0200 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2026-08-03 14:31:25 +0200 |
| commit | 6839831af54cd9302119bcc3bffafe10475958d4 (patch) | |
| tree | 12a1c1fbd864e9579cb9c3a09d4bf4686a280b73 /src/database.js | |
| parent | fccb70cbd876785f6833dfe6efc10ec9e445556d (diff) | |
| download | bycs-sol-6839831af54cd9302119bcc3bffafe10475958d4.tar.gz bycs-sol-6839831af54cd9302119bcc3bffafe10475958d4.zip | |
refactor project structure
* merge sites into single project root
* fix name of mass-graduation site
* enable typescript support
Diffstat (limited to 'src/database.js')
| -rw-r--r-- | src/database.js | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src/database.js b/src/database.js new file mode 100644 index 0000000..e929896 --- /dev/null +++ b/src/database.js @@ -0,0 +1,160 @@ +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 studentDbs = populateStudentDbs(); + +const ID_QUERY_PARAM_REGEX = /[?&]id=(\d+)/ + +async function populateStudentDbs() { + 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'); + + let dbs = new Map(); + for (const link of courseDoc.querySelectorAll("div.activityname a.aalink")) { + if (link.textContent.trim() === "Submit Datenbank") { + const dbId = link.href.match(ID_QUERY_PARAM_REGEX)[1] + dbs.set("submit", new DB(dbId)); + continue; + } + + const match = link.textContent.match(/(\d+)(Shadow|Public|Submit)/); + if (!match) continue; + const studentId = match[1]; + const dbType = match[2]; + const dbId = link.href.match(ID_QUERY_PARAM_REGEX)[1] + + if (!dbs.has(studentId)) { + dbs.set(studentId, {}); + } + + dbs.get(studentId)[dbType.toLowerCase()] = new DB(dbId); + } + + return dbs; +} + +async function getSubmitDb() { + const dbs = await studentDbs; + return dbs.get("submit"); +} + +class DB { + constructor(id) { + this.id = id; + } + + async fetchEntries(params) { + return loadFromDatabaseActivity(this.id, params) + } + + async saveEntry(json) { + return addEntryToDatabaseActivity(this.id, json); + } + + static async getStudentDbs(student) { + const dbs = await studentDbs; + return dbs.get(student.id); + } +} + +async function loadFromDatabaseActivity(id, params) { + let dbUrl = `${window.location.origin}/mod/data/view.php?id=${id}&mode=list&perpage=1000`; + // TODO(muhq): Why does this not include entries? + if (params) { + 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 = []; + dbDoc.querySelectorAll('.db-row').forEach(row => { + let entry = {}; + row.querySelectorAll('.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 loadFromStudentDatabase(student, type) { + const dbs = await DB.getStudentDbs(student); + const db = dbs[type]; + return await db.fetchEntries() +} + +async function addEntryToDatabaseActivity(id, json) { + 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('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, + }); +} + +async function addEntryToStudentDatabase(student, type, json) { + let db; + // global submit database + if (type === "submit") { + db = await getSubmitDb(); + // individuell databases + } else { + const dbs = await DB.getStudentDbs(student); + db = dbs[type]; + } + await db.saveEntry(json); +} + +export { + DB, + getSubmitDb, + loadFromDatabaseActivity, loadFromStudentDatabase, + addEntryToDatabaseActivity, addEntryToStudentDatabase, +}; |
