App-weite Warnung bei ungespeicherten Aenderungen + Options-UI-Fix + Cache-Busting
1. Generischer Ja/Nein-Dialog bei ungespeicherten Aenderungen (kein Opt-in pro Seite noetig): initUnsavedChangesGuard() erkennt automatisch jedes Formular mit echten Eingabefeldern, das seit dem Laden der Seite veraendert wurde, und fragt beim Klick auf einen Link (z.B. Sidebar- Navigation), ob zuerst gespeichert werden soll -- eigener Dialog (confirmSaveDiscard) statt des bestehenden confirmAction (dort ist "Abbrechen" = Bleiben, hier gibt es bewusst nur die zwei angefragten Optionen: speichern oder verwerfen, beide verlassen die Seite). "Ja, speichern" sendet das Formular ganz normal ab (echter POST) und merkt sich das eigentliche Ziel in sessionStorage, um danach automatisch dorthin weiterzuleiten. Nachtrag noch in dieser Session gefixt: ein normales Speichern ueber den Seiten-eigenen Button loeste zusaetzlich die native Browser-Warnung (beforeunload) aus, obwohl die Aenderung bereits gespeichert wurde -- navigatingAway-Flag wird jetzt bei jedem Submit eines beobachteten Formulars (eigener Button ODER eigener Ja/Nein-Dialog) gesetzt, die generische Browser-Warnung erscheint dadurch nur noch bei tatsaechlich ungefragter Navigation (Tab schliessen, Reload, Adresszeile). Live per Playwright in drei Szenarien verifiziert (direktes Speichern, Ja via eigenem Dialog, Nein via eigenem Dialog) -- kein Browser-Popup in den ersten beiden Faellen, korrektes Redirect zum urspruenglichen Ziel nach "Ja". 2. DHCP-Options-Dropdown (Reservierungs-Dialog) verschiebt ein neu ausgewaehltes Options-Feld jetzt direkt unter das Dropdown (in einen .poe-added-options-Container) statt es nur an seiner urspruenglichen Stelle in der bis zu 57 Eintraege langen Liste einzublenden -- lag dort oft ausserhalb des sichtbaren Modal-Ausschnitts und wirkte, als waere nichts passiert. Bereits gesetzte Overrides stehen von Anfang an im selben Container, weitere haengen sich beim Auswaehlen unten an. 3. Cache-Busting fuer app.js/style.css (asset_url()-Helper, haengt die Aenderungszeit der Datei als ?v=... an) -- ein im Browser gecachtes, veraltetes app.js konnte nach einem Update sonst den Eindruck erwecken, eine neue Funktion wuerde "nicht funktionieren", obwohl der Code auf dem Server laengst aktuell war. Alle drei live auf der Test-VM deployt und per Playwright verifiziert, keine Fehler im journalctl-Log. (Testartefakt aufgeraeumt: der echte Host-Hostname wurde durch die Playwright-Tests versehentlich auf "directsave-test"/"navsave-test" geaendert und wieder auf POETEST zurueckgesetzt.)
This commit is contained in:
@@ -421,7 +421,7 @@
|
||||
Nur Options mit gesetztem Override sind sichtbar — über das Dropdown weitere hinzufügen.
|
||||
Leerer Wert übernimmt den globalen Wert (bzw. entfernt den Override).
|
||||
</p>
|
||||
<select onchange="poeShowOptionField(this)" style="margin-bottom:14px;">
|
||||
<select onchange="poeShowOptionField(this)">
|
||||
<option value="">+ Option hinzufügen…</option>
|
||||
{% for d in option_defs %}
|
||||
{% if not option_values.get(d.id, {}).get(r.mac) %}
|
||||
@@ -429,13 +429,31 @@
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
<!-- Neu ausgewählte Felder landen hier direkt unter dem Dropdown
|
||||
(siehe poeShowOptionField in app.js), statt irgendwo in der
|
||||
u.U. langen Liste unten sichtbar zu werden. Bereits gesetzte
|
||||
Overrides stehen von Anfang an hier drin. -->
|
||||
<div class="poe-added-options" style="margin:10px 0;">
|
||||
{% for d in option_defs %}
|
||||
{% set current = option_values.get(d.id, {}).get(r.mac, '') %}
|
||||
{% if current %}
|
||||
<div class="field" id="opt-field-{{ d.id }}-{{ loop.index }}-{{ r.mac }}">
|
||||
<label>{{ d.name }} <span class="text-faint">(Code {{ d.code }})</span></label>
|
||||
<input type="text" name="opt_{{ d.id }}" value="{{ current }}"
|
||||
placeholder="{{ option_values.get(d.id, {}).get('', '(kein globaler Wert)') }}">
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% for d in option_defs %}
|
||||
{% set current = option_values.get(d.id, {}).get(r.mac, '') %}
|
||||
<div class="field" id="opt-field-{{ d.id }}-{{ loop.index }}-{{ r.mac }}" {% if not current %}style="display:none;"{% endif %}>
|
||||
{% if not current %}
|
||||
<div class="field" id="opt-field-{{ d.id }}-{{ loop.index }}-{{ r.mac }}" style="display:none;">
|
||||
<label>{{ d.name }} <span class="text-faint">(Code {{ d.code }})</span></label>
|
||||
<input type="text" name="opt_{{ d.id }}" value="{{ current }}"
|
||||
<input type="text" name="opt_{{ d.id }}" value=""
|
||||
placeholder="{{ option_values.get(d.id, {}).get('', '(kein globaler Wert)') }}">
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
Reference in New Issue
Block a user