Nichts verschwindet mehr ohne eine Nachfrage, die sagt was passiert

Filipe: "Es darf vor allem keine Stellen geben, an denen ein Benutzer
etwas falsch machen kann, nur weil die Seite es nicht verstaendlich
genug erklaert."

Gemessen: 30 Stellen in 16 Dateien benutzten confirm() oder prompt().
Das Haus hatte die richtige Bauweise laengst -- einen <dialog>, in
aufgaben.html sogar ausfuehrlich begruendet -- aber sie stand IN EINER
SEITE. Wer anderswo etwas loeschen liess, hatte sie nicht.

confirm('Wirklich loeschen?') stellt die falsche Frage: Es fragt, ob
man sicher ist, und nennt nicht, WAS passiert, was BLEIBT und ob es
ZURUECK geht. Jetzt beantwortet jeder der 41 Dialoge alle drei.

Neu: workspace/assets/js/nachfrage.js -- window.frageNach() mit
Pflichtgrund, Zahlenfeld, einzeiliger Eingabe und Abtippsicherung.
Drei Ausgaenge: <dialog> / confirm()-Notnagel fuer Safari vor 15.4 /
Abbruch (Esc, Klick daneben, "Doch nicht" -- immer false).

DREIMAL DERSELBE FALLSTRICK, dreimal nachgemessen statt vermutet:
  .dialog stand in aufgaben.css und leistung.css -> auf dateien.html
    waere der Dialog ein weisser Systemkasten gewesen. 14 Regeln
    klammergenau nach module.css verschoben (Klammern gezaehlt, nicht
    per Muster geschnitten -- heute frueh hat ein nicht-gieriges
    Muster schon einmal CSS zerrissen).
  Das Formular trug .neu neu--blank -- und .neu gibt seine Abstaende
    nur in aufgaben.css. Gemessen: padding 0px, und die Felder
    verloren ihre height:44px. Jetzt steht alles unter
    .nachfrage__form in module.css; der Dialog borgt nichts mehr.
  Die erste Fassung der Pruefung zaehlte nachfrage.js SELBST als
    Nutzer -- damit war jede Seite trivialerweise "Nutzer" und die
    Pruefung gruen ohne Inhalt. Jetzt ausdruecklich ausgenommen.

ZWEI FUNDE NEBENBEI:
  hilfeAufraeumen() wird im Betrieb NIE aufgerufen. Der Kommentar
    behauptete "wird beim Start aufgerufen (siehe index.js)" -- das
    war nie wahr; einziger Aufrufer ist die eigene Pruefung. Folge:
    geschlossene vertrauliche Faelle bleiben unbegrenzt stehen. NICHT
    eingeschaltet (das loescht echte Daten und ist Filipes
    Entscheidung), sondern der Kommentar richtiggestellt.
  Einen Hilfe-Fall zu schliessen ist endgueltig -- es gibt keine
    Route, die ihn wieder oeffnet. Vorher stand darueber nur die
    Frage nach einem Schlusswort. Jetzt sagt der Dialog es.

pruef-struktur hat meine eigene Pruefung von heute Nachmittag
erwischt: Sie bildete ihr Datum aus UTC. Beim Beheben erst
heuteLokal(datum) genommen -- die Funktion nimmt gar kein Argument
und haette still "heute" statt "+3 Tage" geliefert. Jetzt tagLokal(3),
nachgerechnet: Abstand 3 Tage.

Am Bildschirm angesehen (Rechner 1280, Handy 390): passt rein, Esc
ergibt false, Fokus liegt auf dem harmlosen Knopf, Knoepfe 44px auf
Touch. Der Platzhalter im Abtippfeld zeigte den erwarteten Namen --
das sah aus wie ein schon ausgefuelltes Feld, entfernt.

Neu: server/pruef-nachfrage.mjs -- 17/0, mit sechs Gegenproben und
beiden Richtungen (wer fragt, laedt die Datei; wer nie fragt, laedt
sie nicht -- sonst truege die Anmeldewand 4,8 KB fuer nichts).

pruef-meldungen 8/0, pruef-css-klassen gruen, pruef-struktur gruen,
pruef-leistung gruen.
This commit is contained in:
2026-09-19 19:57:43 +02:00
parent 26937dda16
commit c516aad4ed
65 changed files with 5099 additions and 4111 deletions
+13 -2
View File
@@ -213,7 +213,12 @@
knoepfe.append(tuKnopf('→ LIVE', 'Als LIVE-Thema vormerken', () => uebernehmen(e, 'live')));
}
knoepfe.append(tuKnopf('löschen', 'Dieses Video entfernen', async () => {
if (!confirm(`„${e.titel}" wirklich löschen?`)) return;
if (!await frageNach({
titel: `„${e.titel}" löschen?`,
was: 'Die Idee verschwindet aus der Planung.',
bleibt: 'Ein schon eingetragener Drehtermin im Kalender bleibt stehen.',
endgueltig: true, ja: 'Löschen',
})) return;
const a = await hole(`/workspace/api/bereich/content/${e.id}`, { method: 'DELETE' });
if (!a.ok) { melde('Löschen hat nicht geklappt.'); return; }
await laden();
@@ -383,7 +388,13 @@
Ausgeblendet ist nicht dasselbe wie nicht vorhanden. */
if (!darfEintragen()) { ziel.append(z); continue; }
z.append(tuKnopf('löschen', 'Säule entfernen, Videos bleiben', async () => {
if (!confirm(`Säule „${s.name}" entfernen? Die Videos bleiben, sie verlieren nur die Zuordnung.`)) return;
if (!await frageNach({
titel: `Säule „${s.name}" entfernen?`,
was: 'Die Säule verschwindet aus der Auswahl.',
bleibt: 'Alle Videos bleiben – sie stehen danach nur ohne Säule da '
+ 'und lassen sich jederzeit einer anderen zuordnen.',
ja: 'Säule entfernen',
})) return;
const a = await hole(`/workspace/api/content/saeulen/${s.id}`, { method: 'DELETE' });
if (!a.ok) { melde('Ging nicht.'); return; }
await laden();