refactor: Consolidate error pages into single ErrorPage component
- Created generic ErrorPage.js with errorCode prop - Centralized error messages in ERROR_MESSAGES dictionary - Updated App.js to use ErrorPage for all error routes - Updated ErrorBoundary.js to use new ErrorPage component - Removed duplicate files: 403Page.js, 404Page.js, 500Page.js, 502Page.js, 503Page.js - Fixed 403/404 routing: protected routes show 403, unknown routes show 404 - Error pages now vertically centered with min-height: 100vh
This commit is contained in:
parent
91d6d06687
commit
e4a76a6b3d
|
|
@ -8,11 +8,7 @@ import ErrorBoundary from './Components/ComponentUtils/ErrorBoundary.js';
|
||||||
// Always loaded (public + internal)
|
// Always loaded (public + internal)
|
||||||
import MultiUploadPage from './Components/Pages/MultiUploadPage';
|
import MultiUploadPage from './Components/Pages/MultiUploadPage';
|
||||||
import ManagementPortalPage from './Components/Pages/ManagementPortalPage';
|
import ManagementPortalPage from './Components/Pages/ManagementPortalPage';
|
||||||
import NotFoundPage from './Components/Pages/404Page.js';
|
import ErrorPage from './Components/Pages/ErrorPage.js';
|
||||||
import ForbiddenPage from './Components/Pages/403Page.js';
|
|
||||||
import InternalServerErrorPage from './Components/Pages/500Page.js';
|
|
||||||
import BadGatewayPage from './Components/Pages/502Page.js';
|
|
||||||
import ServiceUnavailablePage from './Components/Pages/503Page.js';
|
|
||||||
|
|
||||||
// Lazy loaded (internal only) - Code Splitting für Performance
|
// Lazy loaded (internal only) - Code Splitting für Performance
|
||||||
const SlideshowPage = lazy(() => import('./Components/Pages/SlideshowPage'));
|
const SlideshowPage = lazy(() => import('./Components/Pages/SlideshowPage'));
|
||||||
|
|
@ -23,14 +19,14 @@ const ModerationGroupImagesPage = lazy(() => import('./Components/Pages/Moderati
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protected Route Component
|
* Protected Route Component
|
||||||
* Redirects to upload page if accessed from public host
|
* Shows 403 page if accessed from public host
|
||||||
*/
|
*/
|
||||||
const ProtectedRoute = ({ children }) => {
|
const ProtectedRoute = ({ children }) => {
|
||||||
const hostConfig = getHostConfig();
|
const hostConfig = getHostConfig();
|
||||||
|
|
||||||
if (hostConfig.isPublic) {
|
if (hostConfig.isPublic) {
|
||||||
// Redirect to upload page - feature not available on public
|
// Show 403 - feature not available on public
|
||||||
return <Navigate to="/" replace />;
|
return <ErrorPage errorCode="403" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
|
|
@ -67,14 +63,13 @@ function App() {
|
||||||
<Route path="/manage/:token" element={<ManagementPortalPage />} />
|
<Route path="/manage/:token" element={<ManagementPortalPage />} />
|
||||||
|
|
||||||
{/* Error Pages */}
|
{/* Error Pages */}
|
||||||
<Route path="/error/403" element={<ForbiddenPage />} />
|
<Route path="/error/403" element={<ErrorPage errorCode="403" />} />
|
||||||
<Route path="/error/500" element={<InternalServerErrorPage />} />
|
<Route path="/error/404" element={<ErrorPage errorCode="404" />} />
|
||||||
<Route path="/error/502" element={<BadGatewayPage />} />
|
<Route path="/error/500" element={<ErrorPage errorCode="500" />} />
|
||||||
<Route path="/error/503" element={<ServiceUnavailablePage />} />
|
<Route path="/error/502" element={<ErrorPage errorCode="502" />} />
|
||||||
|
<Route path="/error/503" element={<ErrorPage errorCode="503" />} />
|
||||||
|
|
||||||
{/* Internal Only Routes - nur auf internal host geladen */}
|
{/* Internal Only Routes - geschützt durch ProtectedRoute */}
|
||||||
{hostConfig.isInternal && (
|
|
||||||
<>
|
|
||||||
<Route
|
<Route
|
||||||
path="/slideshow"
|
path="/slideshow"
|
||||||
element={
|
element={
|
||||||
|
|
@ -115,11 +110,9 @@ function App() {
|
||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* 404 / Not Found */}
|
{/* 404 / Not Found */}
|
||||||
<Route path="*" element={<NotFoundPage />} />
|
<Route path="*" element={<ErrorPage errorCode="404" />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</Router>
|
</Router>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import InternalServerErrorPage from '../Pages/500Page';
|
import ErrorPage from '../Pages/ErrorPage';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error Boundary Component
|
* Error Boundary Component
|
||||||
|
|
@ -28,7 +28,7 @@ class ErrorBoundary extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
if (this.state.hasError) {
|
if (this.state.hasError) {
|
||||||
// Render 500 Error Page
|
// Render 500 Error Page
|
||||||
return <InternalServerErrorPage />;
|
return <ErrorPage errorCode="500" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.props.children;
|
return this.props.children;
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ const Loading = () => {
|
||||||
<div className="loading-logo-container">
|
<div className="loading-logo-container">
|
||||||
<div className="rotor">
|
<div className="rotor">
|
||||||
<svg
|
<svg
|
||||||
className="loading-logo"
|
class="loading-logo"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 841.89 595.28"
|
viewBox="260 90 310 190"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<g id="g136" display="inline">
|
<g id="g136" display="inline">
|
||||||
|
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import Navbar from '../ComponentUtils/Headers/Navbar'
|
|
||||||
import NavbarUpload from '../ComponentUtils/Headers/NavbarUpload'
|
|
||||||
import ErrorAnimation from '../ComponentUtils/ErrorAnimation/ErrorAnimation'
|
|
||||||
import { getHostConfig } from '../../Utils/hostDetection'
|
|
||||||
|
|
||||||
import './Css/ErrorPage.css'
|
|
||||||
|
|
||||||
function ForbiddenPage() {
|
|
||||||
const hostConfig = getHostConfig();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="allContainerNoBackground">
|
|
||||||
{hostConfig.isPublic ? <NavbarUpload /> : <Navbar />}
|
|
||||||
|
|
||||||
<div className="containerError">
|
|
||||||
<div style={{ textAlign: 'center', marginTop: '2rem' }}>
|
|
||||||
<h1>403 - Zugriff verweigert</h1>
|
|
||||||
<p>Sie haben keine Berechtigung, auf diese Ressource zuzugreifen.</p>
|
|
||||||
<ErrorAnimation errorCode="403" />
|
|
||||||
<a href="/" style={{ color: '#007bff', textDecoration: 'underline' }}>
|
|
||||||
Zurück zur Startseite
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ForbiddenPage
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import Navbar from '../ComponentUtils/Headers/Navbar'
|
|
||||||
import NavbarUpload from '../ComponentUtils/Headers/NavbarUpload'
|
|
||||||
import ErrorAnimation from '../ComponentUtils/ErrorAnimation/ErrorAnimation'
|
|
||||||
import { getHostConfig } from '../../Utils/hostDetection'
|
|
||||||
|
|
||||||
import './Css/ErrorPage.css'
|
|
||||||
import '../../App.css'
|
|
||||||
|
|
||||||
function FZF() {
|
|
||||||
const hostConfig = getHostConfig();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="allContainerNoBackground">
|
|
||||||
{hostConfig.isPublic ? <NavbarUpload /> : <Navbar />}
|
|
||||||
|
|
||||||
<div className="containerError">
|
|
||||||
{hostConfig.isPublic ? (
|
|
||||||
<div style={{ textAlign: 'center', marginTop: '2rem' }}>
|
|
||||||
<h1>404 - Diese Funktion ist nicht verfügbar</h1>
|
|
||||||
<p>Diese Funktion ist nur über das interne Netzwerk erreichbar.</p>
|
|
||||||
<ErrorAnimation errorCode="403" />
|
|
||||||
<a href="/" style={{ color: '#007bff', textDecoration: 'underline' }}>
|
|
||||||
Zurück zum Upload
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div style={{ textAlign: 'center', marginTop: '2rem' }}>
|
|
||||||
<h1>404 - Seite nicht gefunden</h1>
|
|
||||||
<p>Die angeforderte Seite existiert nicht.</p>
|
|
||||||
<ErrorAnimation errorCode="404" />
|
|
||||||
<a href="/" style={{ color: '#007bff', textDecoration: 'underline' }}>
|
|
||||||
Zurück zur Startseite
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export default FZF
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import Navbar from '../ComponentUtils/Headers/Navbar'
|
|
||||||
import NavbarUpload from '../ComponentUtils/Headers/NavbarUpload'
|
|
||||||
import ErrorAnimation from '../ComponentUtils/ErrorAnimation/ErrorAnimation'
|
|
||||||
import { getHostConfig } from '../../Utils/hostDetection'
|
|
||||||
|
|
||||||
import './Css/ErrorPage.css'
|
|
||||||
|
|
||||||
function InternalServerErrorPage() {
|
|
||||||
const hostConfig = getHostConfig();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="allContainerNoBackground">
|
|
||||||
{hostConfig.isPublic ? <NavbarUpload /> : <Navbar />}
|
|
||||||
|
|
||||||
<div className="containerError">
|
|
||||||
<div style={{ textAlign: 'center', marginTop: '2rem' }}>
|
|
||||||
<h1>500 - Interner Serverfehler</h1>
|
|
||||||
<p>Es ist ein unerwarteter Fehler aufgetreten. Bitte versuchen Sie es später erneut.</p>
|
|
||||||
<ErrorAnimation errorCode="500" />
|
|
||||||
<a href="/" style={{ color: '#007bff', textDecoration: 'underline' }}>
|
|
||||||
Zurück zur Startseite
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default InternalServerErrorPage
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import Navbar from '../ComponentUtils/Headers/Navbar'
|
|
||||||
import NavbarUpload from '../ComponentUtils/Headers/NavbarUpload'
|
|
||||||
import ErrorAnimation from '../ComponentUtils/ErrorAnimation/ErrorAnimation'
|
|
||||||
import { getHostConfig } from '../../Utils/hostDetection'
|
|
||||||
|
|
||||||
import './Css/ErrorPage.css'
|
|
||||||
|
|
||||||
function BadGatewayPage() {
|
|
||||||
const hostConfig = getHostConfig();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="allContainerNoBackground">
|
|
||||||
{hostConfig.isPublic ? <NavbarUpload /> : <Navbar />}
|
|
||||||
|
|
||||||
<div className="containerError">
|
|
||||||
<div style={{ textAlign: 'center', marginTop: '2rem' }}>
|
|
||||||
<h1>502 - Bad Gateway</h1>
|
|
||||||
<p>Der Server hat eine ungültige Antwort erhalten. Bitte versuchen Sie es später erneut.</p>
|
|
||||||
<ErrorAnimation errorCode="502" />
|
|
||||||
<a href="/" style={{ color: '#007bff', textDecoration: 'underline' }}>
|
|
||||||
Zurück zur Startseite
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default BadGatewayPage
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import Navbar from '../ComponentUtils/Headers/Navbar'
|
|
||||||
import NavbarUpload from '../ComponentUtils/Headers/NavbarUpload'
|
|
||||||
import ErrorAnimation from '../ComponentUtils/ErrorAnimation/ErrorAnimation'
|
|
||||||
import { getHostConfig } from '../../Utils/hostDetection'
|
|
||||||
|
|
||||||
import './Css/ErrorPage.css'
|
|
||||||
|
|
||||||
function ServiceUnavailablePage() {
|
|
||||||
const hostConfig = getHostConfig();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="allContainerNoBackground">
|
|
||||||
{hostConfig.isPublic ? <NavbarUpload /> : <Navbar />}
|
|
||||||
|
|
||||||
<div className="containerError">
|
|
||||||
<div style={{ textAlign: 'center', marginTop: '2rem' }}>
|
|
||||||
<h1>503 - Service nicht verfügbar</h1>
|
|
||||||
<p>Der Service ist vorübergehend nicht verfügbar. Bitte versuchen Sie es später erneut.</p>
|
|
||||||
<ErrorAnimation errorCode="503" />
|
|
||||||
<a href="/" style={{ color: '#007bff', textDecoration: 'underline' }}>
|
|
||||||
Zurück zur Startseite
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ServiceUnavailablePage
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
/* Error Pages Container */
|
/* Error Pages Container */
|
||||||
.containerError {
|
.containerError {
|
||||||
margin-top: 25vh;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
|
|
|
||||||
56
frontend/src/Components/Pages/ErrorPage.js
Normal file
56
frontend/src/Components/Pages/ErrorPage.js
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
import React from 'react'
|
||||||
|
import Navbar from '../ComponentUtils/Headers/Navbar'
|
||||||
|
import NavbarUpload from '../ComponentUtils/Headers/NavbarUpload'
|
||||||
|
import ErrorAnimation from '../ComponentUtils/ErrorAnimation/ErrorAnimation'
|
||||||
|
import { getHostConfig } from '../../Utils/hostDetection'
|
||||||
|
|
||||||
|
import './Css/ErrorPage.css'
|
||||||
|
import '../../App.css'
|
||||||
|
|
||||||
|
const ERROR_MESSAGES = {
|
||||||
|
'403': {
|
||||||
|
title: '403 - Zugriff verweigert',
|
||||||
|
description: 'Sie haben keine Berechtigung, auf diese Ressource zuzugreifen.'
|
||||||
|
},
|
||||||
|
'404': {
|
||||||
|
title: '404 - Seite nicht gefunden',
|
||||||
|
description: 'Die angeforderte Seite existiert nicht.'
|
||||||
|
},
|
||||||
|
'500': {
|
||||||
|
title: '500 - Interner Serverfehler',
|
||||||
|
description: 'Es ist ein interner Serverfehler aufgetreten.'
|
||||||
|
},
|
||||||
|
'502': {
|
||||||
|
title: '502 - Bad Gateway',
|
||||||
|
description: 'Der Server hat eine ungültige Antwort erhalten.'
|
||||||
|
},
|
||||||
|
'503': {
|
||||||
|
title: '503 - Service nicht verfügbar',
|
||||||
|
description: 'Der Service ist vorübergehend nicht verfügbar.'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function ErrorPage({ errorCode = '404' }) {
|
||||||
|
const hostConfig = getHostConfig();
|
||||||
|
const error = ERROR_MESSAGES[errorCode] || ERROR_MESSAGES['404'];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="allContainerNoBackground">
|
||||||
|
{hostConfig.isPublic ? <NavbarUpload /> : <Navbar />}
|
||||||
|
|
||||||
|
<div className="containerError">
|
||||||
|
<div style={{ textAlign: 'center' }}>
|
||||||
|
<h1 style={{ textAlign: 'center' }}>{error.title}</h1>
|
||||||
|
<p>{error.description}</p>
|
||||||
|
<ErrorAnimation errorCode={errorCode} />
|
||||||
|
<a href="/" style={{ color: '#007bff', textDecoration: 'underline' }}>
|
||||||
|
Zurück zur Startseite
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default ErrorPage
|
||||||
162
test-error-page.html
Normal file
162
test-error-page.html
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Loading Animation Test</title>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Roboto', Arial, sans-serif;
|
||||||
|
background-color: whitesmoke;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-section {
|
||||||
|
background: white;
|
||||||
|
padding: 40px;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||||
|
margin-bottom: 30px;
|
||||||
|
max-width: 800px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-section h2 {
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-description {
|
||||||
|
color: #666;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loading Animation Styles */
|
||||||
|
.loading-logo-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 400px;
|
||||||
|
position: relative;
|
||||||
|
perspective: 1000px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotor {
|
||||||
|
display: inline-block;
|
||||||
|
transform-origin: center;
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
will-change: transform;
|
||||||
|
animation: rotateY 4s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-logo {
|
||||||
|
display: block;
|
||||||
|
width: 400px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-logo #g136 {
|
||||||
|
transform-box: fill-box;
|
||||||
|
transform-origin: center;
|
||||||
|
will-change: transform;
|
||||||
|
animation: rotateHammerAxis 3s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rotateY {
|
||||||
|
from {
|
||||||
|
transform: rotateY(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotateY(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rotateHammerAxis {
|
||||||
|
from {
|
||||||
|
transform: rotate3d(1, -1, 0, 0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate3d(1, -1, 0, 360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>🎨 Loading Animation Test & Fehlerseiten-Design</h1>
|
||||||
|
|
||||||
|
<!-- Original Loading Animation -->
|
||||||
|
<div class="demo-section">
|
||||||
|
<h2>Original Loading Animation</h2>
|
||||||
|
<p class="demo-description">Die Standard-Loading-Animation mit grünem Hammer</p>
|
||||||
|
<div class="loading-logo-container">
|
||||||
|
<div class="rotor">
|
||||||
|
<svg
|
||||||
|
class="loading-logo"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 289.40499 170.09499"
|
||||||
|
id="svg264"
|
||||||
|
>
|
||||||
|
<g id="g561" style="display:inline">
|
||||||
|
<path id="path1353" style="display:inline;fill:#48484a" d="M 138.80469 0 C 97.587768 0 63.224812 29.321264 55.423828 68.242188 C 53.972832 68.119188 52.50934 68.042969 51.027344 68.042969 C 22.8464 68.042969 0 90.887413 0 119.06836 C 0 147.2483 22.8474 170.0957 51.027344 170.0957 C 65.865314 170.0957 210.51721 170.09375 225.61719 170.09375 C 260.84611 170.09375 289.4043 142.40467 289.4043 107.17773 C 289.4053 71.952807 260.84808 43.392578 225.61914 43.392578 C 221.50914 43.392578 217.49456 43.796064 213.60156 44.539062 C 199.2046 18.011166 171.10863 0 138.80469 0 z M 171.96289 40.238281 A 39.540237 71.54811 46.312638 0 1 192.97852 47.357422 A 39.540237 71.54811 46.312638 0 1 170.08984 124.95117 A 39.540237 71.54811 46.312638 0 1 90.582031 147.28711 A 39.540237 71.54811 46.312638 0 1 113.4707 69.695312 A 39.540237 71.54811 46.312638 0 1 171.96289 40.238281 z "/>
|
||||||
|
</g>
|
||||||
|
<g id="g136">
|
||||||
|
<g id="siebensegment" transform="matrix(0.46393276,-0.46393277,0.46393277,0.46393276,33.958225,228.89983)" style="display:inline">
|
||||||
|
<g id="g1758" transform="translate(113.66502,-113.03641)">
|
||||||
|
<polygon points="20,20 10,10 20,0 60,0 70,10 60,20 " id="polygon1573" transform="matrix(0.67523047,0,0,0.67523047,117.69293,49.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="60,20 70,10 80,20 80,40 70,50 60,40 " id="polygon1575" transform="matrix(0.67523047,0,0,0.67523047,119.69293,51.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="80,60 80,80 70,90 60,80 60,60 70,50 " id="polygon1577" transform="matrix(0.67523047,0,0,0.67523047,119.69293,55.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="20,80 60,80 70,90 60,100 20,100 10,90 " id="polygon1579" transform="matrix(0.67523047,0,0,0.67523047,117.69293,57.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="10,80 0,90 -10,80 -10,60 0,50 10,60 " id="polygon1581" transform="matrix(0.67523047,0,0,0.67523047,122.44524,55.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="10,20 10,40 0,50 -10,40 -10,20 0,10 " id="polygon1583" transform="matrix(0.67523047,0,0,0.67523047,122.44524,51.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="20,60 10,50 20,40 60,40 70,50 60,60 " id="polygon1585" transform="matrix(0.67523047,0,0,0.67523047,117.69293,53.286325)" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2"/>
|
||||||
|
</g>
|
||||||
|
<g id="g1782" transform="translate(179.35956,-113.03641)">
|
||||||
|
<polygon points="70,10 60,20 20,20 10,10 20,0 60,0 " id="polygon1768" transform="matrix(0.67523047,0,0,0.67523047,117.69293,49.286325)" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="70,50 60,40 60,20 70,10 80,20 80,40 " id="polygon1770" transform="matrix(0.67523047,0,0,0.67523047,119.69293,51.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="60,60 70,50 80,60 80,80 70,90 60,80 " id="polygon1772" transform="matrix(0.67523047,0,0,0.67523047,119.69293,55.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="20,100 10,90 20,80 60,80 70,90 60,100 " id="polygon1774" transform="matrix(0.67523047,0,0,0.67523047,117.69293,57.286325)" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="0,50 10,60 10,80 0,90 -10,80 -10,60 " id="polygon1776" transform="matrix(0.67523047,0,0,0.67523047,122.44524,55.286325)" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="-10,20 0,10 10,20 10,40 0,50 -10,40 " id="polygon1778" transform="matrix(0.67523047,0,0,0.67523047,122.44524,51.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="70,50 60,60 20,60 10,50 20,40 60,40 " id="polygon1780" transform="matrix(0.67523047,0,0,0.67523047,117.69293,53.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
||||||
|
</g>
|
||||||
|
<g id="g1800" transform="translate(47.970487,-113.03641)">
|
||||||
|
<polygon points="60,20 20,20 10,10 20,0 60,0 70,10 " id="polygon1786" transform="matrix(0.67523047,0,0,0.67523047,117.69293,49.286325)" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="60,40 60,20 70,10 80,20 80,40 70,50 " id="polygon1788" transform="matrix(0.67523047,0,0,0.67523047,119.69293,51.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="70,50 80,60 80,80 70,90 60,80 60,60 " id="polygon1790" transform="matrix(0.67523047,0,0,0.67523047,119.69293,55.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="10,90 20,80 60,80 70,90 60,100 20,100 " id="polygon1792" transform="matrix(0.67523047,0,0,0.67523047,117.69293,57.286325)" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="10,60 10,80 0,90 -10,80 -10,60 0,50 " id="polygon1794" transform="matrix(0.67523047,0,0,0.67523047,122.44524,55.286325)" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="0,10 10,20 10,40 0,50 -10,40 -10,20 " id="polygon1796" transform="matrix(0.67523047,0,0,0.67523047,122.44524,51.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
||||||
|
<polygon points="60,60 20,60 10,50 20,40 60,40 70,50 " id="polygon1798" transform="matrix(0.67523047,0,0,0.67523047,117.69293,53.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -52,7 +52,6 @@
|
||||||
font-size: 0.95rem;
|
font-size: 0.95rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Loading Animation Styles */
|
|
||||||
.loading-logo-container {
|
.loading-logo-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
@ -63,6 +62,7 @@
|
||||||
perspective: 1000px;
|
perspective: 1000px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Äußerer Container: Y-Achsen-Rotation für Wolke UND Hammer zusammen */
|
||||||
.rotor {
|
.rotor {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
transform-origin: center;
|
transform-origin: center;
|
||||||
|
|
@ -77,13 +77,15 @@
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hammer: zusätzliche Rotation um eigene Längsachse */
|
||||||
.loading-logo #g136 {
|
.loading-logo #g136 {
|
||||||
transform-box: fill-box;
|
transform-box: fill-box; /* Bezieht sich auf eigene Bounding Box */
|
||||||
transform-origin: center;
|
transform-origin: center; /* Mittelpunkt der eigenen BBox */
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
animation: rotateHammerAxis 3s linear infinite;
|
animation: rotateHammerAxis 3s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Y-Achsen-Rotation mit leichter X-Neigung (vermeidet Totpunkt bei 90°) */
|
||||||
@keyframes rotateY {
|
@keyframes rotateY {
|
||||||
from {
|
from {
|
||||||
transform: rotateY(0deg);
|
transform: rotateY(0deg);
|
||||||
|
|
@ -93,6 +95,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hammer-Rotation um eigene Längsachse (diagonal) */
|
||||||
@keyframes rotateHammerAxis {
|
@keyframes rotateHammerAxis {
|
||||||
from {
|
from {
|
||||||
transform: rotate3d(1, -1, 0, 0deg);
|
transform: rotate3d(1, -1, 0, 0deg);
|
||||||
|
|
@ -101,6 +104,7 @@
|
||||||
transform: rotate3d(1, -1, 0, 360deg);
|
transform: rotate3d(1, -1, 0, 360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -115,42 +119,26 @@
|
||||||
<svg
|
<svg
|
||||||
class="loading-logo"
|
class="loading-logo"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 289.40499 170.09499"
|
viewBox="260 90 310 190"
|
||||||
id="svg264"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<g id="g561" style="display:inline">
|
<g id="g136" display="inline">
|
||||||
<path id="path1353" style="display:inline;fill:#48484a" d="M 138.80469 0 C 97.587768 0 63.224812 29.321264 55.423828 68.242188 C 53.972832 68.119188 52.50934 68.042969 51.027344 68.042969 C 22.8464 68.042969 0 90.887413 0 119.06836 C 0 147.2483 22.8474 170.0957 51.027344 170.0957 C 65.865314 170.0957 210.51721 170.09375 225.61719 170.09375 C 260.84611 170.09375 289.4043 142.40467 289.4043 107.17773 C 289.4053 71.952807 260.84808 43.392578 225.61914 43.392578 C 221.50914 43.392578 217.49456 43.796064 213.60156 44.539062 C 199.2046 18.011166 171.10863 0 138.80469 0 z M 171.96289 40.238281 A 39.540237 71.54811 46.312638 0 1 192.97852 47.357422 A 39.540237 71.54811 46.312638 0 1 170.08984 124.95117 A 39.540237 71.54811 46.312638 0 1 90.582031 147.28711 A 39.540237 71.54811 46.312638 0 1 113.4707 69.695312 A 39.540237 71.54811 46.312638 0 1 171.96289 40.238281 z "/>
|
<path
|
||||||
</g>
|
display="inline"
|
||||||
<g id="g136">
|
fill="#76b043"
|
||||||
<g id="siebensegment" transform="matrix(0.46393276,-0.46393277,0.46393277,0.46393276,33.958225,228.89983)" style="display:inline">
|
d="m 386.456,248.659 c -0.824,0.825 -2.157,0.825 -2.987,0 L 365.572,230.76 c -0.818,-0.816 -0.818,-2.136 -0.005,-2.962 0.005,-0.008 0.005,-0.011 0.011,-0.019 0.006,-0.002 0.01,-0.002 0.017,-0.01 l 52.177,-52.177 20.877,20.876 z"
|
||||||
<g id="g1758" transform="translate(113.66502,-113.03641)">
|
/>
|
||||||
<polygon points="20,20 10,10 20,0 60,0 70,10 60,20 " id="polygon1573" transform="matrix(0.67523047,0,0,0.67523047,117.69293,49.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
<path
|
||||||
<polygon points="60,20 70,10 80,20 80,40 70,50 60,40 " id="polygon1575" transform="matrix(0.67523047,0,0,0.67523047,119.69293,51.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
display="inline"
|
||||||
<polygon points="80,60 80,80 70,90 60,80 60,60 70,50 " id="polygon1577" transform="matrix(0.67523047,0,0,0.67523047,119.69293,55.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
fill="#76b043"
|
||||||
<polygon points="20,80 60,80 70,90 60,100 20,100 10,90 " id="polygon1579" transform="matrix(0.67523047,0,0,0.67523047,117.69293,57.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
d="m 473.015,185.95 c -0.021,0.018 -0.025,0.045 -0.043,0.063 -0.02,0.02 -0.045,0.022 -0.064,0.041 l -17.811,17.813 c -0.018,0.019 -0.023,0.046 -0.041,0.061 -0.02,0.02 -0.045,0.026 -0.064,0.045 -0.815,0.758 -2.064,0.754 -2.877,-0.012 -0.012,-0.014 -0.035,-0.018 -0.047,-0.033 -0.012,-0.012 -0.019,-0.033 -0.032,-0.046 l -49.265,-49.265 c -0.014,-0.016 -0.035,-0.02 -0.048,-0.034 -0.013,-0.011 -0.019,-0.034 -0.032,-0.049 -0.783,-0.826 -0.779,-2.121 0.032,-2.929 0.31,-0.312 0.698,-0.465 1.093,-0.543 l 0.004,-0.039 30.859,-5.149 0.035,0.034 c 0.607,-0.061 1.232,0.107 1.704,0.578 l 36.547,36.548 c 0.808,0.811 0.819,2.087 0.05,2.916"
|
||||||
<polygon points="10,80 0,90 -10,80 -10,60 0,50 10,60 " id="polygon1581" transform="matrix(0.67523047,0,0,0.67523047,122.44524,55.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
/>
|
||||||
<polygon points="10,20 10,40 0,50 -10,40 -10,20 0,10 " id="polygon1583" transform="matrix(0.67523047,0,0,0.67523047,122.44524,51.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
|
||||||
<polygon points="20,60 10,50 20,40 60,40 70,50 60,60 " id="polygon1585" transform="matrix(0.67523047,0,0,0.67523047,117.69293,53.286325)" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2"/>
|
|
||||||
</g>
|
|
||||||
<g id="g1782" transform="translate(179.35956,-113.03641)">
|
|
||||||
<polygon points="70,10 60,20 20,20 10,10 20,0 60,0 " id="polygon1768" transform="matrix(0.67523047,0,0,0.67523047,117.69293,49.286325)" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2"/>
|
|
||||||
<polygon points="70,50 60,40 60,20 70,10 80,20 80,40 " id="polygon1770" transform="matrix(0.67523047,0,0,0.67523047,119.69293,51.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
|
||||||
<polygon points="60,60 70,50 80,60 80,80 70,90 60,80 " id="polygon1772" transform="matrix(0.67523047,0,0,0.67523047,119.69293,55.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
|
||||||
<polygon points="20,100 10,90 20,80 60,80 70,90 60,100 " id="polygon1774" transform="matrix(0.67523047,0,0,0.67523047,117.69293,57.286325)" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2"/>
|
|
||||||
<polygon points="0,50 10,60 10,80 0,90 -10,80 -10,60 " id="polygon1776" transform="matrix(0.67523047,0,0,0.67523047,122.44524,55.286325)" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2"/>
|
|
||||||
<polygon points="-10,20 0,10 10,20 10,40 0,50 -10,40 " id="polygon1778" transform="matrix(0.67523047,0,0,0.67523047,122.44524,51.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
|
||||||
<polygon points="70,50 60,60 20,60 10,50 20,40 60,40 " id="polygon1780" transform="matrix(0.67523047,0,0,0.67523047,117.69293,53.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
|
||||||
</g>
|
|
||||||
<g id="g1800" transform="translate(47.970487,-113.03641)">
|
|
||||||
<polygon points="60,20 20,20 10,10 20,0 60,0 70,10 " id="polygon1786" transform="matrix(0.67523047,0,0,0.67523047,117.69293,49.286325)" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2"/>
|
|
||||||
<polygon points="60,40 60,20 70,10 80,20 80,40 70,50 " id="polygon1788" transform="matrix(0.67523047,0,0,0.67523047,119.69293,51.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
|
||||||
<polygon points="70,50 80,60 80,80 70,90 60,80 60,60 " id="polygon1790" transform="matrix(0.67523047,0,0,0.67523047,119.69293,55.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
|
||||||
<polygon points="10,90 20,80 60,80 70,90 60,100 20,100 " id="polygon1792" transform="matrix(0.67523047,0,0,0.67523047,117.69293,57.286325)" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2"/>
|
|
||||||
<polygon points="10,60 10,80 0,90 -10,80 -10,60 0,50 " id="polygon1794" transform="matrix(0.67523047,0,0,0.67523047,122.44524,55.286325)" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2"/>
|
|
||||||
<polygon points="0,10 10,20 10,40 0,50 -10,40 -10,20 " id="polygon1796" transform="matrix(0.67523047,0,0,0.67523047,122.44524,51.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
|
||||||
<polygon points="60,60 20,60 10,50 20,40 60,40 70,50 " id="polygon1798" transform="matrix(0.67523047,0,0,0.67523047,117.69293,53.286325)" style="fill:#76b043;stroke:none;stroke-width:2"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
</g>
|
||||||
|
<g id="g561" display="inline">
|
||||||
|
<path
|
||||||
|
fill="#48484a"
|
||||||
|
d="m 501.16,142.979 c -4.11,0 -8.124,0.403 -12.017,1.146 -14.397,-26.528 -42.494,-44.539 -74.798,-44.539 -41.217,0 -75.58,29.322 -83.381,68.243 -1.451,-0.123 -2.914,-0.2 -4.396,-0.2 -28.181,0 -51.027,22.845 -51.027,51.026 0,28.18 22.847,51.026 51.027,51.026 14.838,0 159.491,-10e-4 174.591,-10e-4 35.229,0 63.787,-27.689 63.787,-62.916 10e-4,-35.225 -28.557,-63.785 -63.786,-63.785 M 386.432,248.707 c -0.824,0.825 -2.157,0.825 -2.987,0 l -17.897,-17.899 c -0.818,-0.816 -0.818,-2.136 -0.005,-2.962 0.005,-0.008 0.005,-0.011 0.011,-0.019 0.006,-0.002 0.01,-0.002 0.017,-0.01 l 52.177,-52.177 20.877,20.876 z m 86.558,-62.709 c -0.021,0.018 -0.025,0.045 -0.043,0.063 -0.02,0.02 -0.045,0.022 -0.064,0.041 l -17.811,17.813 c -0.018,0.019 -0.023,0.046 -0.041,0.061 -0.02,0.02 -0.045,0.026 -0.064,0.045 -0.815,0.758 -2.064,0.754 -2.877,-0.012 -0.012,-0.014 -0.035,-0.018 -0.047,-0.033 -0.012,-0.012 -0.019,-0.033 -0.032,-0.046 l -49.265,-49.265 c -0.014,-0.016 -0.035,-0.02 -0.048,-0.034 -0.013,-0.011 -0.019,-0.034 -0.032,-0.049 -0.783,-0.826 -0.779,-2.121 0.032,-2.929 0.31,-0.312 0.698,-0.465 1.093,-0.543 l 0.004,-0.039 30.859,-5.149 0.035,0.034 c 0.607,-0.061 1.232,0.107 1.704,0.578 l 36.547,36.548 c 0.809,0.811 0.82,2.087 0.05,2.916"
|
||||||
|
/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user