feat: systemSettingsSlice hinzugefügt und Header sowie Einstellungen angepasst
- Neuen Redux Slice `systemSettingsSlice` erstellt, um Systemdaten zentral zu verwalten. - Header-Icon für Systemeinstellungen holt jetzt Daten aus `systemSettingsSlice` statt `variablesSlice`. - Die Einstellungen-Seite (`Allgemeine Einstellungen`) wurde umgestellt und liest nun ebenfalls aus `systemSettingsSlice`. - UI-Optimierungen für die Einstellungen-Seite, um alle Eingabefelder kompakter darzustellen.
This commit is contained in:
@@ -4,6 +4,7 @@ import Image from "next/image";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import "bootstrap-icons/font/bootstrap-icons.css";
|
import "bootstrap-icons/font/bootstrap-icons.css";
|
||||||
import SettingsModal from "./settingsModal/SettingsModal";
|
import SettingsModal from "./settingsModal/SettingsModal";
|
||||||
|
import { RootState } from "../../redux/store";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import decodeToken from "../../utils/decodeToken";
|
import decodeToken from "../../utils/decodeToken";
|
||||||
|
|
||||||
@@ -11,7 +12,9 @@ function Header() {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [showSettingsModal, setShowSettingsModal] = useState(false);
|
const [showSettingsModal, setShowSettingsModal] = useState(false);
|
||||||
const [isAdminLoggedIn, setIsAdminLoggedIn] = useState(false);
|
const [isAdminLoggedIn, setIsAdminLoggedIn] = useState(false);
|
||||||
const deviceName = useSelector((state) => state.variables.deviceName);
|
const deviceName = useSelector(
|
||||||
|
(state: RootState) => state.systemSettings.deviceName
|
||||||
|
);
|
||||||
|
|
||||||
const handleSettingsClick = () => setShowSettingsModal(true);
|
const handleSettingsClick = () => setShowSettingsModal(true);
|
||||||
const handleCloseSettingsModal = () => setShowSettingsModal(false);
|
const handleCloseSettingsModal = () => setShowSettingsModal(false);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import ReactModal from "react-modal";
|
import ReactModal from "react-modal";
|
||||||
import "bootstrap-icons/font/bootstrap-icons.css";
|
import "bootstrap-icons/font/bootstrap-icons.css";
|
||||||
|
import { RootState } from "../../../redux/store";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import handleClearDatabase from "./handlers/handleClearDatabase";
|
import handleClearDatabase from "./handlers/handleClearDatabase";
|
||||||
import handleReboot from "./handlers/handleReboot";
|
import handleReboot from "./handlers/handleReboot";
|
||||||
@@ -99,19 +100,37 @@ function SettingModal({ showModal, onClose }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [showModal]);
|
}, [showModal]);
|
||||||
const deviceName_Redux = useSelector((state) => state.variables.deviceName);
|
const deviceName_Redux = useSelector(
|
||||||
const mac1_Redux = useSelector((state) => state.variables.mac1);
|
(state: RootState) => state.systemSettings.deviceName
|
||||||
const ip_Redux = useSelector((state) => state.variables.ip);
|
);
|
||||||
const subnet_Redux = useSelector((state) => state.variables.subnet);
|
const mac1_Redux = useSelector(
|
||||||
const gateway_Redux = useSelector((state) => state.variables.gateway);
|
(state: RootState) => state.systemSettings.mac1
|
||||||
const datetime_Redux = useSelector(
|
);
|
||||||
(state) => state.variables.cplInternalTimestamp
|
const ip_Redux = useSelector((state: RootState) => state.systemSettings.ip);
|
||||||
|
const subnet_Redux = useSelector(
|
||||||
|
(state: RootState) => state.systemSettings.subnet
|
||||||
|
);
|
||||||
|
const gateway_Redux = useSelector(
|
||||||
|
(state: RootState) => state.systemSettings.gateway
|
||||||
|
);
|
||||||
|
const datetime_Redux = useSelector(
|
||||||
|
(state: RootState) => state.systemSettings.cplInternalTimestamp
|
||||||
|
);
|
||||||
|
const ntp1_Redux = useSelector(
|
||||||
|
(state: RootState) => state.systemSettings.ntp1
|
||||||
|
);
|
||||||
|
const ntp2_Redux = useSelector(
|
||||||
|
(state: RootState) => state.systemSettings.ntp2
|
||||||
|
);
|
||||||
|
const ntp3_Redux = useSelector(
|
||||||
|
(state: RootState) => state.systemSettings.ntp3
|
||||||
|
);
|
||||||
|
const ntpTimezone_Redux = useSelector(
|
||||||
|
(state: RootState) => state.systemSettings.ntpTimezone
|
||||||
|
);
|
||||||
|
const active_Redux = useSelector(
|
||||||
|
(state: RootState) => state.systemSettings.ntpActive
|
||||||
);
|
);
|
||||||
const ntp1_Redux = useSelector((state) => state.variables.ntp1);
|
|
||||||
const ntp2_Redux = useSelector((state) => state.variables.ntp2);
|
|
||||||
const ntp3_Redux = useSelector((state) => state.variables.ntp3);
|
|
||||||
const ntpTimezone_Redux = useSelector((state) => state.variables.ntpTimezone);
|
|
||||||
const active_Redux = useSelector((state) => state.variables.ntpActive);
|
|
||||||
|
|
||||||
const [name, setName] = useState(deviceName_Redux || "");
|
const [name, setName] = useState(deviceName_Redux || "");
|
||||||
const [mac1, setMac1] = useState(mac1_Redux || "");
|
const [mac1, setMac1] = useState(mac1_Redux || "");
|
||||||
|
|||||||
@@ -1,117 +1,180 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
"use client";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { RootState } from "../../../redux/store";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import handleClearDatabase from "../../header/settingsModal/handlers/handleReboot";
|
import handleClearDatabase from "../../header/settingsModal/handlers/handleClearDatabase";
|
||||||
import handleReboot from "../../header/settingsModal/handlers/handleReboot";
|
import handleReboot from "../../header/settingsModal/handlers/handleReboot";
|
||||||
import handleSetDateTime from "../../header/settingsModal/handlers/handleReboot";
|
import handleSetDateTime from "../../header/settingsModal/handlers/handleSetDateTime";
|
||||||
import handleSubmit from "../../header/settingsModal/handlers/handleReboot";
|
import handleSubmit from "../../header/settingsModal/handlers/handleSubmit";
|
||||||
|
|
||||||
const GeneralSettings = () => {
|
const GeneralSettings = () => {
|
||||||
const deviceName_Redux = useSelector((state) => state.variables.deviceName);
|
const systemSettings = useSelector(
|
||||||
const ip_Redux = useSelector((state) => state.variables.ip);
|
(state: RootState) => state.systemSettings
|
||||||
const subnet_Redux = useSelector((state) => state.variables.subnet);
|
|
||||||
const gateway_Redux = useSelector((state) => state.variables.gateway);
|
|
||||||
const datetime_Redux = useSelector(
|
|
||||||
(state) => state.variables.cplInternalTimestamp
|
|
||||||
);
|
);
|
||||||
const ntp1_Redux = useSelector((state) => state.variables.ntp1);
|
console.log("Redux SystemSettings:", systemSettings);
|
||||||
const ntp2_Redux = useSelector((state) => state.variables.ntp2);
|
|
||||||
const ntp3_Redux = useSelector((state) => state.variables.ntp3);
|
|
||||||
const ntpTimezone_Redux = useSelector((state) => state.variables.ntpTimezone);
|
|
||||||
const active_Redux = useSelector((state) => state.variables.ntpActive);
|
|
||||||
|
|
||||||
const [name, setName] = useState(deviceName_Redux || "");
|
const [name, setName] = useState(systemSettings.deviceName || "");
|
||||||
const [ip, setIp] = useState(ip_Redux || "");
|
const [ip, setIp] = useState(systemSettings.ip || "");
|
||||||
const [subnet, setSubnet] = useState(subnet_Redux || "");
|
const [subnet, setSubnet] = useState(systemSettings.subnet || "");
|
||||||
const [gateway, setGateway] = useState(gateway_Redux || "");
|
const [gateway, setGateway] = useState(systemSettings.gateway || "");
|
||||||
const [systemUhr, setSystemUhr] = useState(datetime_Redux || "");
|
const [systemUhr, setSystemUhr] = useState(
|
||||||
const [ntp1, setNtp1] = useState(ntp1_Redux || "");
|
systemSettings.cplInternalTimestamp || ""
|
||||||
const [ntp2, setNtp2] = useState(ntp2_Redux || "");
|
);
|
||||||
const [ntp3, setNtp3] = useState(ntp3_Redux || "");
|
const [ntp1, setNtp1] = useState(systemSettings.ntp1 || "");
|
||||||
const [ntpTimezone, setNtpTimezone] = useState(ntpTimezone_Redux || "");
|
const [ntp2, setNtp2] = useState(systemSettings.ntp2 || "");
|
||||||
const [active, setActive] = useState(active_Redux || "");
|
const [ntp3, setNtp3] = useState(systemSettings.ntp3 || "");
|
||||||
|
const [ntpTimezone, setNtpTimezone] = useState(
|
||||||
useEffect(() => {
|
systemSettings.ntpTimezone || ""
|
||||||
setName(deviceName_Redux || "");
|
);
|
||||||
setIp(ip_Redux || "");
|
const [active, setActive] = useState(systemSettings.ntpActive || false);
|
||||||
setSubnet(subnet_Redux || "");
|
|
||||||
setGateway(gateway_Redux || "");
|
|
||||||
setSystemUhr(datetime_Redux || "");
|
|
||||||
setNtp1(ntp1_Redux || "");
|
|
||||||
setNtp2(ntp2_Redux || "");
|
|
||||||
setNtp3(ntp3_Redux || "");
|
|
||||||
setNtpTimezone(ntpTimezone_Redux || "");
|
|
||||||
setActive(active_Redux || "");
|
|
||||||
}, [
|
|
||||||
deviceName_Redux,
|
|
||||||
ip_Redux,
|
|
||||||
subnet_Redux,
|
|
||||||
gateway_Redux,
|
|
||||||
datetime_Redux,
|
|
||||||
ntp1_Redux,
|
|
||||||
ntp2_Redux,
|
|
||||||
ntp3_Redux,
|
|
||||||
ntpTimezone_Redux,
|
|
||||||
active_Redux,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-4 bg-gray-100">
|
<div className="p-2 bg-gray-100">
|
||||||
<h2 className="text-lg font-bold mb-4">General Settings</h2>
|
<h2 className="text-md font-bold mb-2">General Settings</h2>
|
||||||
<form>
|
<form className="grid grid-cols-2 gap-2">
|
||||||
<div className="mb-4">
|
{/* ✅ Geräte-Name */}
|
||||||
<label className="block text-sm font-medium">Name:</label>
|
<div className="col-span-2">
|
||||||
|
<label className="block text-xs font-medium">Name:</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className="border border-gray-300 rounded p-2 w-full"
|
className="border border-gray-300 rounded p-1 w-full text-sm"
|
||||||
value={name}
|
value={name}
|
||||||
onChange={(e) => setName(e.target.value)}
|
onChange={(e) => setName(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-4 grid grid-cols-2 gap-4">
|
{/* ✅ Netzwerk-Einstellungen */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium">IP:</label>
|
<label className="block text-xs font-medium">IP:</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className="border border-gray-300 rounded p-2 w-full"
|
className="border border-gray-300 rounded p-1 w-full text-sm"
|
||||||
value={ip}
|
value={ip}
|
||||||
onChange={(e) => setIp(e.target.value)}
|
onChange={(e) => setIp(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium">Subnet:</label>
|
<label className="block text-xs font-medium">Subnet:</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className="border border-gray-300 rounded p-2 w-full"
|
className="border border-gray-300 rounded p-1 w-full text-sm"
|
||||||
value={subnet}
|
value={subnet}
|
||||||
onChange={(e) => setSubnet(e.target.value)}
|
onChange={(e) => setSubnet(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-xs font-medium">Gateway:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="border border-gray-300 rounded p-1 w-full text-sm"
|
||||||
|
value={gateway}
|
||||||
|
onChange={(e) => setGateway(e.target.value)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-between mt-4">
|
{/* ✅ System-Zeit */}
|
||||||
|
<div className="col-span-2 flex items-center gap-2">
|
||||||
|
<div className="flex-1">
|
||||||
|
<label className="block text-xs font-medium">Systemzeit:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="border border-gray-300 rounded p-1 w-full text-sm"
|
||||||
|
value={systemUhr}
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
className="bg-blue-500 text-white px-4 py-2 rounded"
|
type="button"
|
||||||
|
className="bg-gray-500 text-white px-3 py-1 rounded text-xs"
|
||||||
|
onClick={() => handleSetDateTime()}
|
||||||
|
>
|
||||||
|
Setzen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* ✅ NTP-Server */}
|
||||||
|
<div>
|
||||||
|
<label className="block text-xs font-medium">NTP Server 1:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="border border-gray-300 rounded p-1 w-full text-sm"
|
||||||
|
value={ntp1}
|
||||||
|
onChange={(e) => setNtp1(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-xs font-medium">NTP Server 2:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="border border-gray-300 rounded p-1 w-full text-sm"
|
||||||
|
value={ntp2}
|
||||||
|
onChange={(e) => setNtp2(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-xs font-medium">NTP Server 3:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="border border-gray-300 rounded p-1 w-full text-sm"
|
||||||
|
value={ntp3}
|
||||||
|
onChange={(e) => setNtp3(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-xs font-medium">Zeitzone:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="border border-gray-300 rounded p-1 w-full text-sm"
|
||||||
|
value={ntpTimezone}
|
||||||
|
onChange={(e) => setNtpTimezone(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="col-span-2 flex items-center gap-2">
|
||||||
|
<label className="block text-xs font-medium">NTP Aktiv:</label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={active}
|
||||||
|
onChange={(e) => setActive(e.target.checked)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* ✅ Buttons */}
|
||||||
|
<div className="col-span-2 flex justify-between mt-2">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="bg-blue-500 text-white px-3 py-1 rounded text-xs"
|
||||||
onClick={() => handleReboot()}
|
onClick={() => handleReboot()}
|
||||||
>
|
>
|
||||||
Neustart CPL
|
Neustart
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="bg-blue-500 text-white px-4 py-2 rounded"
|
type="button"
|
||||||
|
className="bg-red-500 text-white px-3 py-1 rounded text-xs"
|
||||||
onClick={() => handleClearDatabase()}
|
onClick={() => handleClearDatabase()}
|
||||||
>
|
>
|
||||||
Datenbank leeren
|
Datenbank leeren
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
type="button"
|
||||||
|
className="bg-green-500 text-white px-3 py-1 rounded text-xs"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
handleSubmit(
|
handleSubmit(
|
||||||
{ name, ip, subnet, gateway },
|
{
|
||||||
{ name: deviceName_Redux, ip: ip_Redux, subnet: subnet_Redux }
|
name,
|
||||||
|
ip,
|
||||||
|
subnet,
|
||||||
|
gateway,
|
||||||
|
ntp1,
|
||||||
|
ntp2,
|
||||||
|
ntp3,
|
||||||
|
ntpTimezone,
|
||||||
|
active,
|
||||||
|
},
|
||||||
|
systemSettings
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
className="bg-blue-500 text-white px-4 py-2 rounded"
|
|
||||||
>
|
>
|
||||||
Übernehmen
|
Speichern
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -6,5 +6,5 @@
|
|||||||
2: Patch oder Hotfix (Bugfixes oder kleine Änderungen).
|
2: Patch oder Hotfix (Bugfixes oder kleine Änderungen).
|
||||||
|
|
||||||
*/
|
*/
|
||||||
const webVersion = "1.6.90";
|
const webVersion = "1.6.91";
|
||||||
export default webVersion;
|
export default webVersion;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import Footer from "../components/footer/Footer";
|
|||||||
import "../styles/globals.css";
|
import "../styles/globals.css";
|
||||||
import { Provider } from "react-redux";
|
import { Provider } from "react-redux";
|
||||||
import { setVariables } from "../redux/slices/variablesSlice";
|
import { setVariables } from "../redux/slices/variablesSlice";
|
||||||
|
import { setSystemSettings } from "../redux/slices/systemSettingsSlice"; // ✅ Für System-Settings
|
||||||
import store from "../redux/store";
|
import store from "../redux/store";
|
||||||
import { AppProps } from "next/app";
|
import { AppProps } from "next/app";
|
||||||
import WindowVariablesInitializer from "../components/WindowVariablesInitializer";
|
import WindowVariablesInitializer from "../components/WindowVariablesInitializer";
|
||||||
@@ -21,10 +22,43 @@ function MyApp({ Component, pageProps }: AppProps) {
|
|||||||
const variables = await loadWindowVariables();
|
const variables = await loadWindowVariables();
|
||||||
if (!variables) throw new Error("Sitzungsfehler");
|
if (!variables) throw new Error("Sitzungsfehler");
|
||||||
|
|
||||||
// last20Messages entfernen, falls es noch in variables existiert
|
// ✅ System-Settings und last20Messages separat speichern
|
||||||
const { last20Messages, ...restVariables } = variables;
|
const {
|
||||||
|
last20Messages, // Entfernen für eigenes Redux-Slice
|
||||||
|
deviceName,
|
||||||
|
mac1,
|
||||||
|
ip,
|
||||||
|
subnet,
|
||||||
|
gateway,
|
||||||
|
cplInternalTimestamp,
|
||||||
|
ntp1,
|
||||||
|
ntp2,
|
||||||
|
ntp3,
|
||||||
|
ntpTimezone,
|
||||||
|
ntpActive,
|
||||||
|
...restVariables
|
||||||
|
} = variables;
|
||||||
|
|
||||||
|
// ✅ Speichere System-Settings in systemSettingsSlice
|
||||||
|
store.dispatch(
|
||||||
|
setSystemSettings({
|
||||||
|
deviceName,
|
||||||
|
mac1,
|
||||||
|
ip,
|
||||||
|
subnet,
|
||||||
|
gateway,
|
||||||
|
cplInternalTimestamp,
|
||||||
|
ntp1,
|
||||||
|
ntp2,
|
||||||
|
ntp3,
|
||||||
|
ntpTimezone,
|
||||||
|
ntpActive,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// ✅ Speichere alle anderen Variablen in variablesSlice
|
||||||
store.dispatch(setVariables(restVariables));
|
store.dispatch(setVariables(restVariables));
|
||||||
|
|
||||||
setSessionExpired(false);
|
setSessionExpired(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Fehler beim Laden der Sitzung:", error);
|
console.error("Fehler beim Laden der Sitzung:", error);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import GeneralSettings from "../components/main/settingsPageComponents/generalSettings";
|
import GeneralSettings from "../components/main/settingsPageComponents/GeneralSettings";
|
||||||
import OPCUAInterfaceSettings from "../components/main/settingsPageComponents/OPCUAInterfaceSettings";
|
import OPCUAInterfaceSettings from "../components/main/settingsPageComponents/OPCUAInterfaceSettings";
|
||||||
|
|
||||||
export default function Settings() {
|
export default function Settings() {
|
||||||
|
|||||||
48
redux/slices/systemSettingsSlice.ts
Normal file
48
redux/slices/systemSettingsSlice.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// /redux/slices/systemSettingsSlice.ts
|
||||||
|
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||||
|
|
||||||
|
interface SystemSettingsState {
|
||||||
|
deviceName: string | null;
|
||||||
|
mac1: string | null;
|
||||||
|
ip: string | null;
|
||||||
|
subnet: string | null;
|
||||||
|
gateway: string | null;
|
||||||
|
cplInternalTimestamp: string | null;
|
||||||
|
ntp1: string | null;
|
||||||
|
ntp2: string | null;
|
||||||
|
ntp3: string | null;
|
||||||
|
ntpTimezone: string | null;
|
||||||
|
ntpActive: boolean | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: SystemSettingsState = {
|
||||||
|
deviceName: "",
|
||||||
|
mac1: "",
|
||||||
|
ip: "",
|
||||||
|
subnet: "",
|
||||||
|
gateway: "",
|
||||||
|
cplInternalTimestamp: "",
|
||||||
|
ntp1: "",
|
||||||
|
ntp2: "",
|
||||||
|
ntp3: "",
|
||||||
|
ntpTimezone: "",
|
||||||
|
ntpActive: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const systemSettingsSlice = createSlice({
|
||||||
|
name: "systemSettings",
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
setSystemSettings: (
|
||||||
|
state,
|
||||||
|
action: PayloadAction<Partial<SystemSettingsState>>
|
||||||
|
) => {
|
||||||
|
return { ...state, ...action.payload };
|
||||||
|
},
|
||||||
|
resetSystemSettings: () => initialState,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const { setSystemSettings, resetSystemSettings } =
|
||||||
|
systemSettingsSlice.actions;
|
||||||
|
export default systemSettingsSlice.reducer;
|
||||||
@@ -15,17 +15,6 @@ export interface VariablesState {
|
|||||||
schleifenintervall: number[];
|
schleifenintervall: number[];
|
||||||
//---------------
|
//---------------
|
||||||
|
|
||||||
deviceName: string | null;
|
|
||||||
mac1: string | null;
|
|
||||||
ip: string | null;
|
|
||||||
subnet: string | null;
|
|
||||||
gateway: string | null;
|
|
||||||
cplInternalTimestamp: string | null;
|
|
||||||
ntp1: string | null;
|
|
||||||
ntp2: string | null;
|
|
||||||
ntp3: string | null;
|
|
||||||
ntpTimezone: string | null;
|
|
||||||
ntpActive: boolean | null;
|
|
||||||
de: string | null;
|
de: string | null;
|
||||||
counter: number | null;
|
counter: number | null;
|
||||||
flutter: string | null;
|
flutter: string | null;
|
||||||
@@ -79,17 +68,6 @@ const initialState: VariablesState = {
|
|||||||
schleifenintervall: [],
|
schleifenintervall: [],
|
||||||
//---------------
|
//---------------
|
||||||
|
|
||||||
deviceName: null,
|
|
||||||
mac1: null,
|
|
||||||
ip: null,
|
|
||||||
subnet: null,
|
|
||||||
gateway: null,
|
|
||||||
cplInternalTimestamp: null,
|
|
||||||
ntp1: null,
|
|
||||||
ntp2: null,
|
|
||||||
ntp3: null,
|
|
||||||
ntpTimezone: null,
|
|
||||||
ntpActive: null,
|
|
||||||
de: null,
|
de: null,
|
||||||
counter: null,
|
counter: null,
|
||||||
flutter: null,
|
flutter: null,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import webVersionReducer from "./slices/webVersionSlice";
|
|||||||
import digitalInputsReducer from "./slices/digitalInputsSlice";
|
import digitalInputsReducer from "./slices/digitalInputsSlice";
|
||||||
import kabelueberwachungChartReducer from "./slices/kabelueberwachungChartSlice";
|
import kabelueberwachungChartReducer from "./slices/kabelueberwachungChartSlice";
|
||||||
import dashboardReducer from "./slices/dashboardSlice";
|
import dashboardReducer from "./slices/dashboardSlice";
|
||||||
|
import systemSettingsReducer from "./slices/systemSettingsSlice";
|
||||||
|
|
||||||
const store = configureStore({
|
const store = configureStore({
|
||||||
reducer: {
|
reducer: {
|
||||||
@@ -17,6 +18,7 @@ const store = configureStore({
|
|||||||
digitalInputs: digitalInputsReducer,
|
digitalInputs: digitalInputsReducer,
|
||||||
kabelueberwachungChart: kabelueberwachungChartReducer,
|
kabelueberwachungChart: kabelueberwachungChartReducer,
|
||||||
dashboard: dashboardReducer,
|
dashboard: dashboardReducer,
|
||||||
|
systemSettings: systemSettingsReducer,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,28 @@
|
|||||||
// utils/loadWindowVariables.ts
|
import store from "../redux/store";
|
||||||
interface WindowVariables {
|
import { setSystemSettings } from "../redux/slices/systemSettingsSlice";
|
||||||
[key: string]: any; // Allgemeiner Typ für die Dynamik, kann spezifischer angepasst werden, falls bekannt
|
|
||||||
|
// ✅ Interface für `window`-Objekt zur TypeScript-Sicherheit
|
||||||
|
interface CustomWindow extends Window {
|
||||||
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadWindowVariables(): Promise<WindowVariables> {
|
// ✅ Interface für System-Einstellungen im Redux-Store
|
||||||
|
interface SystemSettings {
|
||||||
|
deviceName: string;
|
||||||
|
mac1: string;
|
||||||
|
ip: string;
|
||||||
|
subnet: string;
|
||||||
|
gateway: string;
|
||||||
|
cplInternalTimestamp: string;
|
||||||
|
ntp1: string;
|
||||||
|
ntp2: string;
|
||||||
|
ntp3: string;
|
||||||
|
ntpTimezone: string;
|
||||||
|
ntpActive: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Hauptfunktion zum Laden von `window`-Variablen
|
||||||
|
export async function loadWindowVariables(): Promise<Record<string, any>> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const requiredVars: string[] = [
|
const requiredVars: string[] = [
|
||||||
"win_last20Messages",
|
"win_last20Messages",
|
||||||
@@ -61,6 +80,16 @@ export async function loadWindowVariables(): Promise<WindowVariables> {
|
|||||||
"win_da_bezeichnung",
|
"win_da_bezeichnung",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const scripts: string[] = [
|
||||||
|
"da.js",
|
||||||
|
"de.js",
|
||||||
|
"ae.js",
|
||||||
|
"kueData.js",
|
||||||
|
"Start.js",
|
||||||
|
"System.js",
|
||||||
|
"opcua.js",
|
||||||
|
];
|
||||||
|
|
||||||
const loadScript = (src: string): Promise<void> => {
|
const loadScript = (src: string): Promise<void> => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const script = document.createElement("script");
|
const script = document.createElement("script");
|
||||||
@@ -76,40 +105,29 @@ export async function loadWindowVariables(): Promise<WindowVariables> {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const scripts: string[] = [
|
// ✅ Lade alle Skripte nacheinander
|
||||||
"da.js",
|
|
||||||
"de.js",
|
|
||||||
"ae.js",
|
|
||||||
"kueData.js",
|
|
||||||
"Start.js",
|
|
||||||
"System.js",
|
|
||||||
"opcua.js",
|
|
||||||
];
|
|
||||||
|
|
||||||
scripts
|
scripts
|
||||||
.reduce(
|
.reduce(
|
||||||
(promise, script) => promise.then(() => loadScript(script)),
|
(promise, script) => promise.then(() => loadScript(script)),
|
||||||
Promise.resolve()
|
Promise.resolve()
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const variablesObj: WindowVariables = requiredVars.reduce(
|
const win = window as unknown as CustomWindow;
|
||||||
(acc: WindowVariables, variable: string) => {
|
|
||||||
// Prüfe, ob die Variable auf dem window-Objekt existiert
|
// ✅ Erstelle ein Objekt mit allen geladenen Variablen
|
||||||
const winVar = (window as any)[variable];
|
const variablesObj: Record<string, any> = requiredVars.reduce(
|
||||||
if (winVar !== undefined) {
|
(acc, variable) => {
|
||||||
// Wenn es sich um kueID handelt, ersetze %20 durch Leerzeichen
|
if (win[variable] !== undefined) {
|
||||||
if (variable === "win_kueID" && Array.isArray(winVar)) {
|
acc[variable.replace("win_", "")] = win[variable];
|
||||||
acc[variable.replace("win_", "")] = winVar.map((id: string) =>
|
|
||||||
id.replace(/%20/g, " ")
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
acc[variable.replace("win_", "")] = winVar;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ✅ Redux mit Systemvariablen aktualisieren
|
||||||
|
loadAndStoreSystemSettings(win);
|
||||||
|
|
||||||
resolve(variablesObj);
|
resolve(variablesObj);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -118,3 +136,22 @@ export async function loadWindowVariables(): Promise<WindowVariables> {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ✅ Funktion zum Speichern von System-Variablen in Redux
|
||||||
|
const loadAndStoreSystemSettings = (win: CustomWindow) => {
|
||||||
|
const settings: SystemSettings = {
|
||||||
|
deviceName: win.win_deviceName || "",
|
||||||
|
mac1: win.win_mac1 || "",
|
||||||
|
ip: win.win_ip || "",
|
||||||
|
subnet: win.win_subnet || "",
|
||||||
|
gateway: win.win_gateway || "",
|
||||||
|
cplInternalTimestamp: win.win_cplInternalTimestamp || "",
|
||||||
|
ntp1: win.win_ntp1 || "",
|
||||||
|
ntp2: win.win_ntp2 || "",
|
||||||
|
ntp3: win.win_ntp3 || "",
|
||||||
|
ntpTimezone: win.win_ntpTimezone || "",
|
||||||
|
ntpActive: win.win_ntpActive || false,
|
||||||
|
};
|
||||||
|
|
||||||
|
store.dispatch(setSystemSettings(settings));
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user