diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2026-08-06 12:19:33 +0200 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2026-08-06 12:19:33 +0200 |
| commit | c15ff0e4629eeed56a59e79cefdf66fb35451622 (patch) | |
| tree | de61a792e30faea7739e3b3d1c1947e1fb2e5b7e /src/mass-graduation.js | |
| parent | b8523bc935ee63a3246cbd6aa8c0e83d7e75c6db (diff) | |
| download | bycs-sol-c15ff0e4629eeed56a59e79cefdf66fb35451622.tar.gz bycs-sol-c15ff0e4629eeed56a59e79cefdf66fb35451622.zip | |
remove observations and present mandatory candidates in the mass view
Diffstat (limited to 'src/mass-graduation.js')
| -rw-r--r-- | src/mass-graduation.js | 281 |
1 files changed, 52 insertions, 229 deletions
diff --git a/src/mass-graduation.js b/src/mass-graduation.js index 48d23ad..a761130 100644 --- a/src/mass-graduation.js +++ b/src/mass-graduation.js @@ -1,111 +1,59 @@ -import { - OBSERVATION_TYPES, - GraduationChange, - submitGraduationChange, - Observation, - submitObservation, -} from "./graduation-ENV.ts"; +import { GraduationChange, submitGraduationChange } from "./graduation-ENV.ts"; import { fetchGroups } from "./group-fetch.ts"; import { initSelection } from "./selection.js"; -import { getName, DATETIME_FMT, datetimeStringNow } from "./utils-ENV.js"; +import { getName } from "./utils-ENV.js"; let group; let name; -function toggle(btn, others) { +function toggle(btn) { if (btn.innerHTML === "X") { btn.innerHTML = "o"; } else { btn.innerHTML = "X"; - if (others) { - for (const other of others) other.innerHTML = "o"; - } } document.getElementById("submit-mass-graduation").style.display = "inline"; document.getElementById("submit-mass-graduation-state").innerHTML = ""; } -function observationClickHandler(li) { - let observationDiv = li.observationDiv; - // Build the observation container - if (!observationDiv) { - li.style.background = "lightgray"; - - 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.classList.add("group-member-observation-table"); - observationDiv.appendChild(obsTbl); - - const obsTh = document.createElement("thead"); - obsTh.innerHTML = ` -<tr> - <th></th> - <th class="group-member-observation-table-yes">Ja</th> - <th class="group-member-observation-table-no">Nein</th> - <th class="group-member-observation-table-maybe">Kann ich nicht beurteilen</th> -</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; - obsDesc.classList.add("group-member-observation-table-description"); - obsTr.appendChild(obsDesc); - - const obsYes = document.createElement("td"); - obsYes.innerHTML = "o"; - obsYes.dataset.yes = "true"; - obsYes.classList.add("group-member-observation-table-yes"); - obsTr.appendChild(obsYes); - - const obsNo = document.createElement("td"); - obsNo.innerHTML = "o"; - obsNo.dataset.no = "true"; - obsNo.classList.add("group-member-observation-table-no"); - obsTr.appendChild(obsNo); +// https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array +function shuffleArray(array) { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + return array; +} - const obsMaybe = document.createElement("td"); - obsMaybe.innerHTML = "X"; - obsMaybe.dataset.maybe = "true"; - obsMaybe.classList.add("group-member-observation-table-maybe"); - obsTr.appendChild(obsMaybe); +function chooseMandatory(graduations) { + graduations.sort((g1, g2) => g1.mandatory - g2.mandatory); - obsYes.addEventListener("click", () => { - toggle(obsYes, [obsNo, obsMaybe]); - }); - obsNo.addEventListener("click", () => { - toggle(obsNo, [obsYes, obsMaybe]); - }); - obsMaybe.addEventListener("click", () => { - toggle(obsMaybe, [obsYes, obsNo]); - }); + // Get all graduations with smaller mandatory amount than the one with the highest amount + const mandatoryCandidates = graduations.filter( + (g) => g.mandatory < graduations[graduations.length - 1].mandatory, + ); + let rest; - obsTbdy.appendChild(obsTr); - } - // Toggle the observation container visibility + // All graduations have the same mandatory amount + if (mandatoryCandidates.length === 0) { + mandatoryCandidates = graduations; + rest = []; } else { - if (observationDiv.style.display === "none") { - observationDiv.style.display = "block"; - li.style.background = "lightgray"; - } else { - observationDiv.style.display = "none"; - li.style.background = "unset"; - } + rest = graduations.filter((g) => !mandatoryCandidates.includes(g)); } + + // Get a random list of possible indexes + const candidatesIdxs = shuffleArray([...Array(mandatoryCandidates.length).keys()]); + let chosen = candidatesIdxs.slice(0, 5).map((i) => mandatoryCandidates[i]); + if (chosen.length < 5) { + const missing = 5 - chosen.length; + const restIdxs = shuffleArray([...Array(rest.length).keys()]); + chosen = chosen.concat(restIdxs.slice(0, missing).map((i) => rest[i])); + } + + return chosen; } async function loadGroup(selected) { @@ -114,17 +62,20 @@ async function loadGroup(selected) { const graduationPromises = []; document.getElementById("group-content").style.display = "block"; + const mul = document.getElementById("group-mandatory-members"); const ul = document.getElementById("group-members"); - // Clear group list + + mul.innerHTML = ""; ul.innerHTML = ""; + const listEntries = []; for (const student of students) { const graduationPromise = student.getGraduation(); + graduationPromises.push(graduationPromise); const li = document.createElement("li"); - li.classList.add("group-member"); - // Remember the student of the entry li.student = student; + listEntries.push(li); const i = document.createElement("img"); i.classList.add("group-member-icon"); @@ -132,26 +83,19 @@ async function loadGroup(selected) { i.src = graduation.getIcon(); }); li.appendChild(i); + } + + const graduations = await Promise.all(graduationPromises); + const chosen = chooseMandatory(graduations); + + for (const li of listEntries) { + const student = li.student; const n = document.createElement("span"); n.classList.add("group-member-name"); n.innerHTML = `${student.name}`; li.appendChild(n); - const ob = document.createElement("button"); - ob.classList.add("group-member-observation-icon"); - - graduationPromise.then((graduation) => { - if (!graduation.isObserved()) { - return; - } - ob.innerHTML = "👁"; - ob.addEventListener("click", () => observationClickHandler(li)); - }); - graduationPromises.push(graduationPromise); - - li.appendChild(ob); - for (const col of ["green", "orange", "red"]) { const b = document.createElement("button"); b.classList.add(`group-member-${col}`); @@ -160,91 +104,13 @@ async function loadGroup(selected) { 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 = "🖶"; - p.addEventListener("click", () => printNote(li)); - li.appendChild(p); - - ul.appendChild(li); - } - - const graduations = await Promise.all(graduationPromises); - const 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) => { - const g1D = g1.observationRequested ? g1.observationRequested : g1.observation.start; - const 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 = DATETIME_FMT.format(date); - row.appendChild(dateCell); - - const btnCell = document.createElement("td"); - if (graduation.observation && !graduation.observation.ready()) { - btnCell.innerHTML = "In Beobachtungsphase"; + if (chosen.includes(student.graduation)) { + li.classList.add("group-mandatory-member"); + mul.appendChild(li); } 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); + li.classList.add("group-member"); + ul.appendChild(li); } - row.appendChild(btnCell); - - observationReuqestsNode.appendChild(row); } } @@ -275,15 +141,6 @@ function submitMassGraduation() { submitGraduationChange(student, GraduationChange.newRedPointChange(reason, name)), ); } - if (li.observationDiv) { - const status = []; - for (const row of li.observationDiv.querySelectorAll("tbody > tr")) { - 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(""); - } - promises.push(submitObservation(student, new Observation(new Date(), status))); - } } Promise.all(promises) @@ -308,40 +165,6 @@ function submitMassGraduation() { }); } -let prePrintBody = null; -function printNote(li) { - // save the current DOM - prePrintBody = document.body; - - // prepare the printable red point notice - const printBdy = document.createElement("body"); - const reason = li.querySelector(".group-member-point-reason").value; - const dateStr = datetimeStringNow(); - let pointType = ""; - if (li.querySelector(".group-member-orange").innerHTML === "X") { - pointType = "Oranger Punkt"; - } - if (li.querySelector(".group-member-red").innerHTML === "X") { - pointType = "Roter Punkt"; - } - - printBdy.innerHTML = ` -<h2>Dokuzettel</h2> -<h3>${pointType}</h3> -<p>Schüler*in: ${li.student.name}</p> -<p>Datum: ${dateStr}</p> -<p>Lehrkraft: ${name}</p> -<p>Klassenleitung: TODO</p> -<h3>Begründung</h3> -<p>${reason}</p> -`; - - document.body = printBdy; - print(); - // Restore the DOM after printing the red point note - document.body = prePrintBody; -} - async function init() { document.getElementById("submit-mass-graduation").addEventListener("click", submitMassGraduation); name = getName(); |
