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
|
import { getCourseId, getUserIconUrl, getCourseParticipantsUrl } from "./utils-ENV.js";
import { fetchGraduation } from "./graduation-common.js";
/**
* Class to represent Students.
*/
class Student {
graduation = null;
constructor(id, name, group) {
this.id = id;
this.name = name;
this.group = group;
}
async getIconUrl() {
return await getUserIconUrl(this.id);
}
getGroup() {
return this.group;
}
async getGraduation() {
if(!this.graduation) {
// fetchGraduation(this) sets this.graduation
await fetchGraduation(this);
}
return this.graduation;
}
static async fetchById(id) {
let name = "";
let group = "";
const res = await fetch(`/user/view.php?id=${id}&course=${getCourseId()}`);
const doc = new DOMParser().parseFromString(await res.text(), "text/html");
name = doc.querySelector("div.page-header-headings > h2").textContent;
const cards = doc.querySelectorAll("div.card-body dl");
for (const card of cards) {
if (card.querySelector("dt").textContent !== "Gruppe")
continue;
group = card.querySelector("dd > a").textContent;
break;
}
return new Student(id, name, group);
}
}
// Cache the fetched students.
let students = [];
const idRegex = /id=(\d+)/;
async function _fetchStudents() {
const res = await fetch(getCourseParticipantsUrl());
const doc = new DOMParser().parseFromString(await res.text(), "text/html");
const table = doc.querySelector("tbody");
let fetchedStudents = [];
table.querySelectorAll("tr").forEach(row => {
if (row.classList.contains("emptyrow"))
return;
const roleCell = row.querySelector(".c4");
// TODO(muhq): Is this locale dependent?
if (roleCell.innerHTML.includes("Lehrer")) {
return;
}
const nameCell = row.querySelector(".c1");
let name;
if (nameCell.firstChild.firstChild.tagName == "SPAN")
name = nameCell.firstChild.firstChild.title;
else
name = nameCell.innerText;
const profileUrl = nameCell.querySelector("a.aabtn").href;
const match = idRegex.exec(profileUrl);
const id = match[1];
const groupCell = row.querySelector(".c5");
const group = groupCell.querySelector("a.quickeditlink").textContent;
fetchedStudents.push(new Student(id, name, group));
});
return fetchedStudents;
}
async function fetchStudents(idFilter, nameFilter, groupFilter) {
if (!students.size) {
const studentsPromise = _fetchStudents()
const storedStudents = localStorage.getItem("students");
if (storedStudents) {
studentsPromise.then((fetched) => localStorage.setItem("students", JSON.stringify(fetched)));
for (const o of JSON.parse(storedStudents)) {
students.push(new Student(o.id, o.name, o.group));
}
} else {
students = await studentsPromise;
localStorage.setItem("students", JSON.stringify(students));
}
}
return students.filter((s) => (!idFilter || s.id === idFilter) &&
(!nameFilter || s.name.includes(nameFilter)) &&
(!groupFilter || s.group.includes(groupFilter)));
}
async function fetchStudent(idFilter, nameFilter, groupFilter) {
const students = await fetchStudents(idFilter, nameFilter, groupFilter);
return students[0];
}
export { Student, fetchStudents, fetchStudent };
|