fix login box

This commit is contained in:
David Rodenkirchen 2024-11-27 14:33:21 +01:00
parent b1dc4071cf
commit 951e6c8dce
3 changed files with 208 additions and 189 deletions

View File

@ -0,0 +1,102 @@
from typing import Callable
from rio import Component, TextStyle, Color, TextInput, Button, Text, Rectangle, Column, Row, Spacer, TextInputChangeEvent
from src.ez_lan_manager.services.UserService import UserService
from src.ez_lan_manager.types.SessionStorage import SessionStorage
class LoginBox(Component):
status_change_cb: Callable
TEXT_STYLE = TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9)
user_name_input_text: list[str] = [""]
password_input_text: list[str] = [""]
user_name_input_is_valid = True
password_input_is_valid = True
login_button_is_loading = False
async def _on_login_pressed(self) -> None:
if await self.session[UserService].is_login_valid(self.user_name_input_text[0], self.password_input_text[0]):
self.user_name_input_is_valid = True
self.password_input_is_valid = True
self.login_button_is_loading = False
await self.session[SessionStorage].set_user_id((await self.session[UserService].get_user(self.user_name_input_text[0])).user_id)
await self.status_change_cb()
else:
self.user_name_input_is_valid = False
self.password_input_is_valid = False
self.login_button_is_loading = False
await self.force_refresh()
def build(self) -> Component:
def set_user_name_input_text(e: TextInputChangeEvent) -> None:
self.user_name_input_text[0] = e.text
def set_password_input_text(e: TextInputChangeEvent) -> None:
self.password_input_text[0] = e.text
user_name_input = TextInput(
text="",
label="Benutzername",
accessibility_label="Benutzername",
min_height=0.5,
on_confirm=lambda _: self._on_login_pressed(),
on_change=set_user_name_input_text,
is_valid=self.user_name_input_is_valid
)
password_input = TextInput(
text="",
label="Passwort",
accessibility_label="Passwort",
is_secret=True,
on_confirm=lambda _: self._on_login_pressed(),
on_change=set_password_input_text,
is_valid=self.password_input_is_valid
)
login_button = Button(
Text("LOGIN", style=self.TEXT_STYLE, justify="center"),
shape="rectangle",
style="minor",
color="secondary",
margin_bottom=0.4,
on_press=self._on_login_pressed
)
register_button = Button(
Text("REG", style=self.TEXT_STYLE, justify="center"),
shape="rectangle",
style="minor",
color="secondary",
on_press=lambda: self.session.navigate_to("./register")
)
forgot_password_button = Button(
Text("LST PWD", style=self.TEXT_STYLE, justify="center"),
shape="rectangle",
style="minor",
color="secondary",
on_press=lambda: self.session.navigate_to("./forgot-password")
)
return Rectangle(
content=Column(
user_name_input,
password_input,
Column(
Row(
login_button
),
Row(
register_button,
Spacer(),
forgot_password_button,
proportions=(49, 2, 49)
)
),
spacing=0.4
),
fill=Color.TRANSPARENT,
min_height=8,
min_width=12,
align_x=0.5,
margin_top=0.3,
margin_bottom=2
)

View File

