aboutsummaryrefslogtreecommitdiff
path: root/mass-graducation
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2026-07-12 09:33:58 +0200
committerFlorian Fischer <florian.fischer@muhq.space>2026-07-12 09:33:58 +0200
commit1a291fb37fdf0e5a1b2a54825e5af7c5e986f00f (patch)
tree3349f89ce4412b63c403411045185c80ba50a6bf /mass-graducation
parentb39d7dd42c75b096aa88ffc07ae78f1445c8e588 (diff)
downloadbycs-sol-1a291fb37fdf0e5a1b2a54825e5af7c5e986f00f.tar.gz
bycs-sol-1a291fb37fdf0e5a1b2a54825e5af7c5e986f00f.zip
implment observation period handling
Diffstat (limited to 'mass-graducation')
-rw-r--r--mass-graducation/index.css21
-rw-r--r--mass-graducation/index.html19
-rw-r--r--mass-graducation/package-lock.json4
-rw-r--r--mass-graducation/src/main.js163
4 files changed, 183 insertions, 24 deletions
diff --git a/mass-graducation/index.css b/mass-graducation/index.css
index 28f4b88..a8790b8 100644
--- a/mass-graducation/index.css
+++ b/mass-graducation/index.css
@@ -72,6 +72,8 @@
}
.group-member {
+ display: grid;
+ grid-template-columns: 30px 30px 200px repeat(3, 40px) auto 20px;
}
.group-member-name {
@@ -88,12 +90,15 @@
.group-member-green {
background: green;
+ margin: 1px;
}
.group-member-orange {
background: orange;
+ margin: 1px;
}
.group-member-red {
background: red;
+ margin: 1px;
}
#group-member-point-reason {
@@ -115,4 +120,20 @@
.group-member-observation-container {
background: lightgray;
+ width: 600px;
}
+
+.group-member-observation-table {
+ background: lightgray;
+
+}
+.group-member-observation-table-description {
+ width: 80%;
+}
+
+.group-member-observation-table-yes,
+.group-member-observation-table-no {
+ width: 10%;
+ text-align: center;
+}
+
diff --git a/mass-graducation/index.html b/mass-graducation/index.html
index 1ed7042..7a65745 100644
--- a/mass-graducation/index.html
+++ b/mass-graducation/index.html
@@ -16,7 +16,7 @@
class="group-selection"
placeholder="Klasse"
/>
- <button id="group-selection-clear" display="style: none;">&times;</button>
+ <button id="group-selection-clear" style="display: none;">&times;</button>
</div>
<ul id="group-selection-list">
</ul>
@@ -26,9 +26,20 @@
</div>
<div id="group-content" style="display: none">
- <ul id="group-members">
- </ul>
+ <div id="group-member-container">
+ <ul id="group-members">
+ </ul>
+ </div>
+ <button id="submit-mass-graduation" style="display: none;">Speichern</button>
+ <span id="submit-mass-graduation-state" style="display: none;"></span>
+
+ <div id="observation-requests-container" style="display: none;">
+ <h3>Aktuelle Graduierungswünsche</h3>
+ <table>
+ <tbody id="observation-requests">
+ </tbody>
+ </table>
+ </div>
</div>
- <button id="submit-mass-graduation" style="display: none">Speichern</button>
</body>
</html>
diff --git a/mass-graducation/package-lock.json b/mass-graducation/package-lock.json
index 6ba8178..18aa850 100644
--- a/mass-graducation/package-lock.json
+++ b/mass-graducation/package-lock.json
@@ -1,11 +1,11 @@
{
- "name": "cockpit",
+ "name": "mass-graduation",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "cockpit",
+ "name": "mass-graduation",
"version": "1.0.0",
"devDependencies": {
"html-webpack-plugin": "^5.6.7",
diff --git a/mass-graducation/src/main.js b/mass-graducation/src/main.js
index bae20bb..3d20f0b 100644
--- a/mass-graducation/src/main.js
+++ b/mass-graducation/src/main.js
@@ -13,13 +13,16 @@ import { getName } from "../../js/utils-ENV.js";
let group;
let name;
-function toggle(btn) {
- if (btn.innerHTML === "X")
+function toggle(btn, other) {
+ if (btn.innerHTML === "X") {
btn.innerHTML = "o";
- else
+ } else {
btn.innerHTML = "X";
+ if (other)
+ other.innerHTML = "o";
+ }
- document.getElementById("submit-mass-graduation").style.display = "block";
+ document.getElementById("submit-mass-graduation").style.display = "inline";
}
function observationClickHandler(ob, li) {
@@ -36,11 +39,17 @@ function observationClickHandler(ob, li) {
li.appendChild(observationDiv);
const obsTbl = document.createElement("table");
- obsTbl.id = "group-member-observation-table";
+ obsTbl.classList.add("group-member-observation-table");
observationDiv.appendChild(obsTbl);
const obsTh = document.createElement("thead");
- obsTh.innerHTML = "<tr><td></td><td>Ja</td><td>Nein</td></tr>";
+ obsTh.innerHTML = `
+<tr>
+ <th></th>
+ <th class="group-member-observation-table-yes">Ja</th>
+ <th class="group-member-observation-table-no">Nein</th>
+</tr>`;
+
obsTbl.appendChild(obsTh);
const obsTbdy = document.createElement("tbody");
@@ -51,19 +60,28 @@ function observationClickHandler(ob, li) {
const obsDesc = document.createElement("td");
obsDesc.innerHTML = obsType;
+ obsDesc.classList.add("group-member-observation-table-description");
obsTr.appendChild(obsDesc);
const obsYes = document.createElement("td");
obsYes.innerHTML = "o";
- obsYes.addEventListener("click", () => toggle(obsYes));
obsYes.dataset.yes = "true";
+ obsYes.classList.add("group-member-observation-table-yes");
obsTr.appendChild(obsYes);
const obsNo = document.createElement("td");
obsNo.innerHTML = "o";
- obsNo.addEventListener("click", () => toggle(obsNo) );
+ obsNo.dataset.no = "true";
+ obsNo.classList.add("group-member-observation-table-no");
obsTr.appendChild(obsNo);
+ obsYes.addEventListener("click", () => {
+ toggle(obsYes, obsNo);
+ });
+ obsNo.addEventListener("click", () => {
+ toggle(obsNo, obsYes);
+ });
+
obsTbdy.appendChild(obsTr);
}
// Toggle the observation container visibility
@@ -79,6 +97,7 @@ function observationClickHandler(ob, li) {
async function loadGroup(selected) {
group = selected;
const students = await group.getStudents();
+ let graduationPromises = [];
document.getElementById("group-content").style.display = "block";
const ul = document.getElementById("group-members");
@@ -93,18 +112,22 @@ async function loadGroup(selected) {
const ob = document.createElement("button");
ob.classList.add("group-member-observation-icon")
- student.getGraduation().then((graduation) => {
+
+ const graduationPromise = student.getGraduation();
+ graduationPromise.then((graduation) => {
if (!graduation.isObserved()) {
return;
}
ob.innerHTML = "&#128065"
ob.addEventListener("click", () => observationClickHandler(ob, li) );
});
+ graduationPromises.push(graduationPromise);
+
li.appendChild(ob);
const i = document.createElement("img");
i.classList.add("group-member-icon")
- student.getGraduation().then((graduation) => {
+ graduationPromise.then((graduation) => {
i.src = graduation.getIcon();
});
li.appendChild(i);
@@ -134,42 +157,146 @@ async function loadGroup(selected) {
ul.appendChild(li);
}
+
+ const graduations = await Promise.all(graduationPromises);
+ let observations = graduations.filter(
+ (g) => g.observationRequested || (g.observation && !g.observation.end)
+ );
+
+ const observationReuqestsContainer = document.getElementById("observation-requests-container");
+
+ if (observations.length == 0) {
+ observationReuqestsContainer.style.display = "none";
+ return;
+ } else {
+ observationReuqestsContainer.style.display = "unset";
+ }
+
+ const observationReuqestsNode = document.getElementById("observation-requests");
+ observationReuqestsNode.innerHTML = "";
+ observations.sort((g1, g2) => {
+ let g1D, g2D;
+ g1D = g1.observationRequested ? g1.observationRequested : g1.observation.start;
+ g2D = g2.observationRequested ? g2.observationRequested : g2.observation.start;
+ return g1D - g2D;
+ });
+
+ for (const graduation of observations) {
+ const row = document.createElement("tr");
+ const iconCell = document.createElement("td");
+ const icon = document.createElement("img");
+ icon.src = graduation.getIcon();
+ row.appendChild(iconCell);
+
+ const nameCell = document.createElement("td");
+ nameCell.innerHTML = `${graduation.student.name}`;
+ row.appendChild(nameCell);
+
+ const dateCell = document.createElement("td");
+ let date;
+ if (graduation.observationRequested) {
+ date = graduation.observationRequested;
+ } else {
+ date = graduation.observation.start;
+ }
+ dateCell.innerHTML = date.toLocaleString("de-DE", { month: "numeric", day: "numeric", year: "numeric", hour: "numeric", minute: "numeric" });
+ row.appendChild(dateCell);
+
+ const btnCell = document.createElement("td");
+ if (graduation.observation && !graduation.observation.ready()) {
+ btnCell.innerHTML = "In Beobachtungsphase";
+ } else {
+ const startBtn = document.createElement("button");
+ if (graduation.observationRequested) {
+ startBtn.addEventListener("click", () => {
+ graduation.startObservation();
+ //TODO(muhq): Add observation icon-button.
+ startBtn.remove();
+ btnCell.innerHTML = "In Beobachtungsphase";
+ });
+ startBtn.innerHTML = `Beobachtungsphase beginnen`;
+ startBtn.classList.add("start-observation");
+ } else {
+ startBtn.addEventListener("click", () => {
+ window.open(`/mod/page/view.php?id=93017047&userToLoad=${graduation.student.id}`, '_blank');
+ });
+ startBtn.innerHTML = `Graduierung abschließen`;
+ startBtn.classList.add("end-observation");
+ }
+ btnCell.appendChild(startBtn);
+ }
+ row.appendChild(btnCell);
+
+ observationReuqestsNode.appendChild(row);
+ }
}
function submitMassGraduation() {
+ let promises = [];
for(const li of document.querySelectorAll("li.group-member")) {
const reason = li.querySelector(".group-member-point-reason").value;
const student = li.student;
if (li.querySelector(".group-member-green").innerHTML === "X") {
- submitGraduationChange(student, GraduationChange.newGreenPointChange(reason, name));
+ promises.push(submitGraduationChange(student, GraduationChange.newGreenPointChange(reason, name)));
}
if (li.querySelector(".group-member-orange").innerHTML === "X") {
- submitGraduationChange(student, GraduationChange.newOrangePointChange(reason, name));
+ promises.push(submitGraduationChange(student, GraduationChange.newOrangePointChange(reason, name)));
}
if (li.querySelector(".group-member-red").innerHTML === "X") {
- submitGraduationChange(student, GraduationChange.newRedPointChange(reason, name));
+ promises.push(submitGraduationChange(student, GraduationChange.newRedPointChange(reason, name)));
}
if (li.observationDiv) {
let status = [];
for (const row of li.observationDiv.querySelectorAll("tbody > tr")) {
- status.push(row.querySelector('td[data-yes="true"]').innerHTML === "X");
+ if (row.querySelector('td[data-yes="true"]').innerHTML === "X")
+ status.push("yes");
+ else if (row.querySelector('td[data-no="true"]').innerHTML === "X")
+ status.push("no");
+ else
+ status.push("");
}
- submitObservation(student, new Observation(Date.now(), status));
+ promises.push(submitObservation(student, new Observation(new Date(), status)));
}
}
+
+ const state = document.getElementById("submit-mass-graduation-state");
+ Promise.all(promises).then(() => {
+ state.style.display = "inline";
+ state.innerHTML = "✓";
+ state.style.color = "green";
+ for (const li of document.querySelectorAll("li.group-member")) {
+ if (!li.observationDiv)
+ continue;
+ li.observationDiv.remove();
+ li.observationDiv = null;
+ }
+ }).catch((error) => {
+ state.style.display = "inline";
+ state.innerHTML = "X";
+ state.style.color = "red";
+ console.log(error);
+ });
}
function printRedPointNote(li) {
print();
}
-window.onload = function() {
+async function init() {
+ document.getElementById("submit-mass-graduation").addEventListener("click", submitMassGraduation);
+ name = getName();
+
initSelection(
"group-selection",
async function() { return (await fetchGroups()).values(); },
(group) => `${group.name}`,
loadGroup,
);
- document.getElementById("submit-mass-graduation").addEventListener("click", submitMassGraduation);
- name = getName();
}
+
+if (document.readyState === "loading") {
+ document.addEventListener("DOMContentLoaded", init);
+} else {
+ init();
+}
+