add Contact Page

This commit is contained in:
David Rodenkirchen 2024-08-27 14:50:42 +02:00
parent ab01c3d9a4
commit 81ec29cda1
9 changed files with 186 additions and 4 deletions

View File

@ -6,6 +6,7 @@
prices={ "LUXUS" = 3000, "NORMAL" = 2500 } # Eurocent
date_from="2024-10-30 15:00:00"
date_till="2024-11-01 12:00:00"
organizer_mail="tech@example.com"
[database]
db_user="demo_user"

View File

@ -89,7 +89,7 @@ if __name__ == "__main__":
Page(
name="Contact",
page_url="contact",
build=lambda: pages.PlaceholderPage(placeholder_name="Kontakt"),
build=pages.ContactPage,
),
Page(
name="Imprint",

View File

@ -0,0 +1,164 @@
from asyncio import sleep
from datetime import datetime, timedelta
from rio import Text, Column, TextStyle, Component, event, TextInput, MultiLineTextInput, Row, Button
from src.ez_lan_manager import ConfigurationService, UserService, MailingService
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
from src.ez_lan_manager.pages import BasePage
from src.ez_lan_manager.types.SessionStorage import SessionStorage
class ContactPage(Component):
# Workaround: Can not reassign this value without rio triggering refresh
# Using list to bypass this behavior
last_message_sent: list[datetime] = [datetime(day=1, month=1, year=2000)]
display_printing: list[bool] = [False]
@event.on_populate
async def on_populate(self) -> None:
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Kontakt")
async def display_info_animation(self, success: bool, text: str) -> None:
if self.display_printing[0]:
return
else:
self.display_printing[0] = True
self.info_text.text = ""
if success:
self.info_text.style = TextStyle(
fill=self.session.theme.success_color,
font_size=0.9
)
for c in text:
self.info_text.text = self.info_text.text + c
await self.info_text.force_refresh()
await sleep(0.08)
else:
self.info_text.style = TextStyle(
fill=self.session.theme.danger_color,
font_size=0.9
)
for c in text:
self.info_text.text = self.info_text.text + c
await self.info_text.force_refresh()
await sleep(0.08)
self.display_printing[0] = False
async def on_send_pressed(self) -> None:
self.submit_button.is_loading = True
await self.submit_button.force_refresh()
now = datetime.now()
if not self.email_input.text:
self.is_send_button_loading = False
await self.display_info_animation(False, "E-Mail darf nicht leer sein!")
return
if not self.subject_input.text:
self.is_send_button_loading = False
await self.display_info_animation(False, "Betreff darf nicht leer sein!")
return
if not self.message_input.text:
self.is_send_button_loading = False
await self.display_info_animation(False, "Nachricht darf nicht leer sein!")
return
if (now - self.last_message_sent[0]) < timedelta(minutes=1):
await self.display_info_animation(False, "Immer mit der Ruhe!")
return
mail_recipient = self.session[ConfigurationService].get_lan_info().organizer_mail
msg = (f"Kontaktformular vom {now.strftime('%d.%m.%Y %H:%M')}:\n\n"
f"Betreff: {self.subject_input.text}\n"
f"Absender: {self.email_input.text}\n\n"
f"Inhalt:\n"
f"{self.message_input.text}\n")
await self.session[MailingService].send_email("Kontaktformular-Mitteilung", msg, mail_recipient)
self.last_message_sent[0] = datetime.now()
self.submit_button.is_loading = False
await self.display_info_animation(True, "Nachricht erfolgreich gesendet!")
def build(self) -> Component:
if self.session[SessionStorage].user_id is not None:
user = self.session[UserService].get_user(self.session[SessionStorage].user_id)
else:
user = None
self.info_text = Text(
"",
margin_top=2,
margin_bottom=1,
align_x=0.1
)
self.email_input = TextInput(
label="E-Mail Adresse",
text="" if not user else user.user_mail,
margin_left=1,
margin_right=1,
margin_bottom=1,
grow_x=True
)
self.subject_input = TextInput(
label="Betreff",
text="",
margin_left=1,
margin_right=1,
margin_bottom=1,
grow_x=True
)
self.message_input = MultiLineTextInput(
label="Deine Nachricht an uns",
text="",
margin_left=1,
margin_right=1,
margin_bottom=1,
min_height=5
)
self.submit_button = Button(
content=Text(
"Absenden",
style=TextStyle(fill=self.session.theme.success_color, font_size=0.9),
align_x=0.2
),
align_x=0.9,
margin_top=2,
margin_bottom=1,
shape="rectangle",
style="major",
color="primary",
on_press=self.on_send_pressed
)
return BasePage(
content=Column(
MainViewContentBox(
Column(
Text(
text="Kontakt",
style=TextStyle(
fill=self.session.theme.background_color,
font_size=1.2
),
margin_top=2,
margin_bottom=1,
align_x=0.5
),
self.email_input,
self.subject_input,
self.message_input,
Row(
self.info_text,
self.submit_button,
)
)
),
align_y=0
),
grow_x=True
)

View File

@ -15,6 +15,8 @@ from src.ez_lan_manager.types.User import User
class EditProfilePage(Component):
display_printing: list[bool] = [False]
@staticmethod
def optional_date_to_str(d: Optional[date]) -> str:
if not d:
@ -63,6 +65,10 @@ class EditProfilePage(Component):
await self.display_save_result_animation(True)
async def display_save_result_animation(self, success: bool, optional_text: Optional[str] = None) -> None:
if self.display_printing[0]:
return
else:
self.display_printing[0] = True
self.saved_text.text = ""
if success:
self.saved_text.style = TextStyle(
@ -84,6 +90,7 @@ class EditProfilePage(Component):
self.saved_text.text = self.saved_text.text + c
await self.saved_text.force_refresh()
await sleep(0.08)
self.display_printing[0] = False
async def on_save_pressed(self) -> None:
if not all((self.email_input.is_valid, self.birthday_input.is_valid)):

View File

@ -1,8 +1,7 @@
from rio import Text, Column, Rectangle, TextStyle, Component, event, Link, Color
from rio import Text, Column, TextStyle, Component, event, Link, Color
from src.ez_lan_manager import ConfigurationService
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
from src.ez_lan_manager.components.NewsPost import NewsPost
from src.ez_lan_manager.pages import BasePage
class ImprintPage(Component):

View File

@ -14,6 +14,8 @@ MINIMUM_PASSWORD_LENGTH = 6
logger = logging.getLogger(__name__.split(".")[-1])
class RegisterPage(Component):
display_printing: list[bool] = [False]
def on_pw_change(self, _: TextInputChangeEvent) -> None:
if not (self.pw_1.text == self.pw_2.text) or len(self.pw_1.text) < MINIMUM_PASSWORD_LENGTH:
self.pw_1.is_valid = False
@ -86,6 +88,11 @@ class RegisterPage(Component):
await self.display_save_result_animation(True, optional_text="Erfolgreich registriert!")
async def display_save_result_animation(self, success: bool, optional_text: Optional[str] = None) -> None:
if self.display_printing[0]:
return
else:
self.display_printing[0] = True
self.info_text.text = ""
if success:
self.info_text.style = TextStyle(
@ -107,6 +114,7 @@ class RegisterPage(Component):
self.info_text.text = self.info_text.text + c
await self.info_text.force_refresh()
await sleep(0.04)
self.display_printing[0] = False
@event.on_populate
async def on_populate(self) -> None:

View File

@ -7,3 +7,4 @@ from .EditProfile import EditProfilePage
from .ForgotPassword import ForgotPasswordPage
from .RegisterPage import RegisterPage
from .ImprintPage import ImprintPage
from .ContactPage import ContactPage

View File

@ -69,7 +69,8 @@ class ConfigurationService:
iteration=lan_info["iteration"],
ticket_info=ticket_info,
date_from=datetime.strptime(lan_info["date_from"], "%Y-%m-%d %H:%M:%S"),
date_till=datetime.strptime(lan_info["date_till"], "%Y-%m-%d %H:%M:%S")
date_till=datetime.strptime(lan_info["date_till"], "%Y-%m-%d %H:%M:%S"),
organizer_mail=lan_info["organizer_mail"]
)
except KeyError:
logger.fatal("Error loading LAN Info, exiting...")

View File

@ -53,6 +53,7 @@ class LanInfo:
ticket_info: TicketInfo
date_from: datetime
date_till: datetime
organizer_mail: str
@dataclass(frozen=True)
class SeatingConfiguration: