Kableüberwachung Modal und digitale Eingänge Modal

This commit is contained in:
ISA
2025-05-06 14:31:08 +02:00
parent 9c44fa0a49
commit 36f791237c
9 changed files with 81 additions and 79 deletions

View File

@@ -33,6 +33,15 @@ export default function AnalogeEingaengeTable({
return ( return (
<div className="w-full"> <div className="w-full">
<h2 className="text-sm laptop:text-xs font-bold mb-3 flex items-center">
<img
src="/images/analogeEingaengeIcon.svg"
alt="Analoge Eingänge"
className="w-6 h-6 mr-2 text-littwin-blue"
/>
Messwerteingänge
</h2>
<div className="bg-white shadow-lg rounded-lg p-4 border border-gray-200"> <div className="bg-white shadow-lg rounded-lg p-4 border border-gray-200">
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<table className="w-full border-collapse border border-gray-300 text-sm md:text-base"> <table className="w-full border-collapse border border-gray-300 text-sm md:text-base">

View File

@@ -64,7 +64,7 @@ export default function DigitalInputs({ openInputModal, inputRange }: Props) {
</span> </span>
<div className="absolute bottom-full left-1/2 -translate-x-1/2 mb-2 w-max bg-gray-400 text-xs laptop:text-[10px] text-white rounded opacity-0 group-hover:opacity-100 transition p-1 z-10 xl:text-sm "> <div className="absolute bottom-full left-1/2 -translate-x-1/2 mb-2 w-max bg-gray-400 text-xs laptop:text-[10px] text-white rounded opacity-0 group-hover:opacity-100 transition p-1 z-10 xl:text-sm ">
Eingang Aus Eingang Ein
</div> </div>
</div> </div>
) : ( ) : (
@@ -73,7 +73,7 @@ export default function DigitalInputs({ openInputModal, inputRange }: Props) {
</span> </span>
<div className="absolute bottom-full left-1/2 -translate-x-1/2 mb-2 w-max bg-gray-400 text-xs laptop:text-[10px] text-white rounded opacity-0 group-hover:opacity-100 transition p-1 z-10"> <div className="absolute bottom-full left-1/2 -translate-x-1/2 mb-2 w-max bg-gray-400 text-xs laptop:text-[10px] text-white rounded opacity-0 group-hover:opacity-100 transition p-1 z-10">
Eingang Ein Eingang Aus
</div> </div>
</div> </div>
)} )}

View File

@@ -23,6 +23,7 @@ export default function InputModal({ selectedInput, closeInputModal, isOpen }) {
const [filterzeit, setFilterzeit] = useState(0); const [filterzeit, setFilterzeit] = useState(0);
const [gewichtung, setGewichtung] = useState(0); const [gewichtung, setGewichtung] = useState(0);
const [zaehlerAktiv, setZaehlerAktiv] = useState(false); const [zaehlerAktiv, setZaehlerAktiv] = useState(false);
const [eingangOffline, setEingangOffline] = useState(false);
useEffect(() => { useEffect(() => {
if (reduxInput && isInitialLoad) { if (reduxInput && isInitialLoad) {
@@ -31,6 +32,7 @@ export default function InputModal({ selectedInput, closeInputModal, isOpen }) {
setFilterzeit(reduxInput.filterzeit); setFilterzeit(reduxInput.filterzeit);
setGewichtung(reduxInput.gewichtung); setGewichtung(reduxInput.gewichtung);
setZaehlerAktiv(reduxInput.zaehlerAktiv); setZaehlerAktiv(reduxInput.zaehlerAktiv);
setEingangOffline(reduxInput.eingangOffline);
setIsInitialLoad(false); setIsInitialLoad(false);
} }
}, [reduxInput, isInitialLoad]); }, [reduxInput, isInitialLoad]);
@@ -76,6 +78,10 @@ export default function InputModal({ selectedInput, closeInputModal, isOpen }) {
await sendCgiUpdate(`DEZ${id}=${zaehlerAktiv ? 1 : 0}`); await sendCgiUpdate(`DEZ${id}=${zaehlerAktiv ? 1 : 0}`);
hasChange = true; hasChange = true;
} }
if (eingangOffline !== reduxInput.eingangOffline) {
await sendCgiUpdate(`DEO${id}=${eingangOffline ? 1 : 0}`);
hasChange = true;
}
if (!hasChange) { if (!hasChange) {
alert("⚠️ Keine Änderungen erkannt."); alert("⚠️ Keine Änderungen erkannt.");
return; return;
@@ -141,30 +147,13 @@ export default function InputModal({ selectedInput, closeInputModal, isOpen }) {
return ( return (
<div className="fixed top-0 left-0 w-full h-full bg-black bg-opacity-50 flex justify-center items-center z-50"> <div className="fixed top-0 left-0 w-full h-full bg-black bg-opacity-50 flex justify-center items-center z-50">
<div className="bg-white rounded-lg shadow-lg p-6 w-1/2 max-w-lg"> <div className="bg-white rounded-lg shadow-lg p-6 w-1/2 max-w-lg">
<h2 className="text-xl font-semibold text-blue-500 mb-4 border-b pb-2"> <h2 className="text-base font-bold mb-4 border-b pb-2">
Parameter für Eingang {selectedInput.id} Einstellungen Eingang {selectedInput.id}
</h2> </h2>
<div className="grid grid-cols-2 gap-x-4 gap-y-3"> <div className="grid grid-cols-2 gap-x-4 gap-y-3">
<div> <div>
<strong>Zustand:</strong> <span className="font-normal">Bezeichnung:</span>
</div>
<div className="flex items-center gap-3 text-xl font-semibold col-span-1">
{reduxInput.status ? (
<>
<span className="text-red-500 text-2xl"></span>
<span className="text-red-600">Aus</span>
</>
) : (
<>
<span className="text-green-500 text-2xl"></span>
<span className="text-green-600">Ein</span>
</>
)}
</div>
<div>
<strong>Name:</strong>
</div> </div>
<div> <div>
<input <input
@@ -177,17 +166,16 @@ export default function InputModal({ selectedInput, closeInputModal, isOpen }) {
</div> </div>
<div> <div>
<strong>Invertierung:</strong> <span className="font-normal">Invertierung:</span>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span>{invertiert ? "Ein" : "Aus"}</span>
<button <button
type="button" type="button"
role="switch" role="switch"
aria-checked={invertiert} aria-checked={invertiert}
onClick={() => setInvertiert(!invertiert)} onClick={() => setInvertiert(!invertiert)}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors duration-200 ${ className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors duration-200 ${
invertiert ? "bg-green-500" : "bg-gray-300" invertiert ? "bg-littwin-blue" : "bg-gray-300"
}`} }`}
> >
<span <span
@@ -196,17 +184,11 @@ export default function InputModal({ selectedInput, closeInputModal, isOpen }) {
}`} }`}
/> />
</button> </button>
<span>{invertiert ? "Ein" : "Aus"}</span>
</div> </div>
{/* Zählerstand ausblenden */}
{/*
<div>
<strong>Zählerstand:</strong>
</div>
<div>{reduxInput.counter}</div>
*/}
<div> <div>
<strong>Filterzeit:</strong> <span className="font-normal">Filterzeit:</span>
</div> </div>
<div className="relative"> <div className="relative">
<input <input
@@ -220,16 +202,17 @@ export default function InputModal({ selectedInput, closeInputModal, isOpen }) {
setFilterzeit(val); setFilterzeit(val);
} }
}} }}
className="border border-gray-300 rounded px-2 py-1 pr-10 w-full" className="border border-gray-300 rounded px-2 py-1 pr-10 w-full text-right"
title="Maximal 2000 ms erlaubt" title="Maximal 2000 ms erlaubt"
/> />
<span className="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm"> <span className="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm">
ms ms
</span> </span>
</div> </div>
<div> <div>
<strong>Gewichtung:</strong> <span className="font-normal">Gewichtung:</span>
</div> </div>
<div> <div>
<input <input
@@ -243,57 +226,45 @@ export default function InputModal({ selectedInput, closeInputModal, isOpen }) {
setGewichtung(val); setGewichtung(val);
} }
}} }}
className="border border-gray-300 rounded px-2 py-1 w-full" className="border border-gray-300 rounded px-2 py-1 w-full text-right"
title="Maximal 1000 erlaubt" title="Maximal 1000 erlaubt"
/> />
</div> </div>
{/* Zähler aktiv ausblenden */}
{/* <div className="relative group inline-block">
<span className="font-normal">Out of Service:</span>
<div>
<strong>Zähler aktiv:</strong>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span>{zaehlerAktiv ? "Ja" : "Nein"}</span>
<button <button
type="button" type="button"
role="switch" role="switch"
aria-checked={zaehlerAktiv} aria-checked={eingangOffline}
onClick={() => setZaehlerAktiv(!zaehlerAktiv)} onClick={() => setEingangOffline(!eingangOffline)}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors duration-200 ${ className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors duration-200 ${
zaehlerAktiv ? "bg-green-500" : "bg-gray-300" eingangOffline ? "bg-littwin-blue" : "bg-gray-300"
}`} }`}
> >
<span <span
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform duration-200 ${ className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform duration-200 ${
zaehlerAktiv ? "translate-x-6" : "translate-x-1" eingangOffline ? "translate-x-6" : "translate-x-1"
}`} }`}
/> />
</button> </button>
<span>{eingangOffline ? "Ein" : "Aus"}</span>
</div> </div>
*/}
<div className="relative group inline-block">
<strong>OOS:</strong>
<span className="absolute top-full left-1/2 -translate-x-1/2 mt-1 px-2 py-1 text-xs text-white bg-gray-700 rounded opacity-0 group-hover:opacity-100 transition-opacity">
Out of Service
</span>
</div>
<div>{reduxInput.eingangOffline ? "aus" : "ein"}</div>
</div> </div>
<div className="mt-6 flex justify-end gap-2"> <div className="mt-6 flex justify-end gap-2">
<button <button
onClick={handleClose} onClick={handleClose}
className="px-4 py-2 bg-gray-300 hover:bg-gray-400 text-black rounded-lg transition" className="bg-littwin-blue text-white px-4 py-2 rounded flex items-center"
> >
Schließen Schließen
</button> </button>
<button <button
onClick={handleSpeichern} onClick={handleSpeichern}
className="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-lg transition" className="bg-littwin-blue text-white px-4 py-2 rounded flex items-center"
> >
Speichern Speichern
</button> </button>

