Compare commits

...

3 Commits

Author SHA1 Message Date
David Rodenkirchen
d5b677ab68 Rework Team UI 2026-02-20 07:06:16 +01:00
David Rodenkirchen
5b6c5d2076 Deprecation Fix: CursorStyle is deprecated 2026-02-20 07:05:09 +01:00
David Rodenkirchen
a390e4bd10 Bugfix: Trying to remove participant from empty tournament leads to crash 2026-02-20 07:04:37 +01:00
8 changed files with 103 additions and 25 deletions

View File

@ -1 +1 @@
0.3.0
0.3.1

View File

@ -157,6 +157,12 @@ if __name__ == "__main__":
build=pages.ManageTournamentsPage,
guard=team_guard
),
ComponentPage(
name="AdminNavigationPage",
url_segment="admin",
build=pages.AdminNavigationPage,
guard=team_guard
),
ComponentPage(
name="DbErrorPage",
url_segment="db-error",

View File

@ -0,0 +1,36 @@
from rio import Component, Rectangle, Text, Column, Icon, TextStyle, PointerEventListener, PointerEvent
class AdminNavigationCard(Component):
icon_name: str
display_text: str
target_url: str
def on_press(self, _: PointerEvent) -> None:
if self.target_url:
self.session.navigate_to(self.target_url)
def build(self) -> Component:
return PointerEventListener(
Rectangle(
content=Column(
Icon(
self.icon_name,
min_width=3.5,
min_height=3.5,
fill="background",
margin=1
),
Text(self.display_text, style=TextStyle(fill=self.session.theme.background_color), justify="center", margin=1, margin_top=0)
),
cursor="pointer",
stroke_width=0.2,
stroke_color=self.session.theme.background_color,
hover_stroke_width=0.2,
hover_stroke_color=self.session.theme.hud_color,
min_width=10,
min_height=10,
corner_radius=0.2
),
on_press=self.on_press
)

View File

@ -43,7 +43,7 @@ class DesktopNavigation(Component):
lan_info = self.session[ConfigurationService].get_lan_info()
user_info_and_login_box = UserInfoAndLoginBox()
self.force_login_box_refresh.append(user_info_and_login_box.force_refresh)
user_navigation = [
navigation = [
DesktopNavigationButton("News", "./news"),
Spacer(min_height=0.7),
DesktopNavigationButton(f"Über {lan_info.name} {lan_info.iteration}", "./overview"),
@ -60,29 +60,16 @@ class DesktopNavigation(Component):
DesktopNavigationButton("Die EZ GG e.V.", "https://ezgg-ev.de/about", open_new_tab=True),
Spacer(min_height=0.7)
]
team_navigation = [
Text("Verwaltung", align_x=0.5, margin_top=0.3, style=TextStyle(fill=Color.from_hex("F0EADE"), font_size=1.2)),
Text("Vorsichtig sein!", align_x=0.5, margin_top=0.3, style=TextStyle(fill=self.session.theme.danger_color, font_size=0.6)),
DesktopNavigationButton("News", "./manage-news", is_team_navigation=True),
DesktopNavigationButton("Benutzer", "./manage-users", is_team_navigation=True),
DesktopNavigationButton("Catering", "./manage-catering", is_team_navigation=True),
DesktopNavigationButton("Turniere", "./manage-tournaments", is_team_navigation=True),
Spacer(min_height=0.7),
Revealer(
header="Normale Navigation",
content=Column(*user_navigation),
header_style=TextStyle(fill=self.session.theme.primary_color, font_size=0.9)
)
] if self.user is not None and self.user.is_team_member else []
nav_to_use = copy(team_navigation) if self.user is not None and self.user.is_team_member else copy(user_navigation)
if self.user is not None and self.user.is_team_member:
navigation.insert(0, DesktopNavigationButton("Adminbereich", "./admin", is_team_navigation=True))
return Card(
Column(
Text(lan_info.name, align_x=0.5, margin_top=0.3, style=TextStyle(fill=self.session.theme.hud_color, font_size=1.9)),
Text(f"Edition {lan_info.iteration}", align_x=0.5, style=TextStyle(fill=self.session.theme.hud_color, font_size=1.2), margin_top=0.3, margin_bottom=2),
user_info_and_login_box,
*nav_to_use,
*navigation,
Text("Unsere Sponsoren", align_x=0.5, style=TextStyle(fill=self.session.theme.hud_color, font_size=0.9), margin_bottom=0.5, margin_top=1),
NavigationSponsorBox(img_name="crackz", url="https://www.crackz.gg/"),
align_y=0

View File

@ -0,0 +1,44 @@
from rio import Column, Component, event, Text, TextStyle, Row
from src.ezgg_lan_manager.components.AdminNavigationCard import AdminNavigationCard
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
from src.ezgg_lan_manager.services.ConfigurationService import ConfigurationService
class AdminNavigationPage(Component):
@event.on_populate
async def on_populate(self) -> None:
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Admin")
def build(self) -> Component:
return Column(
MainViewContentBox(
Text(
text="Admin",
style=TextStyle(
fill=self.session.theme.background_color,
font_size=1.2
),
margin_top=2,
margin_bottom=2,
align_x=0.5
)
),
MainViewContentBox(
Column(
Row(
AdminNavigationCard(icon_name="material/supervised_user_circle", display_text="Nutzer", target_url="manage-users"),
AdminNavigationCard(icon_name="material/fastfood", display_text="Catering", target_url="manage-catering"),
spacing=1
),
Row(
AdminNavigationCard(icon_name="material/text_ad", display_text="News", target_url="manage-news"),
AdminNavigationCard(icon_name="material/trophy", display_text="Turniere", target_url="manage-tournaments"),
spacing=1
),
margin=1,
spacing=1
)
),
align_y=0
)

View File

@ -1,5 +1,6 @@
import logging
from datetime import datetime
from functools import partial
from typing import Optional
from from_root import from_root
@ -40,7 +41,11 @@ class ManageTournamentsPage(Component):
return
users = await self.session[UserService].get_all_users()
try:
self.cancel_options = {next(filter(lambda u: u.user_id == p.id, users)).user_name: p for p in tournament.participants}
cancel_options = {next(filter(lambda u: u.user_id == p.id, users)).user_name: p for p in tournament.participants}
if cancel_options:
self.cancel_options = cancel_options
else:
self.cancel_options = {"": None}
except StopIteration as e:
logger.error(f"Error trying to find user for participant: {e}")
self.tournament_id_selected_for_participant_removal = tournament_id
@ -70,13 +75,12 @@ class ManageTournamentsPage(Component):
Text(tournament.name, style=TextStyle(fill=self.session.theme.background_color, font_size=0.8), justify="left", margin_right=1.5),
Text(f"{weekday_to_display_text(tournament.start_time.weekday())[:2]}.{tournament.start_time.strftime('%H:%M')} Uhr", style=TextStyle(fill=start_time_color, font_size=0.8), justify="left", margin_right=1),
Spacer(),
Tooltip(anchor=IconButton("material/play_arrow", min_size=2, margin_right=0.5, on_press=lambda: self.on_start_pressed(tournament.id)), tip="Starten"),
Tooltip(anchor=IconButton("material/cancel_schedule_send", min_size=2, margin_right=0.5, on_press=lambda: self.on_cancel_pressed(tournament.id)), tip="Absagen"),
Tooltip(anchor=IconButton("material/person_cancel", min_size=2, on_press=lambda: self.on_remove_participant_pressed(tournament.id)), tip="Spieler entfernen"),
Tooltip(anchor=IconButton("material/play_arrow", min_size=2, margin_right=0.5, on_press=partial(self.on_start_pressed, tournament.id)), tip="Starten"),
Tooltip(anchor=IconButton("material/cancel_schedule_send", min_size=2, margin_right=0.5, on_press=partial(self.on_cancel_pressed, tournament.id)), tip="Absagen"),
Tooltip(anchor=IconButton("material/person_cancel", min_size=2, on_press=partial(self.on_remove_participant_pressed, tournament.id)), tip="Spieler entfernen"),
margin=1
)
)
return Column(
Popup(
anchor=MainViewContentBox(

View File

@ -3,7 +3,7 @@ from dataclasses import field
from typing import Optional
from rio import Column, Component, event, TextStyle, Text, TextInput, ThemeContextSwitcher, Grid, \
PointerEventListener, PointerEvent, Rectangle, CursorStyle, Color, TextInputChangeEvent, Spacer, Row, Switch, \
PointerEventListener, PointerEvent, Rectangle, Color, TextInputChangeEvent, Spacer, Row, Switch, \
SwitchChangeEvent, EventHandler
from src.ezgg_lan_manager import ConfigurationService, UserService, AccountingService, SeatingService, MailingService
@ -42,7 +42,7 @@ class ClickableGridContent(Component):
grow_x=True
),
fill=Color.TRANSPARENT,
cursor=CursorStyle.POINTER
cursor="pointer"
),
on_pointer_enter=self.on_mouse_enter,
on_pointer_leave=self.on_mouse_leave,

View File

@ -24,3 +24,4 @@ from .TournamentDetailsPage import TournamentDetailsPage
from .TournamentRulesPage import TournamentRulesPage
from .ConwayPage import ConwayPage
from .TeamsPage import TeamsPage
from .AdminNavigationPage import AdminNavigationPage