diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2026-08-10 14:19:41 +0200 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2026-08-10 14:19:41 +0200 |
| commit | 44bbb1f70d9663fc5015561118fa922dac3aed76 (patch) | |
| tree | 0c18696928c15f45cc2aadcc9ac6fb8b12332b08 /src | |
| parent | 7540fda09ef2d2c8bf45388255a0376e74807dd7 (diff) | |
| download | bycs-sol-44bbb1f70d9663fc5015561118fa922dac3aed76.tar.gz bycs-sol-44bbb1f70d9663fc5015561118fa922dac3aed76.zip | |
database: support entry deletion
Diffstat (limited to 'src')
| -rw-r--r-- | src/database-mock.ts | 5 | ||||
| -rw-r--r-- | src/database-prod.ts | 86 | ||||
| -rw-r--r-- | src/utils-mock.js | 4 | ||||
| -rw-r--r-- | src/utils-prod.js | 5 |
4 files changed, 90 insertions, 10 deletions
diff --git a/src/database-mock.ts b/src/database-mock.ts index 4d7bf55..1056be1 100644 --- a/src/database-mock.ts +++ b/src/database-mock.ts @@ -16,6 +16,11 @@ class DB { console.log(`Mock DB save entry ${json}`); return; } + + async deleteEntries(entryIds: [number]) { + console.log(`Mock DB delete entries ${entryIds}`); + return; + } } async function getGraduationDb() { diff --git a/src/database-prod.ts b/src/database-prod.ts index 57b9974..d41e829 100644 --- a/src/database-prod.ts +++ b/src/database-prod.ts @@ -1,9 +1,13 @@ -import { getCourseId } from "./utils-ENV.js"; +import { assert } from "./assert.ts"; +import { getCourseId, getSesskey } from "./utils-ENV.js"; const DB_TEMPLATE_LIST_HEADER = ` <table class="table table-striped"> <thead> <tr> + <th>ChangeId</th> + <th>Date</th> + <th>Coach</th> <th>Json</th> </tr> </thead> @@ -11,6 +15,7 @@ const DB_TEMPLATE_LIST_HEADER = ` `; const DB_TEMPLATE_LIST_ENTRY = ` <tr class="db-row"> + <td class="db-cell" data-key="changeId">##id##</td> <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> @@ -45,7 +50,7 @@ async function findGraduationDb() { return new DB(Number(dbId)); } } - console.assert(false, "Graduation DB not found"); + assert(false, "Graduation DB not found"); } interface DatabaseParams { @@ -58,22 +63,56 @@ interface DatabaseEntry { class DB { id: number; + d: Promise<number> | null = null; - constructor(id: number) { + constructor(id: number, d?: number) { this.id = id; + if (typeof d !== "undefined") { + this.d = new Promise((resolve) => { + resolve(d); + }); + } } async fetchEntries(params?: DatabaseParams) { - return loadFromDatabaseActivity(this.id, params); + return loadFromDatabaseActivity(this, params); } async saveEntry(json: string) { - return addEntryToDatabaseActivity(this.id, json); + return addEntryToDatabaseActivity(this, json); + } + + async deleteEntries(entryIds: [number]) { + return deleteFromDatabaseActivity(await this.getD(), entryIds); + } + + async getD() { + if (this.d === null) this.d = fetchDFromDatabaseActivity(this); + return this.d; } } -async function loadFromDatabaseActivity(id: string | number, params?: DatabaseParams) { - let dbUrl = `${window.location.origin}/mod/data/view.php?id=${id}&mode=list&perpage=1000`; +const dRegex = /d=(\d+)/; +function getDFromDbDoc(db: DB, dbDoc: Document) { + const urlWithD = dbDoc.querySelector<HTMLInputElement>('input[name="pageurl"]')!.value; + const match = dRegex.exec(urlWithD); + if (match === null) { + console.error(`d of database ${db.id} not found`); + return -1; + } + return Number(match[1]); +} + +async function fetchDFromDatabaseActivity(db: DB): Promise<number> { + let dbUrl = `${window.location.origin}/mod/data/view.php?id=${db.id}`; + const dbRes = await fetch(encodeURI(dbUrl)); + const dbDoc = new DOMParser().parseFromString(await dbRes.text(), "text/html"); + + return getDFromDbDoc(db, dbDoc); +} + +async function loadFromDatabaseActivity(db: DB, params?: DatabaseParams) { + let dbUrl = `${window.location.origin}/mod/data/view.php?id=${db.id}&mode=list&perpage=1000`; // TODO(muhq): Why does this not include entries? if (typeof params !== "undefined") { dbUrl += "&filter=1&advanced=1"; @@ -84,6 +123,13 @@ async function loadFromDatabaseActivity(id: string | number, params?: DatabasePa const dbRes = await fetch(encodeURI(dbUrl)); const dbDoc = new DOMParser().parseFromString(await dbRes.text(), "text/html"); + + if (db.d === null) { + db.d = new Promise((resolve) => { + resolve(getDFromDbDoc(db, dbDoc)); + }); + } + let data: any[] = []; dbDoc.querySelectorAll(".db-row").forEach((row) => { let entry: DatabaseEntry = {}; @@ -107,9 +153,9 @@ async function getGraduationDb() { return (await graduationDb)!; } -async function addEntryToDatabaseActivity(id: number, json: string) { +async function addEntryToDatabaseActivity(db: DB, json: string) { // TODO(muhq): do not fetch the form - const url = `/mod/data/edit.php?id=${id}`; + const url = `/mod/data/edit.php?id=${db.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'); @@ -127,9 +173,29 @@ async function addEntryToDatabaseActivity(id: number, json: string) { return await fetch("/mod/data/edit.php", { method: "POST", - // Set the FormData instance as the request body body: formData, }); } +async function deleteFromDatabaseActivity(d: number, entryIds: [number]) { + const promises = []; + assert(d != -1, "DB has no valid d yet."); + for (const entryId of entryIds) { + const formData = new FormData(); + + formData.set("d", String(d)); + formData.set("sesskey", getSesskey()); + formData.set("confirm", "1"); + formData.set("delete", String(entryId)); + + promises.push( + fetch("/mod/data/view.php", { + method: "POST", + body: formData, + }), + ); + } + return Promise.all(promises); +} + export { DB, DatabaseEntry, DatabaseParams, getGraduationDb }; diff --git a/src/utils-mock.js b/src/utils-mock.js index ab4bbed..7ee3779 100644 --- a/src/utils-mock.js +++ b/src/utils-mock.js @@ -42,6 +42,10 @@ export function getCourseId() { return "1337"; } +export function getSesskey() { + return "sesskey"; +} + export function getCourseParticipantsUrl() { console.error("Try to get mocked participations URL"); return ""; diff --git a/src/utils-prod.js b/src/utils-prod.js index 94d724a..6b274d8 100644 --- a/src/utils-prod.js +++ b/src/utils-prod.js @@ -40,6 +40,11 @@ export function getCourseId() { return String(M.cfg.courseId); } +export function getSesskey() { + // M is exported by Moodle + return String(M.cfg.sesskey); +} + export function getCourseParticipantsUrl() { return `https://lernplattform.bycs.de/user/index.php?id=${getCourseId()}&perpage=5000`; } |
