From e48cf69b5de6c3d37b02a141961bbd131d1e0fad Mon Sep 17 00:00:00 2001 From: "matthias.lotz" Date: Mon, 24 Nov 2025 20:55:33 +0100 Subject: [PATCH] update pre commit skript, and responsive menu --- docker/prod/backend/Dockerfile | 2 +- docker/prod/docker-compose.yml | 2 +- .../Components/ComponentUtils/Css/Navbar.css | 36 +++++++++- .../ComponentUtils/Headers/Navbar.js | 71 +++++++++++++++---- .../ComponentUtils/Headers/NavbarUpload.js | 57 ++++++++++++--- scripts/git-hooks/pre-commit | 70 +++++++++++++----- 6 files changed, 195 insertions(+), 43 deletions(-) diff --git a/docker/prod/backend/Dockerfile b/docker/prod/backend/Dockerfile index 454ff6b..9dc3821 100644 --- a/docker/prod/backend/Dockerfile +++ b/docker/prod/backend/Dockerfile @@ -15,7 +15,7 @@ RUN npm install --production COPY backend/src ./src # Copy production environment configuration -#COPY docker/prod/backend/config/.env ./.env +# COPY docker/prod/backend/config/.env ./.env # Create data directories for file storage RUN mkdir -p src/data/images src/data/previews src/data/groups diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml index e835e51..7aba6d9 100644 --- a/docker/prod/docker-compose.yml +++ b/docker/prod/docker-compose.yml @@ -36,7 +36,7 @@ services: environment: - REMOVE_IMAGES=false - NODE_ENV=production - - ADMIN_SESSION_SECRET=MvFhivVIPIXvSGvWGfGOiQCkUJrmUsjWQTNGUgnSmtpsGHQlKruTBEBZgbVvOHHr + - ADMIN_SESSION_SECRET=${ADMIN_SESSION_SECRET} - ADMIN_SESSION_DIR=/usr/src/app/src/data/sessions # ⚠️ Für HTTP-only Labs per Override auf "false" setzen (nicht im Repo committen) - ADMIN_SESSION_COOKIE_SECURE=true diff --git a/frontend/src/Components/ComponentUtils/Css/Navbar.css b/frontend/src/Components/ComponentUtils/Css/Navbar.css index d7b834d..f7f7f88 100644 --- a/frontend/src/Components/ComponentUtils/Css/Navbar.css +++ b/frontend/src/Components/ComponentUtils/Css/Navbar.css @@ -77,6 +77,38 @@ header { .menu { display: none; + flex-direction: column; + justify-content: center; + gap: 6px; + background: none; + border: none; + padding: 10px; + cursor: pointer; +} + +.menu span { + width: 28px; + height: 3px; + background-color: #edf0f1; + transition: transform 0.3s ease, opacity 0.3s ease; + display: block; +} + +.menu:focus-visible { + outline: 2px solid #edf0f1; + border-radius: 4px; +} + +.menu--open span:nth-child(1) { + transform: translateY(9px) rotate(45deg); +} + +.menu--open span:nth-child(2) { + opacity: 0; +} + +.menu--open span:nth-child(3) { + transform: translateY(-9px) rotate(-45deg); } .overlay { @@ -121,6 +153,8 @@ header { font-size: 60px; color: #edf0f1; cursor: pointer; + background: none; + border: none; } @media screen and (max-height: 450px) { @@ -140,6 +174,6 @@ header { display: none; } .menu { - display: initial; + display: flex; } } diff --git a/frontend/src/Components/ComponentUtils/Headers/Navbar.js b/frontend/src/Components/ComponentUtils/Headers/Navbar.js index e8441b7..2063628 100644 --- a/frontend/src/Components/ComponentUtils/Headers/Navbar.js +++ b/frontend/src/Components/ComponentUtils/Headers/Navbar.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { NavLink, useLocation } from 'react-router-dom' import '../Css/Navbar.css' @@ -9,22 +9,67 @@ import { Lock as LockIcon } from '@mui/icons-material'; function Navbar() { const location = useLocation(); const isManagementPage = location.pathname.startsWith('/manage/'); + const [menuOpen, setMenuOpen] = useState(false); + + useEffect(() => { + setMenuOpen(false); + }, [location.pathname]); + + const toggleMenu = () => setMenuOpen(prev => !prev); + const closeMenu = () => setMenuOpen(false); return ( -
-
Logo

Upload your Project Images

