aboutsummaryrefslogtreecommitdiff
path: root/src/database-prod.ts
blob: 57b99741947873b1f892471a72e760f2fed26d8a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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 };