From 471b59d5ec40b5078d803fe43bb719c3ca7ca4d1 Mon Sep 17 00:00:00 2001 From: David Rodenkirchen Date: Sat, 30 Nov 2024 00:53:59 +0100 Subject: [PATCH] add basic user manager with user lookup --- src/EzLanManager.py | 6 + src/ez_lan_manager/pages/ManageUsersPage.py | 127 ++++++++++++++++++++ src/ez_lan_manager/pages/__init__.py | 1 + 3 files changed, 134 insertions(+) create mode 100644 src/ez_lan_manager/pages/ManageUsersPage.py diff --git a/src/EzLanManager.py b/src/EzLanManager.py index f4b4910..beea489 100644 --- a/src/EzLanManager.py +++ b/src/EzLanManager.py @@ -137,6 +137,12 @@ if __name__ == "__main__": build=pages.ManageNewsPage, guard=team_guard ), + ComponentPage( + name="ManageUsersPage", + url_segment="manage-users", + build=pages.ManageUsersPage, + guard=team_guard + ), ComponentPage( name="DbErrorPage", url_segment="db-error", diff --git a/src/ez_lan_manager/pages/ManageUsersPage.py b/src/ez_lan_manager/pages/ManageUsersPage.py new file mode 100644 index 0000000..0a92073 --- /dev/null +++ b/src/ez_lan_manager/pages/ManageUsersPage.py @@ -0,0 +1,127 @@ +import logging +from dataclasses import field +from typing import Optional, Coroutine + +import rio +from rio import Column, Component, event, TextStyle, Text, TextInput, ThemeContextSwitcher, Grid, \ + PointerEventListener, PointerEvent, Rectangle, CursorStyle, Color, TextInputChangeEvent + +from src.ez_lan_manager import ConfigurationService, UserService +from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox +from src.ez_lan_manager.types.User import User + +logger = logging.getLogger(__name__.split(".")[-1]) + +# Helps type checker grasp the concept of "lambda _: None" as a Coroutine +async def noop(_) -> None: + pass + +class ClickableGridContent(Component): + text: str = "" + is_hovered: bool = False + clicked_cb: Coroutine = noop + + async def on_mouse_enter(self, _: PointerEvent) -> None: + self.is_hovered = True + + async def on_mouse_leave(self, _: PointerEvent) -> None: + self.is_hovered = False + + async def on_mouse_click(self, _: PointerEvent) -> None: + await self.clicked_cb(self.text) + + def build(self) -> rio.Component: + return PointerEventListener( + content=Rectangle( + content=Text( + self.text, + style=TextStyle(fill=self.session.theme.success_color) if self.is_hovered else TextStyle(fill=self.session.theme.background_color), + grow_x=True + ), + fill=Color.TRANSPARENT, + cursor=CursorStyle.POINTER + ), + on_pointer_enter=self.on_mouse_enter, + on_pointer_leave=self.on_mouse_leave, + on_press=self.on_mouse_click + ) + +class ManageUsersPage(Component): + selected_user: Optional[User] = None + all_users: Optional[list] = None + search_results: list[User] = field(default_factory=list) + + @event.on_populate + async def on_populate(self) -> None: + await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - News Verwaltung") + self.all_users = await self.session[UserService].get_all_users() + self.search_results = self.all_users + + async def on_user_clicked(self, user_name: str) -> None: + self.selected_user = next(filter(lambda user: user.user_name == user_name, self.all_users)) + + async def on_search_parameters_changed(self, e: TextInputChangeEvent) -> None: + self.search_results = list(filter(lambda user: (e.text.lower() in user.user_name.lower()) or e.text.lower() in str(user.user_id), self.all_users)) + + + def build(self) -> Component: + return Column( + MainViewContentBox( + Column( + Text( + text="Nutzersuche", + style=TextStyle( + fill=self.session.theme.background_color, + font_size=1.2 + ), + margin_top=2, + margin_bottom=2, + align_x=0.5 + ), + TextInput( + label="Nutzername oder ID", + margin=1, + on_change=self.on_search_parameters_changed + ), + ThemeContextSwitcher( + Grid( + [ + Text("Nutzername", margin_bottom=1, grow_x=True, style=TextStyle(font_size=1.1)), + Text("Nutzer-ID", margin_bottom=1, style=TextStyle(font_size=1.1)) + ], + *[[ + ClickableGridContent(text=user.user_name, clicked_cb=self.on_user_clicked), + Text( + str(user.user_id), + justify="right" + ) + ] for user in self.search_results], + row_spacing=0.2, + margin=1 + ), + color="primary" + ) + ) + ), + MainViewContentBox( + Text( + text=f"Nutzer {self.selected_user.user_name} gewählt.", + style=TextStyle( + fill=self.session.theme.background_color, + font_size=1.2 + ), + margin_top=2, + margin_bottom=2, + align_x=0.5 + ) if self.selected_user else Text( + text="Bitte Nutzer auswählen...", + style=TextStyle( + fill=self.session.theme.background_color, + font_size=1.2 + ), + margin_top=2, + margin_bottom=2, + align_x=0.5 + )), + align_y=0 + ) diff --git a/src/ez_lan_manager/pages/__init__.py b/src/ez_lan_manager/pages/__init__.py index ce5fa34..869d6a8 100644 --- a/src/ez_lan_manager/pages/__init__.py +++ b/src/ez_lan_manager/pages/__init__.py @@ -16,3 +16,4 @@ from .DbErrorPage import DbErrorPage from .SeatingPlanPage import SeatingPlanPage from .BuyTicketPage import BuyTicketPage from .ManageNewsPage import ManageNewsPage +from .ManageUsersPage import ManageUsersPage