Merge branch 'experimental/rio' into 'main'

Merge experimental branch

See merge request ezgg/ezgg-website!1
This commit is contained in:
David Rodenkirchen 2024-05-27 17:45:05 +00:00
commit c4c7de1831
36 changed files with 1216 additions and 2 deletions

0
.project-root Normal file
View File

17
Dockerfile Normal file
View File

@ -0,0 +1,17 @@
FROM python:3.12
# Create app directory
WORKDIR /app
# Install app dependencies
COPY requirements.txt ./
RUN pip install -r requirements.txt
COPY ezgg_website ./ezgg_website
COPY rio.toml ./
COPY .project-root ./
EXPOSE 8001
CMD [ "rio", "run", "--release", "--public" ]

View File

@ -1,5 +1,11 @@
# EZ GG Webite # EZ GG Website
## Overview ## Overview
This repository contains the code for the EZ GG e.V. website. This repository contains the code for the EZ GG e.V. website.
## How to install
1. Create a Python VENV with Python version 3.11+
2. Install dependencies via `pip install -r requirements.txt`
3. Run dev mode via `rio run`

159
ezgg_website/__init__.py Normal file
View File

@ -0,0 +1,159 @@
from __future__ import annotations
from pathlib import Path
import rio
from from_root import from_root
from . import pages
from . import components as comps
from . import services
rio.Icon.register_single_icon(
set_name="custom",
icon_name="steam",
icon_source=from_root("ezgg_website/assets/icons/steam.svg")
)
themes = [
# Grey/Purple
rio.Theme.from_colors(
primary_color=rio.Color.from_hex("bb86fc"),
secondary_color=rio.Color.from_hex("6200ee"),
neutral_color=rio.Color.from_hex("1e1e1e"),
background_color=rio.Color.from_hex("121212"),
hud_color=rio.Color.from_hex("bb86fc"),
text_color=rio.Color.from_hex("FFFFFF"),
light=False,
),
# Grey/Turquoise
rio.Theme.from_colors(
primary_color=rio.Color.from_hex("03dac5"),
secondary_color=rio.Color.from_hex("018786"),
neutral_color=rio.Color.from_hex("1e1e1e"),
background_color=rio.Color.from_hex("121212"),
hud_color=rio.Color.from_hex("03dac5"),
text_color=rio.Color.from_hex("FFFFFF"),
light=False,
),
# Grey/Pink
rio.Theme.from_colors(
primary_color=rio.Color.from_hex("fe1f70"),
secondary_color=rio.Color.from_hex("a32263"),
neutral_color=rio.Color.from_hex("1e1e1e"),
background_color=rio.Color.from_hex("121212"),
hud_color=rio.Color.from_hex("fe1f70"),
text_color=rio.Color.from_hex("FFFFFF"),
light=False,
),
# Grey/Red
rio.Theme.from_colors(
primary_color=rio.Color.from_hex("ec1e2a"),
secondary_color=rio.Color.from_hex("9b1725"),
neutral_color=rio.Color.from_hex("1e1e1e"),
background_color=rio.Color.from_hex("121212"),
hud_color=rio.Color.from_hex("ec1e2a"),
text_color=rio.Color.from_hex("FFFFFF"),
light=False,
),
# Grey/Orange
rio.Theme.from_colors(
primary_color=rio.Color.from_hex("ff800d"),
secondary_color=rio.Color.from_hex("ae5714"),
neutral_color=rio.Color.from_hex("1e1e1e"),
background_color=rio.Color.from_hex("121212"),
hud_color=rio.Color.from_hex("ff800d"),
text_color=rio.Color.from_hex("FFFFFF"),
light=False,
),
# Grey/Blue
rio.Theme.from_colors(
primary_color=rio.Color.from_hex("2c89ff"),
secondary_color=rio.Color.from_hex("2376dc"),
neutral_color=rio.Color.from_hex("1e1e1e"),
background_color=rio.Color.from_hex("121212"),
hud_color=rio.Color.from_hex("2c89ff"),
text_color=rio.Color.from_hex("FFFFFF"),
light=False,
),
# Turquoise - Dark
rio.Theme.from_colors(
primary_color=rio.Color.from_hex("03dac5"),
secondary_color=rio.Color.from_hex("018786"),
neutral_color=rio.Color.from_hex("1e1e1e"),
background_color=rio.Color.from_hex("121212"),
hud_color=rio.Color.from_hex("03dac5"),
text_color=rio.Color.from_hex("FFFFFF"),
light=False,
),
# Turquoise - Light
rio.Theme.from_colors(
primary_color=rio.Color.from_hex("03dac5"),
secondary_color=rio.Color.from_hex("018786"),
neutral_color=rio.Color.from_hex("FFFFFF"),
background_color=rio.Color.from_hex("FFFFFF"),
hud_color=rio.Color.from_hex("03dac5"),
text_color=rio.Color.from_hex("000000"),
light=True,
)
]
async def on_session_start(s: rio.Session) -> None:
await s.set_title("EZ GG e.V.")
# Create the Rio app
database_service = services.DatabaseService()
app = rio.App(
name='ezgg-website',
pages=[
rio.Page(
name="Home",
page_url='',
build=pages.Home,
),
rio.Page(
name="About",
page_url='about',
build=pages.About,
),
rio.Page(
name="Member",
page_url='member',
build=lambda: pages.Member(database_service),
),
rio.Page(
name="Constitution",
page_url='constitution',
build=pages.Constitution,
),
rio.Page(
name="Join",
page_url='join',
build=pages.Join,
),
rio.Page(
name="Pics",
page_url='pics',
build=lambda: pages.Pics(database_service),
),
rio.Page(
name="Imprint",
page_url='imprint',
build=pages.Imprint,
),
rio.Page(
name="Privacy",
page_url='privacy',
build=pages.Privacy,
)
],
theme=themes[6],
assets_dir=Path(__file__).parent / "assets",
on_session_start=on_session_start
)

View File

