from datetime import date from hashlib import sha256 from typing import Optional from email_validator import validate_email, EmailNotValidError from from_root import from_root from rio import Component, Column, Button, Color, TextStyle, Text, TextInput, Row, Image, event, Spacer, DateInput, \ TextInputChangeEvent, NoFileSelectedError from src.ez_lan_manager.services.UserService import UserService, NameNotAllowedError from src.ez_lan_manager.services.ConfigurationService import ConfigurationService from src.ez_lan_manager.types.SessionStorage import SessionStorage from src.ez_lan_manager.types.User import User class UserEditForm(Component): is_own_profile: bool = True profile_picture: Optional[bytes] = None user: Optional[User] = None input_user_name: str = "" input_user_mail: str = "" input_user_first_name: str = "" input_user_last_name: str = "" input_password_1: str = "" input_password_2: str = "" input_birthday: date = date.today() is_email_valid: bool = True result_text: str = "" result_success: bool = True @event.on_populate async def on_populate(self) -> None: await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Profil bearbeiten") if self.is_own_profile: self.user = await self.session[UserService].get_user(self.session[SessionStorage].user_id) self.profile_picture = await self.session[UserService].get_profile_picture(self.user.user_id) else: self.profile_picture = await self.session[UserService].get_profile_picture(self.user.user_id) self.input_user_name = self.user.user_name self.input_user_mail = self.user.user_mail self.input_user_first_name = self.optional_str_to_str(self.user.user_first_name) self.input_user_last_name = self.optional_str_to_str(self.user.user_last_name) self.input_birthday = self.user.user_birth_day if self.user.user_birth_day else date.today() @staticmethod def optional_str_to_str(s: Optional[str]) -> str: if s: return s return "" def on_email_changed(self, change_event: TextInputChangeEvent) -> None: try: validate_email(change_event.text, check_deliverability=False) self.is_email_valid = True except EmailNotValidError: self.is_email_valid = False async def upload_new_pfp(self) -> None: try: new_pfp = await self.session.pick_file(file_types=("png", "jpg", "jpeg"), multiple=False) except NoFileSelectedError: self.result_text = "Keine Datei ausgewählt!" self.result_success = False return if new_pfp.size_in_bytes > 2 * 1_000_000: self.result_text = "Bild zu groß! (> 2MB)" self.result_success = False return image_data = await new_pfp.read_bytes() await self.session[UserService].set_profile_picture(self.user.user_id, image_data) self.profile_picture = image_data self.result_text = "Gespeichert!" self.result_success = True async def remove_profile_picture(self) -> None: await self.session[UserService].remove_profile_picture(self.user.user_id) self.profile_picture = None self.result_text = "Profilbild entfernt!" self.result_success = True async def on_save_pressed(self) -> None: if not all((self.is_email_valid, self.input_user_name, self.input_user_mail)): self.result_text = "Ungültige Werte!" self.result_success = False return if len(self.input_password_1.strip()) > 0: if self.input_password_1.strip() != self.input_password_2.strip(): self.result_text = "Passwörter nicht gleich!" self.result_success = False return self.user.user_mail = self.input_user_mail if self.input_birthday == date.today(): self.user.user_birth_day = None else: self.user.user_birth_day = self.input_birthday self.user.user_first_name = self.input_user_first_name self.user.user_last_name = self.input_user_last_name self.user.user_name = self.input_user_name if len(self.input_password_1.strip()) > 0: self.user.user_password = sha256(self.input_password_1.strip().encode(encoding="utf-8")).hexdigest() try: await self.session[UserService].update_user(self.user) except NameNotAllowedError: self.result_text = "Ungültige Zeichen in Nutzername" self.result_success = False return self.result_text = "Gespeichert!" self.result_success = True def build(self) -> Component: pfp_image_container = Image( from_root("src/ez_lan_manager/assets/img/anon_pfp.png") if self.profile_picture is None else self.profile_picture, align_x=0.5, min_width=10, min_height=10, margin_top=1, margin_bottom=1 ) return Column( pfp_image_container, Button( content=Text( "Neues Bild hochladen", style=TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9) ), align_x=0.5, margin_bottom=1, shape="rectangle", style="major", color="primary", on_press=self.upload_new_pfp ) if self.is_own_profile else Button( content=Text( "Bild löschen", style=TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9) ), align_x=0.5, margin_bottom=1, shape="rectangle", style="major", color="primary", on_press=self.remove_profile_picture ), Row( TextInput( label=f"{'Deine ' if self.is_own_profile else ''}User-ID", text=str(self.user.user_id), is_sensitive=False, margin_left=1, grow_x=False ), TextInput( label=f"{'Dein ' if self.is_own_profile else ''}Nickname", text=self.bind().input_user_name, is_sensitive=not self.is_own_profile, margin_left=1, margin_right=1, grow_x=True ), margin_bottom=1 ), TextInput( label="E-Mail Adresse", text=self.bind().input_user_mail, margin_left=1, margin_right=1, margin_bottom=1, grow_x=True, is_valid=self.is_email_valid, on_change=self.on_email_changed ), Row( TextInput( label="Vorname", text=self.bind().input_user_first_name, margin_left=1, margin_right=1, grow_x=True ), TextInput( label="Nachname", text=self.bind().input_user_last_name, margin_right=1, grow_x=True ), margin_bottom=1 ), DateInput( value=self.bind().input_birthday, label="Geburtstag", margin_left=1, margin_right=1, margin_bottom=1, grow_x=True ), TextInput( label="Neues Passwort setzen", text=self.bind().input_password_1, margin_left=1, margin_right=1, margin_bottom=1, grow_x=True, is_secret=True ), TextInput( label="Neues Passwort wiederholen", text=self.bind().input_password_2, margin_left=1, margin_right=1, margin_bottom=1, grow_x=True, is_secret=True ), Row( Text( text=self.bind().result_text, style=TextStyle(fill=self.session.theme.success_color if self.result_success else self.session.theme.danger_color), margin_left=1 ), Button( content=Text( "Speichern", 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_save_pressed ), ) ) if self.user else Spacer()