Files
ELM/src/elm/components/SeatingPlanPixels.py
T
David Rodenkirchen 5d422a9863 migrate seaing plan
2026-05-23 01:49:17 +02:00

139 lines
4.5 KiB
Python

from rio import Component, Text, Icon, TextStyle, Rectangle, Spacer, Color, PointerEventListener, Row, PointerEvent, Tooltip
from typing import Optional, Literal
from rio.event import on_populate
from elm.types import Seat, UserSession, User
class SeatPixel(Component):
seat_id: str
seat_orientation: Literal["top", "bottom"]
seat: Optional[Seat] = None
associated_user: Optional[User] = None
@on_populate
async def on_populate(self) -> None:
if self.seat is None:
self.seat = await Seat.find_one(Seat.seat_id == self.seat_id.replace("\n", ""), fetch_links=True)
if self.seat and self.seat.user is not None:
self.associated_user = await self.seat.user.fetch()
async def on_press(self, _: PointerEvent) -> None:
self.session.navigate_to(f"./seat-info?seat_id={self.seat_id.replace("\n", "")}")
def determine_color(self) -> Color:
if self.seat is not None:
try:
user_name = self.session[UserSession].user_name
except KeyError:
user_name = None
if self.seat.user is not None and self.associated_user and self.associated_user.user_name == user_name:
return Color.from_hex("800080")
elif self.seat.is_blocked or self.seat.user is not None:
return self.session.theme.danger_color
return self.session.theme.success_color
return self.session.theme.success_color
def build(self) -> Component:
if self.seat is None:
return Spacer()
text = Text(f"{self.seat_id}", style=TextStyle(fill=Color.BLACK, font_size=0.9), align_x=0.5, selectable=False)
rec = Rectangle(
content=Row(text),
min_width=1,
min_height=1,
fill=self.determine_color(),
stroke_width=0.1,
hover_stroke_width=0.1,
stroke_color=Color.BLACK,
grow_x=True,
grow_y=True,
hover_fill=self.session.theme.hud_color,
transition_time=0.4,
ripple=True
)
if self.associated_user or self.seat.is_blocked:
return PointerEventListener(
content=Tooltip(
anchor=rec,
tip=self.associated_user.user_name if self.associated_user else "Gesperrt",
position=self.seat_orientation,
),
on_press=self.on_press,
)
else:
return PointerEventListener(
content=rec,
on_press=self.on_press,
)
class TextPixel(Component):
text: Optional[str] = None
icon_name: Optional[str] = None
no_outline: bool = False
def build(self) -> Component:
if self.text is not None:
content = Text(self.text, style=TextStyle(fill=self.session.theme.text_color, font_size=1), align_x=0.5, selectable=False)
elif self.icon_name is not None:
content = Icon(self.icon_name, fill=self.session.theme.text_color)
else:
content = None
return Rectangle(
content=content,
min_width=1,
min_height=1,
fill=self.session.theme.background_color,
stroke_width=0.0 if self.no_outline else 0.1,
stroke_color=self.session.theme.neutral_color,
hover_stroke_width=None if self.no_outline else 0.1,
grow_x=True,
grow_y=True,
hover_fill=None,
ripple=True
)
class WallPixel(Component):
def build(self) -> Component:
return Rectangle(
min_width=1,
min_height=1,
fill=Color.from_hex("434343"),
grow_x=True,
grow_y=True,
)
class DebugPixel(Component):
def build(self) -> Component:
return Rectangle(
content=Spacer(),
min_width=1,
min_height=1,
fill=self.session.theme.success_color,
hover_stroke_color=self.session.theme.hud_color,
hover_stroke_width=0.1,
grow_x=True,
grow_y=True,
hover_fill=self.session.theme.secondary_color,
transition_time=0.1
)
class InvisiblePixel(Component):
def build(self) -> Component:
return Rectangle(
content=Spacer(),
min_width=1,
min_height=1,
fill=Color.TRANSPARENT,
hover_stroke_width=0.0,
grow_x=True,
grow_y=True
)