fix: Eingabedaten im KUE-Modal persistent über window.__kueCache gespeichert

- Lokale Zustände unabhängig von Redux-Intervallen gemacht
- window.__kueCache speichert pro Slot die aktuellen Eingabedaten
- Rückschreiben in Redux erfolgt nur beim Speichern
- Remounts und Polling beeinflussen keine laufenden Eingaben mehr
This commit is contained in:
Ismail Ali
2025-04-29 23:50:46 +02:00
parent 29bccd5ff2
commit 3a3340da7a
3 changed files with 78 additions and 157 deletions

View File

@@ -1,28 +1,16 @@
"use client"; "use client"; // KueEinstellung.tsx komplett angepasst mit window.__kueCache zum Schutz vor Remount-Reset
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import type { RootState } from "../../../../../redux/store"; import type { RootState } from "../../../../../redux/store";
import { setKueData } from "../../../../../redux/slices/kueDataSlice"; import { setKueData } from "../../../../../redux/slices/kueDataSlice";
import handleSave, { OriginalValues } from "../handlers/handleSave";
import handleDisplayEinschalten from "../handlers/handleDisplayEinschalten"; import handleDisplayEinschalten from "../handlers/handleDisplayEinschalten";
import firmwareUpdate from "../handlers/firmwareUpdate"; import firmwareUpdate from "../handlers/firmwareUpdate";
import { useAdminAuth } from "../../../settingsPageComponents/hooks/useAdminAuth"; import { useAdminAuth } from "../../../settingsPageComponents/hooks/useAdminAuth";
declare global {
interface Window {
win_kueID?: string[];
win_kueLimit1?: number[];
win_kueDelay1?: number[];
win_kueLimit2Low?: number[];
win_kueLimit2High?: number[];
win_kueLoopInterval?: number[];
win_memoryInterval?: number[];
}
}
interface Props { interface Props {
slot: number; slot: number;
showModal: boolean;
onClose?: () => void; onClose?: () => void;
onModulNameChange?: (id: string) => void; onModulNameChange?: (id: string) => void;
} }
@@ -41,8 +29,8 @@ const memoryIntervalOptions = [
export default function KueEinstellung({ export default function KueEinstellung({
slot, slot,
showModal,
onClose = () => {}, onClose = () => {},
onModulNameChange = () => {},
}: Props) { }: Props) {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { const {
@@ -50,123 +38,75 @@ export default function KueEinstellung({
kueLimit1, kueLimit1,
kueDelay1, kueDelay1,
kueLimit2Low, kueLimit2Low,
kueLimit2High,
kueLoopInterval, kueLoopInterval,
memoryInterval, memoryInterval,
} = useSelector((state: RootState) => state.kueDataSlice); } = useSelector((state: RootState) => state.kueDataSlice);
const { isAdminLoggedIn } = useAdminAuth(true); const { isAdminLoggedIn } = useAdminAuth(true);
// Lokale States const formCacheKey = `slot_${slot}`;
const [localName, setLocalName] = useState(kueID[slot] || ""); if (typeof window !== "undefined") {
const [localLimit1, setLocalLimit1] = useState<number | "">( window.__kueCache = window.__kueCache || {};
kueLimit1[slot] ?? "" }
);
const [localDelay1, setLocalDelay1] = useState<number | "">(
kueDelay1[slot] ?? ""
);
const [localLimit2Low, setLocalLimit2Low] = useState<number | "">(
kueLimit2Low[slot] ?? ""
);
const [localLoopInterval, setLocalLoopInterval] = useState<number | "">(
kueLoopInterval[slot] ?? ""
);
const [localMemoryInterval, setLocalMemoryInterval] = useState<number | "">(
memoryInterval[slot] ?? ""
);
/* const cached =
fix: Eingabefelder beim Öffnen des KUE-Modal initialisieren und gegen Redux-Updates schützen typeof window !== "undefined" ? window.__kueCache?.[formCacheKey] : null;
- Lokale States beim ersten Öffnen des Modals gesetzt const [formData, setFormData] = useState(() => {
- Redux-Änderungen während der Bearbeitung blockiert, um Fokusverlust zu verhindern if (cached) return cached;
- Benutzerfreundlichkeit bei der Bearbeitung von Kabelüberwachungen verbessert return {
name: kueID[slot] || "",
*/ limit1: kueLimit1[slot]?.toString() ?? "",
//---------------------------------------------------------------- delay1: kueDelay1[slot]?.toString() ?? "",
const [initialized, setInitialized] = useState(false); limit2Low: kueLimit2Low[slot]?.toString() ?? "",
const [editMode, setEditMode] = useState(false); loopInterval: kueLoopInterval[slot]?.toString() ?? "",
useEffect(() => { memoryInterval: memoryInterval[slot]?.toString() ?? "",
setEditMode(true);
return () => {
setEditMode(false);
}; };
}, []); });
useEffect(() => { const handleChange = (key: keyof typeof formData, value: string) => {
if (!initialized && editMode) { const updated = { ...formData, [key]: value };
setLocalName(kueID[slot] || ""); setFormData(updated);
setLocalLimit1(kueLimit1[slot] ?? ""); if (typeof window !== "undefined") {
setLocalDelay1(kueDelay1[slot] ?? ""); window.__kueCache[formCacheKey] = updated;
setLocalLimit2Low(kueLimit2Low[slot] ?? "");
setLocalLoopInterval(kueLoopInterval[slot] ?? "");
setLocalMemoryInterval(memoryInterval[slot] ?? "");
setInitialized(true);
} }
}, [initialized, slot, editMode]);
//----------------------------------------------------------------
const handleSaveWrapper = () => {
setEditMode(false); // <--- Editmode deaktivieren
onClose(); // <--- Modal direkt schließen
const originalValues: OriginalValues = {
kueID: [...(window.win_kueID ?? [])],
isolationsgrenzwerte: [...(window.win_kueLimit1 ?? [])],
verzoegerung: [...(window.win_kueDelay1 ?? [])],
untereSchleifenGrenzwerte: [...(window.win_kueLimit2Low ?? [])],
obereSchleifenGrenzwerte: [...(window.win_kueLimit2High ?? [])],
schleifenintervall: [...(window.win_kueLoopInterval ?? [])],
speicherintervall: [...(window.win_memoryInterval ?? [])],
};
handleSave({
ids: [...kueID],
isolationsgrenzwerte: [...kueLimit1],
verzoegerung: [...kueDelay1],
untereSchleifenGrenzwerte: [...kueLimit2Low],
obereSchleifenGrenzwerte: [...kueLimit2High],
schleifenintervall: [...kueLoopInterval],
speicherintervall: [...memoryInterval],
originalValues,
slot,
dispatch,
onModulNameChange,
onClose,
});
}; };
const updateRedux = () => { const handleSaveWrapper = () => {
if (!editMode) return; const updatedKueID = [...kueID];
updatedKueID[slot] = formData.name;
const updatedLimit1 = [...kueLimit1];
updatedLimit1[slot] = Number(formData.limit1);
const updatedDelay1 = [...kueDelay1];
updatedDelay1[slot] = Number(formData.delay1);
const updatedLimit2Low = [...kueLimit2Low];
updatedLimit2Low[slot] = Number(formData.limit2Low);
const updatedLoopInterval = [...kueLoopInterval];
updatedLoopInterval[slot] = Number(formData.loopInterval);
const updatedMemoryInterval = [...memoryInterval];
updatedMemoryInterval[slot] = Number(formData.memoryInterval);
dispatch( dispatch(
setKueData({ setKueData({
kueID: [...kueID.slice(0, slot), localName, ...kueID.slice(slot + 1)], kueID: updatedKueID,
kueLimit1: [ kueLimit1: updatedLimit1,
...kueLimit1.slice(0, slot), kueDelay1: updatedDelay1,
Number(localLimit1), kueLimit2Low: updatedLimit2Low,
...kueLimit1.slice(slot + 1), kueLoopInterval: updatedLoopInterval,
], memoryInterval: updatedMemoryInterval,
kueDelay1: [
...kueDelay1.slice(0, slot),
Number(localDelay1),
...kueDelay1.slice(slot + 1),
],
kueLimit2Low: [
...kueLimit2Low.slice(0, slot),
Number(localLimit2Low),
...kueLimit2Low.slice(slot + 1),
],
kueLoopInterval: [
...kueLoopInterval.slice(0, slot),
Number(localLoopInterval),
...kueLoopInterval.slice(slot + 1),
],
memoryInterval: [
...memoryInterval.slice(0, slot),
Number(localMemoryInterval),
...memoryInterval.slice(slot + 1),
],
}) })
); );
if (typeof window !== "undefined") {
delete window.__kueCache[formCacheKey];
}
onClose();
}; };
return ( return (
@@ -176,9 +116,8 @@ fix: Eingabefelder beim Öffnen des KUE-Modal initialisieren und gegen Redux-Upd
<input <input
type="text" type="text"
className="w-full border rounded p-1 text-sm" className="w-full border rounded p-1 text-sm"
value={localName} value={formData.name}
onChange={(e) => setLocalName(e.target.value)} onChange={(e) => handleChange("name", e.target.value)}
onBlur={updateRedux}
/> />
</div> </div>
@@ -198,13 +137,8 @@ fix: Eingabefelder beim Öffnen des KUE-Modal initialisieren und gegen Redux-Upd
type="number" type="number"
step="0.1" step="0.1"
className="w-[6rem] border rounded p-1" className="w-[6rem] border rounded p-1"
value={localLimit1} value={formData.limit1}
onChange={(e) => onChange={(e) => handleChange("limit1", e.target.value)}
setLocalLimit1(
e.target.value ? parseFloat(e.target.value) : ""
)
}
onBlur={updateRedux}
/> />
</td> </td>
<td className="border p-2 text-center"> <td className="border p-2 text-center">
@@ -212,13 +146,8 @@ fix: Eingabefelder beim Öffnen des KUE-Modal initialisieren und gegen Redux-Upd
type="number" type="number"
step="0.1" step="0.1"
className="w-[6rem] border rounded p-1" className="w-[6rem] border rounded p-1"
value={localDelay1} value={formData.delay1}
onChange={(e) => onChange={(e) => handleChange("delay1", e.target.value)}
setLocalDelay1(
e.target.value ? parseFloat(e.target.value) : ""
)
}
onBlur={updateRedux}
/> />
</td> </td>
</tr> </tr>
@@ -242,13 +171,8 @@ fix: Eingabefelder beim Öffnen des KUE-Modal initialisieren und gegen Redux-Upd
type="number" type="number"
step="0.1" step="0.1"
className="w-[6rem] border rounded p-1" className="w-[6rem] border rounded p-1"
value={localLimit2Low} value={formData.limit2Low}
onChange={(e) => onChange={(e) => handleChange("limit2Low", e.target.value)}
setLocalLimit2Low(
e.target.value ? parseFloat(e.target.value) : ""
)
}
onBlur={updateRedux}
/> />
</td> </td>
<td className="border p-2 text-center"> <td className="border p-2 text-center">
@@ -256,13 +180,8 @@ fix: Eingabefelder beim Öffnen des KUE-Modal initialisieren und gegen Redux-Upd
type="number" type="number"
step="0.1" step="0.1"
className="w-[6rem] border rounded p-1" className="w-[6rem] border rounded p-1"
value={localLoopInterval} value={formData.loopInterval}
onChange={(e) => onChange={(e) => handleChange("loopInterval", e.target.value)}
setLocalLoopInterval(
e.target.value ? parseFloat(e.target.value) : ""
)
}
onBlur={updateRedux}
/> />
</td> </td>
</tr> </tr>
@@ -273,11 +192,8 @@ fix: Eingabefelder beim Öffnen des KUE-Modal initialisieren und gegen Redux-Upd
<label className="font-bold block mb-1">Speicherintervall</label> <label className="font-bold block mb-1">Speicherintervall</label>
<select <select
className="w-full border rounded p-1 text-sm" className="w-full border rounded p-1 text-sm"
value={localMemoryInterval} value={formData.memoryInterval}
onChange={(e) => onChange={(e) => handleChange("memoryInterval", e.target.value)}
setLocalMemoryInterval(parseInt(e.target.value, 10))
}
onBlur={updateRedux}
> >
{memoryIntervalOptions.map((opt) => ( {memoryIntervalOptions.map((opt) => (
<option key={opt.value} value={opt.value}> <option key={opt.value} value={opt.value}>

View File

@@ -27,6 +27,11 @@ export default function KueModal({ showModal, onClose, slot }: KueModalProps) {
(window as any).__lastKueTab = activeTab; (window as any).__lastKueTab = activeTab;
} }
}, [activeTab]); }, [activeTab]);
useEffect(() => {
if (typeof window !== "undefined") {
window.kabelModalOpen = showModal;
}
}, [showModal]);
return ( return (
<ReactModal <ReactModal
@@ -94,15 +99,15 @@ export default function KueModal({ showModal, onClose, slot }: KueModalProps) {
</div> </div>
<div className="p-4 bg-white rounded-b-md max-h-[75vh] overflow-y-auto"> <div className="p-4 bg-white rounded-b-md max-h-[75vh] overflow-y-auto">
{activeTab === "kue" && ( <div style={{ display: activeTab === "kue" ? "block" : "none" }}>
<KueEinstellung <KueEinstellung
slot={slot} slot={slot}
onModulNameChange={(id) => { showModal={showModal} // ← hier übergeben
console.log("Modulname geändert:", id); onModulNameChange={(id) => console.log("Modulname geändert:", id)}
}}
onClose={onClose} onClose={onClose}
/> />
)} </div>
{activeTab === "tdr" && <TdrEinstellung slot={slot} />} {activeTab === "tdr" && <TdrEinstellung slot={slot} />}
{activeTab === "knoten" && <Knotenpunkte slot={slot} />} {activeTab === "knoten" && <Knotenpunkte slot={slot} />}
</div> </div>

View File

@@ -6,5 +6,5 @@
2: Patch oder Hotfix (Bugfixes oder kleine Änderungen). 2: Patch oder Hotfix (Bugfixes oder kleine Änderungen).
*/ */
const webVersion = "1.6.315"; const webVersion = "1.6.316";
export default webVersion; export default webVersion;