From 81ec29cda1ff66b61d86701a3fc9562140e781d9 Mon Sep 17 00:00:00 2001 From: David Rodenkirchen Date: Tue, 27 Aug 2024 14:50:42 +0200 Subject: [PATCH] add Contact Page --- config/config.example.toml | 1 + src/EzLanManager.py | 2 +- src/ez_lan_manager/pages/ContactPage.py | 164 ++++++++++++++++++ src/ez_lan_manager/pages/EditProfile.py | 7 + src/ez_lan_manager/pages/ImprintPage.py | 3 +- src/ez_lan_manager/pages/RegisterPage.py | 8 + src/ez_lan_manager/pages/__init__.py | 1 + .../services/ConfigurationService.py | 3 +- .../types/ConfigurationTypes.py | 1 + 9 files changed, 186 insertions(+), 4 deletions(-) create mode 100644 src/ez_lan_manager/pages/ContactPage.py diff --git a/config/config.example.toml b/config/config.example.toml index aeb244d..918eeba 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -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" diff --git a/src/EzLanManager.py b/src/EzLanManager.py index da0ffc7..0fa8781 100644 --- a/src/EzLanManager.py +++ b/src/EzLanManager.py @@ -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", diff --git a/src/ez_lan_manager/pages/ContactPage.py b/src/ez_lan_manager/pages/ContactPage.py new file mode 100644 index 0000000..03dd126 --- /dev/null +++ b/src/ez_lan_manager/pages/ContactPage.py @@ -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 + ) + diff --git a/src/ez_lan_manager/pages/EditProfile.py b/src/ez_lan_manager/pages/EditProfile.py index fdbaeb8..ff1043e 100644 --- a/src/ez_lan_manager/pages/EditProfile.py +++ b/src/ez_lan_manager/pages/EditProfile.py @@ -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)): diff --git a/src/ez_lan_manager/pages/ImprintPage.py b/src/ez_lan_manager/pages/ImprintPage.py index 4083976..eba4be5 100644 --- a/src/ez_lan_manager/pages/ImprintPage.py +++ b/src/ez_lan_manager/pages/ImprintPage.py @@ -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): diff --git a/src/ez_lan_manager/pages/RegisterPage.py b/src/ez_lan_manager/pages/RegisterPage.py index 7ed1f40..3f82a45 100644 --- a/src/ez_lan_manager/pages/RegisterPage.py +++ b/src/ez_lan_manager/pages/RegisterPage.py @@ -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: diff --git a/src/ez_lan_manager/pages/__init__.py b/src/ez_lan_manager/pages/__init__.py index 7a8b942..a0f93bc 100644 --- a/src/ez_lan_manager/pages/__init__.py +++ b/src/ez_lan_manager/pages/__init__.py @@ -7,3 +7,4 @@ from .EditProfile import EditProfilePage from .ForgotPassword import ForgotPasswordPage from .RegisterPage import RegisterPage from .ImprintPage import ImprintPage +from .ContactPage import ContactPage diff --git a/src/ez_lan_manager/services/ConfigurationService.py b/src/ez_lan_manager/services/ConfigurationService.py index f379680..9f10d69 100644 --- a/src/ez_lan_manager/services/ConfigurationService.py +++ b/src/ez_lan_manager/services/ConfigurationService.py @@ -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...") diff --git a/src/ez_lan_manager/types/ConfigurationTypes.py b/src/ez_lan_manager/types/ConfigurationTypes.py index da5e6cf..e1d06d2 100644 --- a/src/ez_lan_manager/types/ConfigurationTypes.py +++ b/src/ez_lan_manager/types/ConfigurationTypes.py @@ -53,6 +53,7 @@ class LanInfo: ticket_info: TicketInfo date_from: datetime date_till: datetime + organizer_mail: str @dataclass(frozen=True) class SeatingConfiguration: