Aufgaben verteilen: der Knopf ist nie mehr tot, und die Bewerbung steht im Formular
screen1 -- „dogfather, die rechte hand und die linke hand sollen immer
noch aufgaben werden teilen können plus die option dass die modis sich
für aufgaben bewerben können. weil gerade hängt das und weiß nicht
wieso."
WAS WIRKLICH LOS WAR -- gemessen, nicht geraten
Auf entwicklung.html stand oben „Aufgabe verteilen · Wähl LINKS
jemanden aus", und der Knopf war so lange abgeschaltet. Im Browser
nachgemessen (1420 px, als DogFather):
Band oben 284 px, linke Kante 130 px
Personenwahl oben 490 px, linke Kante 130 px
-> UNTER dem Band, 127 px darunter, gleiche linke Kante
Links war nichts. Wer der Anweisung folgte, schaute auf eine leere
Fläche und hatte einen Knopf, der nicht ging. Das Recht selbst war die
ganze Zeit richtig: `darfAufgabenVerteilen` = Leitung oder Hand, also
DogFather, rechte Hand UND linke Hand -- alle drei mit
`darf_verteilen: true` gemessen.
Kurz: Die Regel stimmte, der Weg dorthin nicht.
WAS JETZT ANDERS IST
1. DER KNOPF IST IMMER BENUTZBAR. Er öffnet das Formular, auch ohne
vorherige Auswahl.
2. DIE FRAGE „für wen" STEHT IM FORMULAR, als erste Zeile, mit allen
Personen zur Wahl. Wer unten eine Kachel angeklickt hat, findet sie
angehakt wieder -- beide Wege führen zum selben Ziel.
3. EINE LISTE STATT ZWEIER. „Noch jemanden dazunehmen" ist weg. Es
waren zwei Bedienungen für dieselbe Frage -- und die
Bewerbungs-Option steckte ausgerechnet in der zugeklappten
zweiten: Sie war nur zu finden, wenn man erst aufklappte UND dort
jemanden ankreuzte. Eine Möglichkeit, die man nicht findet, gibt es
nicht.
4. DIE BEWERBUNG STEHT DA, sobald zwei Leute angehakt sind: „Wer
zuerst Zeit hat, übernimmt. Sie bewerben sich, du nimmst an oder
lehnst ab."
ZWEI FEHLER, DIE DABEI AUFFIELEN
* Nach dem Anlegen wurde `fuerPerson` auf null gesetzt und DANACH
`aufgabenZeigen(fuerPerson, …)` aufgerufen -- die Liste, die zeigen
soll, was gerade entstanden ist, blendete sich damit aus. Die Namen
werden jetzt festgehalten, bevor `reset()` sie abräumt.
* Die Bestätigung sagte immer „steht jetzt bei ihm" -- `fuerName` wird
nur beim Klick auf eine Kachel gefüllt. Sie sagt jetzt, was wirklich
passiert ist, und bei einem Pool, dass eine Bewerbung kommt.
* `e-mehr-art` heisst `e-art`: Der Name sagte „gehört zu ‚noch
jemand'", und das gibt es nicht mehr. Dieselbe Sorte Falle wie
`tperson__namen` heute Nachmittag.
DIE PRÜFUNG HATTE MEINEN FEHLER FESTGESCHRIEBEN
`pruef-bewerbung-aufgaben.mjs` enthielt wörtlich:
ok(vorher.aus === true,
"und ist aus, solange niemand gewaehlt ist");
Sie lief, sie war grün, und sie hat den toten Knopf verteidigt. Das
ist die unangenehmste Sorte: nicht übersprungen, nicht kaputt --
sondern eine Bestätigung meines Entwurfs statt der Sache. Jetzt wird
das Gegenteil verlangt.
Dazu zwei neue Abschnitte (84 -> 101 Prüfungen, 0 Fehler):
6b verteilen OHNE vorherige Auswahl, als Pool, samt Nachweis am
Server (verteilart=pool, zwei Leute darin) und der Meldung, die
nicht „bei ihm" sagen darf
6c alle drei Rollen am Bildschirm: DogFather, rechte Hand, linke
Hand -- mit Gegenprobe, dass ein Modi das Band NICHT sieht
EIGENER MESSFEHLER, offen notiert: Mein erster Versuch, die Bewerbung
nachzustellen, meldete „kein Abruf, nichts passiert". Der Knopf öffnet
eine Rückfrage, und die hatte ich nicht beantwortet. Die Bewerbung war
nie kaputt -- meine Messung war es. Erst der zweite Anlauf zeigte den
ganzen Weg: POST /api/aufgaben/1/bewerben -> {"ok":true,"zustand":"beworben"}.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -358,21 +358,35 @@
|
||||
fuerPerson = personId || null;
|
||||
fuerName = name || null;
|
||||
|
||||
/* DER KNOPF IST NIE AUS (22.09.2026 abends).
|
||||
|
||||
Vorher: Ohne vorherige Auswahl war er abgeschaltet, und
|
||||
daneben stand „Wähl links jemanden aus". Gemessen steht die
|
||||
Auswahl aber gar nicht links, sondern 206 px WEITER UNTEN, bei
|
||||
derselben linken Kante. Wer der Anweisung folgte, schaute auf
|
||||
eine leere Fläche -- und hatte einen Knopf, der nicht ging.
|
||||
|
||||
Filipe: „weil gerade hängt das und weiß nicht wieso."
|
||||
|
||||
Ein toter Knopf mit einer falschen Erklärung daneben ist die
|
||||
schlechteste Kombination: Man sucht den Fehler bei sich. Die
|
||||
Auswahl steht jetzt IM Formular; der Knopf öffnet es immer.
|
||||
Wer unten schon jemanden angeklickt hat, findet ihn angehakt
|
||||
wieder. */
|
||||
knopf.disabled = false;
|
||||
if (personId) {
|
||||
knopf.textContent = name ? `Aufgabe für ${name}` : 'Aufgabe anlegen';
|
||||
knopf.disabled = false;
|
||||
satz.textContent = name
|
||||
? `Sie landet direkt bei ${name} — mit einer Meldung.`
|
||||
: 'Sie landet direkt bei der gewählten Person.';
|
||||
} else {
|
||||
knopf.textContent = 'Aufgabe anlegen';
|
||||
/* OHNE PERSON GIBT ES NICHTS ZU VERTEILEN. Der Knopf bleibt
|
||||
sichtbar (sonst springt die Seite beim Auswaehlen), aber
|
||||
abgeschaltet -- und der Satz sagt, was fehlt. */
|
||||
knopf.disabled = true;
|
||||
satz.textContent = 'Wähl links jemanden aus — dann legst du die Aufgabe direkt für ihn an.';
|
||||
formularZu();
|
||||
satz.textContent = 'Aufgabe anlegen und an eine oder mehrere Personen geben.';
|
||||
}
|
||||
/* Steht das Formular schon offen, zieht die Auswahl darin mit --
|
||||
sonst haette man unten jemanden angeklickt und oben stuende
|
||||
weiterhin der alte Haken. */
|
||||
if (!$('e-neu')?.hidden) fuerLeuteBauen();
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
@@ -402,42 +416,87 @@
|
||||
if (auf) auf.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
|
||||
function formularAuf() {
|
||||
const f = $('e-neu');
|
||||
if (!f || !fuerPerson) return;
|
||||
f.hidden = false;
|
||||
$('verteilen-knopf').setAttribute('aria-expanded', 'true');
|
||||
$('e-neu-fehler').textContent = '';
|
||||
/* DIE ANDEREN ZUR AUSWAHL -- ohne die schon gewaehlte Person.
|
||||
Sie zweimal anzubieten hiesse, man koennte sie doppelt
|
||||
eintragen; der Server wuerde es abfangen, aber die Frage
|
||||
haette gar nicht erst gestellt werden duerfen. */
|
||||
const ziel = $('e-mehr-leute');
|
||||
/* =====================================================================
|
||||
DIE EINE PERSONENLISTE
|
||||
|
||||
Sie ersetzt zwei: „Für wen?" (oben, vorher gar nicht im Formular)
|
||||
und „Noch jemanden dazunehmen" (unten, zugeklappt). Zwei Listen
|
||||
für dieselbe Frage waren zwei Bedienungen -- und die
|
||||
Bewerbungs-Option steckte ausgerechnet in der zugeklappten.
|
||||
|
||||
DIE REIHENFOLGE DER HAKEN ENTSCHEIDET, WER VORN STEHT: Der erste
|
||||
Angehakte ist die Hauptperson, die weiteren kommen dazu. Das
|
||||
steht hier an einer Stelle, damit `fuerPerson` und `mehrLeute`
|
||||
nicht auseinanderlaufen können -- sie werden beide aus derselben
|
||||
Liste abgeleitet und nirgends sonst gesetzt.
|
||||
===================================================================== */
|
||||
function auswahlLesen() {
|
||||
const ziel = $('e-fuer-leute');
|
||||
if (!ziel) return;
|
||||
const an = [...ziel.querySelectorAll('input:checked')].map((x) => Number(x.value));
|
||||
fuerPerson = an.length ? an[0] : null;
|
||||
mehrLeute = an.slice(1);
|
||||
/* DIE ART FRAGT NUR, WER MEHR ALS EINEN EINTRAEGT. Bei einer
|
||||
Person gibt es nichts zu verteilen -- die Frage waere
|
||||
Fuellwerk. */
|
||||
$('e-art').hidden = an.length < 2;
|
||||
if (an.length < 2) {
|
||||
const einzeln = $('e-art').querySelector('input[value="mehrere"]');
|
||||
if (einzeln) einzeln.checked = true;
|
||||
}
|
||||
const knopf = $('verteilen-knopf');
|
||||
const name = an.length
|
||||
? (leute.find((x) => String(x.id) === String(fuerPerson))?.name || null) : null;
|
||||
if (knopf) {
|
||||
knopf.textContent = an.length > 1
|
||||
? `Aufgabe für ${an.length} Personen`
|
||||
: name ? `Aufgabe für ${name}` : 'Aufgabe anlegen';
|
||||
}
|
||||
const satz = $('verteilen-satz');
|
||||
if (satz) {
|
||||
satz.textContent = an.length > 1
|
||||
? 'Sie geht an alle Angehakten — wie, sagst du gleich darunter.'
|
||||
: name ? `Sie landet direkt bei ${name} — mit einer Meldung.`
|
||||
: 'Aufgabe anlegen und an eine oder mehrere Personen geben.';
|
||||
}
|
||||
}
|
||||
|
||||
function fuerLeuteBauen() {
|
||||
const ziel = $('e-fuer-leute');
|
||||
if (!ziel) return;
|
||||
/* WAS SCHON ANGEHAKT WAR, BLEIBT ANGEHAKT. Die Liste wird auch
|
||||
neu gebaut, wenn man unten eine andere Person anklickt --
|
||||
wer dabei seine Haken verliert, fängt von vorn an. */
|
||||
const warAn = new Set([...ziel.querySelectorAll('input:checked')].map((x) => x.value));
|
||||
if (fuerPerson !== null && fuerPerson !== undefined) warAn.add(String(fuerPerson));
|
||||
ziel.replaceChildren();
|
||||
mehrLeute = [];
|
||||
for (const p2 of (leute || [])) {
|
||||
if (String(p2.id) === String(fuerPerson)) continue;
|
||||
const zeile = document.createElement('label');
|
||||
zeile.className = 'z-wahl__zeile';
|
||||
const k = document.createElement('input');
|
||||
k.type = 'checkbox';
|
||||
k.value = String(p2.id);
|
||||
k.addEventListener('change', () => {
|
||||
mehrLeute = [...ziel.querySelectorAll('input:checked')].map((x) => Number(x.value));
|
||||
/* DIE ART FRAGT NUR, WER MEHR ALS EINEN EINTRAEGT. Bei einer
|
||||
Person gibt es nichts zu verteilen -- die Frage waere
|
||||
Fuellwerk. */
|
||||
$('e-mehr-art').hidden = mehrLeute.length === 0;
|
||||
});
|
||||
k.checked = warAn.has(String(p2.id));
|
||||
k.addEventListener('change', auswahlLesen);
|
||||
const t = document.createElement('span');
|
||||
t.textContent = p2.name || 'Jemand';
|
||||
zeile.append(k, t);
|
||||
ziel.append(zeile);
|
||||
}
|
||||
$('e-mehr-art').hidden = true;
|
||||
$('e-mehr').hidden = true;
|
||||
$('e-mehr-auf').setAttribute('aria-expanded', 'false');
|
||||
$('e-titel').focus();
|
||||
auswahlLesen();
|
||||
}
|
||||
|
||||
function formularAuf() {
|
||||
const f = $('e-neu');
|
||||
if (!f) return;
|
||||
f.hidden = false;
|
||||
$('verteilen-knopf').setAttribute('aria-expanded', 'true');
|
||||
$('e-neu-fehler').textContent = '';
|
||||
fuerLeuteBauen();
|
||||
/* OHNE AUSWAHL IST DIE ERSTE FRAGE „für wen" -- dorthin der
|
||||
Blick. Steht sie schon fest, fehlt nur noch der Titel. */
|
||||
if (fuerPerson) $('e-titel').focus();
|
||||
else $('e-fuer-leute').querySelector('input')?.focus();
|
||||
}
|
||||
|
||||
function aufgabenFormularAufbauen() {
|
||||
@@ -450,20 +509,20 @@
|
||||
});
|
||||
$('e-neu-abbrechen').addEventListener('click', () => {
|
||||
$('e-neu').reset();
|
||||
mehrLeute = [];
|
||||
/* ZURUECK AUF DIE KACHEL, NICHT AUF NICHTS. Wer abbricht, hat
|
||||
unten meist trotzdem jemanden ausgewaehlt -- der Knopf soll
|
||||
dann wieder „Aufgabe fuer X" heissen und nicht so tun, als
|
||||
waere die Auswahl auch weg. Sie wird aus der Kachel GELESEN
|
||||
und nicht daneben gemerkt: zwei Stellen, die sich dieselbe
|
||||
Person merken, laufen auseinander. */
|
||||
const kachel = document.querySelector('#personen .e-person[aria-pressed="true"]');
|
||||
verteilBandZeigen(kachel ? Number(kachel.dataset.person) : null,
|
||||
kachel ? (kachel.dataset.name || null) : null);
|
||||
formularZu();
|
||||
});
|
||||
$('e-mehr-auf').addEventListener('click', () => {
|
||||
const k = $('e-mehr');
|
||||
k.hidden = !k.hidden;
|
||||
$('e-mehr-auf').setAttribute('aria-expanded', String(!k.hidden));
|
||||
$('e-mehr-auf').textContent = k.hidden
|
||||
? 'Noch jemanden dazunehmen' : 'Doch nur eine Person';
|
||||
if (k.hidden) {
|
||||
for (const x of $('e-mehr-leute').querySelectorAll('input:checked')) x.checked = false;
|
||||
mehrLeute = [];
|
||||
$('e-mehr-art').hidden = true;
|
||||
}
|
||||
});
|
||||
/* Der Klapp-Knopf „Noch jemanden dazunehmen" ist weg -- es gibt
|
||||
nur noch eine Liste, und sie ist von Anfang an offen. */
|
||||
|
||||
$('e-neu').addEventListener('submit', async (ev) => {
|
||||
ev.preventDefault();
|
||||
@@ -476,14 +535,18 @@
|
||||
return;
|
||||
}
|
||||
if (!fuerPerson) {
|
||||
melder.textContent = 'Wähl links erst jemanden aus.';
|
||||
/* KEIN „links" MEHR. Dort steht nichts -- gemessen. Der
|
||||
Hinweis zeigt jetzt auf die Zeile, die im selben Formular
|
||||
direkt darüber steht. */
|
||||
melder.textContent = 'Hak oben an, für wen die Aufgabe ist.';
|
||||
$('e-fuer-leute')?.querySelector('input')?.focus();
|
||||
return;
|
||||
}
|
||||
const knopf = $('e-neu-speichern');
|
||||
knopf.disabled = true;
|
||||
try {
|
||||
const art = mehrLeute.length
|
||||
? ($('e-mehr-art').querySelector('input[name="e-verteilart"]:checked')?.value || 'mehrere')
|
||||
? ($('e-art').querySelector('input[name="e-verteilart"]:checked')?.value || 'mehrere')
|
||||
: 'einzeln';
|
||||
const a = await fetch('/workspace/api/aufgaben', {
|
||||
method: 'POST',
|
||||
@@ -511,16 +574,53 @@
|
||||
oder die Art aendern -- wer das verschweigt, laesst jemanden
|
||||
in dem Glauben, er habe drei Leute eingetragen. */
|
||||
const gesetzt = r?.zuteilung?.gesetzt;
|
||||
const alleIds = [Number(fuerPerson), ...mehrLeute];
|
||||
const fehlt = Array.isArray(gesetzt)
|
||||
? [Number(fuerPerson), ...mehrLeute].filter((x) => !gesetzt.includes(x)).length
|
||||
? alleIds.filter((x) => !gesetzt.includes(x)).length
|
||||
: 0;
|
||||
|
||||
/* ERST MERKEN, DANN AUFRAEUMEN (22.09.2026 abends).
|
||||
|
||||
Hier wurde `fuerPerson` auf null gesetzt und danach
|
||||
`aufgabenZeigen(fuerPerson, …)` aufgerufen -- die Liste,
|
||||
die gerade zeigen soll, was eben entstanden ist, wurde
|
||||
damit ausgeblendet. Und die Meldung las `fuerName`, das
|
||||
nur beim Klick auf eine Kachel gefuellt wird; wer im
|
||||
Formular ankreuzte, bekam „steht jetzt bei ihm".
|
||||
|
||||
Die Namen kommen jetzt aus derselben Liste wie die Haken
|
||||
und werden festgehalten, BEVOR `reset()` sie abraeumt. */
|
||||
const namenVon = (id) =>
|
||||
(leute.find((x) => String(x.id) === String(id))?.name || null);
|
||||
const ersterName = fuerName || namenVon(fuerPerson);
|
||||
const wieViele = alleIds.length;
|
||||
const zeigeFuer = Number(fuerPerson);
|
||||
const zeigeName = ersterName;
|
||||
const istPool = art === 'pool';
|
||||
|
||||
$('e-neu').reset();
|
||||
mehrLeute = [];
|
||||
fuerPerson = null;
|
||||
formularZu();
|
||||
|
||||
/* DIE MELDUNG SAGT, WAS WIRKLICH PASSIERT IST -- nicht immer
|
||||
denselben Satz. Bei einem Pool ist das Entscheidende, dass
|
||||
jetzt eine Bewerbung kommt und nicht etwa schon jemand
|
||||
dransitzt. */
|
||||
melde(fehlt
|
||||
? `Angelegt — aber ${fehlt} Person(en) konnten nicht eingetragen werden.`
|
||||
: `„${titel}" steht jetzt bei ${fuerName || 'ihm'}.`, !fehlt);
|
||||
await aufgabenZeigen(fuerPerson, fuerName);
|
||||
: wieViele === 1
|
||||
? `„${titel}" steht jetzt bei ${ersterName || 'der gewählten Person'}.`
|
||||
: istPool
|
||||
? `„${titel}" liegt für ${wieViele} Leute bereit — wer zuerst Zeit hat,`
|
||||
+ ' bewirbt sich, und du entscheidest.'
|
||||
: `„${titel}" steht jetzt bei ${wieViele} Leuten — jede hat ihren`
|
||||
+ ' eigenen Stand.',
|
||||
!fehlt);
|
||||
/* UND DIE LISTE DARUNTER ZEIGT DIE ERSTE PERSON. Sie ist die,
|
||||
die im Knopf stand; wer mehrere eingetragen hat, findet den
|
||||
Rest ueber deren Kacheln. */
|
||||
await aufgabenZeigen(zeigeFuer, zeigeName);
|
||||
} catch {
|
||||
melder.textContent = 'Das hat gerade nicht geklappt. Versuch es noch einmal.';
|
||||
knopf.disabled = false;
|
||||
|
||||
Reference in New Issue
Block a user