mirror of
				https://github.com/kevinveenbirkenbach/homepage.veen.world.git
				synced 2025-11-04 01:18:09 +00:00 
			
		
		
		
	Replaced German by English comments
This commit is contained in:
		@@ -15,7 +15,6 @@ cache_manager.clear_cache()
 | 
			
		||||
 | 
			
		||||
def load_config(app):
 | 
			
		||||
    """Load and resolve the configuration."""
 | 
			
		||||
    # Lade die Konfigurationsdatei
 | 
			
		||||
    with open("config.yaml", "r") as f:
 | 
			
		||||
        config = yaml.safe_load(f)
 | 
			
		||||
 | 
			
		||||
@@ -28,7 +27,7 @@ def load_config(app):
 | 
			
		||||
app = Flask(__name__)
 | 
			
		||||
load_config(app)
 | 
			
		||||
 | 
			
		||||
# Hole die Umgebungsvariable FLASK_ENV oder setze einen Standardwert
 | 
			
		||||
# Get the environment variable FLASK_ENV or set a default value
 | 
			
		||||
FLASK_ENV = os.getenv("FLASK_ENV", "production")
 | 
			
		||||
    
 | 
			
		||||
@app.before_request
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,11 @@
 | 
			
		||||
/* Den scroll-container so einstellen, dass er nur vertikal scrollt */
 | 
			
		||||
/* Set the scroll container to only scroll vertically */
 | 
			
		||||
