frontend: „Was ist neu?" — neu in Produktion mit gelbem Strahlenkranz
Dokumente von außen (mitgeliefert D27, ?sourceUrl= D23) ändern sich, ohne dass der Betrachter es merkt. Sie zeigen jetzt, was sich seit seinem letzten Besuch getan hat. - „Neu" heißt bewusst NICHT „Zeile hinzugefügt", sondern **neu in Produktion**: ein Knoten trägt jetzt [^] und tat es in der zuletzt gesehenen Fassung nicht. Ein Zeilendiff meldete vor allem Rauschen; die Nachricht, die zählt, ist was live gegangen ist. Nebeneffekt: es leuchtet eine Handvoll Knoten, nicht dreißig. - Basis ist die zuletzt GESEHENE Fassung je Dokument (`werkbaum-seen`), nicht die letzte Auslieferung — wer Fassungen überspringt, sieht alles seither. Fortgeschrieben wird erst beim Bestätigen, sonst wäre die Meldung nach einem Neuladen weg, bevor sie jemand bemerkt. Beim Erstkontakt leuchtet nichts. - Knoten-Identität ist der Label-Pfad, nicht die Zeilennummer: Umeinrücken und Umsortieren erzeugen keine Falschmeldungen; gleichnamige Geschwister per Index; Umbenennen gilt als neuer Knoten (der Text ist der Vertrag, D14). - Darstellung: gelber Strahlenkranz nach außen, kein Blinken (WCAG 2.2.2/2.3.1; Blinken zöge dauerhaft den Blick statt einmal zu melden). Außen, weil die Füllung dem Status gehört (SPEC §4). Zusammen mit der Cursor-Zeile: Tinte innen, Gelb außen. Nicht im Druck und nicht im Grafikexport — die Markierung hängt am persönlichen Besuchsstand. - Knopf im Diagramm-Kopf nur, wenn es etwas gibt; nennt die Anzahl, Klick bestätigt. Kein Dauer-Umschalter. - Bei selbst bearbeitetem mitgeliefertem Dokument wird nichts hervorgehoben — dort fehlt die saubere Vergleichsbasis (D27). Fehler beim Bauen, der zuerst durchrutschte: Die Menge wurde beim Laden aus einem eigenen Parse-Durchlauf berechnet. Der Zähler stimmte, aber kein Knoten leuchtete — `Set.has()` prüft Objektidentität, und die gerenderten Knoten kamen aus einem anderen Parse. `render()` bildet die Menge jetzt bei jedem Durchlauf aus den gerade geparsten Wurzeln; vorgehalten wird nur der geparste Basisbaum. Verifiziert: 9 neue Modelltests (Statuswechsel, neuer [^]-Knoten, nicht-[^] ignoriert, unverändert ignoriert, Erstkontakt leer, Umsortieren/Tabs ohne Falschmeldung, gleiches Label unter verschiedenen Eltern, gleichnamige Geschwister, verworfene). Im Browser: Erstkontakt setzt nur die Basis (Knopf versteckt); zurückgedrehte Basis lässt genau die erwarteten Knoten leuchten (Zähler 3, dann 1); Bestätigen räumt auf und überlebt das Neuladen; ohne Bestätigen bleibt die Meldung über ein Neuladen stehen. Vitest 46/46. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
68abdc6625
commit
7a52277b84
+11
-2
@@ -9,10 +9,19 @@
|
||||
showDiscarded, // verworfene einblenden?
|
||||
cheapPath, // günstigster Pfad aktiv? (steuert das implizite M-Badge)
|
||||
cheapSet, // Set der nötigen Knoten (leer, wenn Pfad aus)
|
||||
freshSet, // optional: Knoten, die neu in Produktion sind (D28)
|
||||
} */
|
||||
|
||||
import { gateOf, needsBreakdown, visibleChildren, cheapCls } from './model.js';
|
||||
|
||||
/* Zusatzklassen eines Knotens: günstigster Pfad (D18) + „neu in Produktion"
|
||||
gegenüber der zuletzt gesehenen Fassung (D28, `freshSet` optional). */
|
||||
function extraCls(n, opts){
|
||||
const cheap = cheapCls(n, opts.cheapSet);
|
||||
const fresh = opts.freshSet && opts.freshSet.has(n) ? 'fresh' : '';
|
||||
return [cheap, fresh].filter(Boolean).join(' ');
|
||||
}
|
||||
|
||||
export function esc(s){
|
||||
return s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
||||
}
|
||||
@@ -85,7 +94,7 @@ function renderChildren(node, warnings, opts){
|
||||
const vk = visibleChildren(k, opts.showDiscarded);
|
||||
const liCls = vk.length ? (gateOf(vk) === 'or' ? ' class="has-or"' : ' class="has-and"') : '';
|
||||
return `<li${liCls}>` +
|
||||
nodeHtml(k, cheapCls(k, opts.cheapSet), opts) +
|
||||
nodeHtml(k, extraCls(k, opts), opts) +
|
||||
renderChildren(k, warnings, opts) +
|
||||
`</li>`;
|
||||
}).join('');
|
||||
@@ -101,7 +110,7 @@ export function renderTreeHtml(roots, opts){
|
||||
const vk = visibleChildren(root, opts.showDiscarded);
|
||||
const liCls = vk.length ? (gateOf(vk) === 'or' ? ' class="has-or"' : ' class="has-and"') : '';
|
||||
return `<li${liCls}>` +
|
||||
nodeHtml(root, ('root-node ' + cheapCls(root, opts.cheapSet)).trim(), opts) +
|
||||
nodeHtml(root, ('root-node ' + extraCls(root, opts)).trim(), opts) +
|
||||
renderChildren(root, warnings, opts) +
|
||||
`</li>`;
|
||||
}).join('');
|
||||
|
||||
Reference in New Issue
Block a user