@ -1,198 +1,15 @@
import logging import logging
from random import choice
from typing import Optional
from rio import Component, Column, Text, Row, Rectangle, Button, TextStyle, Color, Spacer, TextInput, Link, event from rio import Component
from src.ez_lan_manager.components.LoginBox import LoginBox
from src.ez_lan_manager import UserService from src.ez_lan_manager.components.UserInfoBox import UserInfoBox
from src.ez_lan_manager.components.UserInfoBoxButton import UserInfoBoxButton
from src.ez_lan_manager.services.AccountingService import AccountingService
from src.ez_lan_manager.services.TicketingService import TicketingService
from src.ez_lan_manager.services.SeatingService import SeatingService
from src.ez_lan_manager.types.Seat import Seat
from src.ez_lan_manager.types.Ticket import Ticket
from src.ez_lan_manager.types.User import User
from src.ez_lan_manager.types.SessionStorage import SessionStorage from src.ez_lan_manager.types.SessionStorage import SessionStorage
logger = logging.getLogger(__name__.split(".")[-1]) logger = logging.getLogger(__name__.split(".")[-1])
class StatusButton(Component):
STYLE = TextStyle(fill=Color.from_hex("121212"), font_size=0.5)
label: str
target_url: str
enabled: bool
def build(self) -> Component:
return Link(
content=Button(
content=Text(self.label, style=self.STYLE, justify="center"),
shape="rectangle",
style="major",
color="success" if self.enabled else "danger",
grow_x=True,
margin_left=0.6,
margin_right=0.6,
margin_top=0.6
),
target_url=self.target_url,
align_y=0.5,
grow_y=False
)
class UserInfoAndLoginBox(Component): class UserInfoAndLoginBox(Component):
TEXT_STYLE = TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9)
show_login: bool = True
user: Optional[User] = None
user_balance: Optional[int] = 0
user_ticket: Optional[Ticket] = None
user_seat: Optional[Seat] = None
@event.on_populate
async def async_init(self) -> None:
if self.session[SessionStorage].user_id:
self.user = await self.session[UserService].get_user(self.session[SessionStorage].user_id)
self.user_balance = await self.session[AccountingService].get_balance(self.user.user_id)
self.user_ticket = await self.session[TicketingService].get_user_ticket(self.user.user_id)
self.user_seat = await self.session[SeatingService].get_user_seat(self.user.user_id)
@staticmethod
def get_greeting() -> str:
return choice(["Guten Tacho", "Tuten Gag", "Servus", "Moinjour", "Hallöchen", "Heyho", "Moinsen"])
# @FixMe: If the user logs out and then tries to log back in, it does not work
# If the user navigates to another page and then tries again. It works.
# When fixed, remove the workaround below.
async def logout(self) -> None:
self.show_login = True
await self.session[SessionStorage].clear()
await self.force_refresh()
# @FixMe: Workaround for the bug described above. Navigating to another page solves the issue.
# Yet, this is not desired behavior.
subpage = str(self.session.active_page_url)
if subpage.endswith("/") or subpage.endswith("news"):
self.session.navigate_to("./overview")
else:
self.session.navigate_to("./news")
async def _on_login_pressed(self) -> None:
user_name = self.user_name_input.text.lower()
if await self.session[UserService].is_login_valid(user_name, self.password_input.text):
self.user_name_input.is_valid = True
self.password_input.is_valid = True
self.login_button.is_loading = False
await self.session[SessionStorage].set_user_id((await self.session[UserService].get_user(user_name)).user_id)
await self.async_init()
self.show_login = False
else:
self.user_name_input.is_valid = False
self.password_input.is_valid = False
self.login_button.is_loading = False
def build(self) -> Component: def build(self) -> Component:
self.user_name_input = TextInput( if self.session[SessionStorage].user_id is None:
text="", return LoginBox(status_change_cb=self.force_refresh)
label="Benutzername",
accessibility_label="Benutzername",
min_height=0.5,
on_confirm=lambda _: self._on_login_pressed()
)
self.password_input = TextInput(
text="",
label="Passwort",
accessibility_label="Passwort",
is_secret=True,
on_confirm=lambda _: self._on_login_pressed()
)
self.login_button = Button(
Text("LOGIN", style=self.TEXT_STYLE, justify="center"),
shape="rectangle",
style="minor",
color="secondary",
margin_bottom=0.4,
on_press=self._on_login_pressed
)
self.register_button = Button(
Text("REG", style=self.TEXT_STYLE, justify="center"),
shape="rectangle",
style="minor",
color="secondary",
on_press=lambda: self.session.navigate_to("./register")
)
self.forgot_password_button = Button(
Text("LST PWD", style=self.TEXT_STYLE, justify="center"),
shape="rectangle",
style="minor",
color="secondary",
on_press=lambda: self.session.navigate_to("./forgot-password")
)
if self.user is None and self.session[SessionStorage].user_id is None:
return Rectangle(
content=Column(
self.user_name_input,
self.password_input,
Column(
Row(
self.login_button
),
Row(
self.register_button,
Spacer(),
self.forgot_password_button,
proportions=(49, 2, 49)
)
),
spacing=0.4
),
fill=Color.TRANSPARENT,
min_height=8,
min_width=12,
align_x=0.5,
margin_top=0.3,
margin_bottom=2
)
elif self.user is None and self.session[SessionStorage].user_id is not None:
return Rectangle(
content=Column(),
fill=Color.TRANSPARENT,
min_height=8,
min_width=12,
align_x=0.5,
margin_top=0.3,
margin_bottom=2
)
else: else:
return Rectangle( return UserInfoBox(status_change_cb=self.force_refresh)
content=Column(
Text(f"{self.get_greeting()},", style=TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9), justify="center"),
Text(f"{self.user.user_name}", style=TextStyle(fill=Color.from_hex("02dac5"), font_size=1.2), justify="center"),
Row(
StatusButton(label="TICKET", target_url="./buy_ticket",
enabled=self.user_ticket is not None),
StatusButton(label="SITZPLATZ", target_url="./seating",
enabled=self.user_seat is not None),
proportions=(50, 50),
grow_y=False
),
UserInfoBoxButton("Profil bearbeiten", "./edit-profile"),
UserInfoBoxButton(f"Guthaben: {self.session[AccountingService].make_euro_string_from_int(self.user_balance)}", "./account"),
Button(
content=Text("Ausloggen", style=TextStyle(fill=Color.from_hex("02dac5"), font_size=0.6)),
shape="rectangle",
style="minor",
color="secondary",
grow_x=True,
margin_left=0.6,
margin_right=0.6,
margin_top=0.6,
on_press=self.logout
)
),
fill=Color.TRANSPARENT,
min_height=8,
min_width=12,
align_x=0.5,
margin_top=0.3,
margin_bottom=2
)