.scroll-container {
 | 
			
		||||
    overflow-y: auto;
 | 
			
		||||
    overflow-x: hidden;
 | 
			
		||||
    /* Native Scrollbar ausblenden */
 | 
			
		||||
    /* Hide native scrollbar */
 | 
			
		||||
    scrollbar-width: none; /* Firefox */
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.scroll-container::-webkit-scrollbar {
 | 
			
		||||
    display: none; /* WebKit */
 | 
			
		||||
}
 | 
			
		||||
@@ -14,13 +15,13 @@
 | 
			
		||||
    top: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
    width: 8px;
 | 
			
		||||
    /* height: 100vh;  <-- diese Zeile entfernen oder anpassen */
 | 
			
		||||
    /* height: 100vh;  <-- remove or adjust this line */
 | 
			
		||||
    background: transparent;
 | 
			
		||||
    transition: opacity 0.3s ease;
 | 
			
		||||
    opacity: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Der Thumb der Scrollbar */
 | 
			
		||||
/* The scrollbar thumb */
 | 
			
		||||
#scroll-thumb {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 0;
 | 
			
		||||
@@ -28,4 +29,3 @@
 | 
			
		||||
    background-color: rgba(0, 0, 0, 0.2);
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
@@ -24,7 +24,7 @@ a {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Subtle shadow effect */
 | 
			
		||||
.navbar, .card, .dropdown-menu{
 | 
			
		||||
.navbar, .card, .dropdown-menu {
 | 
			
		||||
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -85,26 +85,26 @@ h3.footer-title {
 | 
			
		||||
  font-size: 1.3em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.card-img-top i{
 | 
			
		||||
.card-img-top i {
 | 
			
		||||
  font-size: 100px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div#navbarNavheader li.nav-item{
 | 
			
		||||
div#navbarNavheader li.nav-item {
 | 
			
		||||
  margin-left: 6px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div#navbarNavfooter li.nav-item{
 | 
			
		||||
div#navbarNavfooter li.nav-item {
 | 
			
		||||
  margin-right: 6px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
main {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  box-shadow: 
 | 
			
		||||
    /* Innerer Schatten */
 | 
			
		||||
    inset 10px 0 10px -10px rgba(0, 0, 0, 0.3),  /* linker innerer Schatten */
 | 
			
		||||
    inset -10px 0 10px -10px rgba(0, 0, 0, 0.3), /* rechter innerer Schatten */
 | 
			
		||||
    /* Äußerer Schatten */
 | 
			
		||||
    10px 0 10px -10px rgba(0, 0, 0, 0.3),  /* rechter äußerer Schatten */
 | 
			
		||||
    -10px 0 10px -10px rgba(0, 0, 0, 0.3); /* linker äußerer Schatten */
 | 
			
		||||
    /* Inner shadow */
 | 
			
		||||
    inset 10px 0 10px -10px rgba(0, 0, 0, 0.3),  /* Left inner shadow */
 | 
			
		||||
    inset -10px 0 10px -10px rgba(0, 0, 0, 0.3), /* Right inner shadow */
 | 
			
		||||
    /* Outer shadow */
 | 
			
		||||
    10px 0 10px -10px rgba(0, 0, 0, 0.3),  /* Right outer shadow */
 | 
			
		||||
    -10px 0 10px -10px rgba(0, 0, 0, 0.3); /* Left outer shadow */
 | 
			
		||||
  overflow: visible;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,20 @@
 | 
			
		||||
/* Top-Level Dropdown-Menü */
 | 
			
		||||
/* Top-level dropdown menu */
 | 
			
		||||
.nav-item .dropdown-menu {
 | 
			
		||||
    position: absolute; /* Wichtig für Positionierung */
 | 
			
		||||
    top: 100%; /* Standardmäßige Öffnung nach unten */
 | 
			
		||||
    position: absolute; /* Important for positioning */
 | 
			
		||||
    top: 100%; /* Default opening direction: downwards */
 | 
			
		||||
    left: 0;
 | 
			
		||||
    z-index: 1050; /* Damit das Menü über anderen Elementen liegt */
 | 
			
		||||
    z-index: 1050; /* Ensures the menu appears above other elements */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Submenu-Position */
 | 
			
		||||
/* Submenu position */
 | 
			
		||||
.dropdown-submenu > .dropdown-menu {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    left: 100%; /* Öffnen nach rechts */
 | 
			
		||||
    left: 100%; /* Opens to the right */
 | 
			
		||||
    z-index: 1050;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Sicherstellen, dass der Übergang smooth ist */
 | 
			
		||||
/* Ensure a smooth transition */
 | 
			
		||||
.dropdown-menu {
 | 
			
		||||
    transition: all 0.3s ease-in-out;
 | 
			
		||||
}
 | 
			
		||||
@@ -22,9 +22,9 @@
 | 
			
		||||
nav.navbar.menu-header {
 | 
			
		||||
    border-bottom-left-radius: 0;
 | 
			
		||||
    border-bottom-right-radius: 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
nav.navbar.menu-footer {
 | 
			
		||||
    border-top-left-radius: 0;
 | 
			
		||||
    border-top-right-radius: 0;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,25 +15,24 @@ function adjustScrollContainerHeight() {
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  
 | 
			
		||||
  // Berechne die verfügbare Höhe für den Scrollbereich
 | 
			
		||||
  // Calculate the available height for the scroll area
 | 
			
		||||
  const availableHeight = window.innerHeight - siblingsHeight;
 | 
			
		||||
  scrollContainer.style.maxHeight = availableHeight + 'px';
 | 
			
		||||
  scrollContainer.style.overflowY = 'auto';
 | 
			
		||||
  scrollContainer.style.overflowX = 'hidden';
 | 
			
		||||
 | 
			
		||||
  // Hole die aktuelle Position und Höhe des Scrollbereichs
 | 
			
		||||
  // Get the current position and height of the scroll container
 | 
			
		||||
  const scrollContainerRect = scrollContainer.getBoundingClientRect();
 | 
			
		||||
 | 
			
		||||
  // Setze die Position (top) und die Höhe des benutzerdefinierten Scrollbar-Tracks
 | 
			
		||||
  // Set the position (top) and height of the custom scrollbar track
 | 
			
		||||
  scrollbarContainer.style.top = scrollContainerRect.top + 'px';
 | 
			
		||||
  scrollbarContainer.style.height = scrollContainerRect.height + 'px';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
window.addEventListener('load', adjustScrollContainerHeight);
 | 
			
		||||
window.addEventListener('resize', adjustScrollContainerHeight);
 | 
			
		||||
 | 
			
		||||
// 2. Aktualisiert den Thumb (Größe und Position) der benutzerdefinierten Scrollbar
 | 
			
		||||
// 2. Updates the thumb (size and position) of the custom scrollbar
 | 
			
		||||
function updateCustomScrollbar() {
 | 
			
		||||
  const scrollContainer = document.querySelector('.scroll-container');
 | 
			
		||||
  const thumb = document.getElementById('scroll-thumb');
 | 
			
		||||
@@ -44,22 +43,22 @@ function updateCustomScrollbar() {
 | 
			
		||||
  const containerHeight = scrollContainer.clientHeight;
 | 
			
		||||
  const scrollTop = scrollContainer.scrollTop;
 | 
			
		||||
  
 | 
			
		||||
  // Berechne die Thumb-Höhe (mindestens 20px)
 | 
			
		||||
  // Calculate the thumb height (minimum 20px)
 | 
			
		||||
  let thumbHeight = (containerHeight / contentHeight) * containerHeight;
 | 
			
		||||
  thumbHeight = Math.max(thumbHeight, 20);
 | 
			
		||||
  thumb.style.height = thumbHeight + 'px';
 | 
			
		||||
  
 | 
			
		||||
  // Berechne die Position des Thumbs
 | 
			
		||||
  // Calculate the thumb position
 | 
			
		||||
  const maxScrollTop = contentHeight - containerHeight;
 | 
			
		||||
  const maxThumbTop = containerHeight - thumbHeight;
 | 
			
		||||
  const thumbTop = maxScrollTop ? (scrollTop / maxScrollTop) * maxThumbTop : 0;
 | 
			
		||||
  thumb.style.top = thumbTop + 'px';
 | 
			
		||||
  
 | 
			
		||||
  // Zeige die Scrollbar, falls der Inhalt überläuft, sonst ggf. ausblenden
 | 
			
		||||
  // Show the scrollbar if content overflows, otherwise hide it
 | 
			
		||||
  customScrollbar.style.opacity = contentHeight > containerHeight ? '1' : '0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Aktualisiere den Thumb bei Scrollen des Containers
 | 
			
		||||
// Update the thumb when the container is scrolled
 | 
			
		||||
const scrollContainer = document.querySelector('.scroll-container');
 | 
			
		||||
if (scrollContainer) {
 | 
			
		||||
  scrollContainer.addEventListener('scroll', updateCustomScrollbar);
 | 
			
		||||
@@ -67,7 +66,7 @@ if (scrollContainer) {
 | 
			
		||||
window.addEventListener('resize', updateCustomScrollbar);
 | 
			
		||||
window.addEventListener('load', updateCustomScrollbar);
 | 
			
		||||
 | 
			
		||||
// 3. Interaktivität: Ermögliche Drag & Drop des Scroll-Thumbs
 | 
			
		||||
// 3. Interactivity: Enable drag & drop for the scroll thumb
 | 
			
		||||
let isDragging = false;
 | 
			
		||||
let dragStartY = 0;
 | 
			
		||||
let scrollStartY = 0;
 | 
			
		||||
@@ -93,11 +92,11 @@ document.addEventListener('mousemove', function(e) {
 | 
			
		||||
  const maxThumbTop = containerHeight - thumbHeight;
 | 
			
		||||
  
 | 
			
		||||
  const deltaY = e.clientY - dragStartY;
 | 
			
		||||
  // Berechne neuen Thumb-Top-Wert
 | 
			
		||||
  // Calculate the new thumb top position
 | 
			
		||||
  let newThumbTop = (scrollStartY / maxScrollTop) * maxThumbTop + deltaY;
 | 
			
		||||
  newThumbTop = Math.max(0, Math.min(newThumbTop, maxThumbTop));
 | 
			
		||||
  
 | 
			
		||||
  // Berechne den neuen Scrollwert anhand der Thumb-Position
 | 
			
		||||
  // Calculate the new scroll position based on the thumb position
 | 
			
		||||
  const newScrollTop = (newThumbTop / maxThumbTop) * maxScrollTop;
 | 
			
		||||
  scrollContainer.scrollTop = newScrollTop;
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -17,15 +17,15 @@ document.addEventListener('DOMContentLoaded', () => {
 | 
			
		||||
        }, 500);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Öffnen beim Hovern
 | 
			
		||||
      // Open on hover
 | 
			
		||||
      item.addEventListener('mouseenter', onMouseEnter);
 | 
			
		||||
 | 
			
		||||
      // Verzögertes Schließen beim Verlassen
 | 
			
		||||
      // Delayed close on mouse leave
 | 
			
		||||
      item.addEventListener('mouseleave', onMouseLeave);
 | 
			
		||||
 | 
			
		||||
      // Öffnen und Position anpassen beim Klicken
 | 
			
		||||
      // Open and adjust position on click
 | 
			
		||||
      item.addEventListener('click', (e) => {
 | 
			
		||||
        e.stopPropagation(); // Verhindert das Schließen von Menüs bei Klick
 | 
			
		||||
        e.stopPropagation(); // Prevents menus from closing when clicking inside
 | 
			
		||||
        if (item.classList.contains('open')) {
 | 
			
		||||
          closeMenu(item);
 | 
			
		||||
        } else {
 | 
			
		||||
@@ -44,7 +44,7 @@ document.addEventListener('DOMContentLoaded', () => {
 | 
			
		||||
 | 
			
		||||
  addAllMenuEventListeners();
 | 
			
		||||
 | 
			
		||||
  // Globale Klick-Listener, um Menüs zu schließen, wenn außerhalb geklickt wird
 | 
			
		||||
  // Global click listener to close menus when clicking outside
 | 
			
		||||
  document.addEventListener('click', () => {
 | 
			
		||||
    [...menuItems, ...subMenuItems].forEach(item => closeMenu(item));
 | 
			
		||||
  });
 | 
			
		||||
@@ -70,11 +70,11 @@ document.addEventListener('DOMContentLoaded', () => {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
function isSmallScreen() {
 | 
			
		||||
  return window.innerWidth < 992; // Bootstrap-Breakpoint für 'lg'
 | 
			
		||||
}
 | 
			
		||||
  function isSmallScreen() {
 | 
			
		||||
    return window.innerWidth < 992; // Bootstrap breakpoint for 'lg'
 | 
			
		||||
  }
 | 
			
		||||
    
 | 
			
		||||
function adjustMenuPosition(submenu, parent, isTopLevel) {
 | 
			
		||||
  function adjustMenuPosition(submenu, parent, isTopLevel) {
 | 
			
		||||
    const rect = submenu.getBoundingClientRect();
 | 
			
		||||
    const parentRect = parent.getBoundingClientRect();
 | 
			
		||||
 | 
			
		||||
@@ -89,33 +89,33 @@ function adjustMenuPosition(submenu, parent, isTopLevel) {
 | 
			
		||||
    submenu.style.right = '';
 | 
			
		||||
 | 
			
		||||
    if (isTopLevel) {
 | 
			
		||||
      if (isSmallScreen && spaceBelow < spaceAbove) {
 | 
			
		||||
        // Für kleine Bildschirme: Menü direkt über dem Eltern-Element öffnen
 | 
			
		||||
      if (isSmallScreen() && spaceBelow < spaceAbove) {
 | 
			
		||||
        // For small screens: Open menu directly above the parent element
 | 
			
		||||
        submenu.style.top = 'auto';
 | 
			
		||||
        submenu.style.bottom = `${parentRect.height}px`; // Direkt über dem Eltern-Element
 | 
			
		||||
        submenu.style.bottom = `${parentRect.height}px`; // Directly above the parent element
 | 
			
		||||
      } 
 | 
			
		||||
        // Top-Level-Menü
 | 
			
		||||
        else if (spaceBelow < spaceAbove) {
 | 
			
		||||
            submenu.style.bottom = `${window.innerHeight - parentRect.bottom - parentRect.height}px`;
 | 
			
		||||
            submenu.style.top = 'auto';
 | 
			
		||||
        } else {
 | 
			
		||||
            submenu.style.top = `${parentRect.height}px`;
 | 
			
		||||
            submenu.style.bottom = 'auto';
 | 
			
		||||
        }
 | 
			
		||||
      // Top-level menu
 | 
			
		||||
      else if (spaceBelow < spaceAbove) {
 | 
			
		||||
        submenu.style.bottom = `${window.innerHeight - parentRect.bottom - parentRect.height}px`;
 | 
			
		||||
        submenu.style.top = 'auto';
 | 
			
		||||
      } else {
 | 
			
		||||
        submenu.style.top = `${parentRect.height}px`;
 | 
			
		||||
        submenu.style.bottom = 'auto';
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
        // Submenü
 | 
			
		||||
        const prefersRight = spaceRight >= spaceLeft;
 | 
			
		||||
        submenu.style.left = prefersRight ? '100%' : 'auto';
 | 
			
		||||
        submenu.style.right = prefersRight ? 'auto' : '100%';
 | 
			
		||||
      // Submenu
 | 
			
		||||
      const prefersRight = spaceRight >= spaceLeft;
 | 
			
		||||
      submenu.style.left = prefersRight ? '100%' : 'auto';
 | 
			
		||||
      submenu.style.right = prefersRight ? 'auto' : '100%';
 | 
			
		||||
 | 
			
		||||
        // Nach oben öffnen, wenn unten kein Platz ist
 | 
			
		||||
        if (spaceBelow < spaceAbove) {
 | 
			
		||||
            submenu.style.bottom = `0`;
 | 
			
		||||
            submenu.style.top = `auto`;
 | 
			
		||||
        } else {
 | 
			
		||||
            submenu.style.top = `0`;
 | 
			
		||||
            submenu.style.bottom = '${parentRect.height}px';
 | 
			
		||||
        }
 | 
			
		||||
      // Open upwards if there's no space below
 | 
			
		||||
      if (spaceBelow < spaceAbove) {
 | 
			
		||||
        submenu.style.bottom = `0`;
 | 
			
		||||
        submenu.style.top = `auto`;
 | 
			
		||||
      } else {
 | 
			
		||||
        submenu.style.top = `0`;
 | 
			
		||||
        submenu.style.bottom = `${parentRect.height}px`;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// Initialisiert alle Tooltips auf der Seite
 | 
			
		||||
// Initializes all tooltips on the page
 | 
			
		||||
document.addEventListener('DOMContentLoaded', function () {
 | 
			
		||||
    var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
 | 
			
		||||
    tooltipTriggerList.forEach(function (tooltipTriggerEl) {
 | 
			
		||||
        new bootstrap.Tooltip(tooltipTriggerEl);
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,6 @@
 | 
			
		||||
            {% include "moduls/navigation.html.j2"%}
 | 
			
		||||
            <main id="main">
 | 
			
		||||
            <div class="scroll-container">
 | 
			
		||||
                <!-- Hier kommt dein Hauptinhalt -->
 | 
			
		||||
                {% block content %}{% endblock %}
 | 
			
		||||
            </div>
 | 
			
		||||
            </main>
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ def compute_card_classes(cards):
 | 
			
		||||
    elif num_cards % 2 == 0:
 | 
			
		||||
        lg_classes = ["col-lg-6"] * num_cards
 | 
			
		||||
    else:
 | 
			
		||||
        # Für komplexe Fälle (z. B. 5, 7, 11) – Stelle sicher, dass mindestens 3 pro Zeile erscheinen
 | 
			
		||||
        # For complex cases (e.g., 5, 7, 11) – Ensure at least 3 per row
 | 
			
		||||
        for i in range(num_cards):
 | 
			
		||||
            if num_cards % 4 == 3:
 | 
			
		||||
                if i < 3:
 | 
			
		||||
@@ -32,11 +32,11 @@ def compute_card_classes(cards):
 | 
			
		||||
                    lg_classes.append("col-lg-6")
 | 
			
		||||
                else:
 | 
			
		||||
                    lg_classes.append("col-lg-4")
 | 
			
		||||
    # md-Klassen: Wenn die Anzahl der Karten gerade ist oder wenn nicht die letzte Karte, ansonsten "col-md-12"
 | 
			
		||||
    # md classes: If the number of cards is even or if not the last card, otherwise "col-md-12"
 | 
			
		||||
    md_classes = []
 | 
			
		||||
    for i in range(num_cards):
 | 
			
		||||
        if num_cards % 2 == 0 or i < num_cards - 1:
 | 
			
		||||
            md_classes.append("col-md-6")
 | 
			
		||||
        else:
 | 
			
		||||
            md_classes.append("col-md-12")
 | 
			
		||||
    return lg_classes, md_classes
 | 
			
		||||
    return lg_classes, md_classes
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user