Die Personenkachel wird eine Standkarte -- mit den Aufgaben darauf
Filipe: "mach das bitte viel krasser und viel geiler. die aufgaben die
wir verteilen sollen da auch zu sehen sein und so. viel
uebersichtlicher, viel moderner. nicht so banal und einfach."
VORHER: Name, Rolle, ein flacher Balken und drei Zahlenkaesten. Auf
seinem Bildschirmfoto standen in fuenf von sechs Kacheln exakt
dieselben drei Zahlen (0 / 68 / 0) -- achtzehn Kaesten fuer eine
einzige Auskunft. Und die Aufgaben, die er eine Handbreit darunter
verteilt, kamen auf der Kachel derselben Person gar nicht vor.
JETZT drei Zonen in der Reihenfolge, in der man fragt:
KOPF Ring mit dem Anteil in der Mitte, Name, Rolle.
AUFTRAG Wie viele offen, wie viele ueberfaellig, und die naechste
mit Namen und Frist ("seit gestern ueberfaellig").
FUSS "46 von 68 angesehen" -- und "verschieden gesehen" nur
dann, wenn es dort etwas gibt.
Der Ring rechnet mit stroke-dasharray auf einem Kreis vom Umfang 100:
der Anteil in Prozent ist damit buchstaeblich die Strichlaenge. Keine
Ampelfarbe -- was "genug" ist, haengt davon ab, wie lange jemand dabei
ist. Gewarnt wird nur an einem Massstab, der nicht geraten ist: einer
ueberschrittenen Frist.
Die Aufgabenzeile wird aus derselben Liste gerechnet wie das
Verteil-Band und der Katalog (alleAufgabenV) und in aufgabenHolen()
nachgezogen -- an EINER Stelle, damit es keine gibt, die es vergisst.
GITTER STATT FLIESSREIHE: Bei sieben Leuten stand die letzte Kachel
allein in ihrer Zeile und wuchs auf 1160 px neben 379 px der anderen.
Eine Person sah dreimal so wichtig aus, weil die Teamgroesse ungerade
ist.
Drei Funde nebenbei, alle durch die neuen Messungen:
- pruef-schritt verlangte seit dem 23.09. einen Sprung, der an dem
Tag ABSICHTLICH entfernt wurde. Sie war seither rot, ohne dass
etwas kaputt war. Neu gefasst auf den Sprung, den es noch gibt:
den Weg von aussen ueber "?zeigen=person-...".
- Und der war kaputt. Gesprungen wurde, waehrend in der Karte nur
"wird geladen ..." stand -- die Seite war zu kurz zum Scrollen,
der Browser klemmte bei 0 ab. Wer der Talentseite folgte, landete
oben auf der Liste. Gesprungen wird jetzt, wenn die Karte steht.
- Auf demselben Weg rief karte() das Vorlagenbrett, bevor es
eingerichtet war ("zeigen() vor einrichten()"). Das Einrichten ist
vorgezogen. Ueber "?zeigen=" ging vorher KEINE Pruefung.
Gemessen: pruef-entwicklung-kacheln 31 (vorher 16), pruef-schritt 68
(vorher 65), pruef-entwicklung 48, pruef-modi-katalog 133,
pruef-bewerbung-aufgaben 101, pruef-zuteilung, pruef-css-klassen --
alle gruen. Schriftgroessen unter 11,5 px: 40 statt 42.
Neu: server/mess-entwicklung-kacheln.mjs. Die Pruefung braucht einen
kargen Bestand und zeigt deshalb den Sonderfall (alles auf null); diese
Datei legt sieben Leute mit verschiedenen Staenden und Aufgaben an und
macht Bilder fuer 1280 und 390 px. Sie prueft nichts.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
+359
-104
@@ -139,12 +139,34 @@
|
||||
if (kopf) kopf.textContent = satz;
|
||||
const kachel = personZahlen.get(letzteKarte.id);
|
||||
if (kachel) {
|
||||
/* Zwei Ziffern statt eines Satzes -- und der Ton wechselt auf
|
||||
gruen, sobald nichts mehr offen ist. Ohne das bliebe eine
|
||||
fertig angesehene Person blaugrau wie eine halbe. */
|
||||
kachel.angesehen.textContent = String(gesetzt);
|
||||
kachel.offen.textContent = String(Math.max(0, r.gesamt - gesetzt));
|
||||
kachel.kasten.dataset.stufe = gesetzt >= r.gesamt ? 'gut' : 'offen';
|
||||
/* DER RING WANDERT MIT (24.09.2026).
|
||||
|
||||
Hier standen bis heute die zwei Ziffern der Bilanz-Kaesten.
|
||||
Die gibt es nicht mehr -- die Kachel traegt jetzt einen Ring
|
||||
und darunter "46 von 68 angesehen". Beides muss sich beim
|
||||
Durchklicken bewegen, sonst ist genau der Fehler wieder da,
|
||||
wegen dem diese Funktion ueberhaupt entstanden ist: Die Karte
|
||||
zeigt den neuen Stand, die Kachel darueber den von vorhin. */
|
||||
const anteilNeu = r.gesamt > 0 ? Math.round(gesetzt / r.gesamt * 100) : 0;
|
||||
kachel.bogen.setAttribute('stroke-dasharray',
|
||||
Math.max(0, Math.min(100, anteilNeu)) + ' 100');
|
||||
kachel.ringZahl.textContent = r.gesamt > 0 ? String(anteilNeu) : '–';
|
||||
kachel.ring.setAttribute('aria-label', r.gesamt > 0
|
||||
? `${gesetzt} von ${r.gesamt} angesehen (${anteilNeu} Prozent)`
|
||||
: 'noch nichts einzuschätzen');
|
||||
kachel.standZahl.textContent = String(gesetzt);
|
||||
/* Fertig ist ein ruhiger voller Ring -- kein Gruen, keine Feier:
|
||||
Es ist der Normalzustand, nicht ein Preis. */
|
||||
if (r.gesamt > 0 && gesetzt >= r.gesamt) {
|
||||
kachel.ring.dataset.voll = 'ja';
|
||||
kachel.stand.dataset.voll = 'ja';
|
||||
} else {
|
||||
delete kachel.ring.dataset.voll;
|
||||
delete kachel.stand.dataset.voll;
|
||||
}
|
||||
/* Und der Punkt bei null verschwindet, sobald der Erste sitzt. */
|
||||
if (anteilNeu <= 0) kachel.ring.dataset.leer = 'ja';
|
||||
else delete kachel.ring.dataset.leer;
|
||||
}
|
||||
|
||||
/* Und die Köpfe der Kategorien -- sonst steht zugeklappt „0 / 7“
|
||||
@@ -218,28 +240,145 @@
|
||||
}
|
||||
|
||||
/* ---- Die Personen --------------------------------------------------- */
|
||||
/* EIN BILANZ-KASTEN, wie ihn die Checkliste benutzt (17.09.2026).
|
||||
/* DER BILANZ-KASTEN IST HIER WEG (24.09.2026).
|
||||
|
||||
Filipe, mit zwei Bildschirmfotos nebeneinander: "wieso ist diese
|
||||
seite noch nicht im stil und perfektioniert wie die auf screen2".
|
||||
Er stand seit dem 17.09. da und war damals richtig: Die Zahlen
|
||||
auf der Kachel sahen anders aus als drueben auf der Checkliste,
|
||||
und `bilanz-zahl` aus start.css hat das eingeebnet.
|
||||
|
||||
Der Unterschied war nicht der Aufbau -- der stimmte -- sondern die
|
||||
Zahlen: Hier standen sie als graue Textzeilen, drueben als
|
||||
abgesetzte Kaesten mit grosser Ziffer und eigenem Ton. Zwei
|
||||
Bretter, die dasselbe tun und verschieden aussehen, wirken wie
|
||||
zwei verschiedene Sachen.
|
||||
Die Kachel traegt seit heute keine drei Zahlenkaesten mehr,
|
||||
sondern einen Ring, ihre offenen Aufgaben und eine feine Zeile
|
||||
(siehe personKarte weiter unten). Damit hatte diese Funktion
|
||||
keinen einzigen Aufrufer mehr.
|
||||
|
||||
`bilanz-zahl` steht in start.css und gehoert damit dem ganzen Haus,
|
||||
nicht der Checkliste. Nachbauen waere eine zweite Wahrheit ueber
|
||||
dasselbe Aussehen gewesen. */
|
||||
function bilanzZahl(n, text, stufe, hinweis) {
|
||||
const kasten = el('div', 'bilanz-zahl');
|
||||
kasten.dataset.stufe = stufe;
|
||||
if (hinweis) kasten.title = hinweis;
|
||||
const ziffer = el('span', 'bilanz-zahl__n', String(n));
|
||||
kasten.append(ziffer);
|
||||
kasten.append(el('span', 'bilanz-zahl__text', text));
|
||||
return { kasten, ziffer };
|
||||
STEHENGELASSEN HAETTE SIE GESCHADET: Wer sie beim naechsten Mal
|
||||
findet, haelt sie fuer den Weg, wie Zahlen auf dieser Seite
|
||||
aussehen -- und baut damit neben dem neuen Aufbau einen zweiten
|
||||
auf. `bilanz-zahl` selbst bleibt unangetastet; die Checkliste
|
||||
und die Startseite benutzen sie weiter. */
|
||||
|
||||
/* =====================================================================
|
||||
DIE AUFGABEN AUF DER KACHEL (24.09.2026)
|
||||
=====================================================================
|
||||
|
||||
Filipe: "die aufgaben die wir verteilen sollen da auch zu sehen
|
||||
sein und so."
|
||||
|
||||
Er verteilt sie eine Handbreit weiter unten -- und die Kacheln
|
||||
darueber wussten nichts davon. Wer wissen wollte, ob bei jemandem
|
||||
schon etwas liegt, musste ihn erst anklicken, und dann stand es
|
||||
unter der Karte. Sechs Leute hiessen sechs Klicks.
|
||||
|
||||
GERECHNET WIRD AUS `alleAufgabenV` -- derselben Liste, aus der
|
||||
auch die Liste unter der Karte und der Vorlagenkatalog ihre Zahlen
|
||||
nehmen. Ein zweiter Abruf waere eine zweite Wahrheit ueber
|
||||
dieselbe Sache, und die, die beim naechsten Verteilen nicht
|
||||
mitwandert.
|
||||
|
||||
WER "MEINE" AUFGABE IST, entscheidet dieselbe Regel wie unter der
|
||||
Karte: verantwortlich ODER zugeteilt und nicht abgelehnt. Eine
|
||||
eigene Regel an dieser Stelle waere zwei Antworten auf dieselbe
|
||||
Frage, eine Handbreit auseinander.
|
||||
===================================================================== */
|
||||
|
||||
/** Was liegt bei dieser Person? -- in die Zeile an ihrer Kachel.
|
||||
*
|
||||
* IST DIE LISTE NOCH NICHT DA, bleibt die Zeile weg, statt "0
|
||||
* offen" zu behaupten. Eine Null, die in Wahrheit "ich weiss es
|
||||
* noch nicht" heisst, ist schlimmer als gar nichts -- man glaubt
|
||||
* ihr ja. */
|
||||
function auftragZeichnen(zeile, personId) {
|
||||
if (!zeile) return;
|
||||
zeile.textContent = '';
|
||||
const nr = Number(personId);
|
||||
const alle = Array.isArray(alleAufgabenV) ? alleAufgabenV : [];
|
||||
if (!alle.length || !nr) { zeile.hidden = true; return; }
|
||||
|
||||
const heute = typeof window.heuteLokal === 'function'
|
||||
? window.heuteLokal() : new Date().toISOString().slice(0, 10);
|
||||
const meine = alle.filter((x) => x.status !== 'erledigt' && x.status !== 'abgebrochen')
|
||||
.filter((x) => Number(x.verantwortlich_id) === nr
|
||||
|| (x.zuteilung || []).some((z) => Number(z.person_id) === nr
|
||||
&& z.zustand !== 'abgelehnt'));
|
||||
|
||||
zeile.hidden = false;
|
||||
delete zeile.dataset.spaet;
|
||||
if (!meine.length) {
|
||||
/* AUCH "NICHTS" IST EINE ANTWORT -- und zwar die, nach der man
|
||||
beim Verteilen sucht. Die Zeile bleibt deshalb stehen, nur
|
||||
leise: Waere sie weg, saehe die Kachel aus, als fehle dort
|
||||
eine Auskunft. */
|
||||
zeile.dataset.leer = 'ja';
|
||||
zeile.append(el('span', 'e-person__auftrag-leer', 'keine offene Aufgabe'));
|
||||
return;
|
||||
}
|
||||
delete zeile.dataset.leer;
|
||||
|
||||
const spaet = meine.filter((x) => x.frist && x.frist < heute);
|
||||
if (spaet.length) zeile.dataset.spaet = 'ja';
|
||||
|
||||
const kopf = el('span', 'e-person__auftrag-kopf');
|
||||
kopf.append(el('span', 'e-person__auftrag-zahl', String(meine.length)));
|
||||
kopf.append(el('span', 'e-person__auftrag-wort',
|
||||
meine.length === 1 ? 'offene Aufgabe' : 'offene Aufgaben'));
|
||||
if (spaet.length) {
|
||||
kopf.append(el('span', 'e-person__auftrag-spaet',
|
||||
spaet.length === 1 ? '1 überfällig' : `${spaet.length} überfällig`));
|
||||
}
|
||||
zeile.append(kopf);
|
||||
|
||||
/* DIE NAECHSTE MIT NAMEN, nicht nur als Zahl. "3 offen" sagt, dass
|
||||
etwas da ist; "Clips vom Samstag schneiden, seit 2 Tagen
|
||||
ueberfaellig" sagt, worum es geht -- und genau danach fragt man,
|
||||
bevor man jemanden anspricht.
|
||||
|
||||
Ueberfaellige zuerst, dann nach Frist, und was keine Frist hat,
|
||||
steht hinten: Eine Aufgabe ohne Termin draengt nicht. Dieselbe
|
||||
Reihenfolge wie in der Liste unter der Karte. */
|
||||
const naechste = [...meine].sort((x, y) =>
|
||||
String(x.frist || '9999-99-99').localeCompare(String(y.frist || '9999-99-99')))[0];
|
||||
if (naechste) {
|
||||
const z = el('span', 'e-person__auftrag-naechste');
|
||||
z.append(el('span', 'e-person__auftrag-titel', naechste.titel || 'Ohne Titel'));
|
||||
if (naechste.frist) {
|
||||
const wann = el('span', 'e-person__auftrag-frist', fristWort(naechste.frist, heute));
|
||||
if (naechste.frist < heute) wann.dataset.spaet = 'ja';
|
||||
z.append(wann);
|
||||
}
|
||||
zeile.append(z);
|
||||
}
|
||||
}
|
||||
|
||||
/** "heute fällig", "in 2 Tagen", "seit 3 Tagen überfällig".
|
||||
*
|
||||
* EIN DATUM MUSS MAN GEGEN HEUTE RECHNEN, ein Satz nicht. "bis
|
||||
* 22. Sep. 2026" zwingt zum Nachdenken; "seit 2 Tagen überfällig"
|
||||
* nicht.
|
||||
*
|
||||
* Gerechnet wird in ganzen Tagen ueber die Ortszeit --
|
||||
* `window.heuteLokal()` ist die Stelle im Haus, die das richtig
|
||||
* macht (Mitternacht hier, nicht in Greenwich). */
|
||||
function fristWort(frist, heute) {
|
||||
const a = new Date(`${frist}T00:00:00`);
|
||||
const b = new Date(`${heute}T00:00:00`);
|
||||
if (Number.isNaN(a.getTime()) || Number.isNaN(b.getTime())) return datum(frist);
|
||||
const tage = Math.round((a - b) / 86400000);
|
||||
if (tage === 0) return 'heute fällig';
|
||||
if (tage === 1) return 'morgen fällig';
|
||||
if (tage === -1) return 'seit gestern überfällig';
|
||||
if (tage > 1) return `in ${tage} Tagen`;
|
||||
return `seit ${Math.abs(tage)} Tagen überfällig`;
|
||||
}
|
||||
|
||||
/** Alle Aufgabenzeilen der Kacheln auf den neuesten Stand bringen.
|
||||
*
|
||||
* Steht in `aufgabenHolen()` und nicht an den vier Aufrufstellen:
|
||||
* Wer die Liste neu holt, hat auch den neuen Stand -- und eine
|
||||
* Stelle, die das vergisst, gibt es dann nicht. */
|
||||
function auftraegeNachziehen() {
|
||||
for (const zeile of document.querySelectorAll('#personen .e-person__auftrag')) {
|
||||
auftragZeichnen(zeile, zeile.dataset.fuer);
|
||||
}
|
||||
}
|
||||
|
||||
function personKarte(p, lage) {
|
||||
@@ -253,81 +392,146 @@
|
||||
k.dataset.person = String(p.id);
|
||||
/* Der Name als Angabe, nicht nur als Text: Das Verteil-Band nennt
|
||||
ihn ("Aufgabe fuer Kessi"), und `textContent` der ganzen Kachel
|
||||
waere Name + Rolle + drei Zahlen. */
|
||||
waere Name + Rolle + alles, was sonst noch draufsteht. */
|
||||
k.dataset.name = p.name;
|
||||
k.append(el('span', 'e-person__name', p.name));
|
||||
k.append(el('span', 'e-person__rolle', p.rolle_name));
|
||||
|
||||
const gesamt = Number(lage.gesamt_fremd) || 0;
|
||||
const gesetzt = Number(p.gesetzt) || 0;
|
||||
|
||||
/* ==== DER FORTSCHRITT ALS BALKEN (23.09.2026) ==================
|
||||
|
||||
Filipe: "mal was krass modernes ... viel viel viel
|
||||
uebersichtlicher."
|
||||
|
||||
Auf seinem Bildschirmfoto standen sechs Kacheln mit je drei
|
||||
Zahlenkaesten -- und bei fuenf davon exakt dasselbe. Achtzehn
|
||||
Kaesten fuer eine Auskunft: hier ist noch nichts passiert.
|
||||
|
||||
Drei Zahlen nebeneinander muss man lesen und im Kopf
|
||||
vergleichen. Einen Balken sieht man im Vorbeigehen, und die
|
||||
Frage an diese Liste ist genau das: Wer ist wie weit?
|
||||
|
||||
DIE BREITE IST DIE ANTWORT, die Zahl daneben die Genauigkeit.
|
||||
Keine Farbskala, keine Ampel: Was "genug" ist, haengt davon ab,
|
||||
wie lange jemand dabei ist -- eine Schwelle waere geraten.
|
||||
Der Balken zeigt, WIE WEIT, und urteilt nicht. */
|
||||
const anteil = gesamt > 0 ? Math.round(gesetzt / gesamt * 100) : 0;
|
||||
const spur = el('div', 'e-fortschritt');
|
||||
spur.setAttribute('role', 'img');
|
||||
spur.setAttribute('aria-label',
|
||||
gesamt > 0
|
||||
? `${gesetzt} von ${gesamt} angesehen (${anteil} Prozent)`
|
||||
: 'noch nichts einzuschätzen');
|
||||
const balken = el('div', 'e-fortschritt__balken');
|
||||
balken.style.width = anteil + '%';
|
||||
if (anteil >= 100) spur.dataset.voll = 'ja';
|
||||
spur.append(balken);
|
||||
k.append(spur);
|
||||
|
||||
const zahlen = el('div', 'e-person__bilanz');
|
||||
/* DIESELBEN DREI WIE DRUEBEN, und die ersten beiden teilen dasselbe
|
||||
Ganze: angesehen + noch offen = alle Punkte. Die dritte ist das
|
||||
Ergebnis dieser Seite -- wo zwei Leute dasselbe sehen, gibt es
|
||||
nichts zu besprechen. */
|
||||
/* DIE DREI ZAHLEN BLEIBEN -- aber nicht mehr dreimal gleich laut.
|
||||
/* ==================================================================
|
||||
DIE STANDKARTE (24.09.2026)
|
||||
==================================================================
|
||||
|
||||
"angesehen" und "noch offen" sind zwei Seiten derselben Zahl
|
||||
(zusammen ergeben sie das Ganze). Der Balken darueber zeigt sie
|
||||
ohnehin schon; hier stehen sie als Beleg daneben.
|
||||
Filipe: "mach das bitte viel krasser und viel geiler. die
|
||||
aufgaben die wir verteilen sollen da auch zu sehen sein und so.
|
||||
viel uebersichtlicher, viel moderner."
|
||||
|
||||
"verschieden gesehen" ist die einzige, die zu einer HANDLUNG
|
||||
fuehrt -- dort lohnt das Gespraech. Deshalb faellt sie auf,
|
||||
sobald es etwas gibt. Steht dort eine Null, tritt sie zurueck:
|
||||
Eine Null, die aussieht wie eine Warnung, ist Laerm, und bei
|
||||
sechs Leuten sechsmal derselbe Laerm. */
|
||||
WAS VORHER DASTAND: sechs Kacheln mit je drei Zahlenkaesten --
|
||||
und bei fuenf davon exakt dieselben drei Zahlen: 0 angesehen,
|
||||
68 noch offen, 0 verschieden gesehen. Achtzehn Kaesten fuer eine
|
||||
einzige Auskunft, naemlich: hier ist noch nichts passiert. Und
|
||||
die Aufgaben, die Filipe eine Handbreit darunter verteilt,
|
||||
kamen auf der Kachel derselben Person gar nicht vor.
|
||||
|
||||
DIE FRAGE AN DIESE LISTE ist nicht "wie viele Punkte hat wer".
|
||||
Sie lautet: WEN NEHME ICH MIR JETZT VOR? Darauf antworten drei
|
||||
Dinge, und in dieser Reihenfolge stehen sie jetzt da:
|
||||
|
||||
1. WER -- Ring, Name, Rolle. Der Ring traegt den Anteil in
|
||||
seiner Mitte: Form und Zahl an derselben Stelle, statt
|
||||
eines Balkens ueber die Breite und dreier Kaesten darunter.
|
||||
2. WAS LIEGT AN -- offene Aufgaben, ueberfaellige, und die
|
||||
naechste mit Namen und Frist. Der Teil, den Filipe
|
||||
vermisst hat.
|
||||
3. WIE WEIT -- "46 von 68 angesehen" als feine Zeile, und
|
||||
"verschieden gesehen" nur dann, wenn es dort etwas gibt.
|
||||
|
||||
DIE DREI BILANZ-KAESTEN SIND WEG, nicht verschoben. Zwei davon
|
||||
("angesehen", "noch offen") waren zwei Seiten derselben Zahl --
|
||||
zusammen ergaben sie immer das Ganze. Der Ring zeigt dasselbe
|
||||
ohne Rechnung, und "46 von 68" nennt beide Zahlen in einer
|
||||
Zeile. Die dritte steht nur noch da, wenn sie etwas sagt.
|
||||
================================================================= */
|
||||
const kopf = el('span', 'e-person__kopf');
|
||||
|
||||
/* DER RING. Umfang 100 -- deshalb laesst sich der Anteil in Prozent
|
||||
unmittelbar als Strichlaenge setzen ("68 100"), ohne Umrechnung
|
||||
und ohne eine Grafik je Stand. r = 100 / (2 * PI) = 15,9155.
|
||||
|
||||
KEINE AMPELFARBE. Was "genug" ist, haengt davon ab, wie lange
|
||||
jemand dabei ist; eine Schwelle waere geraten und bei der
|
||||
naechsten Person falsch. Der Ring sagt WIE WEIT und urteilt
|
||||
nicht. Geurteilt wird nur dort, wo es einen Massstab gibt, der
|
||||
nicht geraten ist: bei einer ueberfaelligen Frist. */
|
||||
const ring = el('span', 'e-ring');
|
||||
ring.setAttribute('role', 'img');
|
||||
ring.setAttribute('aria-label', gesamt > 0
|
||||
? `${gesetzt} von ${gesamt} angesehen (${anteil} Prozent)`
|
||||
: 'noch nichts einzuschätzen');
|
||||
if (gesamt > 0 && gesetzt >= gesamt) ring.dataset.voll = 'ja';
|
||||
/* BEI NULL PROZENT DARF NICHTS ZU SEHEN SEIN (gemessen am
|
||||
Bildschirmfoto). Der Bogen hat runde Enden -- damit zeichnet
|
||||
schon "0 100" einen kleinen Punkt auf zwoelf Uhr. Der sieht aus
|
||||
wie ein Staubkorn auf dem Bildschirm oder wie ein Rest vom
|
||||
Zeichnen, nicht wie "hier ist noch nichts". Die Ecke wird
|
||||
deshalb stumpf, solange der Anteil null ist. */
|
||||
if (anteil <= 0) ring.dataset.leer = 'ja';
|
||||
const SVG_NS = 'http://www.w3.org/2000/svg';
|
||||
const bild = document.createElementNS(SVG_NS, 'svg');
|
||||
bild.setAttribute('viewBox', '0 0 36 36');
|
||||
bild.setAttribute('aria-hidden', 'true');
|
||||
bild.setAttribute('class', 'e-ring__bild');
|
||||
const spur = document.createElementNS(SVG_NS, 'circle');
|
||||
const bogen = document.createElementNS(SVG_NS, 'circle');
|
||||
for (const [kreis, klasse] of [[spur, 'e-ring__spur'], [bogen, 'e-ring__bogen']]) {
|
||||
kreis.setAttribute('class', klasse);
|
||||
kreis.setAttribute('cx', '18');
|
||||
kreis.setAttribute('cy', '18');
|
||||
kreis.setAttribute('r', '15.9155');
|
||||
kreis.setAttribute('fill', 'none');
|
||||
bild.append(kreis);
|
||||
}
|
||||
bogen.setAttribute('stroke-dasharray', Math.max(0, Math.min(100, anteil)) + ' 100');
|
||||
ring.append(bild);
|
||||
const ringZahl = el('span', 'e-ring__zahl', gesamt > 0 ? String(anteil) : '–');
|
||||
ring.append(ringZahl);
|
||||
if (gesamt > 0) ring.append(el('span', 'e-ring__prozent', '%'));
|
||||
kopf.append(ring);
|
||||
|
||||
const wer = el('span', 'e-person__wer');
|
||||
wer.append(el('span', 'e-person__name', p.name));
|
||||
wer.append(el('span', 'e-person__rolle', p.rolle_name));
|
||||
kopf.append(wer);
|
||||
k.append(kopf);
|
||||
|
||||
/* ==== WAS LIEGT BEI DIESER PERSON? ============================
|
||||
|
||||
Der Platz wird hier angelegt und erst gefuellt, wenn die
|
||||
Aufgabenliste da ist: Die Kacheln entstehen frueher als der
|
||||
Abruf. Stuende hier der Stand von jetzt, waere die Zeile beim
|
||||
ersten Aufbau immer leer -- und fuellte sich erst beim
|
||||
naechsten Klick. `aufgabenHolen()` zieht sie nach. */
|
||||
const auftrag = el('span', 'e-person__auftrag');
|
||||
auftrag.dataset.fuer = String(p.id);
|
||||
k.append(auftrag);
|
||||
auftragZeichnen(auftrag, p.id);
|
||||
|
||||
/* ==== DER FUSS: die feine Zeile ============================== */
|
||||
const fuss = el('span', 'e-person__fuss');
|
||||
const stand = el('span', 'e-person__stand');
|
||||
const standZahl = el('span', 'e-person__stand-zahl', String(gesetzt));
|
||||
stand.append(standZahl);
|
||||
stand.append(el('span', 'e-person__stand-rest', ` von ${gesamt} angesehen`));
|
||||
if (gesamt > 0 && gesetzt >= gesamt) stand.dataset.voll = 'ja';
|
||||
fuss.append(stand);
|
||||
|
||||
/* "verschieden gesehen" ist die einzige Zahl dieser Seite, die zu
|
||||
einer HANDLUNG fuehrt -- dort lohnt das Gespraech. Deshalb faellt
|
||||
sie auf, sobald es etwas gibt. Steht dort eine Null, steht sie
|
||||
gar nicht mehr da: Eine Null, die aussieht wie eine Warnung, ist
|
||||
Laerm -- und bei sechs Leuten sechsmal derselbe Laerm. */
|
||||
const abw = Number(p.abweichungen) || 0;
|
||||
const a = bilanzZahl(gesetzt, 'angesehen',
|
||||
gesamt && gesetzt >= gesamt ? 'gut' : 'offen');
|
||||
const o = bilanzZahl(Math.max(0, gesamt - gesetzt), 'noch offen', 'offen');
|
||||
const v = bilanzZahl(abw, 'verschieden gesehen',
|
||||
abw ? 'verbessern' : 'ruhig',
|
||||
abw
|
||||
? 'Hier lohnt das Gespräch – nicht dort, wo ihr einig seid.'
|
||||
: 'Ihr seht es bisher überall gleich.');
|
||||
if (!abw) v.kasten.dataset.still = 'ja';
|
||||
zahlen.append(a.kasten, o.kasten, v.kasten);
|
||||
/* Die Kachel merkt sich ihre Ziffern -- daran zieht
|
||||
zaehlerNachziehen() sie nach, ohne die Liste neu zu holen. */
|
||||
personZahlen.set(p.id, { angesehen: a.ziffer, offen: o.ziffer, kasten: a.kasten });
|
||||
k.append(zahlen);
|
||||
if (abw) {
|
||||
const marke = el('span', 'e-person__abw', `${abw} verschieden gesehen`);
|
||||
marke.title = 'Hier lohnt das Gespräch – nicht dort, wo ihr einig seid.';
|
||||
fuss.append(marke);
|
||||
}
|
||||
if (p.veraltet) {
|
||||
const z = el('span', 'e-person__zahl e-person__zahl--alt',
|
||||
const z = el('span', 'e-person__alt',
|
||||
`${p.veraltet} älter als ${lage.verblasst_nach} Tage`);
|
||||
z.title = 'Eine alte Einschätzung ist keine Einschätzung mehr.';
|
||||
k.append(z);
|
||||
fuss.append(z);
|
||||
}
|
||||
k.append(fuss);
|
||||
|
||||
/* Die Kachel merkt sich ihre beweglichen Teile -- daran zieht
|
||||
zaehlerNachziehen() sie nach, ohne die Liste neu zu holen. Ohne
|
||||
das stuende auf der Kachel weiter die Zahl von vorhin, waehrend
|
||||
die Karte darunter schon die neue zeigt: zwei Wahrheiten auf
|
||||
einem Bildschirm, und die falsche oben. */
|
||||
personZahlen.set(p.id, { ring, bogen, ringZahl, stand, standZahl });
|
||||
|
||||
/* KEIN SPRUNG MEHR (23.09.2026) -- die Seite ist umgeraeumt.
|
||||
|
||||
Hier stand "Wer eine Person anklickt, will zu ihrer Karte", und
|
||||
@@ -853,6 +1057,12 @@
|
||||
if (!a.ok) return null;
|
||||
const roh = await a.json();
|
||||
alleAufgabenV = Array.isArray(roh) ? roh : (roh?.aufgaben || []);
|
||||
/* UND DIE KACHELN ERFAHREN ES SOFORT (24.09.2026). Sie tragen
|
||||
seit heute die offenen Aufgaben ihrer Person; diese Zeile
|
||||
steht bewusst HIER und nicht an den vier Aufrufstellen -- wer
|
||||
die Liste neu holt, hat auch den neuen Stand, und eine Stelle,
|
||||
die das Nachziehen vergisst, gibt es dann nicht. */
|
||||
auftraegeNachziehen();
|
||||
return alleAufgabenV;
|
||||
} catch { return null; }
|
||||
}
|
||||
@@ -1092,7 +1302,25 @@
|
||||
ziel.hidden = false;
|
||||
ziel.textContent = '';
|
||||
ziel.append(el('p', 'leise', 'wird geladen …'));
|
||||
if (springen) ziel.scrollIntoView({ behavior: window.sanft?.() || 'auto', block: 'start' });
|
||||
/* HIER STAND DER SPRUNG -- und er kam zu frueh (24.09.2026).
|
||||
|
||||
In diesem Augenblick enthaelt die Karte einen einzigen Satz
|
||||
("wird geladen …"). Die Seite ist damit so kurz, dass der
|
||||
Browser ueberhaupt nicht scrollen KANN: Er klemmt bei 0 ab, und
|
||||
wenn der Inhalt Sekundenbruchteile spaeter ankommt, bewegt sich
|
||||
nichts mehr. Gemessen: scrollY 0, waehrend die Karte weit unten
|
||||
stand.
|
||||
|
||||
Wer von der Talentseite mit "?zeigen=person-…" kam, landete
|
||||
deshalb oben auf der Personenliste -- also genau dort, wo der
|
||||
Link ihn NICHT hinbringen sollte. Derselbe Fehler, vor dem
|
||||
oben an der Kachel gewarnt wird ("vorher haengt sie nicht im
|
||||
Dokument und hat keine Position"), nur eine Ebene tiefer.
|
||||
|
||||
Gesprungen wird jetzt am Ende dieser Funktion, wenn die Karte
|
||||
ihre Hoehe hat. Ein zweiter, frueher Sprung waere ausserdem eine
|
||||
zweite Bewegung fuer denselben Klick -- und Bewegung ist genau
|
||||
das, worueber Filipe sich beschwert hat. */
|
||||
|
||||
const a = await hole(`/workspace/api/entwicklung/person/${id}`);
|
||||
if (!a.ok) { melde('Die Karte ließ sich nicht laden.'); return; }
|
||||
@@ -1325,10 +1553,18 @@
|
||||
/* Die Zahl auf der Personenkachel mitziehen -- sie kommt aus einer
|
||||
Liste, die nur beim Laden der Seite geholt wird. */
|
||||
zaehlerNachziehen();
|
||||
/* UND DIE HÖHE HALTEN. Ohne diese Zeile springt die Seite auch ohne
|
||||
scrollIntoView: Der Neuaufbau ändert die Höhe der Karte, und der
|
||||
Browser behält nur die Pixelzahl, nicht die Stelle. */
|
||||
if (!springen) window.scrollTo({ top: vorherY, behavior: 'instant' });
|
||||
/* JETZT ERST SPRINGEN -- die Karte steht vollstaendig und hat eine
|
||||
Hoehe, der Browser kann also wirklich dorthin scrollen.
|
||||
|
||||
UND SONST DIE HÖHE HALTEN. Ohne diese Zeile springt die Seite
|
||||
auch ohne scrollIntoView: Der Neuaufbau ändert die Höhe der
|
||||
Karte, und der Browser behält nur die Pixelzahl, nicht die
|
||||
Stelle. */
|
||||
if (springen) {
|
||||
ziel.scrollIntoView({ behavior: window.sanft?.() || 'auto', block: 'start' });
|
||||
} else {
|
||||
window.scrollTo({ top: vorherY, behavior: 'instant' });
|
||||
}
|
||||
}
|
||||
|
||||
function punktZeile(personId, pt, erwartung) {
|
||||
@@ -1588,6 +1824,37 @@
|
||||
const lage = await a.json();
|
||||
stufen = lage.stufen;
|
||||
|
||||
/* DER KATALOG WIRD ZUERST EINGERICHTET (vorgezogen am 24.09.2026).
|
||||
|
||||
Er stand weiter unten, hinter dem ganzen Leitungsteil. Das ging
|
||||
gut, solange niemand vorher eine Karte oeffnete -- "karte()"
|
||||
ruft am Ende aber "Vorlagenbrett.zeigen()", und auf dem Weg
|
||||
ueber "?zeigen=person-…" passiert genau das, bevor der Katalog
|
||||
eingerichtet ist. In der Browserkonsole stand dann
|
||||
"Vorlagenbrett: zeigen() vor einrichten()", und der Katalog
|
||||
blieb beim ersten Zeichnen leer.
|
||||
|
||||
Gefunden am 24.09.2026, weil die Gegenprobe in pruef-schritt
|
||||
neu gefasst wurde und seither ueber diesen Weg geht. Vorher
|
||||
ging KEINE Pruefung ueber "?zeigen=" -- der Weg von der
|
||||
Talentseite war ungeprueft.
|
||||
|
||||
Einrichten legt nur die Rueckrufe an (alle "() => …", also
|
||||
traege); es hat mit der Leitungssicht nichts zu tun und darf
|
||||
deshalb fuer alle und als Erstes laufen. */
|
||||
/* DER VORLAGENKATALOG STEHT FUER BEIDE DA -- Leitung und Modi.
|
||||
|
||||
Er gehoert ausdruecklich NICHT in den Leitungszweig darueber.
|
||||
Filipe: "die modis sollen bei all diesen voschlaegen auch nur
|
||||
bewerben koennen." Genau dafuer muessen sie ihn sehen. Was
|
||||
jemand damit tun darf -- uebernehmen oder sich bewerben --,
|
||||
entscheidet der Server und nicht diese Zeile.
|
||||
|
||||
Vor der Personenwahl: Der Katalog steht trotzdem schon da und
|
||||
sagt, dass noch niemand gewaehlt ist. Ein Block, der erst nach
|
||||
einem Klick erscheint, wird uebersehen. */
|
||||
katalogAnschliessen();
|
||||
|
||||
if (lage.leitung) {
|
||||
/* DIE LEUTE FUER „NOCH JEMANDEN DAZUNEHMEN" kommen aus
|
||||
derselben Antwort wie die Kacheln. Ein eigener Abruf waere
|
||||
@@ -1644,18 +1911,6 @@
|
||||
+ 'Keine Noten, keine Punktzahl.';
|
||||
}
|
||||
|
||||
/* DER VORLAGENKATALOG STEHT FUER BEIDE DA -- Leitung und Modi.
|
||||
|
||||
Er gehoert ausdruecklich NICHT in den Leitungszweig darueber.
|
||||
Filipe: "die modis sollen bei all diesen voschlaegen auch nur
|
||||
bewerben koennen." Genau dafuer muessen sie ihn sehen. Was
|
||||
jemand damit tun darf -- uebernehmen oder sich bewerben --,
|
||||
entscheidet der Server und nicht diese Zeile.
|
||||
|
||||
Vor der Personenwahl: Der Katalog steht trotzdem schon da und
|
||||
sagt, dass noch niemand gewaehlt ist. Ein Block, der erst nach
|
||||
einem Klick erscheint, wird uebersehen. */
|
||||
katalogAnschliessen();
|
||||
/* ERST DIE AUFGABEN, DANN DER KATALOG. Er markiert daran, was
|
||||
schon uebernommen wurde -- ohne diesen Abruf stuende die
|
||||
Markierung beim ersten Zeichnen nicht da, und fuer einen Modi
|
||||
|
||||
Reference in New Issue
Block a user