mirror of
https://github.com/kevinveenbirkenbach/homepage.veen.world.git
synced 2025-06-28 23:55:31 +02:00
Compare commits
3 Commits
3c240fc16b
...
96ab80eaf2
Author | SHA1 | Date | |
---|---|---|---|
96ab80eaf2 | |||
1fc9176000 | |||
f7282eba73 |
12
README.md
12
README.md
@ -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
|
||||||
```
|
```
|
||||||
@ -32,4 +32,6 @@ docker run -d -p 5000:5000 --name landingpage application-landingpage
|
|||||||
### Debug
|
### Debug
|
||||||
```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]()
|
||||||
|
@ -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:
|
||||||
|
@ -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 }}
|
||||||
|
@ -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])}. "
|
||||||
@ -74,9 +76,9 @@ class ConfigurationResolver:
|
|||||||
f"Invalid path segment '{part}'. Current type: {type(current)}. "
|
f"Invalid path segment '{part}'. Current type: {type(current)}. "
|
||||||
f"Path so far: {' > '.join(parts[:parts.index(part)+1])}"
|
f"Path so far: {' > '.join(parts[:parts.index(part)+1])}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user