View File

@ -0,0 +1,100 @@
from random import choice
from typing import Optional, Callable
from rio import Component, TextStyle, Color, Button, Text, Rectangle, Column, Row, Spacer, Link, event
from src.ez_lan_manager.components.UserInfoBoxButton import UserInfoBoxButton
from src.ez_lan_manager.services.UserService import UserService
from src.ez_lan_manager.services.AccountingService import AccountingService
from src.ez_lan_manager.services.TicketingService import TicketingService
from src.ez_lan_manager.services.SeatingService import SeatingService
from src.ez_lan_manager.types.Seat import Seat
from src.ez_lan_manager.types.Ticket import Ticket
from src.ez_lan_manager.types.User import User
from src.ez_lan_manager.types.SessionStorage import SessionStorage
class StatusButton(Component):
STYLE = TextStyle(fill=Color.from_hex("121212"), font_size=0.5)
label: str
target_url: str
enabled: bool
def build(self) -> Component:
return Link(
content=Button(
content=Text(self.label, style=self.STYLE, justify="center"),
shape="rectangle",
style="major",
color="success" if self.enabled else "danger",
grow_x=True,
margin_left=0.6,
margin_right=0.6,
margin_top=0.6
),
target_url=self.target_url,
align_y=0.5,
grow_y=False
)
class UserInfoBox(Component):
status_change_cb: Callable
TEXT_STYLE = TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9)
user: Optional[User] = None
user_balance: Optional[int] = 0
user_ticket: Optional[Ticket] = None
user_seat: Optional[Seat] = None
@staticmethod
def get_greeting() -> str:
return choice(["Guten Tacho", "Tuten Gag", "Servus", "Moinjour", "Hallöchen", "Heyho", "Moinsen"])
async def logout(self) -> None:
await self.session[SessionStorage].clear()
self.user = None
await self.status_change_cb()
@event.on_populate
async def async_init(self) -> None:
if self.session[SessionStorage].user_id:
self.user = await self.session[UserService].get_user(self.session[SessionStorage].user_id)
self.user_balance = await self.session[AccountingService].get_balance(self.user.user_id)
self.user_ticket = await self.session[TicketingService].get_user_ticket(self.user.user_id)
self.user_seat = await self.session[SeatingService].get_user_seat(self.user.user_id)
def build(self) -> Component:
if not self.user:
return Spacer()
return Rectangle(
content=Column(
Text(f"{self.get_greeting()},", style=TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9), justify="center"),
Text(f"{self.user.user_name}", style=TextStyle(fill=Color.from_hex("02dac5"), font_size=1.2), justify="center"),
Row(
StatusButton(label="TICKET", target_url="./buy_ticket",
enabled=self.user_ticket is not None),
StatusButton(label="SITZPLATZ", target_url="./seating",
enabled=self.user_seat is not None),
proportions=(50, 50),
grow_y=False
),
UserInfoBoxButton("Profil bearbeiten", "./edit-profile"),
UserInfoBoxButton(f"Guthaben: {self.session[AccountingService].make_euro_string_from_int(self.user_balance)}", "./account"),
Button(
content=Text("Ausloggen", style=TextStyle(fill=Color.from_hex("02dac5"), font_size=0.6)),
shape="rectangle",
style="minor",
color="secondary",
grow_x=True,
margin_left=0.6,
margin_right=0.6,
margin_top=0.6,
on_press=self.logout
)
),
fill=Color.TRANSPARENT,
min_height=8,
min_width=12,
align_x=0.5,
margin_top=0.3,
margin_bottom=2
)