@ -0,0 +1,5 @@
Das hier ist nur ein dummer Demo Text. Hier gibts keinen Inhalt. Soll nur zeigen wie längerer Text aussieht.
Du musst das wirklich nicht lesen. Ganz ehrlich.
ÜBERRASCHUNG! ZEILENUMBNRUCH. Cool oder? Wie wärs mit einem Link? Zum Beispiel zur Seite der [BieberLAN](https://bieberlan.de).
Ich füll dann mal mit noch viel sinnloserem Zeug auf: Flauschige Einhörner singen in schillernden Farben, während tanzende Kakteen Kaffeetassen balancieren. Zwitschernde Regenbogenfische fliegen durch wabernden Pudding, und glitzernde Zebras jonglieren mit leuchtenden Sternen. Fliegende Teppiche plaudern fröhlich mit summenden Waffeleisen in einer Seifenblasenstadt.

View File

@ -0,0 +1,7 @@
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" id="mdi-steam" viewBox="0 0 24 24"><path d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22C7.4,22 3.55,18.92 2.36,14.73L6.19,16.31C6.45,17.6 7.6,18.58 8.97,18.58C10.53,18.58 11.8,17.31 11.8,15.75V15.62L15.2,13.19H15.28C17.36,13.19 19.05,11.5 19.05,9.42C19.05,7.34 17.36,5.65 15.28,5.65C13.2,5.65 11.5,7.34 11.5,9.42V9.47L9.13,12.93L8.97,12.92C8.38,12.92 7.83,13.1 7.38,13.41L2,11.2C2.43,6.05 6.73,2 12,2M8.28,17.17C9.08,17.5 10,17.13 10.33,16.33C10.66,15.53 10.28,14.62 9.5,14.29L8.22,13.76C8.71,13.58 9.26,13.57 9.78,13.79C10.31,14 10.72,14.41 10.93,14.94C11.15,15.46 11.15,16.04 10.93,16.56C10.5,17.64 9.23,18.16 8.15,17.71C7.65,17.5 7.27,17.12 7.06,16.67L8.28,17.17M17.8,9.42C17.8,10.81 16.67,11.94 15.28,11.94C13.9,11.94 12.77,10.81 12.77,9.42A2.5,2.5 0 0,1 15.28,6.91C16.67,6.91 17.8,8.04 17.8,9.42M13.4,9.42C13.4,10.46 14.24,11.31 15.29,11.31C16.33,11.31 17.17,10.46 17.17,9.42C17.17,8.38 16.33,7.53 15.29,7.53C14.24,7.53 13.4,8.38 13.4,9.42Z" /></svg>

After

Width:  |  Height:  |  Size: 993 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View File

@ -0,0 +1,3 @@
Nach Abschluss der Diskussionsrunde um die Vereinsfarben geht nun die Entwicklung der Vereinshomepage in Arbeit.
Geplant sind im ersten Schritt Informationsseiten über den Verein sowie rechtliche Angelegenheiten. In weiterer Zukunft ist jedoch weitere Funktionalität geplant. Das Projekt "Vereinswebsite" könnte auch als gemeintschftliches Projekt umgesetzt werden bei dem Interessierte ihre eigenen Module einbringen.

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

View File

@ -0,0 +1,4 @@
from .navigation import Navigation
from .header import Header
from .news_post import NewsPost
from .member_card import MemberInfo, MemberCard

View File

@ -0,0 +1,46 @@
import rio
from from_root import from_root
from rio import TextStyle
from ezgg_website.components.ticker import Ticker
class Header(rio.Component):
def build(self) -> rio.Component:
return rio.Column(
rio.Rectangle(
content=rio.Column(
rio.Row(
rio.Link(
rio.Image(from_root("ezgg_website/assets/placeholder_logo_grey.png"), align_x=0, width=8),
"/"
),
rio.Text("Sinnlose Infos aus dem Vereinskern:", justify="left", width="grow", margin_left=0.8),
Ticker(
texts=[
"Ganz im Geiste der EZ GG wurde der Verein in einer schlecht beleuchteten Kellerbar gegründet",
"Aktuelle hat der EZ GG e.V. sieben Mitglieder",
"Bist du auch ein Genießer? Dann tritt uns doch bei!",
"Auch Wasser wird zum edlen Tropfen, mischt man es mit Malz und Hopfen."
],
refresh_interval=30,
tick_in_order=True,
style=TextStyle(italic=True),
width="grow",
justify="right"
)
),
margin=1
),
fill=self.session.theme.neutral_color,
corner_radius=self.session.theme.corner_radius_medium,
shadow_radius=0.5,
shadow_color=self.session.theme.hud_color,
shadow_offset_y=0
),
align_y=0,
margin_top=1,
margin_left=1,
margin_right=1,
height=4
)

View File

@ -0,0 +1,53 @@
from pathlib import Path
from dataclasses import dataclass
from typing import Optional
import rio
@dataclass
class MemberInfo:
picture_path: Path
name: str
position: str
entry_date: str
contact_mail: Optional[str]
contact_steam: Optional[str]
class MemberCard(rio.Component):
def __init__(self, info: MemberInfo) -> None:
super().__init__()
self._info = info
self.align_y = 0
self.margin_top = 0
self.margin_bottom = 2
self.margin_right = 1
def build(self) -> rio.Component:
contact_row = rio.Row()
content = rio.Column(
rio.Image(self._info.picture_path, height=9, margin_bottom=1.3, margin_top=0.8),
rio.Text(self._info.name, margin_bottom=0.4, style=rio.TextStyle(font_weight="bold")),
rio.Text(self._info.position, margin_bottom=0.4, style=rio.TextStyle(italic=True)),
rio.Text(f"Mitglied seit {self._info.entry_date}", style=rio.TextStyle(italic=True), margin_bottom=0.4),
contact_row
)
# @Todo: Icon alignment broken if only one icon should be shown.
if self._info.contact_mail:
contact_row.add(rio.Link(rio.Icon("material/mail"), f"mailto://{self._info.contact_mail}", open_in_new_tab=True, margin_top=1, margin_bottom=1, align_x=0.9))
if self._info.contact_steam:
contact_row.add(rio.Link(rio.Icon("custom/steam"), self._info.contact_steam, open_in_new_tab=True, margin_top=1, margin_bottom=1, align_x=0.1))
if not self._info.contact_steam and not self._info.contact_mail:
contact_row.add(rio.Text("", margin_top=2))
return rio.Rectangle(
content=content,
fill=self.session.theme.neutral_color,
corner_radius=self.session.theme.corner_radius_medium,
shadow_radius=0.5,
shadow_color=self.session.theme.hud_color,
shadow_offset_y=0
)

View File

@ -0,0 +1,68 @@
from dataclasses import dataclass
from pathlib import Path
import rio
from from_root import from_root
@dataclass
class NavigationLink:
text: str
icon: str
target: str
NAVIGATION_LINKS = [
NavigationLink("Start", "material/home", "/"),
NavigationLink("Über den Verein", "material/info", "/about"),
NavigationLink("Mitglieder", "material/groups", "/member"),
NavigationLink("Satzung", "material/contract", "/constitution"),
NavigationLink("Mitglied werden", "material/contract-edit", "/join"),
NavigationLink("Galerie", "material/gallery-thumbnail", "/pics"),
NavigationLink("Impressum", "material/data-info-alert", "/imprint"),
NavigationLink("Datenschutz", "material/privacy-tip", "/privacy")
]
class Navigation(rio.Component):
@rio.event.on_page_change
async def on_page_change(self) -> None:
await self.force_refresh()
def build(self) -> rio.Component:
active_page = self.session.active_page_instances[0]
links = [
rio.Link(
rio.Button(
rio.Row(
rio.Icon(link_data.icon),
rio.Text(link_data.text),
spacing=0.5,
margin_x=1,
margin_y=0.2,
align_x=0,
),
style=("major" if active_page.page_url == link_data.target.replace("/", "") else "plain"),
),
link_data.target,
)
for link_data in NAVIGATION_LINKS
]
return rio.Row(
rio.Rectangle(
content=rio.Column(
*links,
spacing=1,
margin=1, align_x=0
),
fill=self.session.theme.neutral_color,
corner_radius=self.session.theme.corner_radius_medium,
shadow_radius=0.5,
shadow_color=self.session.theme.hud_color,
shadow_offset_y=0
),
align_y=0,
margin=1,
margin_top=0
)

View File

@ -0,0 +1,39 @@
from pathlib import Path
from typing import Union
import rio
class NewsPost(rio.Component):
def __init__(self, header: str, article_text: Union[str, Path], date: str):
super().__init__()
self.align_y = 0
self.margin_top = 0
self.margin_bottom = 2
self.margin_right = 1
self._header = header
self._date = date
if isinstance(article_text, str):
self._article_text = article_text
elif isinstance(article_text, Path):
with open(article_text, "r", encoding="utf-8") as f:
self._article_text = f.read()
def build(self) -> rio.Component:
return rio.Rectangle(
content=rio.Column(
rio.Row(
rio.Text(self._header, align_x=0.1, style="heading2"),
rio.Text(self._date, align_x=0.9, style=rio.TextStyle(italic=True)),
margin_top=0.5
),
rio.Column(
rio.Markdown(self._article_text, margin=1)
)
),
fill=self.session.theme.neutral_color,
corner_radius=self.session.theme.corner_radius_medium,
shadow_radius=0.5,
shadow_color=self.session.theme.hud_color,
shadow_offset_y=0
)

View File

@ -0,0 +1,60 @@
import asyncio
import logging
from random import randint
from rio import Text, Component, TextStyle
class Ticker(Component):
def __init__(self, texts: list[str], refresh_interval: float, style: TextStyle, tick_in_order: bool, **kwargs) -> None:
super().__init__()
if refresh_interval <= 0:
raise ValueError("refresh_interval must be greater than zero")
self.kwargs = kwargs
self.kwargs.pop("text", None)
self.kwargs.pop("style", None)
self.texts = texts
self.refresh_interval = refresh_interval
self.style = style
self._tick_in_order = tick_in_order
self._last_text = -1
self._task = asyncio.get_event_loop().create_task(self._set_next_text())
def stop_ticking(self) -> None:
self._task.cancel()
def start_ticking(self) -> None:
if not self._task.cancelled():
self._task.cancel()
self._task = asyncio.get_event_loop().create_task(self._set_next_text())
def set_new_texts(self, new_texts: list[str]) -> None:
self.stop_ticking()
self._last_text = -1
self.texts = new_texts
self.start_ticking()
def add_text(self, text: str) -> None:
self.texts.append(text)
def build(self) -> Component:
try:
self.kwargs["text"] = self.texts[self._last_text]
return Text(**self.kwargs, style=self.style)
except Exception as e:
logging.error(e)
logging.error("Ticker stopped due to an exception")
self.stop_ticking()
async def _set_next_text(self) -> None:
while True:
if self._tick_in_order:
self._last_text += 1
if self._last_text >= len(self.texts):
self._last_text = 0
else:
self._last_text = randint(0, len(self.texts) - 1)
await self.force_refresh()
await asyncio.sleep(self.refresh_interval)

5
ezgg_website/main.py Normal file
View File

@ -0,0 +1,5 @@
from __future__ import annotations
from ezgg_website import app
if __name__ == "__main__":
app.run_as_web_server(host="0.0.0.0", port=8080)

View File

@ -0,0 +1,9 @@
from .home import Home
from .about import About
from .member import Member
from .constitution import Constitution
from .join import Join
from .pics import Pics
from .privacy import Privacy
from .imprint import Imprint
from .page_builder import build_page

View File

@ -0,0 +1,42 @@
from __future__ import annotations
import asyncio
from functools import partial
from typing import * # type: ignore
import rio
from from_root import from_root
from .page_builder import build_page
from .. import components as comps
class About(rio.Component):
@rio.event.on_populate
async def on_populate(self) -> None:
await self.session.set_title("EZ GG e.V. - Über den Verein")
def build(self) -> rio.Component:
return build_page(rio.Column(
comps.NewsPost(
header="Die \"Einfach Zocken Genuss Gesellschaft\"",
article_text="""
Die Einfach Zocken Genussgesellschaft wurde am 29. Oktober 2023 in Bad Endbach-Bottenhorn gegründet. Der Verein entstand aus der gemeinsamen Begeisterung für Videospiele, die einige Freunde in einer gemütlichen Kellerbar zusammenbrachte. Unsere Mission ist es, die Freizeitbeschäftigung "Videospiele" zu fördern und Menschen zusammenzubringen, die diese Leidenschaft teilen.
### Unsere Ziele und Mission
Unser Hauptziel ist es, die gemeinschaftliche Ausübung von Videospielen zu fördern. Dabei geht es uns nicht nur um das Spielen selbst, sondern auch um die Kommunikation, die Weiterentwicklung und das gemeinsame Erleben dieser Freizeitbeschäftigung. Wir organisieren regelmäßig Spieleabende, besuchen LAN-Partys und setzen themenverwandte Projekte um. Unser Verein steht dabei jedem offen, der Interesse an Videospielen hat und sich aktiv einbringen möchte.
### Gemeinnützigkeit und Mitgliedschaft
Als eingetragener, gemeinnütziger Verein legen wir großen Wert darauf, dass unsere Aktivitäten allen Interessierten zugutekommen.
Wir sind stets auf der Suche nach neuen Mitgliedern, die unsere Leidenschaft teilen und sich aktiv im Vereinsleben einbringen möchten. Interessierte können sich gerne über unsere Homepage an den Vorstand wenden, um mehr über eine Mitgliedschaft zu erfahren.
### Kontakt
Unser Vorstand steht als Ansprechpartner zur Verfügung und kann über die Mitgliederliste auf unserer Homepage kontaktiert werden. Wir freuen uns auf neue Mitglieder und gemeinsame Erlebnisse in der Welt der Videospiele!
""",
date=""
)
))

View File

@ -0,0 +1,154 @@
from __future__ import annotations
from typing import * # type: ignore
import rio
from .page_builder import build_page
from .. import components as comps
class Constitution(rio.Component):
@rio.event.on_populate
async def on_populate(self) -> None:
await self.session.set_title("EZ GG e.V. - Satzung")
def build(self) -> rio.Component:
return build_page(rio.Column(
comps.NewsPost(
header="Satzung der Einfach Zocken Gaming Gesellschaft",
article_text="""
§ 1 Name, Sitz, Geschäftsjahr
1. Der Verein trägt den Namen "Einfach Zocken Gaming Gesellschaft". Er soll in das
Vereinsregister eingetragen werden und führt dann den Zusatz "e. V."
2. Der Sitz des Vereins ist in Bad Endbach Bottenhorn.
3. Das Kalenderjahr ist das Geschäftsjahr des Vereins.
4. Der Verein ist politisch, ethnisch und konfessionell neutral.
§ 2 - Vereinszweck
1. Der Verein fördert die Freizeitbeschäftigung "Videospiele" und setzt sich für die
gemeinschaftliche Ausübung, Kommunikation, Weiterentwicklung und das gemeinsame
Erleben dieser Freizeitbeschäftigung ein.
2. Der Verein sorgt, in einem gemeinnütziger Rahmen, dafür, dass diese Aktivitäten der
Allgemeinheit offenstehen. Unser Ziel ist es, die Begeisterung für Videospiele zu fördern
und für jeden Interessierten zugänglich zu machen.
3. Der Vereinszweck wird durch die Planung und Durchführung öffentlicher Versammlungen,
eSport-Veranstaltungen sowie die Bereitstellung kostenfreier technischer Ressourcen des
Vereins realisiert. Darüber hinaus steht der Verein bei Bedarf zur Unterstützung bei
technischen Herausforderungen zur Verfügung.
4. Der Verein verfolgt ausschließlich und unmittelbar gemeinnützige Zwecke i. S. d. Abschnitts
"Steuerbegünstigte Zwecke" der Abgabenordnung.
5. Mittel des Vereins dürfen nur für die satzungsgemäßen Zwecke verwendet werden. Die
Mitglieder erhalten in der Regel keine Zuwendungen aus den Mitteln des Vereins. Es darf
keine Person durch Ausgaben, die dem Zweck des Vereins fremd sind oder durch
unverhältnismäßig hohe Vergütung begünstigt werden.
§ 3 Erwerb der Mitgliedschaft
1. Jede natürliche und juristische Person kann die Aufnahme in den Verein beantragen.
Natürliche Personen müssen das 16. Lebensjahr vollendet haben, um dem Verein als
Mitglied beitreten zu können. Minderjährige bedürfen hierzu der Erlaubnis ihrer
gesetzlichen Vertreter.
2. Der Antrag auf Mitgliedschaft ist schriftlich oder über die Internetseite des Vereins
einzureichen.
3. Die Mitgliedschaft beginnt nach einer 3-Monatigen Probezeit und Bestätigung durch den
Vorstand.
4. Eine aktive Teilnahme am Vereinsalltag ist erwünscht, jedoch nicht zwingend erforderlich.
5. Mitglieder haben dem Verein eine gültige E-Mail Adresse mitzuteilen und diese in
regelmäßigen Abständen abzufragen. Sollte die Gültigkeit der E-Mail Adresse verfallen, so
ist dem Verein eine Ersatzadresse mitzuteilen.
6. Der Mitgliedsbeitrag beträgt 1 pro Monat bzw. 12 pro Jahr. Der Vorstand kann in
geeigneten Fällen Gebühren, Beiträge und Umlagen ganz oder teilweise erlassen oder
stunden.
§ 4 Erhaltung der Mitgliedschaft
1. Ein Austritt aus dem Verein ist zum jeweiligen Monatsende möglich. Der Austritt muss bei
dem Vorstand schriftlich eingereicht werden.
2. Ein Mitglied kann durch Beschluss des Vorstands von der Mitgliederliste gestrichen werden,
wenn es trotz zweimaliger Mahnung mit der Zahlung des Beitrags im Rückstand ist. Die
Streichung ist dem Mitglied schriftlich mitzuteilen.
3. Ein Mitglied kann, wenn es gegen die Vereinsinteressen gröblich verstoßen hat, durch
Beschluss der Mitgliederversammlung aus dem Verein ausgeschlossen werden. Vor der
Beschlussfassung ist dem Mitglied Gelegenheit zu geben, sich persönlich zu rechtfertigen.
Eine etwaige schriftliche Stellungnahme des Betroffenen ist in der Mitgliederversammlung
zu verlesen.
4. Im Sterbefall (natürliche Person) oder bei einer Auflösung (juristische Person) endet die
Mitgliedschaft.
§ 5 - Organe des Vereins
1. Organe des Vereins sind der Vorstand und die Mitgliederversammlung.
2. Die Mitgliederversammlung wählt alle zwei Jahre einen neuen Vorstand, der die täglichen
Geschäfte des Vereins führt.
3. Der Vorstand besteht aus
1. Dem Vorsitzenden
2. Dem zweiten Vorsitzenden
3. Dem Schatzmeister
4. Scheidet ein Mitglied des Vorstandes während der Amtsperiode aus, so wählt der Vorstand
ein Ersatzmitglied (aus den Reihen der Vereinsmitglieder) für die restliche Amtsdauer des
Ausgeschiedenen.
5. Der Vorsitzende, der zweite Vorsitzende und der Schatzmeister vertreten den Verein jeweils
allein.
6. Dem Vorstand des Vereins obliegen die Vertretung des Vereins nach § 26 BGB und die
Führung seiner Geschäfte
§ 6 - Mitgliederversammlung
1. Die Mitgliederversammlung findet einmal im Jahr statt.
2. Die Einberufung erfolgt über E-Mail mindestens vier Wochen vor dem
Versammlungsdatum.
3. Das Einladungsschreiben gilt als dem Mitglied zugegangen, wenn es an die letzte vom
Mitglied dem Verein schriftlich bekannt gegebene Adresse gerichtet ist. Die Tagesordnung
setzt der Vorstand fest.
4. Der Vorstand kann außerordentliche Sitzungen einberufen.
5. Die Mitgliederversammlung ist insbesondere für die folgenden Angelegenheiten zuständig:
1. Entgegennahme des Jahresberichtes des Vorstandes
2. Entlastung des Vorstandes
3. Festsetzung der Höhe und der Fälligkeit des Jahresbeitrages
4. Wahl und Abberufung der Mitglieder des Vorstandes
5. Beschlussfassung über die Änderung der Satzung und über die Auflösung des
Vereins
6. Ernennung von Ehrenmitgliedern
6. Über jede Mitgliederversammlung ist ein Protokoll aufzunehmen, welches vom Vorstand zu
unterzeichnen ist.
§ 7 - Finanzangelegenheiten
1. Der Schatzmeister übernimmt die Buchhaltung des Vereins.
2. Die Finanzen des Vereins werden auf jeder Mitgliederversammlung den Mitgliedern
gegenüber offengelegt.
3. Der Verein wird durch Mitgliedsbeiträge und den Überschuss an Finanzmitteln aus den
Veranstaltungen, des Weiteren durch Spenden- und Sponsorengelder finanziert. Außerdem
können Einnahmen aus der Vermietung von Vereinseigentum erzielt werden.
§ 8 - Auflösung des Vereins
1. Der Verein wird automatisch aufgelöst, wenn die Gesamtzahl der Mitglieder unter 3 sinkt.
2. Eine Auflösung kann auch auf Antrag auf der Mitgliederversammlung beschlossen werden.
Hierbei ist eine Einstimmigkeit erforderlich.
3. Im Falle der Auflösung oder Aufhebung des Vereins wird das Vereinsvermögen wie folgt
verteilt.
1. Alle Geldmittel werden an wohltätige Vereine gespendet die die
Mitgliederversammlung bestimmt. Kann die Mitgliederversammlung zu keinem
Entschluss kommen, so wir dieser Verein vom Vorstand bestimmt.
2. Sachspenden werden dem Spender zurückgegeben sofern dieser bekannt ist.
3. Anonyme Sachspenden werden verkauft. Für den Erlös gilt §8 Absatz 1.
§ 9 - Änderungen der Satzung
1. Änderungen an der Satzung werden durch einen Vorschlag auf der Mitgliederversammlung
diskutiert und mit relativer Mehrheit beschlossen.
§10 Beschlussfähigkeit und Stimmrecht
1. Stimmberechtigt sind alle Mitglieder des Vereins. Jedes Mitglied hat genau eine Stimme die
nur von ihm persönlich abgegeben werden darf.
2. Die Mitgliederversammlung ist ohne Rücksicht auf die Anzahl der erschienenen Mitglieder
beschlussfähig.
3. Die Mitgliederversammlung fasst ihre Beschlüsse, sofern nicht anders in der Satzung
angegeben, mit relativer Mehrheit. Enthaltungen und ungültige Stimmen werden nicht in die
Mehrheitsberechnung miteinbezogen. Bei Stimmgleichheit geht die Entscheidung in den
Vorstand über.
4. Die Abstimmung erfolgt, soweit nicht von einem Mitglied eine geheime Abstimmung
gefordert wird, durch Handzeichen.
5. Die Mitgliederversammlung wird durch den Vorsitzenden geleitet. Ist dieser nicht anwesend,
kann ein anderes Mitglied des Vorstandes die Leitung übernehmen. Ist kein solches Mitglied
anwesend wird die Mitgliederversammlung abgebrochen und vom Vorsitzenden zu einem
späteren Zeitpunkt erneut angesetzt.
""",
date="29.10.2023"
)
))

View File

@ -0,0 +1,34 @@
from __future__ import annotations
from typing import * # type: ignore
import rio
from from_root import from_root
from .page_builder import build_page
from .. import components as comps
class Home(rio.Component):
@rio.event.on_populate
async def on_populate(self) -> None:
await self.session.set_title("EZ GG e.V.")
def build(self) -> rio.Component:
return build_page(rio.Column(
rio.Rectangle(
content=rio.Markdown("### Willkommen auf der Homepage der EZ GG e.V.", margin=1),
fill=self.session.theme.neutral_color,
corner_radius=self.session.theme.corner_radius_medium,
shadow_radius=0.5,
shadow_color=self.session.theme.hud_color,
shadow_offset_y=0,
margin_bottom=1,
margin_right=1
),
comps.NewsPost(
header="Startschuss für Homepage",
article_text=from_root("ezgg_website/assets/news_27_05_24.md"),
date="24.05.2024"
)
))

View File

@ -0,0 +1,51 @@
from __future__ import annotations
from typing import * # type: ignore
import rio
from from_root import from_root
from .page_builder import build_page
from .. import components as comps
class Imprint(rio.Component):
@rio.event.on_populate
async def on_populate(self) -> None:
await self.session.set_title("EZ GG e.V. - Impressum")
def build(self) -> rio.Component:
return build_page(rio.Column(
comps.NewsPost(
header="Impressum",
article_text="""
#### Einfach Zocken Genuss Gesellschaft e.V.
```txt
Im Elchgrund 18
35080 Bad Endbach - Bottenhorn
Telefon: +4917657993174
E-Mail: davidr.develop@gmail.com
```
#### Vertreten durch:
```txt
David Rodenkirchen
Julia Albring
```
#### Registereintrag:
```txt
Eingetragen im Vereinsregister.
Registergericht: Amtsgericht Marburg
Registernummer: - folgt -
```
""",
date=""
)
))

View File

@ -0,0 +1,34 @@
from __future__ import annotations
import asyncio
from typing import * # type: ignore
import rio
from .page_builder import build_page
from .. import components as comps
class Join(rio.Component):
@rio.event.on_populate
async def on_populate(self) -> None:
await self.session.set_title("EZ GG e.V. - Mitglied werden")
def build(self) -> rio.Component:
return build_page(rio.Column(
comps.NewsPost(
header="Eintritt in die EZ GG e.V.",
article_text="""
Wir freuen uns sehr, dass du Interesse daran hast, Mitglied bei der Einfach Zocken Genussgesellschaft zu werden! Unsere Gemeinschaft lebt von der Begeisterung und dem Engagement unserer Mitglieder.
Als Mitglied hast du die Möglichkeit, aktiv an unseren Veranstaltungen teilzunehmen und die Entwicklung des Vereins mitzugestalten. Egal, ob du ein erfahrener Gamer oder ein Neuling bist bei uns bist du herzlich willkommen!
Um Mitglied zu werden, fülle bitte das untenstehende Formular aus und sende es uns [per Mail an den Vorstand](./member) oder [per Post](./imprint). Wir freuen uns darauf, dich bald in unserer Gemeinschaft begrüßen zu dürfen!
_[Mitgliedsantragsformular kommt noch, wir bitten um Geduld]_
Bei Fragen oder weiteren Informationen kannst du dich jederzeit an unseren Vorstand wenden. Die Kontaktdaten findest du auf [hier](./member). Wir freuen uns auf dich!
""",
date=""
)
))

View File

@ -0,0 +1,29 @@
from __future__ import annotations
from typing import * # type: ignore
import rio
from .page_builder import build_page
from .. import components as comps
from .. import services
class Member(rio.Component):
def __init__(self, database_service: services.database_service.DatabaseService) -> None:
super().__init__()
self._database_service = database_service
@rio.event.on_populate
async def on_populate(self) -> None:
await self.session.set_title("EZ GG e.V. - Mitglieder")
def build(self) -> rio.Component:
grid = rio.Grid()
for i, member in enumerate(self._database_service.get_members()):
grid.add(
comps.MemberCard(member),
row=i // 2,
column=i % 2,
)
return build_page(grid)

View File

@ -0,0 +1,36 @@
from __future__ import annotations
from dataclasses import KW_ONLY, field
from typing import * # type: ignore
import rio
from .. import components as comps
def build_page(main_component: rio.Component) -> rio.Component:
return rio.Column(
rio.Row(
comps.Header()
),
rio.Row(
rio.Column(
comps.Navigation(),
width="natural",
align_y=0,
margin_right=1
),
rio.Column(
main_component,
width="grow",
align_y=0
),
width="grow",
height="grow"
),
spacing=2,
margin=0,
width="grow",
height="grow"
)

View File

@ -0,0 +1,64 @@
from __future__ import annotations
from functools import partial
from typing import * # type: ignore
import rio
from .page_builder import build_page
from .. import components as comps, services
class Pics(rio.Component):
def __init__(self, database_service: services.database_service.DatabaseService) -> None:
super().__init__()
self._database_service = database_service
self._active_picture: Optional[rio.URL] = None
@rio.event.on_populate
async def on_populate(self) -> None:
await self.session.set_title("EZ GG e.V. - Galerie")
def build(self) -> rio.Component:
if self._active_picture is None:
grid = rio.Grid(row_spacing=0.4, column_spacing=0.5, margin_right=1)
for i, link in enumerate(self._database_service.get_picture_paths()):
grid.add(
rio.Button(
rio.Image(
link,
height=12,
width=12
),
shape="rectangle",
style="plain",
on_press=partial(self.on_picture_clicked, link)
),
row=i // 3,
column=i % 3,
)
return build_page(grid)
return rio.Overlay(
rio.Column(
rio.Button(
rio.Image(
self._active_picture,
height="grow",
width="grow"
),
shape="rectangle",
style="plain",
height="grow",
on_press=self.exit_overlay
),
rio.Text("Click to exit", margin_bottom=2)
)
)
async def on_picture_clicked(self, link_to_picture: str) -> None:
self._active_picture = link_to_picture
await self.force_refresh()
async def exit_overlay(self) -> None:
self._active_picture = None
await self.force_refresh()

View File

@ -0,0 +1,187 @@
from __future__ import annotations
from typing import * # type: ignore
import rio
from from_root import from_root
from .page_builder import build_page
from .. import components as comps
class Privacy(rio.Component):
@rio.event.on_populate
async def on_populate(self) -> None:
await self.session.set_title("EZ GG e.V. - Datenschutz")
def build(self) -> rio.Component:
return build_page(rio.Column(
comps.NewsPost(
header="Datenschutzerklärung",
article_text="""
### Präambel
Mit der folgenden Datenschutzerklärung möchten wir Sie darüber aufklären, welche Arten Ihrer personenbezogenen Daten (nachfolgend auch kurz als "Daten" bezeichnet) wir zu welchen Zwecken und in welchem Umfang verarbeiten. Die Datenschutzerklärung gilt für alle von uns durchgeführten Verarbeitungen personenbezogener Daten, sowohl im Rahmen der Erbringung unserer Leistungen als auch insbesondere auf unseren Webseiten, in mobilen Applikationen sowie innerhalb externer Onlinepräsenzen, wie z. B. unserer Social-Media-Profile (nachfolgend zusammenfassend bezeichnet als "Onlineangebot").
Die verwendeten Begriffe sind nicht geschlechtsspezifisch.
Stand: _27. Mai 2024_
#### Verantwortlicher:
```txt
Einfach Zocken Genuss Gesellschaft e.V.
Im Elchgrund 18
35080 Bad Endbach - Bottenhorn
Deutschland
```
### Übersicht der Verarbeitungen
Die nachfolgende Übersicht fasst die Arten der verarbeiteten Daten und die Zwecke ihrer Verarbeitung zusammen und verweist auf die betroffenen Personen.
#### Arten der verarbeiteten Daten
- Bestandsdaten
- Kontaktdaten
- Inhaltsdaten
- Nutzungsdaten
- Meta-, Kommunikations- und Verfahrensdaten
- Protokolldaten
#### Kategorien betroffener Personen
- Kommunikationspartner
- Nutzer
#### Zwecke der Verarbeitung
- Kommunikation
- Sicherheitsmaßnahmen
- Organisations- und Verwaltungsverfahren
- Feedback
- Bereitstellung unseres Onlineangebotes und Nutzerfreundlichkeit
- Informationstechnische Infrastruktur
### Maßgebliche Rechtsgrundlagen
Maßgebliche Rechtsgrundlagen nach der DSGVO: Im Folgenden erhalten Sie eine Übersicht der Rechtsgrundlagen der DSGVO, auf deren Basis wir personenbezogene Daten verarbeiten. Bitte nehmen Sie zur Kenntnis, dass neben den Regelungen der DSGVO nationale Datenschutzvorgaben in Ihrem bzw. unserem Wohn- oder Sitzland gelten können. Sollten ferner im Einzelfall speziellere Rechtsgrundlagen maßgeblich sein, teilen wir Ihnen diese in der Datenschutzerklärung mit.
- **Einwilligung (Art. 6 Abs. 1 S. 1 lit. a) DSGVO)** - Die betroffene Person hat ihre Einwilligung in die Verarbeitung der sie betreffenden personenbezogenen Daten für einen spezifischen Zweck oder mehrere bestimmte Zwecke gegeben.
- **Vertragserfüllung und vorvertragliche Anfragen (Art. 6 Abs. 1 S. 1 lit. b) DSGVO)** - Die Verarbeitung ist für die Erfüllung eines Vertrags, dessen Vertragspartei die betroffene Person ist, oder zur Durchführung vorvertraglicher Maßnahmen erforderlich, die auf Anfrage der betroffenen Person erfolgen.
- **Berechtigte Interessen (Art. 6 Abs. 1 S. 1 lit. f) DSGVO)** - die Verarbeitung ist zur Wahrung der berechtigten Interessen des Verantwortlichen oder eines Dritten notwendig, vorausgesetzt, dass die Interessen, Grundrechte und Grundfreiheiten der betroffenen Person, die den Schutz personenbezogener Daten verlangen, nicht überwiegen.
**Nationale Datenschutzregelungen in Deutschland:** Zusätzlich zu den Datenschutzregelungen der DSGVO gelten nationale Regelungen zum Datenschutz in Deutschland. Hierzu gehört insbesondere das Gesetz zum Schutz vor Missbrauch personenbezogener Daten bei der Datenverarbeitung (Bundesdatenschutzgesetz BDSG). Das BDSG enthält insbesondere Spezialregelungen zum Recht auf Auskunft, zum Recht auf Löschung, zum Widerspruchsrecht, zur Verarbeitung besonderer Kategorien personenbezogener Daten, zur Verarbeitung für andere Zwecke und zur Übermittlung sowie automatisierten Entscheidungsfindung im Einzelfall einschließlich Profiling. Ferner können Landesdatenschutzgesetze der einzelnen Bundesländer zur Anwendung gelangen.
### Sicherheitsmaßnahmen
Wir treffen nach Maßgabe der gesetzlichen Vorgaben unter Berücksichtigung des Stands der Technik, der Implementierungskosten und der Art, des Umfangs, der Umstände und der Zwecke der Verarbeitung sowie der unterschiedlichen Eintrittswahrscheinlichkeiten und des Ausmaßes der Bedrohung der Rechte und Freiheiten natürlicher Personen geeignete technische und organisatorische Maßnahmen, um ein dem Risiko angemessenes Schutzniveau zu gewährleisten.
Zu den Maßnahmen gehören insbesondere die Sicherung der Vertraulichkeit, Integrität und Verfügbarkeit von Daten durch Kontrolle des physischen und elektronischen Zugangs zu den Daten als auch des sie betreffenden Zugriffs, der Eingabe, der Weitergabe, der Sicherung der Verfügbarkeit und ihrer Trennung. Des Weiteren haben wir Verfahren eingerichtet, die eine Wahrnehmung von Betroffenenrechten, die Löschung von Daten und Reaktionen auf die Gefährdung der Daten gewährleisten. Ferner berücksichtigen wir den Schutz personenbezogener Daten bereits bei der Entwicklung bzw. Auswahl von Hardware, Software sowie Verfahren entsprechend dem Prinzip des Datenschutzes, durch Technikgestaltung und durch datenschutzfreundliche Voreinstellungen.
Sicherung von Online-Verbindungen durch TLS-/SSL-Verschlüsselungstechnologie (HTTPS): Um die Daten der Nutzer, die über unsere Online-Dienste übertragen werden, vor unerlaubten Zugriffen zu schützen, setzen wir auf die TLS-/SSL-Verschlüsselungstechnologie. Secure Sockets Layer (SSL) und Transport Layer Security (TLS) sind die Eckpfeiler der sicheren Datenübertragung im Internet. Diese Technologien verschlüsseln die Informationen, die zwischen der Website oder App und dem Browser des Nutzers (oder zwischen zwei Servern) übertragen werden, wodurch die Daten vor unbefugtem Zugriff geschützt sind. TLS, als die weiterentwickelte und sicherere Version von SSL, gewährleistet, dass alle Datenübertragungen den höchsten Sicherheitsstandards entsprechen. Wenn eine Website durch ein SSL-/TLS-Zertifikat gesichert ist, wird dies durch die Anzeige von HTTPS in der URL signalisiert. Dies dient als ein Indikator für die Nutzer, dass ihre Daten sicher und verschlüsselt übertragen werden.
### Übermittlung von personenbezogenen Daten
Im Rahmen unserer Verarbeitung von personenbezogenen Daten kommt es vor, dass diese an andere Stellen, Unternehmen, rechtlich selbstständige Organisationseinheiten oder Personen übermittelt beziehungsweise ihnen gegenüber offengelegt werden. Zu den Empfängern dieser Daten können z. B. mit IT-Aufgaben beauftragte Dienstleister gehören oder Anbieter von Diensten und Inhalten, die in eine Website eingebunden sind. In solchen Fällen beachten wir die gesetzlichen Vorgaben und schließen insbesondere entsprechende Verträge bzw. Vereinbarungen, die dem Schutz Ihrer Daten dienen, mit den Empfängern Ihrer Daten ab.
### Internationale Datentransfers
Datenverarbeitung in Drittländern: Sofern wir Daten in einem Drittland (d. h., außerhalb der Europäischen Union (EU), des Europäischen Wirtschaftsraums (EWR)) verarbeiten oder die Verarbeitung im Rahmen der Inanspruchnahme von Diensten Dritter oder der Offenlegung bzw. Übermittlung von Daten an andere Personen, Stellen oder Unternehmen stattfindet, erfolgt dies nur im Einklang mit den gesetzlichen Vorgaben. Sofern das Datenschutzniveau in dem Drittland mittels eines Angemessenheitsbeschlusses anerkannt wurde (Art. 45 DSGVO), dient dieser als Grundlage des Datentransfers. Im Übrigen erfolgen Datentransfers nur dann, wenn das Datenschutzniveau anderweitig gesichert ist, insbesondere durch Standardvertragsklauseln (Art. 46 Abs. 2 lit. c) DSGVO), ausdrückliche Einwilligung oder im Fall vertraglicher oder gesetzlich erforderlicher Übermittlung (Art. 49 Abs. 1 DSGVO). Im Übrigen teilen wir Ihnen die Grundlagen der Drittlandübermittlung bei den einzelnen Anbietern aus dem Drittland mit, wobei die Angemessenheitsbeschlüsse als Grundlagen vorrangig gelten. Informationen zu Drittlandtransfers und vorliegenden Angemessenheitsbeschlüssen können dem Informationsangebot der EU-Kommission entnommen werden: https://commission.europa.eu/law/law-topic/data-protection/international-dimension-data-protection_en?prefLang=de.
EU-US Trans-Atlantic Data Privacy Framework: Im Rahmen des sogenannten Data Privacy Framework" (DPF) hat die EU-Kommission das Datenschutzniveau ebenfalls für bestimmte Unternehmen aus den USA im Rahmen der Angemessenheitsbeschlusses vom 10.07.2023 als sicher anerkannt. Die Liste der zertifizierten Unternehmen als auch weitere Informationen zu dem DPF können Sie der Website des Handelsministeriums der USA unter https://www.dataprivacyframework.gov/ (in Englisch) entnehmen. Wir informieren Sie im Rahmen der Datenschutzhinweise, welche von uns eingesetzten Diensteanbieter unter dem Data Privacy Framework zertifiziert sind.
### Allgemeine Informationen zur Datenspeicherung und Löschung
Wir löschen personenbezogene Daten, die wir verarbeiten, gemäß den gesetzlichen Bestimmungen, sobald die zugrundeliegenden Einwilligungen widerrufen werden oder keine weiteren rechtlichen Grundlagen für die Verarbeitung bestehen. Dies betrifft Fälle, in denen der ursprüngliche Verarbeitungszweck entfällt oder die Daten nicht mehr benötigt werden. Ausnahmen von dieser Regelung bestehen, wenn gesetzliche Pflichten oder besondere Interessen eine längere Aufbewahrung oder Archivierung der Daten erfordern.
Insbesondere müssen Daten, die aus handels- oder steuerrechtlichen Gründen aufbewahrt werden müssen oder deren Speicherung notwendig ist zur Rechtsverfolgung oder zum Schutz der Rechte anderer natürlicher oder juristischer Personen, entsprechend archiviert werden.
Unsere Datenschutzhinweise enthalten zusätzliche Informationen zur Aufbewahrung und Löschung von Daten, die speziell für bestimmte Verarbeitungsprozesse gelten.
Bei mehreren Angaben zur Aufbewahrungsdauer oder Löschungsfristen eines Datums, ist stets die längste Frist maßgeblich.
Beginnt eine Frist nicht ausdrücklich zu einem bestimmten Datum und beträgt sie mindestens ein Jahr, so startet sie automatisch am Ende des Kalenderjahres, in dem das fristauslösende Ereignis eingetreten ist. Im Fall laufender Vertragsverhältnisse, in deren Rahmen Daten gespeichert werden, ist das fristauslösende Ereignis der Zeitpunkt des Wirksamwerdens der Kündigung oder sonstige Beendigung des Rechtsverhältnisses.
Daten, die nicht mehr für den ursprünglich vorgesehenen Zweck, sondern aufgrund gesetzlicher Vorgaben oder anderer Gründe aufbewahrt werden, verarbeiten wir ausschließlich zu den Gründen, die ihre Aufbewahrung rechtfertigen.
#### Weitere Hinweise zu Verarbeitungsprozessen, Verfahren und Diensten:
- **Aufbewahrung und Löschung von Daten:** Die folgenden allgemeinen Fristen gelten für die Aufbewahrung und Archivierung nach deutschem Recht:
- 10 Jahre - Aufbewahrungsfrist für Bücher und Aufzeichnungen, Jahresabschlüsse, Inventare, Lageberichte, Eröffnungsbilanz sowie die zu ihrem Verständnis erforderlichen Arbeitsanweisungen und sonstigen Organisationsunterlagen, Buchungsbelege und Rechnungen (§ 147 Abs. 3 i. V. m. Abs. 1 Nr. 1, 4 und 4a AO, § 14b Abs. 1 UStG, § 257 Abs. 1 Nr. 1 u. 4, Abs. 4 HGB).
- 6 Jahre - Übrige Geschäftsunterlagen: empfangene Handels- oder Geschäftsbriefe, Wiedergaben der abgesandten Handels- oder Geschäftsbriefe, sonstige Unterlagen, soweit sie für die Besteuerung von Bedeutung sind, z. B. Stundenlohnzettel, Betriebsabrechnungsbögen, Kalkulationsunterlagen, Preisauszeichnungen, aber auch Lohnabrechnungsunterlagen, soweit sie nicht bereits Buchungsbelege sind und Kassenstreifen (§ 147 Abs. 3 i. V. m. Abs. 1 Nr. 2, 3, 5 AO, § 257 Abs. 1 Nr. 2 u. 3, Abs. 4 HGB).
- 3 Jahre - Daten, die erforderlich sind, um potenzielle Gewährleistungs- und Schadensersatzansprüche oder ähnliche vertragliche Ansprüche und Rechte zu berücksichtigen sowie damit verbundene Anfragen zu bearbeiten, basierend auf früheren Geschäftserfahrungen und üblichen Branchenpraktiken, werden für die Dauer der regulären gesetzlichen Verjährungsfrist von drei Jahren gespeichert (§§ 195, 199 BGB).
### Rechte der betroffenen Personen
Rechte der betroffenen Personen aus der DSGVO: Ihnen stehen als Betroffene nach der DSGVO verschiedene Rechte zu, die sich insbesondere aus Art. 15 bis 21 DSGVO ergeben:
- **Widerspruchsrecht:** Sie haben das Recht, aus Gründen, die sich aus Ihrer besonderen Situation ergeben, jederzeit gegen die Verarbeitung der Sie betreffenden personenbezogenen Daten, die aufgrund von Art. 6 Abs. 1 lit. e oder f DSGVO erfolgt, Widerspruch einzulegen; dies gilt auch für ein auf diese Bestimmungen gestütztes Profiling. Werden die Sie betreffenden personenbezogenen Daten verarbeitet, um Direktwerbung zu betreiben, haben Sie das Recht, jederzeit Widerspruch gegen die Verarbeitung der Sie betreffenden personenbezogenen Daten zum Zwecke derartiger Werbung einzulegen; dies gilt auch für das Profiling, soweit es mit solcher Direktwerbung in Verbindung steht.
- **Widerrufsrecht bei Einwilligungen:** Sie haben das Recht, erteilte Einwilligungen jederzeit zu widerrufen.
- **Auskunftsrecht:** Sie haben das Recht, eine Bestätigung darüber zu verlangen, ob betreffende Daten verarbeitet werden und auf Auskunft über diese Daten sowie auf weitere Informationen und Kopie der Daten entsprechend den gesetzlichen Vorgaben.
- **Recht auf Berichtigung:** Sie haben entsprechend den gesetzlichen Vorgaben das Recht, die Vervollständigung der Sie betreffenden Daten oder die Berichtigung der Sie betreffenden unrichtigen Daten zu verlangen.
- **Recht auf Löschung und Einschränkung der Verarbeitung:** Sie haben nach Maßgabe der gesetzlichen Vorgaben das Recht, zu verlangen, dass Sie betreffende Daten unverzüglich gelöscht werden, bzw. alternativ nach Maßgabe der gesetzlichen Vorgaben eine Einschränkung der Verarbeitung der Daten zu verlangen.
- **Recht auf Datenübertragbarkeit:** Sie haben das Recht, Sie betreffende Daten, die Sie uns bereitgestellt haben, nach Maßgabe der gesetzlichen Vorgaben in einem strukturierten, gängigen und maschinenlesbaren Format zu erhalten oder deren Übermittlung an einen anderen Verantwortlichen zu fordern.
- **Beschwerde bei Aufsichtsbehörde:** Sie haben unbeschadet eines anderweitigen verwaltungsrechtlichen oder gerichtlichen Rechtsbehelfs das Recht auf Beschwerde bei einer Aufsichtsbehörde, insbesondere in dem Mitgliedstaat ihres gewöhnlichen Aufenthaltsorts, ihres Arbeitsplatzes oder des Orts des mutmaßlichen Verstoßes, wenn Sie der Ansicht sind, dass die Verarbeitung der Sie betreffenden personenbezogenen Daten gegen die Vorgaben der DSGVO verstößt.
### Bereitstellung des Onlineangebots und Webhosting
Wir verarbeiten die Daten der Nutzer, um ihnen unsere Online-Dienste zur Verfügung stellen zu können. Zu diesem Zweck verarbeiten wir die IP-Adresse des Nutzers, die notwendig ist, um die Inhalte und Funktionen unserer Online-Dienste an den Browser oder das Endgerät der Nutzer zu übermitteln.
- **Verarbeitete Datenarten:** Nutzungsdaten (z. B. Seitenaufrufe und Verweildauer, Klickpfade, Nutzungsintensität und -frequenz, verwendete Gerätetypen und Betriebssysteme, Interaktionen mit Inhalten und Funktionen); Meta-, Kommunikations- und Verfahrensdaten (z. B. IP-Adressen, Zeitangaben, Identifikationsnummern, beteiligte Personen). Protokolldaten (z. B. Logfiles betreffend Logins oder den Abruf von Daten oder Zugriffszeiten.).
- **Betroffene Personen:** Nutzer (z. B. Webseitenbesucher, Nutzer von Onlinediensten).
- **Zwecke der Verarbeitung:** Bereitstellung unseres Onlineangebotes und Nutzerfreundlichkeit; Informationstechnische Infrastruktur (Betrieb und Bereitstellung von Informationssystemen und technischen Geräten (Computer, Server etc.).). Sicherheitsmaßnahmen.
- **Aufbewahrung und Löschung:** Löschung entsprechend Angaben im Abschnitt "Allgemeine Informationen zur Datenspeicherung und Löschung".
- **Rechtsgrundlagen:** Berechtigte Interessen (Art. 6 Abs. 1 S. 1 lit. f) DSGVO).
#### Weitere Hinweise zu Verarbeitungsprozessen, Verfahren und Diensten:
- **Bereitstellung Onlineangebot auf gemietetem Speicherplatz:** Für die Bereitstellung unseres Onlineangebotes nutzen wir Speicherplatz, Rechenkapazität und Software, die wir von einem entsprechenden Serveranbieter (auch "Webhoster" genannt) mieten oder anderweitig beziehen; Rechtsgrundlagen: Berechtigte Interessen (Art. 6 Abs. 1 S. 1 lit. f) DSGVO).
- **Erhebung von Zugriffsdaten und Logfiles:** Der Zugriff auf unser Onlineangebot wird in Form von sogenannten "Server-Logfiles" protokolliert. Zu den Serverlogfiles können die Adresse und der Name der abgerufenen Webseiten und Dateien, Datum und Uhrzeit des Abrufs, übertragene Datenmengen, Meldung über erfolgreichen Abruf, Browsertyp nebst Version, das Betriebssystem des Nutzers, Referrer URL (die zuvor besuchte Seite) und im Regelfall IP-Adressen und der anfragende Provider gehören. Die Serverlogfiles können zum einen zu Sicherheitszwecken eingesetzt werden, z. B. um eine Überlastung der Server zu vermeiden (insbesondere im Fall von missbräuchlichen Angriffen, sogenannten DDoS-Attacken), und zum anderen, um die Auslastung der Server und ihre Stabilität sicherzustellen; Rechtsgrundlagen: Berechtigte Interessen (Art. 6 Abs. 1 S. 1 lit. f) DSGVO). Löschung von Daten: Logfile-Informationen werden für die Dauer von maximal 30 Tagen gespeichert und danach gelöscht oder anonymisiert. Daten, deren weitere Aufbewahrung zu Beweiszwecken erforderlich ist, sind bis zur endgültigen Klärung des jeweiligen Vorfalls von der Löschung ausgenommen.
### Einsatz von Cookies
Cookies sind kleine Textdateien bzw. sonstige Speichervermerke, die Informationen auf Endgeräten speichern und aus ihnen auslesen. Zum Beispiel, um den Log-in-Status in einem Nutzerkonto, einen Warenkorbinhalt in einem E-Shop, die aufgerufenen Inhalte oder verwendete Funktionen eines Onlineangebots zu speichern. Cookies können ferner in Bezug auf unterschiedliche Anliegen Einsatz finden, etwa zu Zwecken der Funktionsfähigkeit, der Sicherheit und des Komforts von Onlineangeboten sowie der Erstellung von Analysen der Besucherströme.
**Hinweise zur Einwilligung:** Wir setzen Cookies im Einklang mit den gesetzlichen Vorschriften ein. Daher holen wir von den Nutzern eine vorhergehende Einwilligung ein, es sei denn, sie ist laut Gesetzeslage nicht gefordert. Eine Erlaubnis ist insbesondere nicht notwendig, wenn das Speichern und das Auslesen der Informationen, also auch von Cookies, unbedingt erforderlich sind, um den Nutzern einen von ihnen ausdrücklich gewünschten Telemediendienst (also unser Onlineangebot) zur Verfügung zu stellen. Die widerrufliche Einwilligung wird ihnen gegenüber deutlich kommuniziert und enthält die Informationen zur jeweiligen Cookie-Nutzung.
**Hinweise zu datenschutzrechtlichen Rechtsgrundlagen:** Auf welcher datenschutzrechtlichen Grundlage wir die personenbezogenen Daten der Nutzer mithilfe von Cookies verarbeiten, hängt davon ab, ob wir sie um eine Einwilligung bitten. Falls die Nutzer akzeptieren, ist die Rechtsgrundlage der Verwertung ihrer Daten die erklärte Einwilligung. Andernfalls werden die mithilfe von Cookies verwerteten Daten auf Grundlage unserer berechtigten Interessen (z. B. an einem betriebswirtschaftlichen Betrieb unseres Onlineangebots und der Verbesserung seiner Nutzbarkeit) verarbeitet oder, falls dies im Rahmen der Erfüllung unserer vertraglichen Pflichten erfolgt, wenn der Einsatz von Cookies erforderlich ist, um unseren vertraglichen Verpflichtungen nachzukommen. Zu welchen Zwecken die Cookies von uns verwertet werden, darüber klären wir im Laufe dieser Datenschutzerklärung oder im Rahmen von unseren Einwilligungs- und Verarbeitungsprozessen auf.
**Speicherdauer:** Im Hinblick auf die Speicherdauer werden die folgenden Arten von Cookies unterschieden:
- **Temporäre Cookies (auch: Session- oder Sitzungscookies):** Temporäre Cookies werden spätestens gelöscht, nachdem ein Nutzer ein Onlineangebot verlassen und sein Endgerät (z. B. Browser oder mobile Applikation) geschlossen hat.
- **Permanente Cookies:** Permanente Cookies bleiben auch nach dem Schließen des Endgeräts gespeichert. So können beispielsweise der Log-in-Status gespeichert und bevorzugte Inhalte direkt angezeigt werden, wenn der Nutzer eine Website erneut besucht. Ebenso können die mithilfe von Cookies erhobenen Nutzerdaten zur Reichweitenmessung Verwendung finden. Sofern wir Nutzern keine expliziten Angaben zur Art und Speicherdauer von Cookies mitteilen (z. B. im Rahmen der Einholung der Einwilligung), sollten sie davon ausgehen, dass diese permanent sind und die Speicherdauer bis zu zwei Jahre betragen kann.
**Allgemeine Hinweise zum Widerruf und Widerspruch (Opt-out):** Nutzer können die von ihnen abgegebenen Einwilligungen jederzeit widerrufen und zudem einen Widerspruch gegen die Verarbeitung entsprechend den gesetzlichen Vorgaben, auch mittels der Privatsphäre-Einstellungen ihres Browsers, erklären.
- **Verarbeitete Datenarten:** Meta-, Kommunikations- und Verfahrensdaten (z. B. IP-Adressen, Zeitangaben, Identifikationsnummern, beteiligte Personen).
- **Betroffene Personen:** Nutzer (z. B. Webseitenbesucher, Nutzer von Onlinediensten).
- **Rechtsgrundlagen:** Berechtigte Interessen (Art. 6 Abs. 1 S. 1 lit. f) DSGVO). Einwilligung (Art. 6 Abs. 1 S. 1 lit. a) DSGVO).
**Weitere Hinweise zu Verarbeitungsprozessen, Verfahren und Diensten:**
- **Verarbeitung von Cookie-Daten auf Grundlage einer Einwilligung:** Wir setzen eine Einwilligungs-Management-Lösung ein, bei der die Einwilligung der Nutzer zur Verwendung von Cookies oder zu den im Rahmen der Einwilligungs-Management-Lösung genannten Verfahren und Anbietern eingeholt wird. Dieses Verfahren dient der Einholung, Protokollierung, Verwaltung und dem Widerruf von Einwilligungen, insbesondere bezogen auf den Einsatz von Cookies und vergleichbaren Technologien, die zur Speicherung, zum Auslesen und zur Verarbeitung von Informationen auf den Endgeräten der Nutzer eingesetzt werden. Im Rahmen dieses Verfahrens werden die Einwilligungen der Nutzer für die Nutzung von Cookies und die damit verbundenen Verarbeitungen von Informationen, einschließlich der im Einwilligungs-Management-Verfahren genannten spezifischen Verarbeitungen und Anbieter, eingeholt. Die Nutzer haben zudem die Möglichkeit, ihre Einwilligungen zu verwalten und zu widerrufen. Die Einwilligungserklärungen werden gespeichert, um eine erneute Abfrage zu vermeiden und den Nachweis der Einwilligung gemäß der gesetzlichen Anforderungen führen zu können. Die Speicherung erfolgt serverseitig und/oder in einem Cookie (sogenanntes Opt-In-Cookie) oder mittels vergleichbarer Technologien, um die Einwilligung einem spezifischen Nutzer oder dessen Gerät zuordnen zu können. Sofern keine spezifischen Angaben zu den Anbietern von Einwilligungs-Management-Diensten vorliegen, gelten folgende allgemeine Hinweise: Die Dauer der Speicherung der Einwilligung beträgt bis zu zwei Jahre. Dabei wird ein pseudonymer Nutzer-Identifikator erstellt, der zusammen mit dem Zeitpunkt der Einwilligung, den Angaben zum Umfang der Einwilligung (z. B. betreffende Kategorien von Cookies und/oder Diensteanbieter) sowie Informationen über den Browser, das System und das verwendete Endgerät gespeichert wird; Rechtsgrundlagen: Einwilligung (Art. 6 Abs. 1 S. 1 lit. a) DSGVO).
### Kontakt- und Anfrageverwaltung
Bei der Kontaktaufnahme mit uns (z. B. per Post, Kontaktformular, E-Mail, Telefon oder via soziale Medien) sowie im Rahmen bestehender Nutzer- und Geschäftsbeziehungen werden die Angaben der anfragenden Personen verarbeitet, soweit dies zur Beantwortung der Kontaktanfragen und etwaiger angefragter Maßnahmen erforderlich ist.
- **Verarbeitete Datenarten:** Bestandsdaten (z. B. der vollständige Name, Wohnadresse, Kontaktinformationen, Kundennummer, etc.); Kontaktdaten (z. B. Post- und E-Mail-Adressen oder Telefonnummern); Inhaltsdaten (z. B. textliche oder bildliche Nachrichten und Beiträge sowie die sie betreffenden Informationen, wie z. B. Angaben zur Autorenschaft oder Zeitpunkt der Erstellung); Nutzungsdaten (z. B. Seitenaufrufe und Verweildauer, Klickpfade, Nutzungsintensität und -frequenz, verwendete Gerätetypen und Betriebssysteme, Interaktionen mit Inhalten und Funktionen). Meta-, Kommunikations- und Verfahrensdaten (z. B. IP-Adressen, Zeitangaben, Identifikationsnummern, beteiligte Personen).
- **Betroffene Personen:** Kommunikationspartner.
- **Zwecke der Verarbeitung:** Kommunikation; Organisations- und Verwaltungsverfahren; Feedback (z. B. Sammeln von Feedback via Online-Formular). Bereitstellung unseres Onlineangebotes und Nutzerfreundlichkeit.
- **Aufbewahrung und Löschung:** Löschung entsprechend Angaben im Abschnitt "Allgemeine Informationen zur Datenspeicherung und Löschung".
- **Rechtsgrundlagen:** Berechtigte Interessen (Art. 6 Abs. 1 S. 1 lit. f) DSGVO). Vertragserfüllung und vorvertragliche Anfragen (Art. 6 Abs. 1 S. 1 lit. b) DSGVO).
**Weitere Hinweise zu Verarbeitungsprozessen, Verfahren und Diensten:**
- **Kontaktformular:** Bei Kontaktaufnahme über unser Kontaktformular, per E-Mail oder anderen Kommunikationswegen, verarbeiten wir die uns übermittelten personenbezogenen Daten zur Beantwortung und Bearbeitung des jeweiligen Anliegens. Dies umfasst in der Regel Angaben wie Name, Kontaktinformationen und gegebenenfalls weitere Informationen, die uns mitgeteilt werden und zur angemessenen Bearbeitung erforderlich sind. Wir nutzen diese Daten ausschließlich für den angegebenen Zweck der Kontaktaufnahme und Kommunikation; Rechtsgrundlagen: Vertragserfüllung und vorvertragliche Anfragen (Art. 6 Abs. 1 S. 1 lit. b) DSGVO), Berechtigte Interessen (Art. 6 Abs. 1 S. 1 lit. f) DSGVO).
### Änderung und Aktualisierung
Wir bitten Sie, sich regelmäßig über den Inhalt unserer Datenschutzerklärung zu informieren. Wir passen die Datenschutzerklärung an, sobald die Änderungen der von uns durchgeführten Datenverarbeitungen dies erforderlich machen. Wir informieren Sie, sobald durch die Änderungen eine Mitwirkungshandlung Ihrerseits (z. B. Einwilligung) oder eine sonstige individuelle Benachrichtigung erforderlich wird.
Sofern wir in dieser Datenschutzerklärung Adressen und Kontaktinformationen von Unternehmen und Organisationen angeben, bitten wir zu beachten, dass die Adressen sich über die Zeit ändern können und bitten die Angaben vor Kontaktaufnahme zu prüfen.
""",
date=""
)
))

View File

@ -0,0 +1 @@
from .database_service import DatabaseService

View File

@ -0,0 +1,97 @@
import rio
from from_root import from_root
from ezgg_website.components import MemberInfo
from ezgg_website.components.member_card import MemberInfo
# @ToDo: Make real database service at some point
class DatabaseService:
def __init__(self):
pass
def get_members(self) -> list[MemberInfo]:
return [
MemberInfo(
picture_path=from_root("ezgg_website/assets/member_pictures/david.png"),
name="David \"Typhus\" R.",
position="1. Vorsitzender",
entry_date="29.10.2023",
contact_mail="davidr.develop@gmail.com",
contact_steam="https://steamcommunity.com/id/originaltyphus"
), MemberInfo(
picture_path=from_root("ezgg_website/assets/member_pictures/jule.png"),
name="Julia \"Ravenchild\" A.",
position="2. Vorsitzende",
entry_date="29.10.2023",
contact_mail="Julia-albring95@hotmail.de",
contact_steam="https://steamcommunity.com/profiles/76561198089911312"
), MemberInfo(
picture_path=from_root("ezgg_website/assets/member_pictures/jessy.png"),
name="Jessy \"JessySixx\" R.",
position="Schatzmeisterin",
entry_date="29.10.2023",
contact_mail=None,
contact_steam=None
), MemberInfo(
picture_path=from_root("ezgg_website/assets/member_pictures/anon.png"),
name="Tim \"Matschwicht\" B.",
position="Mitglied",
entry_date="29.10.2023",
contact_mail=None,
contact_steam=None
), MemberInfo(
picture_path=from_root("ezgg_website/assets/member_pictures/anon.png"),
name="Dennis \"Goodman\" P.",
position="Mitglied",
entry_date="29.10.2023",
contact_mail=None,
contact_steam=None
), MemberInfo(
picture_path=from_root("ezgg_website/assets/member_pictures/tom.png"),
name="Tom \"Tcprod\" C.",
position="Mitglied",
entry_date="29.10.2023",
contact_mail=None,
contact_steam=None
), MemberInfo(
picture_path=from_root("ezgg_website/assets/member_pictures/anon.png"),
name="Chris \"Meliodas\" K.",
position="Mitglied",
entry_date="29.10.2023",
contact_mail=None,
contact_steam=None
)
]
def get_picture_paths(self) -> list[rio.URL]:
return [
# BK-LAN 18
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=c345a1b8-0c74-4d8f-8f3d-c747d04c2c12&photo_nr=1"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=c345a1b8-0c74-4d8f-8f3d-c747d04c2c12&photo_nr=2"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=c345a1b8-0c74-4d8f-8f3d-c747d04c2c12&photo_nr=3"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=c345a1b8-0c74-4d8f-8f3d-c747d04c2c12&photo_nr=4"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=c345a1b8-0c74-4d8f-8f3d-c747d04c2c12&photo_nr=5"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=c345a1b8-0c74-4d8f-8f3d-c747d04c2c12&photo_nr=6"),
# BL 46
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=4abbc55b-fc19-445a-9f84-b07c8d4ced12&photo_nr=1"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=4abbc55b-fc19-445a-9f84-b07c8d4ced12&photo_nr=2"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=4abbc55b-fc19-445a-9f84-b07c8d4ced12&photo_nr=3"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=4abbc55b-fc19-445a-9f84-b07c8d4ced12&photo_nr=4"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=4abbc55b-fc19-445a-9f84-b07c8d4ced12&photo_nr=5"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=4abbc55b-fc19-445a-9f84-b07c8d4ced12&photo_nr=6"),
# BL 45
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=d4c862f1-65cd-4051-9525-8be408ef80a8&photo_nr=1"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=d4c862f1-65cd-4051-9525-8be408ef80a8&photo_nr=2"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=d4c862f1-65cd-4051-9525-8be408ef80a8&photo_nr=3"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=d4c862f1-65cd-4051-9525-8be408ef80a8&photo_nr=4"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=d4c862f1-65cd-4051-9525-8be408ef80a8&photo_nr=5"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=d4c862f1-65cd-4051-9525-8be408ef80a8&photo_nr=6"),
# BL 42
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=235bf57f-c65c-4b5f-8029-061775eeec45&photo_nr=1"),
rio.URL("https://verwaltung.ezgg-ev.de/adm_program/modules/photos/photo_show.php?photo_uuid=235bf57f-c65c-4b5f-8029-061775eeec45&photo_nr=2")
]

BIN
requirements.txt Normal file

Binary file not shown.

3
rio.toml Normal file
View File

@ -0,0 +1,3 @@
[app]
app_type = "website" # This is either "website" or "app"
main_module = "ezgg_website" # The name of your Python module