feat: Digitale Ausgänge aus Redux-Store in UI integriert
- DigitalOutputs.tsx auf Redux umgestellt, um Werte direkt aus dem Store zu lesen - toggleSwitch-Funktion angepasst, um den Status von digitalen Ausgängen in Redux zu aktualisieren - useDigitalOutputsData.ts nutzt nun Redux zum Speichern der `win_da_state` und `win_da_bezeichnung` Werte - Entfernen von Prop `digitalOutputs` in `DigitalOutputs.tsx`, da Redux nun als Datenquelle dient - Weboberfläche zeigt nun digitale Ausgänge korrekt an und Status kann geändert werden
This commit is contained in:
@@ -1,13 +1,26 @@
|
||||
"use client"; // components/main/einausgaenge/DigitalOutputs.tsx
|
||||
|
||||
"use client";
|
||||
import React from "react";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { RootState } from "../../../redux/store";
|
||||
import { setDigitalOutputs } from "../../../redux/slices/digitalOutputsSlice";
|
||||
import { Icon } from "@iconify/react";
|
||||
|
||||
export default function DigitalOutputs({
|
||||
digitalOutputs,
|
||||
openOutputModal,
|
||||
toggleSwitch,
|
||||
}) {
|
||||
export default function DigitalOutputs({ openOutputModal }) {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
// Redux-Store für digitale Ausgänge nutzen
|
||||
const digitalOutputs = useSelector(
|
||||
(state: RootState) => state.digitalOutputs?.outputs ?? []
|
||||
);
|
||||
|
||||
// Funktion zum Umschalten des Ausgangsstatus
|
||||
const toggleSwitch = (id: number) => {
|
||||
const updatedOutputs = digitalOutputs.map((output) =>
|
||||
output.id === id ? { ...output, status: !output.status } : output
|
||||
);
|
||||
dispatch(setDigitalOutputs(updatedOutputs));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-white shadow-md rounded-lg border border-gray-200 p-4 w-2/5 h-[fit-content]">
|
||||
<h2 className="text-md font-bold mb-4 flex items-center">
|
||||
@@ -33,16 +46,16 @@ export default function DigitalOutputs({
|
||||
/>
|
||||
{output.id}
|
||||
</td>
|
||||
<td className="px-2 py-1">{output.description}</td>
|
||||
<td className="px-2 py-1">{output.label}</td>
|
||||
<td className="px-2 py-1">
|
||||
<span
|
||||
title={`Schalter ${output.toggle ? "EIN" : "AUS"} schalten`}
|
||||
title={`Schalter ${output.status ? "EIN" : "AUS"} schalten`}
|
||||
>
|
||||
<Icon
|
||||
icon="ion:switch"
|
||||
onClick={() => toggleSwitch(output.id)}
|
||||
className={`cursor-pointer text-2xl transform ${
|
||||
output.toggle
|
||||
output.status
|
||||
? "text-blue-500 scale-x-100"
|
||||
: "text-gray-500 scale-x-[-1]"
|
||||
}`}
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
2: Patch oder Hotfix (Bugfixes oder kleine Änderungen).
|
||||
|
||||
*/
|
||||
const webVersion = "1.6.94";
|
||||
const webVersion = "1.6.95";
|
||||
export default webVersion;
|
||||
|
||||
@@ -1,42 +1,63 @@
|
||||
"use client"; // /hooks/einausgaenge/useDigitalOutputsData.ts
|
||||
import { useState, useEffect } from "react";
|
||||
"use client";
|
||||
import { useEffect } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { RootState } from "../../redux/store";
|
||||
import { setDigitalOutputs } from "../../redux/slices/digitalOutputsSlice";
|
||||
|
||||
// Definition des Typs für digitale Ausgänge
|
||||
// Typ für digitale Ausgänge
|
||||
interface DigitalOutput {
|
||||
id: number;
|
||||
description: string;
|
||||
toggle: boolean;
|
||||
label: string;
|
||||
status: boolean;
|
||||
}
|
||||
|
||||
export function useDigitalOutputs() {
|
||||
const [digitalOutputs, setDigitalOutputs] = useState<DigitalOutput[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const dispatch = useDispatch();
|
||||
const digitalOutputs = useSelector(
|
||||
(state: RootState) => state.digitalOutputs?.outputs ?? []
|
||||
);
|
||||
const isLoading = digitalOutputs.length === 0;
|
||||
|
||||
useEffect(() => {
|
||||
console.log("Lade da.js für digitale Ausgänge...");
|
||||
|
||||
const script = document.createElement("script");
|
||||
script.src = "/CPLmockData/SERVICE/da.js";
|
||||
script.async = true;
|
||||
|
||||
script.onload = () => {
|
||||
console.log("Skript geladen. Überprüfe window-Variablen:");
|
||||
console.log("win_da_state:", window.win_da_state);
|
||||
console.log("win_da_bezeichnung:", window.win_da_bezeichnung);
|
||||
|
||||
const da = window.win_da_state;
|
||||
const bezeichnungen = window.win_da_bezeichnung;
|
||||
|
||||
if (da && bezeichnungen) {
|
||||
const outputs = da.map((status: number, index: number) => ({
|
||||
id: index + 1,
|
||||
description: bezeichnungen[index] || `Ausgang${index + 1}`,
|
||||
toggle: status === 1,
|
||||
}));
|
||||
setDigitalOutputs(outputs);
|
||||
if (
|
||||
Array.isArray(da) &&
|
||||
Array.isArray(bezeichnungen) &&
|
||||
da.length === bezeichnungen.length
|
||||
) {
|
||||
const outputs: DigitalOutput[] = da.map(
|
||||
(status: number, index: number) => ({
|
||||
id: index + 1,
|
||||
label: bezeichnungen[index] || `Ausgang ${index + 1}`,
|
||||
status: status === 1,
|
||||
})
|
||||
);
|
||||
|
||||
console.log("Dispatching setDigitalOutputs mit Werten:", outputs);
|
||||
dispatch(setDigitalOutputs(outputs));
|
||||
} else {
|
||||
console.error("Daten konnten nicht geladen werden.");
|
||||
console.error("Digitale Ausgänge konnten nicht geladen werden.", {
|
||||
da_state: da,
|
||||
da_bezeichnung: bezeichnungen,
|
||||
});
|
||||
}
|
||||
setIsLoading(false);
|
||||
};
|
||||
|
||||
script.onerror = () => {
|
||||
console.error("Fehler beim Laden der da.js-Datei.");
|
||||
setIsLoading(false);
|
||||
};
|
||||
|
||||
document.body.appendChild(script);
|
||||
@@ -44,7 +65,7 @@ export function useDigitalOutputs() {
|
||||
return () => {
|
||||
document.body.removeChild(script);
|
||||
};
|
||||
}, []);
|
||||
}, [dispatch]);
|
||||
|
||||
return { digitalOutputs, isLoading, setDigitalOutputs };
|
||||
return { digitalOutputs, isLoading };
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
// hooks/windowvariables/useLoadWindowVariables.ts
|
||||
import { useEffect } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { setDigitalOutputs } from "../../redux/slices/digitalOutputsSlice";
|
||||
|
||||
const requiredVars: string[] = [
|
||||
// Hier verbleiben nur die noch benötigten Variablen
|
||||
];
|
||||
const requiredVars: string[] = ["win_da_state", "win_da_bezeichnung"];
|
||||
|
||||
const scripts: string[] = [
|
||||
"da.js",
|
||||
@@ -37,24 +36,29 @@ export const useLoadWindowVariables = () => {
|
||||
useEffect(() => {
|
||||
const loadVariables = async () => {
|
||||
try {
|
||||
await loadScript("da.js"); // Lade `da.js` zuerst
|
||||
for (const script of scripts) {
|
||||
await loadScript(script);
|
||||
if (script !== "da.js") await loadScript(script);
|
||||
}
|
||||
|
||||
const variablesObj: { [key: string]: any } = requiredVars.reduce(
|
||||
(acc, variable) => {
|
||||
const winVar = (window as any)[variable];
|
||||
if (winVar !== undefined) {
|
||||
acc[variable.replace("win_", "")] = winVar;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
console.log("Laden abgeschlossen. Jetzt werden Variablen geprüft.");
|
||||
console.log("win_da_state:", window.win_da_state);
|
||||
console.log("win_da_bezeichnung:", window.win_da_bezeichnung);
|
||||
|
||||
// Falls noch andere Variablen verarbeitet werden müssen, kann hier Code eingefügt werden
|
||||
if (window.win_da_state && window.win_da_bezeichnung) {
|
||||
const digitalOutputs = window.win_da_state.map(
|
||||
(status: number, index: number) => ({
|
||||
id: index + 1,
|
||||
label: window.win_da_bezeichnung[index] || `Ausgang ${index + 1}`,
|
||||
status: status === 1,
|
||||
})
|
||||
);
|
||||
|
||||
console.log("Dispatching digitalOutputs:", digitalOutputs);
|
||||
dispatch(setDigitalOutputs(digitalOutputs));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Laden der Skripte oder Variablen:", error);
|
||||
console.error("Fehler beim Laden der Skripte:", error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ function MyApp({ Component, pageProps }: AppProps) {
|
||||
de,
|
||||
de_label,
|
||||
de_state,
|
||||
da_state,
|
||||
da_bezeichnung,
|
||||
...restVariables
|
||||
} = variables;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client"; // pages/einausgaenge.tsx
|
||||
|
||||
"use client";
|
||||
import React, { useState } from "react";
|
||||
import DigitalOutputs from "../components/main/einausgaenge/DigitalOutputs";
|
||||
import DigitalInputs from "../components/main/einausgaenge/DigitalInputs";
|
||||
@@ -7,14 +8,13 @@ import InputModal from "../components/main/einausgaenge/modals/InputModal";
|
||||
import OutputModal from "../components/main/einausgaenge/modals/OutputModal";
|
||||
import { useDigitalInputData } from "../hooks/einausgaenge/useDigitalInputsData";
|
||||
import { useDigitalOutputs } from "../hooks/einausgaenge/useDigitalOutputsData";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { setDigitalOutputs } from "../redux/slices/digitalOutputsSlice";
|
||||
|
||||
function EinAusgaenge() {
|
||||
// Verwendung des benutzerdefinierten Hooks für digitale Ausgänge
|
||||
const {
|
||||
digitalOutputs,
|
||||
isLoading: isLoadingOutputs,
|
||||
setDigitalOutputs,
|
||||
} = useDigitalOutputs();
|
||||
const dispatch = useDispatch();
|
||||
const { digitalOutputs, isLoading: isLoadingOutputs } = useDigitalOutputs();
|
||||
const { mockData, isLoading: isLoadingInputs } = useDigitalInputData();
|
||||
|
||||
// Zustand für Modale
|
||||
const [selectedInput, setSelectedInput] = useState(null);
|
||||
@@ -22,16 +22,12 @@ function EinAusgaenge() {
|
||||
const [isInputModalOpen, setIsInputModalOpen] = useState(false);
|
||||
const [isOutputModalOpen, setIsOutputModalOpen] = useState(false);
|
||||
|
||||
// Laden der digitalen Eingänge
|
||||
const { mockData, isLoading: isLoadingInputs } = useDigitalInputData();
|
||||
|
||||
// Funktion zum Umschalten des Ausgangs
|
||||
const toggleSwitch = (id: number) => {
|
||||
setDigitalOutputs((prevOutputs) =>
|
||||
prevOutputs.map((output) =>
|
||||
output.id === id ? { ...output, toggle: !output.toggle } : output
|
||||
)
|
||||
const updatedOutputs = digitalOutputs.map((output) =>
|
||||
output.id === id ? { ...output, status: !output.status } : output
|
||||
);
|
||||
dispatch(setDigitalOutputs(updatedOutputs));
|
||||
};
|
||||
|
||||
// Funktionen zum Öffnen und Schließen der Modale
|
||||
|
||||
35
redux/slices/digitalOutputsSlice.ts
Normal file
35
redux/slices/digitalOutputsSlice.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
// redux/slices/digitalOutputsSlice.ts
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
|
||||
// Typ für den Zustand der digitalen Ausgänge
|
||||
interface DigitalOutput {
|
||||
id: number;
|
||||
label: string;
|
||||
status: boolean;
|
||||
}
|
||||
|
||||
interface DigitalOutputsState {
|
||||
outputs: DigitalOutput[];
|
||||
}
|
||||
|
||||
// Initialer Zustand
|
||||
const initialState: DigitalOutputsState = {
|
||||
outputs: [],
|
||||
};
|
||||
|
||||
// Slice erstellen
|
||||
const digitalOutputsSlice = createSlice({
|
||||
name: "digitalOutputs",
|
||||
initialState,
|
||||
reducers: {
|
||||
setDigitalOutputs(state, action: PayloadAction<DigitalOutput[]>) {
|
||||
state.outputs = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Aktionen exportieren
|
||||
export const { setDigitalOutputs } = digitalOutputsSlice.actions;
|
||||
|
||||
// Reducer exportieren
|
||||
export default digitalOutputsSlice.reducer;
|
||||
@@ -9,6 +9,7 @@ import kabelueberwachungChartReducer from "./slices/kabelueberwachungChartSlice"
|
||||
import dashboardReducer from "./slices/dashboardSlice";
|
||||
import systemSettingsReducer from "./slices/systemSettingsSlice";
|
||||
import opcuaSettingsReducer from "./slices/opcuaSettingsSlice";
|
||||
import digitalOutputsReducer from "./slices/digitalOutputsSlice";
|
||||
|
||||
const store = configureStore({
|
||||
reducer: {
|
||||
@@ -21,6 +22,7 @@ const store = configureStore({
|
||||
dashboard: dashboardReducer,
|
||||
systemSettings: systemSettingsReducer,
|
||||
opcuaSettings: opcuaSettingsReducer,
|
||||
digitalOutputs: digitalOutputsReducer,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
addOpcUaUser,
|
||||
removeOpcUaUser,
|
||||
} from "../redux/slices/opcuaSettingsSlice";
|
||||
import { setDigitalOutputs } from "../redux/slices/digitalOutputsSlice";
|
||||
|
||||
// ✅ Interface für `window`-Objekt zur TypeScript-Sicherheit
|
||||
interface CustomWindow extends Window {
|
||||
@@ -234,3 +235,32 @@ const loadAndStoreOpcUaSettings = (win: CustomWindow) => {
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// ✅ Funktion zum Speichern der digitalen Ausgänge in Redux
|
||||
const loadAndStoreDigitalOutputs = (win: CustomWindow) => {
|
||||
console.log("Prüfe digitale Ausgänge in window:");
|
||||
console.log("win_da_state:", win.win_da_state);
|
||||
console.log("win_da_bezeichnung:", win.win_da_bezeichnung);
|
||||
|
||||
if (
|
||||
Array.isArray(win.win_da_state) &&
|
||||
Array.isArray(win.win_da_bezeichnung) &&
|
||||
win.win_da_state.length === win.win_da_bezeichnung.length
|
||||
) {
|
||||
const digitalOutputs = win.win_da_state.map(
|
||||
(status: number, index: number) => ({
|
||||
id: index + 1,
|
||||
label: win.win_da_bezeichnung[index] || `Ausgang ${index + 1}`,
|
||||
status: status === 1, // Status in Boolean umwandeln
|
||||
})
|
||||
);
|
||||
|
||||
console.log("Dispatching digitalOutputs:", digitalOutputs);
|
||||
store.dispatch(setDigitalOutputs(digitalOutputs));
|
||||
} else {
|
||||
console.warn("Digitale Ausgänge konnten nicht geladen werden:", {
|
||||
da_state: win.win_da_state,
|
||||
da_bezeichnung: win.win_da_bezeichnung,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user