View File

@@ -164,26 +164,30 @@ export default function KueEinstellung({
<h3 className="font-bold mb-2">Isolationsmessung</h3> <h3 className="font-bold mb-2">Isolationsmessung</h3>
<div className="mb-4 grid grid-cols-3 items-center gap-2 w-full"> <div className="mb-4 grid grid-cols-3 items-center gap-2 w-full">
<label className="w-48 ">Grenzwert:</label> <label className="w-48 ">Grenzwert:</label>
<div> <div className="relative w-36">
<input <input
type="number" type="number"
className="w-24 border rounded p-1 mr-2 text-right" className="border rounded px-2 py-1 pr-20 w-full text-right"
value={formData.limit1} value={formData.limit1}
onChange={(e) => handleChange("limit1", e.target.value)} onChange={(e) => handleChange("limit1", e.target.value)}
/> />
<span>MOhm</span> <span className="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm">
MOhm
</span>
</div> </div>
</div> </div>
<div className="mb-4 grid grid-cols-3 items-center gap-2 w-full"> <div className="mb-4 grid grid-cols-3 items-center gap-2 w-full">
<label className="w-48 ">Verzögerung:</label> <label className="w-48 ">Verzögerung:</label>
<div> <div className="relative w-36">
<input <input
type="number" type="number"
className="w-24 border rounded p-1 mr-2 text-right" className="border rounded px-2 py-1 pr-20 w-full text-right"
value={formData.delay1} value={formData.delay1}
onChange={(e) => handleChange("delay1", e.target.value)} onChange={(e) => handleChange("delay1", e.target.value)}
/> />
<span>Sekunden</span> <span className="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm">
Sekunden
</span>
</div> </div>
</div> </div>
</div> </div>
@@ -192,26 +196,30 @@ export default function KueEinstellung({
<h3 className="font-bold mb-2">Schleifenmessung</h3> <h3 className="font-bold mb-2">Schleifenmessung</h3>
<div className="mb-4 grid grid-cols-3 items-center gap-2 w-full"> <div className="mb-4 grid grid-cols-3 items-center gap-2 w-full">
<label className="w-48 ">Grenzwert:</label> <label className="w-48 ">Grenzwert:</label>
<div> <div className="relative w-36">
<input <input
type="number" type="number"
className="w-24 border rounded p-1 mr-2 text-right" className="border rounded px-2 py-1 pr-20 w-full text-right"
value={formData.limit2Low} value={formData.limit2Low}
onChange={(e) => handleChange("limit2Low", e.target.value)} onChange={(e) => handleChange("limit2Low", e.target.value)}
/> />
<span>kOhm</span> <span className="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm">
kOhm
</span>
</div> </div>
</div> </div>
<div className="mb-4 grid grid-cols-3 items-center gap-2 w-full"> <div className="mb-4 grid grid-cols-3 items-center gap-2 w-full">
<label className="w-48 ">Schleifenmessintervall:</label> <label className="w-48 ">Schleifenmessintervall:</label>
<div> <div className="relative w-36">
<input <input
type="number" type="number"
className="w-24 border rounded p-1 mr-2 text-right" className="border rounded px-2 py-1 pr-20 w-full text-right"
value={formData.loopInterval} value={formData.loopInterval}
onChange={(e) => handleChange("loopInterval", e.target.value)} onChange={(e) => handleChange("loopInterval", e.target.value)}
/> />
<span>Stunden</span> <span className="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm">
Stunden
</span>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -189,10 +189,10 @@ export default function TdrEinstellung({ slot, onClose }: Props) {
<div className="mt-6 mb-4"> <div className="mt-6 mb-4">
<div className="mb-4 grid grid-cols-3 items-center gap-2 w-full"> <div className="mb-4 grid grid-cols-3 items-center gap-2 w-full">
<label className="">TDR Dämpfung:</label> <label className="">TDR Dämpfung:</label>
<div className="flex items-center gap-2"> <div className="relative w-36">
<input <input
type="number" type="number"
className="w-24 border rounded p-1 mr-2 text-right" className="border rounded px-2 py-1 pr-20 w-full text-right"
value={tdrData.daempfung} value={tdrData.daempfung}
onChange={(e) => { onChange={(e) => {
const updated = { ...tdrData, daempfung: e.target.value }; const updated = { ...tdrData, daempfung: e.target.value };
@@ -200,15 +200,17 @@ export default function TdrEinstellung({ slot, onClose }: Props) {
updateCache(updated); updateCache(updated);
}} }}
/> />
<span>dB</span> <span className="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm">
dB
</span>
</div> </div>
</div> </div>
<div className="mb-4 grid grid-cols-3 items-center gap-2 w-full"> <div className="mb-4 grid grid-cols-3 items-center gap-2 w-full">
<label className="">Geschwindigkeit:</label> <label className="">Geschwindigkeit:</label>
<div className="flex items-center gap-2"> <div className="relative w-36">
<input <input
type="number" type="number"
className="w-24 border rounded p-1 mr-2 text-right" className="border rounded px-2 py-1 pr-20 w-full text-right"
value={tdrData.geschwindigkeit} value={tdrData.geschwindigkeit}
onChange={(e) => { onChange={(e) => {
const updated = { ...tdrData, geschwindigkeit: e.target.value }; const updated = { ...tdrData, geschwindigkeit: e.target.value };
@@ -216,7 +218,9 @@ export default function TdrEinstellung({ slot, onClose }: Props) {
updateCache(updated); updateCache(updated);
}} }}
/> />
<span>m/µs</span> <span className="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm">
m/µs
</span>
</div> </div>
</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.369"; const webVersion = "1.6.370";
export default webVersion; export default webVersion;

View File

@@ -43,7 +43,7 @@ const EinAusgaenge: React.FC = () => {
return ( return (
<div className="flex flex-col gap-3 p-4 h-[calc(100vh-13vh-8vh)] laptop:h-[calc(100vh-10vh-5vh)] xl:h-[calc(100vh-10vh-6vh)] laptop:gap-0"> <div className="flex flex-col gap-3 p-4 h-[calc(100vh-13vh-8vh)] laptop:h-[calc(100vh-10vh-5vh)] xl:h-[calc(100vh-10vh-6vh)] laptop:gap-0">
<h1 className="text-base font-semibold mb-2">Ein- und Ausgänge</h1> <h1 className="text-base font-semibold mb-2">Schaltausgänge</h1>
<div className="grid grid-cols-1 xl:grid-cols-3 gap-4 items-start "> <div className="grid grid-cols-1 xl:grid-cols-3 gap-4 items-start ">
<DigitalOutputs openOutputModal={openOutputModal} /> <DigitalOutputs openOutputModal={openOutputModal} />

View File

@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="#FFFFFF" stroke="#00B0F0" stroke-width="1.06497" stroke-linecap="round" stroke-linejoin="round">
<!-- Rahmen -->
<rect x="1" y="1" width="30" height="30" rx="4" ry="4" fill="none" stroke="#00B0F0" stroke-width="1.5" />
<!-- Wellenlinie -->
<path d="M4 16h3l3 8 4-16 3 8h11" />
</svg>

After

Width:  |  Height:  |  Size: 382 B

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF" stroke="#00B0F0" stroke-width="1.06497" stroke-linecap="round" stroke-linejoin="round">
<path d="M2 12h3l3 8 4-16 3 8h7" />
</svg>

After

Width:  |  Height:  |  Size: 231 B