feat: Unterstützung für JSON- und Production-Modus hinzugefügt
- API-Handler `updateDigitalOutputsHandler` überarbeitet:
- JSON-Dateien werden jetzt korrekt im gültigen Format gespeichert (`{ key: value }`)
- Schreibzugriff im production-Modus blockiert
- JS-Mock-Struktur vorbereitet (noch nicht aktiv getestet)
- Verzeichnisstruktur vereinheitlicht:
- JSON-Mocks unter `/mocks/api/SERVICE/`
- CGI-Platzhalter unter `/public/CPL/`
- JSMock-Ordner für CPL-Simulation vorbereitet (`/mocks/js-simulator/`)
- README.md um Betriebsmodi erweitert (`NEXT_PUBLIC_CPL_MODE` mit `json`, `jsmock`, `production`)
- `.env`-Dateien angepasst zur besseren Modussteuerung
This commit is contained in:
@@ -6,6 +6,6 @@ NEXT_PUBLIC_USE_MOCK_BACKEND_LOOP_START=false
|
|||||||
NEXT_PUBLIC_EXPORT_STATIC=false
|
NEXT_PUBLIC_EXPORT_STATIC=false
|
||||||
NEXT_PUBLIC_USE_CGI=false
|
NEXT_PUBLIC_USE_CGI=false
|
||||||
# App-Versionsnummer
|
# App-Versionsnummer
|
||||||
NEXT_PUBLIC_APP_VERSION=1.6.415
|
NEXT_PUBLIC_APP_VERSION=1.6.416
|
||||||
NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsmock (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter)
|
NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsmock (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter)
|
||||||
|
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ NEXT_PUBLIC_CPL_API_PATH=/CPL
|
|||||||
NEXT_PUBLIC_EXPORT_STATIC=true
|
NEXT_PUBLIC_EXPORT_STATIC=true
|
||||||
NEXT_PUBLIC_USE_CGI=true
|
NEXT_PUBLIC_USE_CGI=true
|
||||||
# App-Versionsnummer
|
# App-Versionsnummer
|
||||||
NEXT_PUBLIC_APP_VERSION=1.6.415
|
NEXT_PUBLIC_APP_VERSION=1.6.416
|
||||||
NEXT_PUBLIC_CPL_MODE=production
|
NEXT_PUBLIC_CPL_MODE=production
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
win_da_state = [1, 0, 1, 0];
|
win_da_state = [0, 0, 1, 0];
|
||||||
win_da_bezeichnung = ["Ausgang1", "Ausgang2", "Ausgang3", "Ausgang4"];
|
win_da_bezeichnung = ["Ausgang1", "Ausgang2", "Ausgang3", "Ausgang4"];
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export default function DigitalOutputsModal({
|
|||||||
// 💡 Modal wird nicht automatisch geschlossen — da Seite neu lädt.
|
// 💡 Modal wird nicht automatisch geschlossen — da Seite neu lädt.
|
||||||
} else {
|
} else {
|
||||||
// 🧪 Lokaler Entwicklungsmodus
|
// 🧪 Lokaler Entwicklungsmodus
|
||||||
const res = await fetch("/api/cpl/updateDigitalOutputs", {
|
const res = await fetch("/api/cpl/updateDigitalOutputsHandler", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ outputs: updatedOutputs }),
|
body: JSON.stringify({ outputs: updatedOutputs }),
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"win_da_state": [
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0
|
|
||||||
],
|
|
||||||
"win_da_bezeichnung": [
|
|
||||||
"Ausgang1",
|
|
||||||
"Ausgang2",
|
|
||||||
"Ausgang3",
|
|
||||||
"Ausgang4"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
2
mocks/api/SERVICE/digitaleAusgaengeMockData.js
Normal file
2
mocks/api/SERVICE/digitaleAusgaengeMockData.js
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
win_da_state = [1, 1, 1, 0];
|
||||||
|
win_da_bezeichnung = ["Ausgang1", "Ausgang2", "Ausgang3", "Ausgang4"];
|
||||||
@@ -1,4 +1,14 @@
|
|||||||
{
|
{
|
||||||
"win_da_state": [1, 0, 1, 0],
|
"win_da_state": [
|
||||||
"win_da_bezeichnung": ["Ausgang1", "Ausgang2", "Ausgang3", "Ausgang4"]
|
1,
|
||||||
}
|
0,
|
||||||
|
1,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"win_da_bezeichnung": [
|
||||||
|
"Ausgang1",
|
||||||
|
"Ausgang2",
|
||||||
|
"Ausgang3",
|
||||||
|
"Ausgang4"
|
||||||
|
]
|
||||||
|
}
|
||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "cpl-v4",
|
"name": "cpl-v4",
|
||||||
"version": "1.6.415",
|
"version": "1.6.416",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "cpl-v4",
|
"name": "cpl-v4",
|
||||||
"version": "1.6.415",
|
"version": "1.6.416",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource/roboto": "^5.1.0",
|
"@fontsource/roboto": "^5.1.0",
|
||||||
"@iconify-icons/ri": "^1.2.10",
|
"@iconify-icons/ri": "^1.2.10",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cpl-v4",
|
"name": "cpl-v4",
|
||||||
"version": "1.6.415",
|
"version": "1.6.416",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// /pages/api/cpl/digitalOutputsAPIHandler.ts
|
// /pages/api/cpl/analogeEingaengeAPIHandler.ts
|
||||||
|
|
||||||
import { NextApiRequest, NextApiResponse } from "next";
|
import { NextApiRequest, NextApiResponse } from "next";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
@@ -10,13 +10,16 @@ export default async function handler(
|
|||||||
) {
|
) {
|
||||||
const filePath = path.join(
|
const filePath = path.join(
|
||||||
process.cwd(),
|
process.cwd(),
|
||||||
"apiMockData",
|
"mocks",
|
||||||
|
"api",
|
||||||
"SERVICE",
|
"SERVICE",
|
||||||
"digitaleAusgaengeMockData.js"
|
"digitaleAusgaengeMockData.json"
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await fs.readFile(filePath, "utf-8");
|
const data = await fs.readFile(filePath, "utf-8");
|
||||||
|
|
||||||
|
res.setHeader("Content-Type", "text/javascript");
|
||||||
res.status(200).send(data);
|
res.status(200).send(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(404).json({ error: "File not found" });
|
res.status(404).json({ error: "File not found" });
|
||||||
|
|||||||
@@ -1,46 +1,75 @@
|
|||||||
// /pages/api/cpl/updateDigitalOutputsHandler.ts
|
// /pages/api/cpl/updateDigitalOutputs.ts
|
||||||
|
|
||||||
import { NextApiRequest, NextApiResponse } from "next";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import fs from "fs/promises";
|
|
||||||
|
|
||||||
export default async function handler(
|
export default function handler(req, res) {
|
||||||
req: NextApiRequest,
|
|
||||||
res: NextApiResponse
|
|
||||||
) {
|
|
||||||
if (req.method !== "POST") {
|
if (req.method !== "POST") {
|
||||||
return res.status(405).json({ error: "Method not allowed" });
|
return res.status(405).json({ message: "Nur POST erlaubt" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const filePath = path.join(
|
const { outputs } = req.body;
|
||||||
process.cwd(),
|
|
||||||
"apiMockdata",
|
|
||||||
"SERVICE",
|
|
||||||
"digitaleAusgaengeMockData.js"
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
if (!Array.isArray(outputs)) {
|
||||||
const { outputs } = req.body;
|
return res.status(400).json({ error: "Ungültige Datenstruktur" });
|
||||||
|
}
|
||||||
|
|
||||||
if (!Array.isArray(outputs) || outputs.length !== 4) {
|
const mode = process.env.NEXT_PUBLIC_CPL_MODE;
|
||||||
return res
|
|
||||||
.status(400)
|
const jsonData = {
|
||||||
.json({ error: "Ungültiges Datenformat (4 Einträge erwartet)" });
|
win_da_state: outputs.map((o) => (o.status ? 1 : 0)),
|
||||||
|
win_da_bezeichnung: outputs.map((o) => o.label),
|
||||||
|
};
|
||||||
|
|
||||||
|
let filePath = "";
|
||||||
|
|
||||||
|
if (mode === "json") {
|
||||||
|
filePath = path.join(
|
||||||
|
process.cwd(),
|
||||||
|
"mocks",
|
||||||
|
"api",
|
||||||
|
"SERVICE",
|
||||||
|
"digitaleAusgaengeMockData.json"
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
||||||
|
fs.writeFileSync(filePath, JSON.stringify(jsonData, null, 2), "utf-8");
|
||||||
|
|
||||||
|
console.log("✅ Datei (JSON) geschrieben:", filePath);
|
||||||
|
res.status(200).json({ success: true });
|
||||||
|
} catch (err) {
|
||||||
|
console.error("❌ Fehler beim Schreiben der JSON-Datei:", err);
|
||||||
|
res.status(500).json({ error: "Fehler beim Schreiben der Datei" });
|
||||||
}
|
}
|
||||||
|
} else if (mode === "jsmock") {
|
||||||
|
filePath = path.join(
|
||||||
|
process.cwd(),
|
||||||
|
"mocks",
|
||||||
|
"js-simulator",
|
||||||
|
"SERVICE",
|
||||||
|
"digitaleAusgaengeMockData.js"
|
||||||
|
);
|
||||||
|
|
||||||
const stateArray = outputs.map((o) => (o.status ? 1 : 0)).join(", ");
|
const jsContent =
|
||||||
const labelArray = outputs.map((o) => `"${o.label}"`).join(", ");
|
`win_da_state = [${jsonData.win_da_state.join(", ")}];\n` +
|
||||||
|
`win_da_bezeichnung = [${jsonData.win_da_bezeichnung
|
||||||
|
.map((s) => `"${s}"`)
|
||||||
|
.join(", ")}];\n`;
|
||||||
|
|
||||||
const fileContent = `win_da_state = [${stateArray}];\nwin_da_bezeichnung = [${labelArray}];\n`;
|
try {
|
||||||
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
||||||
|
fs.writeFileSync(filePath, jsContent, "utf-8");
|
||||||
|
|
||||||
await fs.writeFile(filePath, fileContent, "utf-8");
|
console.log("✅ Datei (JS-Mock) geschrieben:", filePath);
|
||||||
|
res.status(200).json({ success: true });
|
||||||
return res
|
} catch (err) {
|
||||||
.status(200)
|
console.error("❌ Fehler beim Schreiben der JS-Datei:", err);
|
||||||
.json({ message: "Mockdaten erfolgreich gespeichert." });
|
res.status(500).json({ error: "Fehler beim Schreiben der JS-Datei" });
|
||||||
} catch (error) {
|
}
|
||||||
return res
|
} else {
|
||||||
.status(500)
|
res
|
||||||
.json({ error: "Speichern fehlgeschlagen", detail: error });
|
.status(403)
|
||||||
|
.json({ error: "In production ist Schreiben nicht erlaubt" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,44 @@
|
|||||||
// /services/fetchDigitalOutputsService.ts
|
// /services/fetchDigitalOutputsService.ts
|
||||||
|
|
||||||
export const fetchDigitalOutputsService = async () => {
|
export const fetchDigitalOutputsService = async () => {
|
||||||
if (typeof window === "undefined") return [];
|
const mode = process.env.NEXT_PUBLIC_CPL_MODE;
|
||||||
|
|
||||||
const scriptSrc =
|
if (mode === "json") {
|
||||||
process.env.NEXT_PUBLIC_NODE_ENV === "production"
|
const res = await fetch("/api/cpl/digitalOutputsAPIHandler");
|
||||||
? "/CPL?/CPL/SERVICE/da.js"
|
if (!res.ok)
|
||||||
: "/api/cpl/digitalOutputsAPIHandler";
|
throw new Error("❌ Fehler beim Laden der digitalen Ausgänge (JSON)");
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
const state = data.win_da_state;
|
||||||
|
const labels = data.win_da_bezeichnung;
|
||||||
|
|
||||||
|
if (!Array.isArray(state)) {
|
||||||
|
console.warn("⚠️ win_da_state fehlt oder ist ungültig:", state);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return state.slice(0, 4).map((status: number, index: number) => ({
|
||||||
|
id: index + 1,
|
||||||
|
label:
|
||||||
|
Array.isArray(labels) && labels[index]
|
||||||
|
? labels[index]
|
||||||
|
: `Ausgang ${index + 1}`,
|
||||||
|
status: status === 1,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// jsmock oder production
|
||||||
|
const scriptUrl =
|
||||||
|
mode === "production"
|
||||||
|
? "/CPL?/CPL/SERVICE/digitalOutputs.js"
|
||||||
|
: "/CPLmockData/SERVICE/digitalOutputsMockData.js";
|
||||||
|
|
||||||
await new Promise<void>((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
const script = document.createElement("script");
|
const script = document.createElement("script");
|
||||||
script.src = scriptSrc;
|
script.src = scriptUrl;
|
||||||
script.async = true;
|
script.async = true;
|
||||||
script.onload = () => resolve();
|
script.onload = () => resolve();
|
||||||
script.onerror = () => reject("❌ Fehler beim Laden von da.js");
|
script.onerror = () => reject("❌ Fehler beim Laden der digitalOutputs.js");
|
||||||
document.body.appendChild(script);
|
document.body.appendChild(script);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -26,16 +51,12 @@ export const fetchDigitalOutputsService = async () => {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const outputs = state
|
return state.slice(0, 4).map((status: number, index: number) => ({
|
||||||
.slice(0, 4) // ✅ Nur die 4 Ausgänge verwenden
|
id: index + 1,
|
||||||
.map((status: number, index: number) => ({
|
label:
|
||||||
id: index + 1,
|
Array.isArray(labels) && labels[index]
|
||||||
label:
|
? labels[index]
|
||||||
Array.isArray(labels) && labels[index]
|
: `Ausgang ${index + 1}`,
|
||||||
? labels[index]
|
status: status === 1,
|
||||||
: `Ausgang ${index + 1}`,
|
}));
|
||||||
status: status === 1,
|
|
||||||
}));
|
|
||||||
|
|
||||||
return outputs;
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user