feat: dynamische URL-Anpassung für Entwicklungs- und Produktionsumgebung

- Navigation und Weiterleitungen angepasst, um dynamisch `.html`-Endungen in Produktionsumgebung anzuhängen.
- Nutzung von `NEXT_PUBLIC_NODE_ENV` ermöglicht unterschiedliche URL-Strukturen in Entwicklungs- und Produktionsumgebung.
- `Navigation`-Komponente und `index.js` entsprechend konfiguriert, um `.html` in der Produktionsumgebung automatisch anzuhängen.
- Verbesserte Konsistenz und Funktionalität zwischen beiden Umgebungen, 404-Fehler in Produktion behoben.
This commit is contained in:
ISA
2024-10-25 11:21:56 +02:00
parent 655a86e915
commit ab8a80f34c
21 changed files with 108 additions and 110 deletions

View File

@@ -1,20 +0,0 @@
"use client"; // Wichtiger Hinweis, wenn du Next.js App Router verwendest
import { useEffect } from "react";
export default function Json() {
// Beispielvariable
const myVariable = "<%=KIZ0%>";
// useEffect, um sicherzustellen, dass die Konsole nach dem Laden der Seite ausgeführt wird
useEffect(() => {
console.log("Die Variable ist: ", myVariable);
}, []); // Der leere Array sorgt dafür, dass es nur einmal beim Laden der Komponente ausgeführt wird
return (
<div>
<h1>Json Page</h1>
<p>Überprüfe die Konsole, um die Variable zu sehen.</p>
</div>
);
}

View File

@@ -1,31 +0,0 @@
"use client"; // Nur in Client-Komponenten verwenden, nicht in Layout-Dateien
import React from "react";
import Header from "../components/Header";
import Navigation from "../components/Navigation";
import Footer from "../components/Footer";
import "../app/globals.css";
// Diese Datei befindet sich in /app/layout.js
export default function RootLayout({ children }) {
return (
<html lang="de">
<head>
{/* Hier können Meta-Tags oder Links für CSS hinzugefügt werden */}
<link rel="icon" href="/favicon.png" type="image/png" />
<title>Littwin Systemtechnik GmbH & Co. KG</title>
</head>
<body>
{/* Hier das Layout mit Header, Navigation und Footer */}
<div className="bg-gray-100 flex flex-col min-h-screen overflow-hidden">
<Header className="bg-gray-300 " />
<div className="flex flex-grow w-full">
<Navigation />
<main className="flex-1 ">{children}</main>
</div>
<Footer className="bg-gray-300 " />
</div>
</body>
</html>
);
}

View File

@@ -1,38 +0,0 @@
"use client";
import { useEffect } from "react";
import { useRouter } from "next/navigation"; // App-Router Hook für Navigation
// Importiere `storePage` nur im Client
export default function Home() {
const router = useRouter();
useEffect(() => {
// Überprüfe, ob der Code im Browser läuft
if (typeof window !== "undefined") {
// Dynamischer Import von `storePage` nur im Browser
import("../utils/indexedDB").then(({ storePage }) => {
const pageContent = `
<div style="text-align: center; margin-top: 100px;">
<h1>Bitte warten...</h1>
<div class="spinner"></div>
<p>Die Seite wird automatisch neu geladen.</p>
</div>`;
storePage("waitPage", new Blob([pageContent], { type: "text/html" }))
.then(() => {
console.log("Seite 'wait' erfolgreich gespeichert.");
// Weiterleitung zur Dashboard-Seite
router.push("/dashboard");
})
.catch((error) => {
console.error("Fehler beim Speichern der Seite 'wait':", error);
router.push("/dashboard");
});
});
} else {
// Falls kein Browser oder IndexedDB verfügbar ist, direkt zur Dashboard-Seite weiterleiten
router.push("/dashboard");
}
}, [router]);
return <div>Wird geladen...</div>; // Temporärer Ladezustand
}

View File

