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

View File

@ -89,7 +89,7 @@ if __name__ == "__main__":
Page( Page(
name="Contact", name="Contact",
page_url="contact", page_url="contact",
build=lambda: pages.PlaceholderPage(placeholder_name="Kontakt"), build=pages.ContactPage,
), ),
Page( Page(
name="Imprint", 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): class EditProfilePage(Component):
display_printing: list[bool] = [False]
@staticmethod @staticmethod
def optional_date_to_str(d: Optional[date]) -> str: def optional_date_to_str(d: Optional[date]) -> str:
if not d: if not d:
@ -63,6 +65,10 @@ class EditProfilePage(Component):
await self.display_save_result_animation(True) await self.display_save_result_animation(True)
async def display_save_result_animation(self, success: bool, optional_text: Optional[str] = None) -> None: 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 = "" self.saved_text.text = ""
if success: if success:
self.saved_text.style = TextStyle( self.saved_text.style = TextStyle(
@ -84,6 +90,7 @@ class EditProfilePage(Component):
self.saved_text.text = self.saved_text.text + c self.saved_text.text = self.saved_text.text + c
await self.saved_text.force_refresh() await self.saved_text.force_refresh()
await sleep(0.08) await sleep(0.08)
self.display_printing[0] = False
async def on_save_pressed(self) -> None: async def on_save_pressed(self) -> None:
if not all((self.email_input.is_valid, self.birthday_input.is_valid)): 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 import ConfigurationService
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox 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 from src.ez_lan_manager.pages import BasePage
class ImprintPage(Component): class ImprintPage(Component):

View File

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

View File

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

View File

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

View File

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