feat(diagram): Unassigned-Pille zeigt das Sprach-Kürzel — de N.N., en TBD; Langform im Tooltip (D87-Nachtrag)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-08-27 13:52:39 +02:00
co-authored by Claude Fable 5
parent e684ac73d3
commit e3742feffb
4 changed files with 33 additions and 2 deletions
+1
View File
@@ -19,6 +19,7 @@ reverse.
## 2026-08-27 ## 2026-08-27
- The unassigned pill in the people bar shows each language's short form now — German `N.N.`, English `TBD` — with the long wording in the tooltip
- `pull-doc --open` opens the fetched document in IntelliJ IDEA afterwards — also when nothing changed - `pull-doc --open` opens the fetched document in IntelliJ IDEA afterwards — also when nothing changed
- A dead live session now reconnects by itself — unsent text stays in the editor and goes out as a diff once the server answers again - A dead live session now reconnects by itself — unsent text stays in the editor and goes out as a diff once the server answers again
- The connection state stands next to the document name: disconnected or unsent changes turn the kind label amber, instead of only a warning below the diagram - The connection state stands next to the document name: disconnected or unsent changes turn the kind label amber, instead of only a warning below the diagram
+15
View File
@@ -7806,3 +7806,18 @@ Nachgemessen mit einem Log-Stub im PATH: `--git-commit --open` committet und
öffnet, `--open` allein öffnet auch den unveränderten Stand, ohne Schalter öffnet, `--open` allein öffnet auch den unveränderten Stand, ohne Schalter
kein Aufruf, ohne `idea` im PATH der Hinweis, `--commit` (Tippfehler) bricht kein Aufruf, ohne `idea` im PATH der Hinweis, `--commit` (Tippfehler) bricht
mit Meldung ab. mit Meldung ab.
## D87 — Nachtrag: Die Unassigned-Pille trägt ein Kürzel, die Langform den Tooltip
Nutzerwunsch mit Sprachfrage: In der Personen-Leiste solle im Deutschen
„n/n" oder „n.n." statt der Langform stehen — und gibt es solche Kürzel auch
in anderen Sprachen? Die Antwort: Richtig ist **„N.N."** (lateinisch *nomen
nominandum*, „der noch zu nennende Name" — die etablierte Konvention, groß
mit Punkten; „n/n" gibt es nicht). Kürzel je Sprache, wo eines etabliert
ist, sonst das kürzeste übliche Wort: en „TBD", zh „未分配", ja „未割当",
fr „à pourvoir", es „sin asignar" — dort bewusst NICHT „N.N.", das in
Lateinamerika für unidentifizierte Personen steht —, pl „nieprzypisane",
ru „не назначено", hi „तय नहीं". Neuer Schlüssel `peopleUnassignedShort`
neben der Langform: **Die Pille zeigt das Kürzel, Tooltip und `aria-label`
die Langform** — ein Kürzel, das nirgends aufgelöst wird, wäre nur ein
Rätsel. Nachgemessen im Browser: de-Pille „N.N." mit Tooltip
„ohne Zuständigen: 29 % …", en-Pille „TBD" mit „unassigned: 29% …".
+3 -1
View File
@@ -770,7 +770,9 @@ Arbeit des günstigsten Pfads — dasselbe Maß wie der Zuständigen-Engpass
Engpass-Person erscheint auch hier. Angezeigt werden **Anteile, keine Engpass-Person erscheint auch hier. Angezeigt werden **Anteile, keine
absoluten Zahlen** — die Größen sind ordinal, jede Summe ist eine Näherung. absoluten Zahlen** — die Größen sind ordinal, jede Summe ist eine Näherung.
Der Rest **ohne Zuständigen** bekommt einen eigenen, gestrichelten Eintrag, Der Rest **ohne Zuständigen** bekommt einen eigenen, gestrichelten Eintrag,
damit die Anteile auf 100 % summieren. Gerechnet wird auch bei damit die Anteile auf 100 % summieren; seine Pille trägt das **Kürzel** der
Sprache (deutsch „N.N.“ — *nomen nominandum* —, englisch „TBD“, …), die
Langform steht im Tooltip und im `aria-label`. Gerechnet wird auch bei
ausgeschaltetem Pfad-Umschalter (wie die `path`-Voreinstellung des ausgeschaltetem Pfad-Umschalter (wie die `path`-Voreinstellung des
Falt-Durchschalters: die Frage gilt dem Pfad, nicht seiner Anzeige). Ohne Falt-Durchschalters: die Frage gilt dem Pfad, nicht seiner Anzeige). Ohne
Tags gibt es die Leiste nicht. Tags gibt es die Leiste nicht.
+14 -1
View File
@@ -385,14 +385,18 @@ function renderPeopleBar(roots, docTags, loadSet, overload){
if(rest > 0) entries.push({tag: null, pct: share(rest)}); if(rest > 0) entries.push({tag: null, pct: share(rest)});
peopleBar.innerHTML = entries.map(e => { peopleBar.innerHTML = entries.map(e => {
const active = !!lens && lens.tag === e.tag; const active = !!lens && lens.tag === e.tag;
/* Die Pille traegt das Kürzel (de N.N." nomen nominandum; en TBD",
zh 未分配 ), Tooltip und aria-label die Langform: Ein Kürzel, das
niemand aufloest, waere nur ein Raetsel (D87-Nachtrag). */
const label = e.tag === null ? t('peopleUnassigned') : e.tag; const label = e.tag === null ? t('peopleUnassigned') : e.tag;
const pill = e.tag === null ? t('peopleUnassignedShort') : e.tag;
const tip = t('peopleShare', {share: e.pct}) + ' · ' + const tip = t('peopleShare', {share: e.pct}) + ' · ' +
t(active ? 'peopleLensOff' : 'peopleLensOn'); t(active ? 'peopleLensOff' : 'peopleLensOn');
const warm = overload && e.tag !== null && overload.tag === e.tag; const warm = overload && e.tag !== null && overload.tag === e.tag;
return `<button type="button" class="pbperson" aria-pressed="${active}"` + return `<button type="button" class="pbperson" aria-pressed="${active}"` +
(e.tag === null ? ' data-nobody' : ` data-tag="${esc(e.tag)}"`) + (e.tag === null ? ' data-nobody' : ` data-tag="${esc(e.tag)}"`) +
` title="${esc(label)}: ${esc(tip)}" aria-label="${esc(label)}: ${esc(tip)}">` + ` title="${esc(label)}: ${esc(tip)}" aria-label="${esc(label)}: ${esc(tip)}">` +
`<span class="tag${warm ? ' overload' : ''}${e.tag === null ? ' nobody' : ''}" aria-hidden="true">${esc(label)}</span>` + `<span class="tag${warm ? ' overload' : ''}${e.tag === null ? ' nobody' : ''}" aria-hidden="true">${esc(pill)}</span>` +
`<span class="pbbar" aria-hidden="true"><span class="pbfill" style="width:${e.pct}%"></span></span>` + `<span class="pbbar" aria-hidden="true"><span class="pbfill" style="width:${e.pct}%"></span></span>` +
`<span class="pbpct" aria-hidden="true">${e.pct}%</span></button>`; `<span class="pbpct" aria-hidden="true">${e.pct}%</span></button>`;
}).join(''); }).join('');
@@ -2483,6 +2487,7 @@ const I18N = {
assigneeOverloadWarn:"@{tag} trägt {share} % der offenen Arbeit auf dem günstigsten Pfad ({stations} von {total} Stationen) — mögliche Engstelle.", assigneeOverloadWarn:"@{tag} trägt {share} % der offenen Arbeit auf dem günstigsten Pfad ({stations} von {total} Stationen) — mögliche Engstelle.",
peopleBarLabel:"Zuständige", peopleBarLabel:"Zuständige",
peopleUnassigned:"ohne Zuständigen", peopleUnassigned:"ohne Zuständigen",
peopleUnassignedShort:"N.N.",
peopleShare:"{share} % der offenen Arbeit auf dem günstigsten Pfad", peopleShare:"{share} % der offenen Arbeit auf dem günstigsten Pfad",
peopleLensOn:"Klick: nur diese Knoten zeigen, alles andere zuklappen", peopleLensOn:"Klick: nur diese Knoten zeigen, alles andere zuklappen",
peopleLensOff:"Klick: Filter aufheben", peopleLensOff:"Klick: Filter aufheben",
@@ -2617,6 +2622,7 @@ const I18N = {
assigneeOverloadWarn:"@{tag} carries {share}% of the open work on the cheapest path ({stations} of {total} stations) — a possible bottleneck.", assigneeOverloadWarn:"@{tag} carries {share}% of the open work on the cheapest path ({stations} of {total} stations) — a possible bottleneck.",
peopleBarLabel:"Assignees", peopleBarLabel:"Assignees",
peopleUnassigned:"unassigned", peopleUnassigned:"unassigned",
peopleUnassignedShort:"TBD",
peopleShare:"{share}% of the open work on the cheapest path", peopleShare:"{share}% of the open work on the cheapest path",
peopleLensOn:"Click: show only these nodes, fold everything else", peopleLensOn:"Click: show only these nodes, fold everything else",
peopleLensOff:"Click: remove the filter", peopleLensOff:"Click: remove the filter",
@@ -2751,6 +2757,7 @@ const I18N = {
assigneeOverloadWarn:"@{tag} lleva el {share} % del trabajo pendiente en el camino más barato ({stations} de {total} estaciones) — posible cuello de botella.", assigneeOverloadWarn:"@{tag} lleva el {share} % del trabajo pendiente en el camino más barato ({stations} de {total} estaciones) — posible cuello de botella.",
peopleBarLabel:"Responsables", peopleBarLabel:"Responsables",
peopleUnassigned:"sin responsable", peopleUnassigned:"sin responsable",
peopleUnassignedShort:"sin asignar",
peopleShare:"{share} % del trabajo pendiente en el camino más barato", peopleShare:"{share} % del trabajo pendiente en el camino más barato",
peopleLensOn:"Clic: mostrar solo estos nodos y plegar el resto", peopleLensOn:"Clic: mostrar solo estos nodos y plegar el resto",
peopleLensOff:"Clic: quitar el filtro", peopleLensOff:"Clic: quitar el filtro",
@@ -2885,6 +2892,7 @@ const I18N = {
assigneeOverloadWarn:"@{tag} porte {share} % du travail restant sur le chemin le moins cher ({stations} stations sur {total}) — goulot d’étranglement possible.", assigneeOverloadWarn:"@{tag} porte {share} % du travail restant sur le chemin le moins cher ({stations} stations sur {total}) — goulot d’étranglement possible.",
peopleBarLabel:"Responsables", peopleBarLabel:"Responsables",
peopleUnassigned:"sans responsable", peopleUnassigned:"sans responsable",
peopleUnassignedShort:"à pourvoir",
peopleShare:"{share} % du travail restant sur le chemin le moins cher", peopleShare:"{share} % du travail restant sur le chemin le moins cher",
peopleLensOn:"Clic : nafficher que ces nœuds, replier le reste", peopleLensOn:"Clic : nafficher que ces nœuds, replier le reste",
peopleLensOff:"Clic : retirer le filtre", peopleLensOff:"Clic : retirer le filtre",
@@ -3019,6 +3027,7 @@ const I18N = {
assigneeOverloadWarn:"@{tag} niesie {share} % otwartej pracy na najtańszej ścieżce ({stations} z {total} stacji) — możliwe wąskie gardło.", assigneeOverloadWarn:"@{tag} niesie {share} % otwartej pracy na najtańszej ścieżce ({stations} z {total} stacji) — możliwe wąskie gardło.",
peopleBarLabel:"Odpowiedzialni", peopleBarLabel:"Odpowiedzialni",
peopleUnassigned:"bez odpowiedzialnego", peopleUnassigned:"bez odpowiedzialnego",
peopleUnassignedShort:"nieprzypisane",
peopleShare:"{share} % otwartej pracy na najtańszej ścieżce", peopleShare:"{share} % otwartej pracy na najtańszej ścieżce",
peopleLensOn:"Klik: pokaż tylko te węzły, resztę zwiń", peopleLensOn:"Klik: pokaż tylko te węzły, resztę zwiń",
peopleLensOff:"Klik: usuń filtr", peopleLensOff:"Klik: usuń filtr",
@@ -3153,6 +3162,7 @@ const I18N = {
assigneeOverloadWarn:"@{tag} несёт {share} % открытой работы на самом дешёвом пути ({stations} из {total} станций) — возможное узкое место.", assigneeOverloadWarn:"@{tag} несёт {share} % открытой работы на самом дешёвом пути ({stations} из {total} станций) — возможное узкое место.",
peopleBarLabel:"Ответственные", peopleBarLabel:"Ответственные",
peopleUnassigned:"без ответственного", peopleUnassigned:"без ответственного",
peopleUnassignedShort:"не назначено",
peopleShare:"{share} % открытой работы на самом дешёвом пути", peopleShare:"{share} % открытой работы на самом дешёвом пути",
peopleLensOn:"Клик: показать только эти узлы, остальное свернуть", peopleLensOn:"Клик: показать только эти узлы, остальное свернуть",
peopleLensOff:"Клик: снять фильтр", peopleLensOff:"Клик: снять фильтр",
@@ -3287,6 +3297,7 @@ const I18N = {
assigneeOverloadWarn:"@{tag} सबसे सस्ते पथ पर खुले काम का {share}% उठाए हुए है ({total} में से {stations} स्टेशन) — संभावित अड़चन।", assigneeOverloadWarn:"@{tag} सबसे सस्ते पथ पर खुले काम का {share}% उठाए हुए है ({total} में से {stations} स्टेशन) — संभावित अड़चन।",
peopleBarLabel:"ज़िम्मेदार", peopleBarLabel:"ज़िम्मेदार",
peopleUnassigned:"बिना ज़िम्मेदार", peopleUnassigned:"बिना ज़िम्मेदार",
peopleUnassignedShort:"तय नहीं",
peopleShare:"सबसे सस्ते पथ पर खुले काम का {share}%", peopleShare:"सबसे सस्ते पथ पर खुले काम का {share}%",
peopleLensOn:"क्लिक: केवल ये नोड दिखाएँ, बाकी सब समेटें", peopleLensOn:"क्लिक: केवल ये नोड दिखाएँ, बाकी सब समेटें",
peopleLensOff:"क्लिक: फ़िल्टर हटाएँ", peopleLensOff:"क्लिक: फ़िल्टर हटाएँ",
@@ -3421,6 +3432,7 @@ const I18N = {
assigneeOverloadWarn:"@{tag} 承担最便宜路径上 {share}% 的未完成工作({total} 个站点中的 {stations} 个)——可能的瓶颈。", assigneeOverloadWarn:"@{tag} 承担最便宜路径上 {share}% 的未完成工作({total} 个站点中的 {stations} 个)——可能的瓶颈。",
peopleBarLabel:"负责人", peopleBarLabel:"负责人",
peopleUnassigned:"未分配", peopleUnassigned:"未分配",
peopleUnassignedShort:"未分配",
peopleShare:"最便宜路径上未完成工作的 {share}%", peopleShare:"最便宜路径上未完成工作的 {share}%",
peopleLensOn:"点击:只显示这些节点,折叠其余部分", peopleLensOn:"点击:只显示这些节点,折叠其余部分",
peopleLensOff:"点击:取消筛选", peopleLensOff:"点击:取消筛选",
@@ -3555,6 +3567,7 @@ const I18N = {
assigneeOverloadWarn:"@{tag} が最安パスの未完了作業の {share}% を担っています(全 {total} 駅中 {stations} 駅)— ボトルネックの可能性。", assigneeOverloadWarn:"@{tag} が最安パスの未完了作業の {share}% を担っています(全 {total} 駅中 {stations} 駅)— ボトルネックの可能性。",
peopleBarLabel:"担当者", peopleBarLabel:"担当者",
peopleUnassigned:"担当者なし", peopleUnassigned:"担当者なし",
peopleUnassignedShort:"未割当",
peopleShare:"最安パスの未完了作業の {share}%", peopleShare:"最安パスの未完了作業の {share}%",
peopleLensOn:"クリック:このノードだけを表示し、他を折りたたむ", peopleLensOn:"クリック:このノードだけを表示し、他を折りたたむ",
peopleLensOff:"クリック:フィルターを解除", peopleLensOff:"クリック:フィルターを解除",