From 80b6e49d388f5e181aa63f434b95bb93e05db370 Mon Sep 17 00:00:00 2001 From: David Rodenkirchen Date: Tue, 3 Feb 2026 13:49:02 +0100 Subject: [PATCH] add participant list view --- .../components/TournamentDetailsInfoRow.py | 8 ++-- .../pages/TournamentDetailsPage.py | 41 ++++++++++++++++--- .../services/TournamentService.py | 6 +++ 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/ezgg_lan_manager/components/TournamentDetailsInfoRow.py b/src/ezgg_lan_manager/components/TournamentDetailsInfoRow.py index 9992dc9..8f3a77f 100644 --- a/src/ezgg_lan_manager/components/TournamentDetailsInfoRow.py +++ b/src/ezgg_lan_manager/components/TournamentDetailsInfoRow.py @@ -6,14 +6,16 @@ from rio import Component, Row, Text, TextStyle, Color class TournamentDetailsInfoRow(Component): key: str value: str - color: Optional[Color] = None + key_color: Optional[Color] = None + value_color: Optional[Color] = None + def build(self) -> Component: return Row( Text( text=self.key, style=TextStyle( - fill=self.session.theme.background_color, + fill=self.key_color if self.key_color is not None else self.session.theme.background_color, font_size=1 ), margin_bottom=0.5, @@ -22,7 +24,7 @@ class TournamentDetailsInfoRow(Component): Text( text=self.value, style=TextStyle( - fill=self.color if self.color is not None else self.session.theme.background_color, + fill=self.value_color if self.value_color is not None else self.session.theme.background_color, font_size=1 ), margin_bottom=0.5, diff --git a/src/ezgg_lan_manager/pages/TournamentDetailsPage.py b/src/ezgg_lan_manager/pages/TournamentDetailsPage.py index 35161f5..c04c464 100644 --- a/src/ezgg_lan_manager/pages/TournamentDetailsPage.py +++ b/src/ezgg_lan_manager/pages/TournamentDetailsPage.py @@ -1,12 +1,14 @@ from typing import Optional, Union, Literal from from_root import from_root -from rio import Column, Component, event, TextStyle, Text, Row, Image, Spacer, ProgressCircle, Button, Checkbox, ThemeContextSwitcher, Link +from rio import Column, Component, event, TextStyle, Text, Row, Image, Spacer, ProgressCircle, Button, Checkbox, ThemeContextSwitcher, Link, Revealer, PointerEventListener, \ + PointerEvent, Rectangle, Color from src.ezgg_lan_manager import ConfigurationService, TournamentService, UserService from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox from src.ezgg_lan_manager.components.TournamentDetailsInfoRow import TournamentDetailsInfoRow from src.ezgg_lan_manager.types.DateUtil import weekday_to_display_text +from src.ezgg_lan_manager.types.Participant import Participant from src.ezgg_lan_manager.types.SessionStorage import SessionStorage from src.ezgg_lan_manager.types.Tournament import Tournament from src.ezgg_lan_manager.types.TournamentBase import TournamentStatus, tournament_status_to_display_text, tournament_format_to_display_texts @@ -18,6 +20,9 @@ class TournamentDetailsPage(Component): rules_accepted: bool = False user: Optional[User] = None loading: bool = False + participant_revealer_open: bool = False + current_tournament_user_list: list[User] = [] # ToDo: Integrate Teams + # State for message above register button message: str = "" is_success: bool = False @@ -32,6 +37,7 @@ class TournamentDetailsPage(Component): self.tournament = await self.session[TournamentService].get_tournament_by_id(tournament_id) if self.tournament is not None: await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - {self.tournament.name}") + self.current_tournament_user_list = await self.session[TournamentService].get_users_from_participant_list(self.tournament.participants) else: await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Turniere") @@ -39,6 +45,9 @@ class TournamentDetailsPage(Component): self.loading_done() + def open_close_participant_revealer(self, _: PointerEvent) -> None: + self.participant_revealer_open = not self.participant_revealer_open + async def register_pressed(self) -> None: self.loading = True if not self.user: @@ -52,6 +61,7 @@ class TournamentDetailsPage(Component): self.is_success = False self.message = f"Fehler: {e}" self.loading = False + await self.on_populate() async def unregister_pressed(self) -> None: self.loading = True @@ -66,6 +76,7 @@ class TournamentDetailsPage(Component): self.is_success = False self.message = f"Fehler: {e}" self.loading = False + await self.on_populate() async def tree_button_clicked(self) -> None: pass # ToDo: Implement tournament tree view @@ -179,14 +190,32 @@ class TournamentDetailsPage(Component): margin_left=6 ), Spacer(min_height=1), - TournamentDetailsInfoRow("Status", tournament_status_to_display_text(self.tournament.status), tournament_status_color), + TournamentDetailsInfoRow("Status", tournament_status_to_display_text(self.tournament.status), value_color=tournament_status_color), TournamentDetailsInfoRow("Startzeit", f"{weekday_to_display_text(self.tournament.start_time.weekday())}, {self.tournament.start_time.strftime('%H:%M')} Uhr"), TournamentDetailsInfoRow("Format", tournament_format_to_display_texts(self.tournament.format)[0]), TournamentDetailsInfoRow("Best of", tournament_format_to_display_texts(self.tournament.format)[1]), - TournamentDetailsInfoRow( - "Teilnehmer", - f"{len(self.tournament.participants)} / {self.tournament.max_participants}", - self.session.theme.danger_color if self.tournament.is_full else self.session.theme.background_color + PointerEventListener( + content=Rectangle( + content=TournamentDetailsInfoRow( + "Teilnehmer ▴" if self.participant_revealer_open else "Teilnehmer ▾", + f"{len(self.tournament.participants)} / {self.tournament.max_participants}", + value_color=self.session.theme.danger_color if self.tournament.is_full else self.session.theme.background_color, + key_color=self.session.theme.secondary_color + ), + fill=Color.TRANSPARENT, + cursor="pointer" + ), + on_press=self.open_close_participant_revealer + ), + Revealer( + header=None, + content=Text( + "\n".join([u.user_name for u in self.current_tournament_user_list]), # ToDo: Integrate Teams + style=TextStyle(fill=self.session.theme.background_color) + ), + is_open=self.participant_revealer_open, + margin_left=4, + margin_right=4 ), tree_button, Row( diff --git a/src/ezgg_lan_manager/services/TournamentService.py b/src/ezgg_lan_manager/services/TournamentService.py index 1fb0b85..ad4d28f 100644 --- a/src/ezgg_lan_manager/services/TournamentService.py +++ b/src/ezgg_lan_manager/services/TournamentService.py @@ -5,6 +5,7 @@ from src.ezgg_lan_manager.services.UserService import UserService from src.ezgg_lan_manager.types.Participant import Participant from src.ezgg_lan_manager.types.Tournament import Tournament from src.ezgg_lan_manager.types.TournamentBase import ParticipantType, TournamentError +from src.ezgg_lan_manager.types.User import User class TournamentService: @@ -50,3 +51,8 @@ class TournamentService: if self._cache_dirty: await self._update_cache() return self._cache.get(tournament_id, None) + + async def get_users_from_participant_list(self, participants: list[Participant]) -> list[User]: + all_users = await self._db_service.get_all_users() + participant_ids = [p.id for p in participants] + return list(filter(lambda u: u.user_id in participant_ids, all_users))