- -
+ About + + + ) } diff --git a/frontend/src/Components/ComponentUtils/Headers/NavbarUpload.js b/frontend/src/Components/ComponentUtils/Headers/NavbarUpload.js index 454b2d6..b6966a9 100644 --- a/frontend/src/Components/ComponentUtils/Headers/NavbarUpload.js +++ b/frontend/src/Components/ComponentUtils/Headers/NavbarUpload.js @@ -1,24 +1,59 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { NavLink, useLocation } from 'react-router-dom' import '../Css/Navbar.css' import logo from '../../../Images/logo.png' -import { Lock as LockIcon } from '@mui/icons-material'; function Navbar() { const location = useLocation(); - const isManagementPage = location.pathname.startsWith('/manage/'); + const [menuOpen, setMenuOpen] = useState(false); + + useEffect(() => { + setMenuOpen(false); + }, [location.pathname]); + + const toggleMenu = () => setMenuOpen(prev => !prev); + const closeMenu = () => setMenuOpen(false); return ( -
-
Logo

Upload your Project Images

- -
+ <> +
+
+ + Logo +

Upload your Project Images

+
+
+ +
+
+ +
+ About +
+
+ ) } diff --git a/scripts/git-hooks/pre-commit b/scripts/git-hooks/pre-commit index 5577d76..5cb1636 100755 --- a/scripts/git-hooks/pre-commit +++ b/scripts/git-hooks/pre-commit @@ -5,6 +5,9 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" TARGET_FILE="$ROOT_DIR/docker/prod/docker-compose.yml" ANCHOR_LINE=" - ADMIN_SESSION_DIR=/usr/src/app/src/data/sessions" EXPECTED_LINE=" - ADMIN_SESSION_COOKIE_SECURE=true" +SECRET_ANCHOR_LINE=' - NODE_ENV=production' +SECRET_EXPECTED_LINE=' - ADMIN_SESSION_SECRET=${ADMIN_SESSION_SECRET}' +SECRET_VALUE='${ADMIN_SESSION_SECRET}' if [[ ! -f "$TARGET_FILE" ]]; then exit 0 @@ -13,6 +16,9 @@ fi export TARGET_FILE export ANCHOR_LINE export EXPECTED_LINE +export SECRET_ANCHOR_LINE +export SECRET_EXPECTED_LINE +export SECRET_VALUE result=$(python3 <<'PY' import os @@ -23,30 +29,62 @@ import sys path = pathlib.Path(os.environ['TARGET_FILE']) anchor = os.environ['ANCHOR_LINE'] expected = os.environ['EXPECTED_LINE'] +secret_anchor = os.environ['SECRET_ANCHOR_LINE'] +secret_expected = os.environ['SECRET_EXPECTED_LINE'] +secret_value = os.environ['SECRET_VALUE'] + text = path.read_text() +new_text = text changed = False -if 'ADMIN_SESSION_COOKIE_SECURE' in text: - pattern = re.compile(r'(\-\s*ADMIN_SESSION_COOKIE_SECURE\s*=\s*)([^\n\r]+)') - new_text, count = pattern.subn(r'\1true', text, count=1) - if count: - changed = new_text != text -else: - if anchor not in text: - print('ERROR: Anchor line not found for ADMIN_SESSION_COOKIE_SECURE insertion', file=sys.stderr) - sys.exit(2) - new_text = text.replace(anchor, anchor + '\n' + expected, 1) - changed = True +cookie_pattern = re.compile(r'(\-\s*ADMIN_SESSION_COOKIE_SECURE\s*=\s*)([^\n\r]+)') +secret_pattern = re.compile(r'(\-\s*ADMIN_SESSION_SECRET\s*=\s*)([^\n\r]+)') + +def ensure_entry(text, *, pattern, value, anchor_line, expected_line, label): + match = pattern.search(text) + if match: + desired = f"{match.group(1)}{value}" + if match.group(0) == desired: + return text, False + return pattern.sub(lambda m: f"{m.group(1)}{value}", text, count=1), True + if anchor_line not in text: + print(f"ERROR: Anchor line not found for {label}", file=sys.stderr) + sys.exit(2) + return text.replace(anchor_line, anchor_line + '\n' + expected_line, 1), True + +new_text, cookie_changed = ensure_entry( + new_text, + pattern=cookie_pattern, + value='true', + anchor_line=anchor, + expected_line=expected, + label='ADMIN_SESSION_COOKIE_SECURE' +) +changed = changed or cookie_changed if expected not in new_text: - print('ERROR: Failed to ensure ADMIN_SESSION_COOKIE_SECURE=true in docker-compose.yml', file=sys.stderr) - sys.exit(3) + print('ERROR: Failed to ensure ADMIN_SESSION_COOKIE_SECURE=true in docker-compose.yml', file=sys.stderr) + sys.exit(3) + +new_text, secret_changed = ensure_entry( + new_text, + pattern=secret_pattern, + value=secret_value, + anchor_line=secret_anchor, + expected_line=secret_expected, + label='ADMIN_SESSION_SECRET' +) +changed = changed or secret_changed + +if secret_expected not in new_text: + print('ERROR: Failed to ensure ADMIN_SESSION_SECRET uses environment variable in docker-compose.yml', file=sys.stderr) + sys.exit(4) if changed: - path.write_text(new_text) - print('UPDATED') + path.write_text(new_text) + print('UPDATED') else: - print('UNCHANGED') + print('UNCHANGED') PY ) status=$?