Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6217c1b2d0 | |||
| 33d937d385 | |||
| 210e01bb96 | |||
| 041ddaa334 | |||
| bbcf18d790 | |||
| 87eb94045c |
@@ -9,6 +9,8 @@
|
||||
has_showers=false
|
||||
ts3_address=""
|
||||
discord_invite_link=""
|
||||
location_name=""
|
||||
location_link=""
|
||||
|
||||
[database]
|
||||
database_host="localhost"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from rio import Component, Rectangle, Row, Text, Spacer, ProgressBar, Column, Color, TextStyle
|
||||
from rio import Component, Rectangle, Row, Text, Spacer, ProgressBar, Column, Color, TextStyle, Link
|
||||
from rio.event import on_populate
|
||||
|
||||
from elm.services import ConfigurationService
|
||||
@@ -36,6 +36,7 @@ class LanInfoBox(Component):
|
||||
stroke_color=self.session.theme.box_border_color,
|
||||
),
|
||||
Column(
|
||||
Row(Text("Location:", font_size=0.7), Spacer(), Link(Text(lan_info.location_name, fill=self.session.theme.primary_color, font_size=0.8, overflow="nowrap"), target_url=lan_info.location_link, open_in_new_tab=True)),
|
||||
Row(Text("Start:", font_size=0.7), Spacer(), Text(lan_info.date_from.strftime("%d.%m.%Y"), fill=self.session.theme.primary_color, font_size=0.8, overflow="nowrap")),
|
||||
Row(Text("Ende:", font_size=0.7), Spacer(), Text(lan_info.date_till.strftime("%d.%m.%Y"), fill=self.session.theme.primary_color, font_size=0.8, overflow="nowrap")),
|
||||
Row(Text("Einlass:", font_size=0.7), Spacer(), Text(lan_info.date_from.strftime("%H:%M Uhr"), fill=self.session.theme.primary_color, font_size=0.8, overflow="nowrap")),
|
||||
@@ -81,6 +82,7 @@ class LanInfoBox(Component):
|
||||
stroke_color=self.session.theme.box_border_color,
|
||||
),
|
||||
Column(
|
||||
Row(Text("Location:", font_size=0.9), Spacer(), Link(Text(lan_info.location_name, fill=self.session.theme.primary_color, font_size=0.9, overflow="nowrap"), target_url=lan_info.location_link, open_in_new_tab=True)),
|
||||
Row(Text("Start:", font_size=0.9), Spacer(), Text(lan_info.date_from.strftime("%d.%m.%Y"), fill=self.session.theme.primary_color, font_size=0.9, overflow="nowrap")),
|
||||
Row(Text("Ende:", font_size=0.9), Spacer(), Text(lan_info.date_till.strftime("%d.%m.%Y"), fill=self.session.theme.primary_color, font_size=0.9, overflow="nowrap")),
|
||||
Row(Text("Einlass:", font_size=0.9), Spacer(), Text(lan_info.date_from.strftime("%H:%M Uhr"), fill=self.session.theme.primary_color, font_size=0.9, overflow="nowrap")),
|
||||
|
||||
@@ -94,6 +94,7 @@ class NavigationBar(Component):
|
||||
NavigationButton("material/house", "Startseite", "/", extension_state_changed=self.on_extension_pressed),
|
||||
NavigationButton("material/local_activity", "Tickets", "/tickets", extension_state_changed=self.on_extension_pressed),
|
||||
NavigationButton("material/chair_alt", "Sitzplan", "/seating", extension_state_changed=self.on_extension_pressed),
|
||||
NavigationButton("material/group", "Teilnehmer", "/participants", extension_state_changed=self.on_extension_pressed),
|
||||
NavigationButton("material/local_dining", "Catering", "/catering", extension_state_changed=self.on_extension_pressed),
|
||||
NavigationButton("material/trophy", "Turniere", "/tournaments", extension_state_changed=self.on_extension_pressed),
|
||||
margin_bottom=6
|
||||
|
||||
@@ -20,7 +20,8 @@ class SeatPixel(Component):
|
||||
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", "")}")
|
||||
seat_id = self.seat_id.replace("\n", "")
|
||||
self.session.navigate_to(f"./seat-info?seat_id={seat_id}")
|
||||
|
||||
def determine_color(self) -> Color:
|
||||
if self.seat is not None:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from _sha2 import sha256
|
||||
from hashlib import sha256
|
||||
from random import choices
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class TransactionRow(Component):
|
||||
return Rectangle(
|
||||
content=Row(
|
||||
Text(
|
||||
f"{self.transaction_time.strftime("%d.%m.%y")} /",
|
||||
f"{self.transaction_time.strftime('%d.%m.%y')} /",
|
||||
justify="left",
|
||||
font_size=0.8,
|
||||
margin_left=0.5,
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from copy import copy
|
||||
from typing import Any, Optional
|
||||
from uuid import uuid4
|
||||
|
||||
from rio import Component, Column, Row, Text, Spacer, page, Color, Rectangle, TextInput, GuardEvent
|
||||
from rio.event import on_populate
|
||||
|
||||
from elm.types import UserSession, User, Ticket, Seat
|
||||
from elm.services import UserService, LocalData, LocalDataService, ConfigurationService
|
||||
from elm.components import ElmButton
|
||||
|
||||
@page(name="Participants", url_segment="participants")
|
||||
class ParticipantsPage(Component):
|
||||
participants: list[tuple[User, Seat]] = []
|
||||
|
||||
@on_populate
|
||||
async def on_populate(self) -> None:
|
||||
seats = await Seat.find_many(
|
||||
Seat.user != None,
|
||||
fetch_links=True
|
||||
).to_list()
|
||||
|
||||
self.participants = [(seat.user, seat) for seat in seats]
|
||||
|
||||
def build(self) -> Component:
|
||||
return Row(
|
||||
Rectangle(
|
||||
content=Column(
|
||||
Rectangle(
|
||||
content=Rectangle(
|
||||
content=Text("Teilnehmer", margin=0.5, selectable=False, overflow="wrap"),
|
||||
fill=self.session.theme.header_box_background_color,
|
||||
margin=0.4
|
||||
),
|
||||
stroke_width=0.1,
|
||||
stroke_color=self.session.theme.box_border_color,
|
||||
),
|
||||
Column(
|
||||
Row(
|
||||
Text("Nutzer", grow_x=True, font_weight="bold"),
|
||||
Text("Sitzplatz", font_weight="bold"),
|
||||
margin=0.5
|
||||
),
|
||||
*[
|
||||
Rectangle(
|
||||
content=Row(
|
||||
Text(user.user_name, grow_x=True, font_size=0.8),
|
||||
Text(seat.seat_id, font_size=0.8),
|
||||
margin=0.5
|
||||
),
|
||||
hover_fill=self.session.theme.secondary_color,
|
||||
transition_time=0.2
|
||||
) for user, seat in self.participants],
|
||||
margin=1
|
||||
),
|
||||
Spacer()
|
||||
),
|
||||
fill=self.session.theme.box_color,
|
||||
stroke_width=0.1,
|
||||
stroke_color=self.session.theme.box_border_color
|
||||
),
|
||||
margin=1,
|
||||
grow_x=True
|
||||
)
|
||||
@@ -1,15 +1,18 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from copy import copy
|
||||
from functools import partial
|
||||
from typing import Optional
|
||||
from decimal import Decimal
|
||||
|
||||
from beanie.odm.interfaces.find import FindInterface
|
||||
from bson import ObjectId
|
||||
from rio import Component, Column, Row, Text, Spacer, page, Rectangle, TextInput, GuardEvent, Button, TextInputChangeEvent, NumberInput, IconButton
|
||||
from rio.event import on_populate
|
||||
|
||||
from elm.types import UserSession, User, Transaction
|
||||
from elm.services import AccountingService, MailingService
|
||||
from elm.types import UserSession, User, Transaction, Ticket, Seat
|
||||
from elm.services import AccountingService, MailingService, ConfigurationService
|
||||
from elm.components import AccountInfoBox
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
@@ -95,6 +98,36 @@ class UserAdminPage(Component):
|
||||
receiver=self.active_user.user_mail
|
||||
))
|
||||
|
||||
async def cancel_ticket(self) -> None:
|
||||
if self.active_user is None:
|
||||
return
|
||||
|
||||
ticket = await Ticket.find_one({"owner.$id": self.active_user.id})
|
||||
if ticket is None:
|
||||
return
|
||||
|
||||
ticket_price = Decimal(0)
|
||||
for ticket_info in self.session[ConfigurationService].get_ticket_info():
|
||||
if ticket_info.category == ticket.category:
|
||||
ticket_price = ticket_info.price
|
||||
|
||||
await ticket.delete()
|
||||
await self.session[AccountingService].add_balance(self.active_user.user_name, ticket_price, "TICKET STORNO", skip_mail=True)
|
||||
await self.free_seat()
|
||||
|
||||
async def free_seat(self) -> None:
|
||||
if self.active_user is None:
|
||||
return
|
||||
|
||||
seat = await Seat.find_one({"user.$id": ObjectId(self.active_user.id)})
|
||||
if seat is None:
|
||||
self.active_user = None
|
||||
return
|
||||
|
||||
seat.user = None
|
||||
await seat.save()
|
||||
self.active_user = None
|
||||
|
||||
def build(self) -> Component:
|
||||
right_panel_contents = []
|
||||
if not self.active_user:
|
||||
@@ -153,6 +186,44 @@ class UserAdminPage(Component):
|
||||
stroke_width=0.1,
|
||||
stroke_color=self.session.theme.box_border_color
|
||||
),
|
||||
Rectangle(
|
||||
content=Column(
|
||||
Rectangle(
|
||||
content=Rectangle(
|
||||
content=Text(f"Sonstiges", margin=0.5,
|
||||
selectable=False, overflow="wrap"),
|
||||
fill=self.session.theme.header_box_background_color,
|
||||
margin=0.4
|
||||
),
|
||||
stroke_width=0.1,
|
||||
stroke_color=self.session.theme.box_border_color,
|
||||
),
|
||||
Column(
|
||||
Row(
|
||||
Button(
|
||||
content="Ticket stornieren",
|
||||
shape="rectangle",
|
||||
color="danger",
|
||||
margin=1,
|
||||
on_press=self.cancel_ticket
|
||||
),
|
||||
Button(
|
||||
content="Sitzplatz freigeben",
|
||||
shape="rectangle",
|
||||
color="danger",
|
||||
margin=1,
|
||||
on_press=self.free_seat
|
||||
)
|
||||
),
|
||||
margin=1,
|
||||
spacing=1
|
||||
),
|
||||
Spacer()
|
||||
),
|
||||
fill=self.session.theme.box_color,
|
||||
stroke_width=0.1,
|
||||
stroke_color=self.session.theme.box_border_color
|
||||
),
|
||||
])
|
||||
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ class AccountingService:
|
||||
return True
|
||||
return False
|
||||
|
||||
async def add_balance(self, user_name: str, balance_to_add: Decimal, title: str) -> Decimal:
|
||||
async def add_balance(self, user_name: str, balance_to_add: Decimal, title: str, skip_mail: bool = False) -> Decimal:
|
||||
user = await User.find_one(User.user_name == user_name)
|
||||
if not user:
|
||||
raise KeyError("User does not exist")
|
||||
@@ -142,11 +142,12 @@ class AccountingService:
|
||||
).save()
|
||||
logger.debug(f"Added balance of {self.make_euro_string_from_decimal(balance_to_add)} to user '{user_name}'")
|
||||
new_balance = await self.get_balance(user_name)
|
||||
await self._mailing_service.send_email(
|
||||
"Dein Guthaben wurde aufgeladen",
|
||||
self._mailing_service.generate_account_balance_added_mail_body(user, balance_to_add, new_balance),
|
||||
user.user_mail
|
||||
)
|
||||
if not skip_mail:
|
||||
await self._mailing_service.send_email(
|
||||
"Dein Guthaben wurde aufgeladen",
|
||||
self._mailing_service.generate_account_balance_added_mail_body(user, balance_to_add, new_balance),
|
||||
user.user_mail
|
||||
)
|
||||
return new_balance
|
||||
|
||||
async def remove_balance(self, user_name: str, balance_to_remove: Decimal, title: str) -> Decimal:
|
||||
|
||||
@@ -103,7 +103,9 @@ class ConfigurationService:
|
||||
has_wifi=lan_info["has_wifi"],
|
||||
has_showers=lan_info["has_showers"],
|
||||
ts3_address=lan_info["ts3_address"],
|
||||
discord_invite_link=lan_info["discord_invite_link"]
|
||||
discord_invite_link=lan_info["discord_invite_link"],
|
||||
location_name=lan_info["location_name"],
|
||||
location_link=lan_info["location_link"]
|
||||
)
|
||||
except KeyError:
|
||||
logger.fatal("Error loading LAN Info, exiting...")
|
||||
|
||||
@@ -34,6 +34,8 @@ class LanInfo:
|
||||
has_showers: bool
|
||||
ts3_address: str
|
||||
discord_invite_link: str
|
||||
location_name: str
|
||||
location_link: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
||||
Reference in New Issue
Block a user