Compare commits

..

3 Commits

4 changed files with 34 additions and 31 deletions

View File

@ -1,7 +1,7 @@
# Landingpage # Landingpage
## Access ## Access
### Locale
http://127.0.0.1:5000 http://127.0.0.1:5000
@ -19,12 +19,12 @@ docker build -t application-landingpage .
### Run ### Run
#### Development #### Run Development Environment
```bash ```bash
sudo docker run -d -p 5000:5000 --name landingpage -v $(pwd)/app/:/app -e FLASK_APP=app.py -e FLASK_ENV=development application-landingpage docker run -d -p 5000:5000 --name landingpage -v $(pwd)/app/:/app -e FLASK_APP=app.py -e FLASK_ENV=development application-landingpage
``` ```
#### Production #### Run Production Environment
```bash ```bash
docker run -d -p 5000:5000 --name landingpage application-landingpage docker run -d -p 5000:5000 --name landingpage application-landingpage
``` ```
@ -33,3 +33,5 @@ docker run -d -p 5000:5000 --name landingpage application-landingpage
```bash ```bash
docker logs -f landingpage docker logs -f landingpage
``` ```
## Author
This software was created from [Kevin Veen-Birkenbach](https://www.veen.world/) with the help of [ChatGPT]()

View File

@ -240,12 +240,10 @@ navigation:
class: fa-brands fa-whatsapp class: fa-brands fa-whatsapp
url: https://wa.me/491781798023 url: https://wa.me/491781798023
identifier: "+491781798023" identifier: "+491781798023"
warning: |
⚠️ **Caution with Meta Services**
Using software and platforms from the Meta corporation (e.g., Facebook, Instagram, WhatsApp) may compromise your data privacy and digital freedom due to centralized control, extensive data collection practices, and inconsistent moderation policies. These platforms often fail to adequately address harmful content, misinformation, and abuse.
📌 **Recommendation:** Consider using decentralized and privacy-respecting alternatives to maintain control over your data, improve security, and foster healthier online interactions.
alternatives: alternatives:
- link: navigation.header.contact.matrix - link: navigation.header.contact.matrix
warning: |
Using software and platforms from the Meta corporation (e.g., Facebook, Instagram, WhatsApp) may compromise your data privacy and digital freedom due to centralized control, extensive data collection practices, and inconsistent moderation policies. These platforms often fail to adequately address harmful content, misinformation, and abuse.
footer: footer:
- name: External Accounts - name: External Accounts
@ -257,13 +255,14 @@ navigation:
description: Social and developer networks description: Social and developer networks
icon: icon:
class: fa-brands fa-meta class: fa-brands fa-meta
url:
subitems: subitems:
- name: Instagram - name: Instagram
description: Follow me on Instagram description: Follow me on Instagram
icon: icon:
class: fa-brands fa-instagram class: fa-brands fa-instagram
url: https://www.instagram.com/kevinveenbirkenbach/ url: https://www.instagram.com/kevinveenbirkenbach/
identifier: kevinveenbirkenbach
link: navigation.header.contact.whatsapp.warning
- name: Facebook - name: Facebook
description: Like my Facebook page description: Like my Facebook page
icon: icon:

View File

@ -10,7 +10,7 @@
{{ render_subitems(subitem.subitems) }} {{ render_subitems(subitem.subitems) }}
</ul> </ul>
</li> </li>
{% elif subitem.identifier %} {% elif subitem.identifier or subitem.warning or subitem.info %}
<li> <li>
<a class="dropdown-item" onclick='openDynamicPopup({{ subitem|tojson|safe }})' data-bs-toggle="tooltip" title="{{ subitem.description }}"> <a class="dropdown-item" onclick='openDynamicPopup({{ subitem|tojson|safe }})' data-bs-toggle="tooltip" title="{{ subitem.description }}">
<i class="{{ subitem.icon.class }}"></i> {{ subitem.name }} <i class="{{ subitem.icon.class }}"></i> {{ subitem.name }}

View File

@ -1,9 +1,4 @@
class ConfigurationResolver: class ConfigurationResolver:
"""
A class to resolve `link` entries in a nested configuration structure.
Supports navigation through dictionaries, lists, and `subitems`.
"""
def __init__(self, config): def __init__(self, config):
self.config = config self.config = config
@ -21,15 +16,22 @@ class ConfigurationResolver:
for key, value in list(current_config.items()): for key, value in list(current_config.items()):
if key == "link": if key == "link":
try: try:
target = self._find_entry(root_config, value.lower()) # Attempt to find the target entry in the root configuration
current_config.clear() target = self._find_entry(root_config, value.lower().replace(" ", "_"))
current_config.update(target)
if isinstance(target, dict):
# Replace the current config dictionary with the target dictionary
current_config.clear()
current_config.update(target)
else:
current_config[value.split(".")[-1]] = target
except Exception as e: except Exception as e:
raise ValueError( raise ValueError(
f"Error resolving link '{value}': {str(e)}. " f"Error resolving link '{value}': {str(e)}. "
f"Current path: {key}, Current config: {current_config}" f"Current path: {key}, Current config: {current_config}"
) )
else: else:
# Recurse into nested structures
self._recursive_resolve(value, root_config) self._recursive_resolve(value, root_config)
elif isinstance(current_config, list): elif isinstance(current_config, list):
for item in current_config: for item in current_config:
@ -43,26 +45,26 @@ class ConfigurationResolver:
parts = path.split('.') parts = path.split('.')
current = config current = config
for part in parts: for part in parts:
part = part.replace(" ", "_")
if isinstance(current, list): if isinstance(current, list):
# Look for a matching name in the list # Search for a matching entry in a list
found = next( found = next(
(item for item in current if isinstance(item, dict) and item.get("name", "").lower() == part), (
item
for item in current
if isinstance(item, dict) and item.get("name", "").lower().replace(" ", "_") == part
),
None None
) )
if found: if not found:
print(
f"Matching entry for '{part}' in list. Path so far: {' > '.join(parts[:parts.index(part)+1])}. "
f"Current list: {current}"
)
else:
raise ValueError( raise ValueError(
f"No matching entry for '{part}' in list. Path so far: {' > '.join(parts[:parts.index(part)+1])}. " f"No matching entry for '{part}' in list. Path so far: {' > '.join(parts[:parts.index(part)+1])}. "
f"Current list: {current}" f"Current list: {current}"
) )
current = found current = found
elif isinstance(current, dict): elif isinstance(current, dict):
# Case-insensitive dictionary lookup # Perform a case-insensitive dictionary lookup
key = next((k for k in current if k.lower() == part), None) key = next((k for k in current if k.lower().replace(" ", "_") == part), None)
if key is None: if key is None:
raise KeyError( raise KeyError(
f"Key '{part}' not found in dictionary. Path so far: {' > '.join(parts[:parts.index(part)+1])}. " f"Key '{part}' not found in dictionary. Path so far: {' > '.join(parts[:parts.index(part)+1])}. "
@ -76,7 +78,7 @@ class ConfigurationResolver:
) )
# Navigate into `subitems` if present # Navigate into `subitems` if present
if isinstance(current, dict) and ("subitems" in current and current["subitems"]): if isinstance(current, dict) and "subitems" in current and current["subitems"]:
current = current["subitems"] current = current["subitems"]
return current return current