@@ -13,20 +13,22 @@ function Navigation() {
} }
}, [pathname]); }, [pathname]);
// Dynamische Anpassung der Pfade mit oder ohne .html
const isProduction = process.env.NEXT_PUBLIC_NODE_ENV === "production";
const menuItems = [ const menuItems = [
{ name: "Übersicht", path: "/dashboard" }, { name: "Übersicht", path: "/dashboard" },
{ name: "Kabelüberwachung", path: "/kabelueberwachung" }, { name: "Kabelüberwachung", path: "/kabelueberwachung" },
//{ name: "Zutrittskontrolle", path: "/access" }, // Weitere Menüpunkte hier
//{ name: "Ein- und Ausgänge", path: "/einausgaenge" },
//{ name: "Analoge Eingänge", path: "/analogeEingaenge" },
//{ name: "Meldungen", path: "/meldungen" },
]; ];
return ( return (
<aside> <aside>
<nav className="w-64 flex-shrink-0 mt-32 overflow-hidden"> <nav className="w-64 flex-shrink-0 mt-32 overflow-hidden">
{menuItems.map((item) => ( {menuItems.map((item) => (
<Link href={item.path} key={item.name}> <Link
href={`${item.path}${isProduction ? ".html" : ""}`}
key={item.name}
>
<div <div
className={`block px-4 py-2 mb-4 font-bold whitespace-nowrap transition duration-300 ${ className={`block px-4 py-2 mb-4 font-bold whitespace-nowrap transition duration-300 ${
activeLink.startsWith(item.path) || activeLink.startsWith(item.path) ||

View File

@@ -1,10 +1,10 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = { const nextConfig = {
reactStrictMode: true, reactStrictMode: true, // Aktiviert Strict Mode zur Identifizierung potenzieller Probleme in der Anwendung
output: "export", output: "export", // Stellt sicher, dass Next.js eine statische Version der Website generiert (SSG)
trailingSlash: false, trailingSlash: false, // Fügt einen Schrägstrich am Ende der URLs hinzu (nützlich für statische Verzeichnisse)
images: { images: {
unoptimized: true, unoptimized: true, // Verzichtet auf Next.js' Bildoptimierung (nützlich für statische Exporte)
}, },
}; };

16
package-lock.json generated
View File

@@ -24,6 +24,7 @@
}, },
"devDependencies": { "devDependencies": {
"postcss": "^8.4.47", "postcss": "^8.4.47",
"rimraf": "^5.0.10",
"tailwindcss": "^3.4.12" "tailwindcss": "^3.4.12"
} }
}, },
@@ -1549,6 +1550,21 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/rimraf": {
"version": "5.0.10",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz",
"integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==",
"dev": true,
"dependencies": {
"glob": "^10.3.7"
},
"bin": {
"rimraf": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/run-parallel": { "node_modules/run-parallel": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",

View File

@@ -4,8 +4,9 @@
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
"build": "next build", "clean": "rimraf .next out",
"postbuild": "cp LICENSE_ICONIFY.txt out/LICENSE_ICONIFY.txt", "build": "npm run clean && next build",
"postbuild": "copy LICENSE_ICONIFY.txt out\\LICENSE_ICONIFY.txt",
"start": "next start", "start": "next start",
"lint": "next lint" "lint": "next lint"
}, },
@@ -26,6 +27,7 @@
}, },
"devDependencies": { "devDependencies": {
"postcss": "^8.4.47", "postcss": "^8.4.47",
"rimraf": "^5.0.10",
"tailwindcss": "^3.4.12" "tailwindcss": "^3.4.12"
} }
} }

34
pages/_app.js Normal file
View File

@@ -0,0 +1,34 @@
import { useEffect } from "react";
import Header from "../components/Header";
import Navigation from "../components/Navigation";
import Footer from "../components/Footer";
import "../styles/globals.css";
function MyApp({ Component, pageProps }) {
// Client-seitige Logik kann hier hinzugefügt werden
useEffect(() => {
if (typeof window !== "undefined") {
console.log("Client-side logic can run here.");
}
}, []);
return (
<div className="bg-gray-100 flex flex-col min-h-screen overflow-hidden">
<Header />
<div className="flex flex-grow w-full">
{" "}
{/* Flexbox-Container für Navigation und Content */}
<Navigation className="w-1/5" />{" "}
{/* Navigation nimmt 20% der Breite ein */}
<main className="flex-1 p-4">
{" "}
{/* Der Content nimmt den restlichen Platz ein */}
<Component {...pageProps} />
</main>
</div>
<Footer />
</div>
);
}
export default MyApp;

16
pages/_document.js Normal file
View File

@@ -0,0 +1,16 @@
import { Html, Head, Main, NextScript } from "next/document";
export default function Document() {
return (
<Html lang="de">
<Head>
{/* Füge Meta-Tags, CSS-Links und andere Header-Inhalte hier hinzu */}
<link rel="icon" href="/favicon.png" type="image/png" />
</Head>
<body>
<Main /> {/* Hier wird der Seiteninhalt eingebettet */}
<NextScript /> {/* Fügt Next.js-Skripte für die Seite hinzu */}
</body>
</Html>
);
}

View File

@@ -4,13 +4,13 @@ import { useRouter } from "next/navigation";
import "tailwindcss/tailwind.css"; import "tailwindcss/tailwind.css";
import "@fontsource/roboto"; import "@fontsource/roboto";
import "bootstrap-icons/font/bootstrap-icons.css"; import "bootstrap-icons/font/bootstrap-icons.css";
import { loadWindowVariables } from "../../utils/loadWindowVariables"; import { loadWindowVariables } from "../utils/loadWindowVariables";
import CPLStatus from "../../components/modulesStatus/CPLStatus"; import CPLStatus from "../components/modulesStatus/CPLStatus";
import Access1Status from "../../components/modulesStatus/Access1Status"; import Access1Status from "../components/modulesStatus/Access1Status";
import Access2Status from "../../components/modulesStatus/Access2Status"; import Access2Status from "../components/modulesStatus/Access2Status";
import KabelModulStatus from "../../components/modulesStatus/KabelModulStatus"; import KabelModulStatus from "../components/modulesStatus/KabelModulStatus";
import XioPM1Status from "../../components/modulesStatus/XioPM1Status"; import XioPM1Status from "../components/modulesStatus/XioPM1Status";
import XioPM2Status from "../../components/modulesStatus/XioPM2Status"; import XioPM2Status from "../components/modulesStatus/XioPM2Status";
import { Icon } from "@iconify/react"; import { Icon } from "@iconify/react";
function Dashboard() { function Dashboard() {

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

17
pages/index.js Normal file
View File

@@ -0,0 +1,17 @@
import { useEffect } from "react";
import { useRouter } from "next/router";
export default function Home() {
const router = useRouter();
useEffect(() => {
// Prüft die Umgebung und hängt .html in der Produktion an
const isProduction = process.env.NEXT_PUBLIC_NODE_ENV === "production";
const dashboardPath = `/dashboard${isProduction ? ".html" : ""}`;
// Leitet den Benutzer sofort zur richtigen Dashboard-Seite weiter
router.replace(dashboardPath);
}, [router]);
return null; // Die Seite zeigt keinen Inhalt an und leitet sofort um
}

View File

@@ -1,8 +1,8 @@
"use client"; // app/kabelueberwachung/page.jsx "use client"; // app/kabelueberwachung/page.jsx
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import Kue705FO from "../../components/modules/Kue705FO"; import Kue705FO from "../components/modules/Kue705FO";
import { loadWindowVariables } from "../../utils/loadWindowVariables"; import { loadWindowVariables } from "../utils/loadWindowVariables";
function Kabelueberwachung() { function Kabelueberwachung() {
const router = useRouter(); const router = useRouter();

View File

@@ -6,7 +6,7 @@ import { ClipLoader } from "react-spinners";
// IndexedDB functions only in the browser // IndexedDB functions only in the browser
let storePage, getPage; let storePage, getPage;
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
const indexedDBModule = require("../../utils/indexedDB"); const indexedDBModule = require("../utils/indexedDB");
storePage = indexedDBModule.storePage; storePage = indexedDBModule.storePage;
getPage = indexedDBModule.getPage; getPage = indexedDBModule.getPage;
} }