diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2026-07-01 18:39:16 +0200 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2026-07-01 18:39:16 +0200 |
| commit | 4de58eb1723247d327bb9adbdd35d92cd050369b (patch) | |
| tree | c46cfa469d71ecde478d3e5544ebb6967188478d | |
| parent | 38456da30c1729ef3696ec935f19dfa982e07ec7 (diff) | |
| download | bycs-sol-4de58eb1723247d327bb9adbdd35d92cd050369b.tar.gz bycs-sol-4de58eb1723247d327bb9adbdd35d92cd050369b.zip | |
mass-graduation: implement the requested prototype
| -rw-r--r-- | mass-graducation/index.css | 30 | ||||
| -rw-r--r-- | mass-graducation/index.html | 1 | ||||
| -rw-r--r-- | mass-graducation/src/main.js | 179 |
3 files changed, 116 insertions, 94 deletions
diff --git a/mass-graducation/index.css b/mass-graducation/index.css index e5abccf..28f4b88 100644 --- a/mass-graducation/index.css +++ b/mass-graducation/index.css @@ -87,23 +87,19 @@ } .group-member-green { - color: green; + background: green; } .group-member-orange { - color: orange; + background: orange; } .group-member-red { - color: red; + background: red; } -#group-member-point-reason-container { - margin: 0.2rem; -} - -#grou-member-point-reason { +#group-member-point-reason { box-sizing: border-box; padding: 10px; - width: 100%; + width: 50%; font-size: 0.8rem; letter-spacing: 1px; line-height: 1.5; @@ -111,14 +107,12 @@ border: 1px solid #cccccc; } -#group-member-point-reason-submit { - position: absolute; - right: 0.75rem; - transform: translateY(-175%); - border: none; - background: transparent; - font-size: 1.875rem; - cursor: pointer; - color: #888; +.group-member-print { + background: none; + border: none; + font-size: larger; } +.group-member-observation-container { + background: lightgray; +} diff --git a/mass-graducation/index.html b/mass-graducation/index.html index 88ac916..1ed7042 100644 --- a/mass-graducation/index.html +++ b/mass-graducation/index.html @@ -29,5 +29,6 @@ <ul id="group-members"> </ul> </div> + <button id="submit-mass-graduation" style="display: none">Speichern</button> </body> </html> diff --git a/mass-graducation/src/main.js b/mass-graducation/src/main.js index 0f0de07..bae20bb 100644 --- a/mass-graducation/src/main.js +++ b/mass-graducation/src/main.js @@ -1,84 +1,79 @@ import { + OBSERVATION_TYPES, GraduationChange, - submitGraduationChange + submitGraduationChange, + Observation, + submitObservation } from "../../js/graduation-ENV.js"; -import { fetchBycsGroups } from "../../js/group.js"; +import { fetchGroups } from "../../js/group.js"; import { initSelection } from "../../js/selection.js"; +import { getName } from "../../js/utils-ENV.js"; let group; +let name; -function observationClickHandler(li, student) { - const observationDiv = document.createElement("div"); - observationDiv.id = "group-member-observation-container"; - observationDiv.popover = true; - li.appendChild(observationDiv); +function toggle(btn) { + if (btn.innerHTML === "X") + btn.innerHTML = "o"; + else + btn.innerHTML = "X"; - const submitBtn = document.createElement("button"); - submitBtn.id = "group-member-observation-submit"; - observationDiv.appendChild(submitBtn); + document.getElementById("submit-mass-graduation").style.display = "block"; } -function pointClickHandler(li, student, color) { - const textareaDiv = document.createElement("div"); - textareaDiv.id = "group-member-point-reason-container"; - li.appendChild(textareaDiv); - - const textarea = document.createElement("textarea"); - textarea.id = "group-member-point-reason"; - textareaDiv.appendChild(textarea); - - const submitBtn = document.createElement("button"); - submitBtn.id = "group-member-point-reason-submit"; - textareaDiv.appendChild(submitBtn); - - // TODO(muhq): Prefill the textarea with common reasons - switch (color) { - case "green": - textarea.style.background = "rgb(from green r g b / 20%)" - textarea.value = ""; - break; - case "orange": - textarea.style.background = "rgb(from orange r g b / 20%)" - textarea.value = ""; - break; - case "red": - textarea.style.background = "rgb(from red r g b / 20%)" - textarea.value = ""; - break; - } - textarea.focus(); - - let submit = function() { - let change; - switch (color) { - case "green": - change = GraduationChange.newGreenPointChange(student, textarea.value); - break; - case "orange": - change = GraduationChange.newOrangePointChange(student, textarea.value); - break; - case "red": - change = GraduationChange.newRedPointChange(student, textarea.value); - break; - default: - alert("Invalid color"); - break; - } - submitGraduationChange(student, change); - li.removeChild(textareaDiv); - } - - // Use onEVENT to override any previous handler - textarea.onkeydown = function(e) { - if (e.shiftKey && e.key === "Enter") { - submit(); +function observationClickHandler(ob, li) { + ob.style.background = "lightgray"; + + let observationDiv = li.observationDiv; + // Build the observation container + if(!observationDiv) { + observationDiv = document.createElement("div"); + // Remember the observation div for this student + li.observationDiv = observationDiv; + observationDiv.id = `${li.student.name}-observation-container`; + observationDiv.classList.add("group-member-observation-container"); + li.appendChild(observationDiv); + + const obsTbl = document.createElement("table"); + obsTbl.id = "group-member-observation-table"; + observationDiv.appendChild(obsTbl); + + const obsTh = document.createElement("thead"); + obsTh.innerHTML = "<tr><td></td><td>Ja</td><td>Nein</td></tr>"; + obsTbl.appendChild(obsTh); + + const obsTbdy = document.createElement("tbody"); + obsTbl.appendChild(obsTbdy); + + for (const obsType of OBSERVATION_TYPES) { + const obsTr = document.createElement("tr"); + + const obsDesc = document.createElement("td"); + obsDesc.innerHTML = obsType; + obsTr.appendChild(obsDesc); + + const obsYes = document.createElement("td"); + obsYes.innerHTML = "o"; + obsYes.addEventListener("click", () => toggle(obsYes)); + obsYes.dataset.yes = "true"; + obsTr.appendChild(obsYes); + + const obsNo = document.createElement("td"); + obsNo.innerHTML = "o"; + obsNo.addEventListener("click", () => toggle(obsNo) ); + obsTr.appendChild(obsNo); + + obsTbdy.appendChild(obsTr); } - if (e.key === "Escape") { - textareaDiv.style.display = "none"; + // Toggle the observation container visibility + } else { + if (observationDiv.style.display === "none") { + observationDiv.style.display = "block"; + } else { + observationDiv.style.display = "none"; } - }; - submitBtn.onclick = submit; + } } async function loadGroup(selected) { @@ -93,16 +88,17 @@ async function loadGroup(selected) { for (const student of students) { const li = document.createElement("li"); li.classList.add("group-member") + // Remember the student of the entry + li.student = student; const ob = document.createElement("button"); ob.classList.add("group-member-observation-icon") - ob.popovertarget="group-member-observation-popover" student.getGraduation().then((graduation) => { if (!graduation.isObserved()) { return; } ob.innerHTML = "👁" - ob.addEventListener("click", () => observationClickHandler(li, student) ); + ob.addEventListener("click", () => observationClickHandler(ob, li) ); }); li.appendChild(ob); @@ -111,7 +107,6 @@ async function loadGroup(selected) { student.getGraduation().then((graduation) => { i.src = graduation.getIcon(); }); - // TODO: fetch the students state icon li.appendChild(i); const n = document.createElement("span"); @@ -122,27 +117,59 @@ async function loadGroup(selected) { for (const col of ["green", "orange", "red"]) { const b = document.createElement("button"); b.classList.add(`group-member-${col}`) - b.innerHTML = col; - b.addEventListener("click", () => pointClickHandler(li, student, col)); + b.innerHTML = "o"; + b.addEventListener("click", () => toggle(b) ); li.appendChild(b); } + const textarea = document.createElement("textarea"); + textarea.classList.add("group-member-point-reason"); + li.appendChild(textarea); + const p = document.createElement("button"); p.classList.add("group-member-print") - p.innerHTML = `print`; - p.addEventListener("click", () => print() ); + p.innerHTML = "🖶"; + p.addEventListener("click", () => printRedPointNote(li) ); li.appendChild(p); ul.appendChild(li); } } +function submitMassGraduation() { + 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)); + } + if (li.querySelector(".group-member-orange").innerHTML === "X") { + submitGraduationChange(student, GraduationChange.newOrangePointChange(reason, name)); + } + if (li.querySelector(".group-member-red").innerHTML === "X") { + 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"); + } + submitObservation(student, new Observation(Date.now(), status)); + } + } +} + +function printRedPointNote(li) { + print(); +} + window.onload = function() { initSelection( "group-selection", - async function() { return (await fetchBycsGroups()).values(); }, + async function() { return (await fetchGroups()).values(); }, (group) => `${group.name}`, loadGroup, ); + document.getElementById("submit-mass-graduation").addEventListener("click", submitMassGraduation); name = getName(); } |
