Compare commits
3 Commits
main
...
feature/to
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d98482f540 | ||
|
|
1679f537de | ||
|
|
3eb9d6ab8c |
22
502.html
22
502.html
@ -1,22 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>EZGG LAN Manager - Wartungsmodus</title>
|
||||
<style>
|
||||
body { text-align: center; padding: 150px; }
|
||||
h1 { font-size: 50px; }
|
||||
body { font: 20px Helvetica, sans-serif; color: #333; }
|
||||
article { display: block; text-align: left; width: 650px; margin: 0 auto; }
|
||||
a { color: #dc8100; text-decoration: none; }
|
||||
a:hover { color: #333; text-decoration: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<article>
|
||||
<h1>Wir sind bald wieder da!</h1>
|
||||
<div>
|
||||
<p>Wir führen zurzeit Wartungsarbeiten durch und sind in kürze wieder für euch da.</p>
|
||||
<p>— Euer EZGG LAN Team</p>
|
||||
</div>
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
||||
12
Dockerfile
12
Dockerfile
@ -1,12 +0,0 @@
|
||||
FROM python:3.12-bookworm
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt install dumb-init
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
EXPOSE 8000
|
||||
EXPOSE 8001
|
||||
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
44
README.md
44
README.md
@ -1,45 +1,13 @@
|
||||
# EZGG LAN Manager
|
||||
# EZ LAN Manager
|
||||
|
||||
## Overview
|
||||
|
||||
This repository contains the code for the EZGG LAN Manager.
|
||||
This repository contains the code for the EZ LAN Manager.
|
||||
|
||||
## Development Setup
|
||||
## How to install [prod]
|
||||
|
||||
### Prerequisites
|
||||
TBD
|
||||
|
||||
- Working Installation of MySQL 5 or latest MariaDB Server (`mariadb-server` for Debian-based Linux, `XAMPP` for Windows)
|
||||
- Python 3.9 or higher
|
||||
- PyCharm or similar IDE (optional)
|
||||
## How to install [dev]
|
||||
|
||||
### Step 1: Preparing Database
|
||||
|
||||
To prepare the database, apply the SQL file located in `sql/create_database.sql` to your database server. This is easily accomplished with the MYSQL Workbench, but it can be also done by pipeing the file into the mariadb-server executable.
|
||||
|
||||
Optionally, you can now execute the script `create_demo_database_content.py`, found in `src/ezgg_lan_manager/helpers`. Be aware that it can be buggy sometimes, especially if you overwrite existing data.
|
||||
|
||||
### Step 2: Preparing configuration
|
||||
|
||||
Use the example configuration at `config/config.example.toml` to create a `config.toml` at the base of the repository. Most of the parameters do not matter to get the development setup done, but the database credentials need to be correct.
|
||||
|
||||
### Step 3: Install dependecies
|
||||
|
||||
Use `pip install -r requirements.txt` to install the requirements. The usage of a venv is recommended.
|
||||
|
||||
### Step 4: Running the application
|
||||
|
||||
Run the application by executing the file `EzggLanManager.py` found at `src/ezgg_lan_manager`. Check the STDOUT for information regarding the port on which the application is now served.
|
||||
|
||||
## Docker Deployment
|
||||
|
||||
To get the docker compose setup running, you need to manually complete the following steps:
|
||||
|
||||
1. Create a valid `config.toml` in the project root, so it gets copied over into the container.
|
||||
2. Create the database user:
|
||||
```sql
|
||||
CREATE USER 'ezgg_lan_manager'@'%' IDENTIFIED BY 'PASSWORD';
|
||||
GRANT ALL PRIVILEGES ON ezgg_lan_manager.* TO 'ezgg_lan_manager'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
3. Make sure to **NOT** use the default passwords!
|
||||
4. Apply the `create_database.sql` when starting the MariaDB container for the first time.
|
||||
TBD
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
[lan]
|
||||
name="EZGG LAN"
|
||||
name="EZ LAN"
|
||||
iteration="0.5"
|
||||
date_from="2024-10-30 15:00:00"
|
||||
date_till="2024-11-01 12:00:00"
|
||||
@ -10,7 +10,7 @@
|
||||
db_password="demo_password"
|
||||
db_host="127.0.0.1"
|
||||
db_port=3306
|
||||
db_name="ezgg_lan_manager"
|
||||
db_name="ez_lan_manager"
|
||||
|
||||
[mailing]
|
||||
smtp_server=""
|
||||
@ -19,6 +19,12 @@
|
||||
username=""
|
||||
password=""
|
||||
|
||||
[seating]
|
||||
# SeatID -> Category
|
||||
A01 = "NORMAL"
|
||||
A02 = "NORMAL"
|
||||
C01 = "LUXUS"
|
||||
|
||||
[tickets]
|
||||
[tickets."NORMAL"]
|
||||
total_tickets=30
|
||||
@ -34,11 +40,5 @@
|
||||
additional_info="Berechtigt zur Nutzung eines verbesserten Platzes. Dieser ist mit einer höheren Internet-Bandbreite und einem Sitzkissen ausgestattet."
|
||||
is_default=false
|
||||
|
||||
[receipt_printing]
|
||||
host="127.0.0.1"
|
||||
port="5000"
|
||||
order_print_endpoint="print_order"
|
||||
password="Alkohol1"
|
||||
|
||||
[misc]
|
||||
dev_mode_active=true # Supresses E-Mail sending
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
services:
|
||||
lan_manager:
|
||||
build: .
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
PYTHONPATH: /opt/ezgg-lan-manager
|
||||
ports:
|
||||
- "8000:8000"
|
||||
- "8001:8001"
|
||||
volumes:
|
||||
- ./:/opt/ezgg-lan-manager
|
||||
entrypoint: ["/bin/sh", "-c", "cd /opt/ezgg-lan-manager/src && python3 /opt/ezgg-lan-manager/src/EzggLanManager.py"]
|
||||
|
||||
db:
|
||||
image: mariadb:latest
|
||||
environment:
|
||||
MARIADB_ROOT_PASSWORD: Alkohol1
|
||||
MARIADB_DATABASE: ezgg_lan_manager
|
||||
MARIADB_USER: ezgg_lan_manager
|
||||
MARIADB_PASSWORD: Alkohol1
|
||||
healthcheck:
|
||||
test: ["CMD", "mariadb-admin", "ping", "-h", "localhost"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
ports:
|
||||
- "127.0.0.1:3306:3306"
|
||||
volumes:
|
||||
- database:/var/lib/mysql
|
||||
- ./sql/create_database.sql:/docker-entrypoint-initdb.d/init.sql
|
||||
|
||||
|
||||
volumes:
|
||||
database:
|
||||
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
@ -1,65 +0,0 @@
|
||||
INSERT INTO `catering_menu_items` VALUES
|
||||
(1,'Schnitzel Wiener Art','mit Pommes Frites und Salat',20.50,'MAIN_COURSE',1),
|
||||
(2,'Jäger Schnitzel mit Champignonrahm Sauce','mit Spätzlen und Salat',22.50,'MAIN_COURSE',1),
|
||||
(3,'Rumpsteak 250g','mit Pommes Frites und Salat',35.50,'MAIN_COURSE',1),
|
||||
(4,'Rindergeschnetzeltes','mit Spätzlen und Salat',22.50,'MAIN_COURSE',1),
|
||||
(5,'Galloway Burger','mit Amazing Fries',20.00,'MAIN_COURSE',1),
|
||||
(6,'Käsespätzle mit Röstzwiebel','mit Salat',20.00,'MAIN_COURSE',1),
|
||||
(11,'Käse Schinken Wrap','',5.00,'SNACK',1),
|
||||
(12,'Puten Paprika Wrap','',7.00,'SNACK',1),
|
||||
(13,'Tomate Mozzarella Wrap','',6.00,'SNACK',1),
|
||||
(14,'Portion Pommes','',4.00,'SNACK',1),
|
||||
(15,'Rinds-Currywurst','',4.50,'SNACK',1),
|
||||
(16,'Rinds-Currywurst mit Pommes','',6.50,'SNACK',1),
|
||||
(17,'Nudelsalat','',4.50,'SNACK',1),
|
||||
(18,'Nudelsalat mit Bockwurst','',6.00,'SNACK',1),
|
||||
(19,'Kartoffelsalat','',4.50,'SNACK',1),
|
||||
(20,'Kartoffelsalat mit Bockwurst','',6.00,'SNACK',1),
|
||||
(21,'Sandwichtoast - Schinken','',1.80,'SNACK',1),
|
||||
(22,'Sandwichtoast - Käse','',1.80,'SNACK',1),
|
||||
(23,'Sandwichtoast - Schinken/Käse','',2.10,'SNACK',1),
|
||||
(24,'Sandwichtoast - Salami','',1.80,'SNACK',1),
|
||||
(25,'Sandwichtoast - Salami/Käse','',2.10,'SNACK',1),
|
||||
(26,'Chips - Western Style','',1.50,'SNACK',1),
|
||||
(27,'Nachos - Salted','',1.50,'SNACK',1),
|
||||
(28,'Panna Cotta mit Erdbeersauce','',7.00,'DESSERT',1),
|
||||
(29,'Panna Cotta mit Blaubeersauce','',7.00,'DESSERT',1),
|
||||
(30,'Mousse au Chocolat','',7.00,'DESSERT',1),
|
||||
(31,'Fruit Loops','',1.50,'BREAKFAST',1),
|
||||
(32,'Smacks','',1.50,'BREAKFAST',1),
|
||||
(33,'Knuspermüsli','Schoko',2.00,'BREAKFAST',1),
|
||||
(34,'Cini Minis','',1.50,'BREAKFAST',1),
|
||||
(35,'Brötchen - Schinken','mit Margarine',1.20,'BREAKFAST',1),
|
||||
(36,'Brötchen - Käse','mit Margarine',1.20,'BREAKFAST',1),
|
||||
(37,'Brötchen - Schinken/Käse','mit Margarine',1.40,'BREAKFAST',1),
|
||||
(38,'Brötchen - Salami','mit Margarine',1.20,'BREAKFAST',1),
|
||||
(39,'Brötchen - Salami/Käse','mit Margarine',1.40,'BREAKFAST',1),
|
||||
(40,'Brötchen - Nutella','mit Margarine',1.20,'BREAKFAST',1),
|
||||
(41,'Wasser - Still','1L Flasche',2.00,'BEVERAGE_NON_ALCOHOLIC',1),
|
||||
(42,'Wasser - Medium','1L Flasche',2.00,'BEVERAGE_NON_ALCOHOLIC',1),
|
||||
(43,'Wasser - Spritzig','1L Flasche',2.00,'BEVERAGE_NON_ALCOHOLIC',1),
|
||||
(44,'Coca-Cola','1L Flasche',2.00,'BEVERAGE_NON_ALCOHOLIC',1),
|
||||
(45,'Coca-Cola Zero','1L Flasche',2.00,'BEVERAGE_NON_ALCOHOLIC',1),
|
||||
(46,'Fanta','1L Flasche',2.00,'BEVERAGE_NON_ALCOHOLIC',1),
|
||||
(47,'Sprite','1L Flasche',2.00,'BEVERAGE_NON_ALCOHOLIC',1),
|
||||
(48,'Spezi','von Paulaner, 0,5L Flasche',1.50,'BEVERAGE_NON_ALCOHOLIC',1),
|
||||
(49,'Red Bull','',2.00,'BEVERAGE_NON_ALCOHOLIC',1),
|
||||
(50,'Energy','Hausmarke',1.50,'BEVERAGE_NON_ALCOHOLIC',1),
|
||||
(51,'Pils','0,33L Flasche',1.90,'BEVERAGE_ALCOHOLIC',1),
|
||||
(52,'Radler','0,33L Flasche',1.90,'BEVERAGE_ALCOHOLIC',1),
|
||||
(53,'Diesel','0,33L Flasche',1.90,'BEVERAGE_ALCOHOLIC',1),
|
||||
(54,'Apfelwein Pur','0,33L Flasche',1.90,'BEVERAGE_ALCOHOLIC',1),
|
||||
(55,'Apfelwein Sauer','0,33L Flasche',1.90,'BEVERAGE_ALCOHOLIC',1),
|
||||
(56,'Apfelwein Cola','0,33L Flasche',1.90,'BEVERAGE_ALCOHOLIC',1),
|
||||
(57,'Vodka Energy','',4.00,'BEVERAGE_COCKTAIL',1),
|
||||
(58,'Vodka O-Saft','',4.00,'BEVERAGE_COCKTAIL',1),
|
||||
(59,'Whiskey Cola','mit Bourbon',4.00,'BEVERAGE_COCKTAIL',1),
|
||||
(60,'Jägermeister Energy','',4.00,'BEVERAGE_COCKTAIL',1),
|
||||
(61,'Sex on the Beach','',5.50,'BEVERAGE_COCKTAIL',1),
|
||||
(62,'Long Island Ice Tea','',5.50,'BEVERAGE_COCKTAIL',1),
|
||||
(63,'Caipirinha','',5.50,'BEVERAGE_COCKTAIL',1),
|
||||
(64,'Jägermeister','',2.00,'BEVERAGE_SHOT',1),
|
||||
(65,'Tequila','',2.00,'BEVERAGE_SHOT',1),
|
||||
(66,'Pfeffi','Pfefferminz-Schnaps',1.50,'BEVERAGE_SHOT',1),
|
||||
(67,'Zigaretten','Elixyr',8.00,'NON_FOOD',1),
|
||||
(68,'Mentholfilter','passend für Elixyr',1.20,'NON_FOOD',1);
|
||||
@ -1,15 +1,15 @@
|
||||
CREATE DATABASE IF NOT EXISTS `ezgg_lan_manager` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */;
|
||||
USE `ezgg_lan_manager`;
|
||||
-- MySQL dump 10.13 Distrib 5.7.24, for Linux (x86_64)
|
||||
CREATE DATABASE IF NOT EXISTS `ez_lan_manager` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */;
|
||||
USE `ez_lan_manager`;
|
||||
-- MySQL dump 10.13 Distrib 8.0.41, for Win64 (x86_64)
|
||||
--
|
||||
-- Host: 127.0.0.1 Database: ezgg_lan_manager
|
||||
-- Host: 127.0.0.1 Database: ez_lan_manager
|
||||
-- ------------------------------------------------------
|
||||
-- Server version 5.5.5-10.11.8-MariaDB-0ubuntu0.24.04.1
|
||||
-- Server version 5.5.5-10.4.32-MariaDB
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!50503 SET NAMES utf8 */;
|
||||
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||
@ -23,7 +23,7 @@ USE `ezgg_lan_manager`;
|
||||
|
||||
DROP TABLE IF EXISTS `catering_menu_items`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `catering_menu_items` (
|
||||
`catering_menu_item_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(45) NOT NULL,
|
||||
@ -32,7 +32,7 @@ CREATE TABLE `catering_menu_items` (
|
||||
`category` varchar(80) NOT NULL,
|
||||
`is_disabled` tinyint(4) DEFAULT 0,
|
||||
PRIMARY KEY (`catering_menu_item_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=69 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@ -41,7 +41,7 @@ CREATE TABLE `catering_menu_items` (
|
||||
|
||||
DROP TABLE IF EXISTS `news`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `news` (
|
||||
`news_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`news_content` text DEFAULT NULL,
|
||||
@ -52,7 +52,7 @@ CREATE TABLE `news` (
|
||||
PRIMARY KEY (`news_id`),
|
||||
KEY `user_is_idx` (`news_author`),
|
||||
CONSTRAINT `user_is` FOREIGN KEY (`news_author`) REFERENCES `users` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@ -61,7 +61,7 @@ CREATE TABLE `news` (
|
||||
|
||||
DROP TABLE IF EXISTS `order_catering_menu_item`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `order_catering_menu_item` (
|
||||
`order_id` int(11) NOT NULL,
|
||||
`catering_menu_item_id` int(11) NOT NULL,
|
||||
@ -79,7 +79,7 @@ CREATE TABLE `order_catering_menu_item` (
|
||||
|
||||
DROP TABLE IF EXISTS `orders`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `orders` (
|
||||
`order_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`status` varchar(45) NOT NULL,
|
||||
@ -87,7 +87,7 @@ CREATE TABLE `orders` (
|
||||
`order_date` datetime NOT NULL DEFAULT current_timestamp(),
|
||||
`is_delivery` tinyint(4) NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY (`order_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@ -96,7 +96,7 @@ CREATE TABLE `orders` (
|
||||
|
||||
DROP TABLE IF EXISTS `seats`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `seats` (
|
||||
`seat_id` varchar(5) NOT NULL,
|
||||
`is_blocked` tinyint(4) NOT NULL DEFAULT 0,
|
||||
@ -113,7 +113,7 @@ CREATE TABLE `seats` (
|
||||
|
||||
DROP TABLE IF EXISTS `tickets`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `tickets` (
|
||||
`ticket_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`ticket_category` varchar(45) NOT NULL,
|
||||
@ -122,7 +122,40 @@ CREATE TABLE `tickets` (
|
||||
PRIMARY KEY (`ticket_id`),
|
||||
KEY `user_id_idx` (`user`),
|
||||
CONSTRAINT `user` FOREIGN KEY (`user`) REFERENCES `users` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `tournament_participants`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `tournament_participants`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `tournament_participants` (
|
||||
`tournament_id` int(11) NOT NULL,
|
||||
`user_id` int(11) NOT NULL,
|
||||
`registered_at_timestamp` varchar(45) NOT NULL DEFAULT 'CURRENT_TIMESTAMP',
|
||||
PRIMARY KEY (`tournament_id`,`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `tournaments`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `tournaments`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `tournaments` (
|
||||
`tournament_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(45) NOT NULL,
|
||||
`additional_info` varchar(300) DEFAULT NULL,
|
||||
`start_time` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
`participants_limit` int(4) DEFAULT NULL,
|
||||
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
PRIMARY KEY (`tournament_id`,`start_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@ -131,7 +164,7 @@ CREATE TABLE `tickets` (
|
||||
|
||||
DROP TABLE IF EXISTS `transactions`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `transactions` (
|
||||
`transaction_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(11) NOT NULL,
|
||||
@ -143,7 +176,7 @@ CREATE TABLE `transactions` (
|
||||
UNIQUE KEY `transaction_id_UNIQUE` (`transaction_id`),
|
||||
KEY `user_id_idx` (`user_id`),
|
||||
CONSTRAINT `user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@ -152,7 +185,7 @@ CREATE TABLE `transactions` (
|
||||
|
||||
DROP TABLE IF EXISTS `user_profile_picture`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `user_profile_picture` (
|
||||
`user_id` int(11) NOT NULL,
|
||||
`picture` mediumblob DEFAULT NULL,
|
||||
@ -167,7 +200,7 @@ CREATE TABLE `user_profile_picture` (
|
||||
|
||||
DROP TABLE IF EXISTS `users`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `users` (
|
||||
`user_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`user_name` varchar(50) NOT NULL,
|
||||
@ -185,7 +218,7 @@ CREATE TABLE `users` (
|
||||
UNIQUE KEY `user_id_UNIQUE` (`user_id`),
|
||||
UNIQUE KEY `user_mail_UNIQUE` (`user_mail`),
|
||||
UNIQUE KEY `user_name_UNIQUE` (`user_name`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||
|
||||
@ -197,4 +230,4 @@ CREATE TABLE `users` (
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
-- Dump completed on 2024-08-25 22:37:14
|
||||
-- Dump completed on 2025-02-09 21:52:04
|
||||
|
||||
@ -1,61 +0,0 @@
|
||||
INSERT INTO `seats` (`seat_id`, `is_blocked`, `seat_category`) VALUES
|
||||
('A01', '0', 'NORMAL'),
|
||||
('A02', '0', 'NORMAL'),
|
||||
('A03', '0', 'NORMAL'),
|
||||
('A04', '0', 'NORMAL'),
|
||||
('A05', '0', 'NORMAL'),
|
||||
('A06', '0', 'NORMAL'),
|
||||
('A10', '0', 'NORMAL'),
|
||||
('A11', '0', 'NORMAL'),
|
||||
('A12', '0', 'NORMAL'),
|
||||
('A13', '0', 'NORMAL'),
|
||||
('A14', '0', 'NORMAL'),
|
||||
('A15', '0', 'NORMAL'),
|
||||
|
||||
('B01', '0', 'NORMAL'),
|
||||
('B02', '0', 'NORMAL'),
|
||||
('B03', '0', 'NORMAL'),
|
||||
('B04', '0', 'NORMAL'),
|
||||
('B05', '0', 'NORMAL'),
|
||||
('B10', '0', 'NORMAL'),
|
||||
('B11', '0', 'NORMAL'),
|
||||
('B12', '0', 'NORMAL'),
|
||||
('B13', '0', 'NORMAL'),
|
||||
('B14', '0', 'NORMAL'),
|
||||
|
||||
('C01', '0', 'NORMAL'),
|
||||
('C02', '0', 'NORMAL'),
|
||||
('C03', '0', 'NORMAL'),
|
||||
('C04', '0', 'NORMAL'),
|
||||
('C05', '0', 'NORMAL'),
|
||||
('C10', '0', 'NORMAL'),
|
||||
('C11', '0', 'NORMAL'),
|
||||
('C12', '0', 'NORMAL'),
|
||||
('C13', '0', 'NORMAL'),
|
||||
('C14', '0', 'NORMAL'),
|
||||
|
||||
('D01', '0', 'NORMAL'),
|
||||
('D02', '0', 'NORMAL'),
|
||||
('D03', '0', 'NORMAL'),
|
||||
('D04', '0', 'NORMAL'),
|
||||
('D05', '0', 'NORMAL'),
|
||||
('D06', '0', 'NORMAL'),
|
||||
('D10', '0', 'NORMAL'),
|
||||
('D11', '0', 'NORMAL'),
|
||||
('D12', '0', 'NORMAL'),
|
||||
('D13', '0', 'NORMAL'),
|
||||
('D14', '0', 'NORMAL'),
|
||||
('D15', '0', 'NORMAL'),
|
||||
|
||||
('E01', '0', 'NORMAL'),
|
||||
('E02', '0', 'NORMAL'),
|
||||
('E03', '0', 'NORMAL'),
|
||||
('E04', '0', 'NORMAL'),
|
||||
('E05', '0', 'NORMAL'),
|
||||
('E06', '0', 'NORMAL'),
|
||||
('E10', '0', 'NORMAL'),
|
||||
('E11', '0', 'NORMAL'),
|
||||
('E12', '0', 'NORMAL'),
|
||||
('E13', '0', 'NORMAL'),
|
||||
('E14', '0', 'NORMAL'),
|
||||
('E15', '0', 'NORMAL');
|
||||
@ -8,13 +8,13 @@ from pathlib import Path
|
||||
from rio import App, Theme, Color, Font, ComponentPage, Session
|
||||
from from_root import from_root
|
||||
|
||||
from src.ezgg_lan_manager import pages, init_services
|
||||
from src.ezgg_lan_manager.helpers.LoggedInGuard import logged_in_guard, not_logged_in_guard, team_guard
|
||||
from src.ezgg_lan_manager.services.DatabaseService import NoDatabaseConnectionError
|
||||
from src.ezgg_lan_manager.services.LocalDataService import LocalData
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager import pages, init_services
|
||||
from src.ez_lan_manager.helpers.LoggedInGuard import logged_in_guard, not_logged_in_guard, team_guard
|
||||
from src.ez_lan_manager.services.DatabaseService import NoDatabaseConnectionError
|
||||
from src.ez_lan_manager.services.LocalDataService import LocalData
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
|
||||
logger = logging.getLogger("EzggLanManager")
|
||||
logger = logging.getLogger("EzLanManager")
|
||||
|
||||
if __name__ == "__main__":
|
||||
theme = Theme.from_colors(
|
||||
@ -28,7 +28,7 @@ if __name__ == "__main__":
|
||||
corner_radius_small=0,
|
||||
corner_radius_medium=0,
|
||||
corner_radius_large=0,
|
||||
font=Font(from_root("src/ezgg_lan_manager/assets/fonts/joystix.otf"))
|
||||
font=Font(from_root("src/ez_lan_manager/assets/fonts/joystix.otf"))
|
||||
)
|
||||
default_attachments = [LocalData()]
|
||||
default_attachments.extend(init_services())
|
||||
@ -46,7 +46,7 @@ if __name__ == "__main__":
|
||||
sys.exit(1)
|
||||
|
||||
app = App(
|
||||
name="EZGG LAN Manager",
|
||||
name="EZ LAN Manager",
|
||||
build=pages.BasePage,
|
||||
pages=[
|
||||
ComponentPage(
|
||||
@ -62,7 +62,7 @@ if __name__ == "__main__":
|
||||
ComponentPage(
|
||||
name="Overview",
|
||||
url_segment="overview",
|
||||
build=pages.OverviewPage,
|
||||
build=lambda: pages.PlaceholderPage(placeholder_name="LAN Übersicht"),
|
||||
),
|
||||
ComponentPage(
|
||||
name="BuyTicket",
|
||||
@ -168,13 +168,13 @@ if __name__ == "__main__":
|
||||
default_attachments=default_attachments,
|
||||
on_session_start=on_session_start,
|
||||
on_app_start=on_app_start,
|
||||
icon=from_root("src/ezgg_lan_manager/assets/img/favicon.png"),
|
||||
icon=from_root("src/ez_lan_manager/assets/img/favicon.png"),
|
||||
meta_tags={
|
||||
"robots": "INDEX,FOLLOW",
|
||||
"description": f"Info und Verwaltungs-Seite der LAN Party '{lan_info.name} - {lan_info.iteration}'.",
|
||||
"og:description": f"Info und Verwaltungs-Seite der LAN Party '{lan_info.name} - {lan_info.iteration}'.",
|
||||
"keywords": "Gaming, Clan, Guild, Verein, Club, Einfach, Zocken, Gesellschaft, Videospiele, "
|
||||
"Videogames, LAN, Party, EZ, EZGG, LAN, Manager",
|
||||
"Videogames, LAN, Party, EZ, LAN, Manager",
|
||||
"author": "David Rodenkirchen",
|
||||
"publisher": "EZ GG e.V.",
|
||||
"copyright": "EZ GG e.V.",
|
||||
@ -186,7 +186,4 @@ if __name__ == "__main__":
|
||||
}
|
||||
)
|
||||
|
||||
sys.exit(app.run_as_web_server(
|
||||
host="0.0.0.0",
|
||||
port=8000,
|
||||
))
|
||||
sys.exit(app.run_as_web_server())
|
||||
36
src/ez_lan_manager/__init__.py
Normal file
36
src/ez_lan_manager/__init__.py
Normal file
@ -0,0 +1,36 @@
|
||||
import logging
|
||||
|
||||
from from_root import from_root
|
||||
|
||||
from src.ez_lan_manager.services import *
|
||||
from src.ez_lan_manager.services.AccountingService import AccountingService
|
||||
from src.ez_lan_manager.services.CateringService import CateringService
|
||||
from src.ez_lan_manager.services.ConfigurationService import ConfigurationService
|
||||
from src.ez_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ez_lan_manager.services.LocalDataService import LocalDataService
|
||||
from src.ez_lan_manager.services.MailingService import MailingService
|
||||
from src.ez_lan_manager.services.NewsService import NewsService
|
||||
from src.ez_lan_manager.services.SeatingService import SeatingService
|
||||
from src.ez_lan_manager.services.TicketingService import TicketingService
|
||||
from src.ez_lan_manager.services.TournamentService import TournamentService
|
||||
from src.ez_lan_manager.services.UserService import UserService
|
||||
from src.ez_lan_manager.types import *
|
||||
|
||||
|
||||
# Inits services in the correct order
|
||||
def init_services() -> tuple[AccountingService, CateringService, ConfigurationService, DatabaseService, MailingService, NewsService, SeatingService, TicketingService, UserService, LocalDataService, TournamentService]:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
configuration_service = ConfigurationService(from_root("config.toml"))
|
||||
db_service = DatabaseService(configuration_service.get_database_configuration())
|
||||
user_service = UserService(db_service)
|
||||
accounting_service = AccountingService(db_service)
|
||||
news_service = NewsService(db_service)
|
||||
mailing_service = MailingService(configuration_service)
|
||||
ticketing_service = TicketingService(configuration_service.get_ticket_info(), db_service, accounting_service)
|
||||
tournament_service = TournamentService(db_service)
|
||||
seating_service = SeatingService(configuration_service.get_seating_configuration(),
|
||||
configuration_service.get_lan_info(), db_service, ticketing_service)
|
||||
catering_service = CateringService(db_service, accounting_service, user_service)
|
||||
local_data_service = LocalDataService()
|
||||
|
||||
return accounting_service, catering_service, configuration_service, db_service, mailing_service, news_service, seating_service, ticketing_service, user_service, local_data_service, tournament_service
|
||||
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@ -4,7 +4,7 @@ from decimal import Decimal
|
||||
import rio
|
||||
from rio import Component, Row, Text, IconButton, TextStyle
|
||||
|
||||
from src.ezgg_lan_manager import AccountingService
|
||||
from src.ez_lan_manager import AccountingService
|
||||
|
||||
MAX_LEN = 24
|
||||
|
||||
@ -3,9 +3,9 @@ from typing import Optional, Callable
|
||||
|
||||
from rio import Component, Row, Card, Column, Text, TextStyle, Spacer, PointerEventListener, Button
|
||||
|
||||
from src.ezgg_lan_manager.services.CateringService import CateringService
|
||||
from src.ezgg_lan_manager.types.CateringOrder import CateringOrder, CateringOrderStatus
|
||||
from src.ezgg_lan_manager.types.Seat import Seat
|
||||
from src.ez_lan_manager.services.CateringService import CateringService
|
||||
from src.ez_lan_manager.types.CateringOrder import CateringOrder, CateringOrderStatus
|
||||
from src.ez_lan_manager.types.Seat import Seat
|
||||
|
||||
class CateringManagementOrderDisplayStatusButton(Component):
|
||||
status: CateringOrderStatus
|
||||
@ -3,7 +3,7 @@ from typing import Callable
|
||||
from rio import Component, Row, Text, TextStyle, Color, Rectangle, CursorStyle
|
||||
from rio.components.pointer_event_listener import PointerEvent, PointerEventListener
|
||||
|
||||
from src.ezgg_lan_manager.types.CateringOrder import CateringOrderStatus, CateringOrder
|
||||
from src.ez_lan_manager.types.CateringOrder import CateringOrderStatus, CateringOrder
|
||||
|
||||
MAX_LEN = 24
|
||||
|
||||
@ -4,7 +4,7 @@ from typing import Callable
|
||||
import rio
|
||||
from rio import Component, Row, Text, IconButton, TextStyle, Column, Spacer, Card, Color
|
||||
|
||||
from src.ezgg_lan_manager import AccountingService
|
||||
from src.ez_lan_manager import AccountingService
|
||||
|
||||
MAX_LEN = 24
|
||||
|
||||
@ -3,12 +3,12 @@ from typing import Optional, Callable
|
||||
|
||||
from rio import *
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, UserService, LocalDataService
|
||||
from src.ezgg_lan_manager.components.DesktopNavigationButton import DesktopNavigationButton
|
||||
from src.ezgg_lan_manager.components.UserInfoAndLoginBox import UserInfoAndLoginBox
|
||||
from src.ezgg_lan_manager.services.LocalDataService import LocalData
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager import ConfigurationService, UserService, LocalDataService
|
||||
from src.ez_lan_manager.components.DesktopNavigationButton import DesktopNavigationButton
|
||||
from src.ez_lan_manager.components.UserInfoAndLoginBox import UserInfoAndLoginBox
|
||||
from src.ez_lan_manager.services.LocalDataService import LocalData
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
|
||||
class DesktopNavigation(Component):
|
||||
@ -54,7 +54,7 @@ class DesktopNavigation(Component):
|
||||
DesktopNavigationButton("FAQ", "./faq"),
|
||||
DesktopNavigationButton("Regeln & AGB", "./rules-gtc"),
|
||||
Spacer(min_height=1),
|
||||
DesktopNavigationButton("Discord", "https://discord.gg/8gTjg34yyH", open_new_tab=True),
|
||||
DesktopNavigationButton("Discord", "#", open_new_tab=True), # Temporarily disabled: https://discord.gg/8gTjg34yyH
|
||||
DesktopNavigationButton("Die EZ GG e.V.", "https://ezgg-ev.de/about", open_new_tab=True),
|
||||
DesktopNavigationButton("Kontakt", "./contact"),
|
||||
DesktopNavigationButton("Impressum & DSGVO", "./imprint"),
|
||||
@ -79,7 +79,7 @@ class DesktopNavigation(Component):
|
||||
|
||||
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(lan_info.name, align_x=0.5, margin_top=0.3, style=TextStyle(fill=self.session.theme.hud_color, font_size=2.5)),
|
||||
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,
|
||||
@ -1,14 +1,15 @@
|
||||
from rio import Component, TextStyle, Color, TextInput, Button, Text, Rectangle, Column, Row, Spacer, \
|
||||
EventHandler
|
||||
|
||||
from src.ezgg_lan_manager.services.LocalDataService import LocalDataService, LocalData
|
||||
from src.ezgg_lan_manager.services.UserService import UserService
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager.services.LocalDataService import LocalDataService, LocalData
|
||||
from src.ez_lan_manager.services.UserService import UserService
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
|
||||
class LoginBox(Component):
|
||||
status_change_cb: EventHandler = None
|
||||
TEXT_STYLE = TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9)
|
||||
user_name_input_text: str = ""
|
||||
password_input_text: str = ""
|
||||
user_name_input_is_valid = True
|
||||
@ -56,7 +57,7 @@ class LoginBox(Component):
|
||||
is_valid=self.password_input_is_valid
|
||||
)
|
||||
login_button = Button(
|
||||
Text("LOGIN", fill=Color.from_hex("02dac5"), style=TextStyle(font_size=0.9), justify="center"),
|
||||
Text("LOGIN", style=self.TEXT_STYLE, justify="center"),
|
||||
shape="rectangle",
|
||||
style="minor",
|
||||
color="secondary",
|
||||
@ -64,14 +65,14 @@ class LoginBox(Component):
|
||||
on_press=self._on_login_pressed
|
||||
)
|
||||
register_button = Button(
|
||||
Text("REG", fill=Color.from_hex("02dac5"), style=TextStyle(font_size=0.9), justify="center"),
|
||||
Text("REG", style=self.TEXT_STYLE, justify="center"),
|
||||
shape="rectangle",
|
||||
style="minor",
|
||||
color="secondary",
|
||||
on_press=lambda: self.session.navigate_to("./register")
|
||||
)
|
||||
forgot_password_button = Button(
|
||||
Text("LST PWD", fill=Color.from_hex("02dac5"), style=TextStyle(font_size=0.9), justify="center"),
|
||||
Text("LST PWD", style=self.TEXT_STYLE, justify="center"),
|
||||
shape="rectangle",
|
||||
style="minor",
|
||||
color="secondary",
|
||||
@ -94,7 +95,7 @@ class LoginBox(Component):
|
||||
),
|
||||
margin_bottom=0.5
|
||||
),
|
||||
Text(text="Dieses Konto\nist gesperrt", fill=self.session.theme.danger_color, style=TextStyle(font_size=0.9 if self.is_account_locked else 0), align_x=0.5),
|
||||
Text(text="Dieses Konto\nist gesperrt", style=TextStyle(fill=self.session.theme.danger_color, font_size=0.9 if self.is_account_locked else 0), align_x=0.5),
|
||||
spacing=0.4
|
||||
),
|
||||
fill=Color.TRANSPARENT,
|
||||
@ -4,8 +4,8 @@ from typing import Optional
|
||||
|
||||
from rio import Component, Column, NumberInput, ThemeContextSwitcher, TextInput, Row, Button, EventHandler
|
||||
|
||||
from src.ezgg_lan_manager.types.Transaction import Transaction
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager.types.Transaction import Transaction
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
|
||||
class NewTransactionForm(Component):
|
||||
@ -46,6 +46,7 @@ class NewTransactionForm(Component):
|
||||
label="Betrag",
|
||||
suffix_text="€",
|
||||
decimals=2,
|
||||
thousands_separator=".",
|
||||
margin=1,
|
||||
margin_bottom=0
|
||||
),
|
||||
@ -21,8 +21,8 @@ class NewsPost(Component):
|
||||
grow_x=True,
|
||||
margin=2,
|
||||
margin_bottom=0,
|
||||
fill=self.session.theme.background_color,
|
||||
style=TextStyle(
|
||||
fill=self.session.theme.background_color,
|
||||
font_size=1.3
|
||||
),
|
||||
overflow="ellipsize"
|
||||
@ -31,8 +31,8 @@ class NewsPost(Component):
|
||||
self.date,
|
||||
margin=2,
|
||||
align_x=1,
|
||||
fill=self.session.theme.background_color,
|
||||
style=TextStyle(
|
||||
fill=self.session.theme.background_color,
|
||||
font_size=0.6
|
||||
),
|
||||
overflow="wrap"
|
||||
@ -44,8 +44,8 @@ class NewsPost(Component):
|
||||
margin=2,
|
||||
margin_top=0,
|
||||
margin_bottom=0,
|
||||
fill=self.session.theme.background_color,
|
||||
style=TextStyle(
|
||||
fill=self.session.theme.background_color,
|
||||
font_size=0.8
|
||||
),
|
||||
overflow="ellipsize"
|
||||
@ -53,7 +53,9 @@ class NewsPost(Component):
|
||||
Text(
|
||||
self.text,
|
||||
margin=2,
|
||||
fill=self.session.theme.background_color,
|
||||
style=TextStyle(
|
||||
fill=self.session.theme.background_color
|
||||
),
|
||||
overflow="wrap"
|
||||
),
|
||||
Text(
|
||||
@ -63,8 +65,8 @@ class NewsPost(Component):
|
||||
margin=2,
|
||||
margin_top=0,
|
||||
margin_bottom=1,
|
||||
fill=self.session.theme.background_color,
|
||||
style=TextStyle(
|
||||
fill=self.session.theme.background_color,
|
||||
font_size=0.5,
|
||||
italic=True
|
||||
),
|
||||
194
src/ez_lan_manager/components/SeatingPlan.py
Normal file
194
src/ez_lan_manager/components/SeatingPlan.py
Normal file
@ -0,0 +1,194 @@
|
||||
from typing import Callable
|
||||
|
||||
from rio import Component, Rectangle, Grid, Column, Row, Text, TextStyle, Color
|
||||
|
||||
from src.ez_lan_manager.components.SeatingPlanPixels import SeatPixel, WallPixel, InvisiblePixel, TextPixel
|
||||
from src.ez_lan_manager.types.Seat import Seat
|
||||
|
||||
MAX_GRID_WIDTH_PIXELS = 34
|
||||
MAX_GRID_HEIGHT_PIXELS = 45
|
||||
|
||||
class SeatingPlanLegend(Component):
|
||||
def build(self) -> Component:
|
||||
return Column(
|
||||
Text("Legende", style=TextStyle(fill=self.session.theme.neutral_color), justify="center", margin=1),
|
||||
Row(
|
||||
Text("L = Luxus Platz", justify="center", style=TextStyle(fill=self.session.theme.neutral_color)),
|
||||
Text("N = Normaler Platz", justify="center", style=TextStyle(fill=self.session.theme.neutral_color)),
|
||||
),
|
||||
Row(
|
||||
Rectangle(
|
||||
content=Column(
|
||||
Text(f"Freier Platz", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.7), align_x=0.5, selectable=False),
|
||||
Text(f"", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.9), align_x=0.5,
|
||||
selectable=False, overflow="wrap")
|
||||
),
|
||||
min_width=1,
|
||||
min_height=1,
|
||||
fill=self.session.theme.success_color,
|
||||
grow_x=False,
|
||||
grow_y=False,
|
||||
hover_fill=self.session.theme.success_color,
|
||||
transition_time=0.4,
|
||||
ripple=True
|
||||
),
|
||||
Rectangle(
|
||||
content=Column(
|
||||
Text(f"Belegter Platz", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.7), align_x=0.5, selectable=False),
|
||||
Text(f"", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.9), align_x=0.5,
|
||||
selectable=False, overflow="wrap")
|
||||
),
|
||||
min_width=1,
|
||||
min_height=1,
|
||||
fill=self.session.theme.danger_color,
|
||||
grow_x=False,
|
||||
grow_y=False,
|
||||
hover_fill=self.session.theme.danger_color,
|
||||
transition_time=0.4,
|
||||
ripple=True
|
||||
),
|
||||
Rectangle(
|
||||
content=Column(
|
||||
Text(f"Eigener Platz", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.7), align_x=0.5, selectable=False),
|
||||
Text(f"", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.9), align_x=0.5,
|
||||
selectable=False, overflow="wrap")
|
||||
),
|
||||
min_width=1,
|
||||
min_height=1,
|
||||
fill=Color.from_hex("800080"),
|
||||
grow_x=False,
|
||||
grow_y=False,
|
||||
hover_fill=Color.from_hex("800080"),
|
||||
transition_time=0.4,
|
||||
ripple=True
|
||||
),
|
||||
margin=1,
|
||||
spacing=1
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class SeatingPlan(Component):
|
||||
seat_clicked_cb: Callable
|
||||
seating_info: list[Seat]
|
||||
|
||||
def get_seat(self, seat_id: str) -> Seat:
|
||||
return next(filter(lambda seat: seat.seat_id == seat_id, self.seating_info))
|
||||
|
||||
"""
|
||||
This seating plan is for the community center "Bottenhorn"
|
||||
"""
|
||||
def build(self) -> Component:
|
||||
grid = Grid()
|
||||
# Outlines
|
||||
for column_id in range(0, MAX_GRID_WIDTH_PIXELS):
|
||||
grid.add(InvisiblePixel(), row=0, column=column_id)
|
||||
for y in range(0, 13):
|
||||
grid.add(WallPixel(), row=y, column=0)
|
||||
for y in range(13, 19):
|
||||
grid.add(InvisiblePixel(), row=y, column=0)
|
||||
for y in range(19, MAX_GRID_HEIGHT_PIXELS):
|
||||
grid.add(WallPixel(), row=y, column=0)
|
||||
|
||||
# Block A
|
||||
block_a_margin_left = 12
|
||||
block_a_margin_top = 1
|
||||
(grid
|
||||
.add(SeatPixel("A01", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A01")), row=block_a_margin_top, column=block_a_margin_left, width=2, height=3)
|
||||
.add(SeatPixel("A02", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A02")), row=block_a_margin_top + 4, column=block_a_margin_left, width=2, height=3)
|
||||
.add(SeatPixel("A03", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A03")), row=block_a_margin_top + 8, column=block_a_margin_left, width=2, height=3)
|
||||
.add(SeatPixel("A10", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A10")), row=block_a_margin_top, column=block_a_margin_left + 3, width=2, height=3)
|
||||
.add(SeatPixel("A11", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A11")), row=block_a_margin_top + 4, column=block_a_margin_left + 3, width=2, height=3)
|
||||
.add(SeatPixel("A12", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A12")), row=block_a_margin_top + 8, column=block_a_margin_left + 3, width=2, height=3)
|
||||
)
|
||||
|
||||
# Block B
|
||||
block_b_margin_left = 20
|
||||
block_b_margin_top = 1
|
||||
(grid
|
||||
.add(SeatPixel("B01", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B01")), row=block_b_margin_top, column=block_b_margin_left, width=2, height=3)
|
||||
.add(SeatPixel("B02", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B02")), row=block_b_margin_top + 4, column=block_b_margin_left, width=2, height=3)
|
||||
.add(SeatPixel("B03", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B03")), row=block_b_margin_top + 8, column=block_b_margin_left, width=2, height=3)
|
||||
.add(SeatPixel("B10", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B10")), row=block_b_margin_top, column=block_b_margin_left + 3, width=2, height=3)
|
||||
.add(SeatPixel("B11", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B11")), row=block_b_margin_top + 4, column=block_b_margin_left + 3, width=2, height=3)
|
||||
.add(SeatPixel("B12", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B12")), row=block_b_margin_top + 8, column=block_b_margin_left + 3, width=2, height=3)
|
||||
)
|
||||
|
||||
# Block C
|
||||
block_c_margin_left = 28
|
||||
block_c_margin_top = 1
|
||||
(grid
|
||||
.add(SeatPixel("C01", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C01")), row=block_c_margin_top, column=block_c_margin_left, width=2, height=3)
|
||||
.add(SeatPixel("C02", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C02")), row=block_c_margin_top + 4, column=block_c_margin_left, width=2, height=3)
|
||||
.add(SeatPixel("C03", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C03")), row=block_c_margin_top + 8, column=block_c_margin_left, width=2, height=3)
|
||||
.add(SeatPixel("C10", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C10")), row=block_c_margin_top, column=block_c_margin_left + 3, width=2, height=3)
|
||||
.add(SeatPixel("C11", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C11")), row=block_c_margin_top + 4, column=block_c_margin_left + 3, width=2, height=3)
|
||||
.add(SeatPixel("C12", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C12")), row=block_c_margin_top + 8, column=block_c_margin_left + 3, width=2, height=3)
|
||||
)
|
||||
|
||||
# Block D
|
||||
block_d_margin_left = 20
|
||||
block_d_margin_top = 20
|
||||
(grid
|
||||
.add(SeatPixel("D01", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D01")), row=block_d_margin_top, column=block_d_margin_left, width=2, height=3)
|
||||
.add(SeatPixel("D02", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D02")), row=block_d_margin_top + 4, column=block_d_margin_left, width=2, height=3)
|
||||
.add(SeatPixel("D03", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D03")), row=block_d_margin_top + 8, column=block_d_margin_left, width=2, height=3)
|
||||
.add(SeatPixel("D10", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D10")), row=block_d_margin_top, column=block_d_margin_left + 3, width=2, height=3)
|
||||
.add(SeatPixel("D11", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D11")), row=block_d_margin_top + 4, column=block_d_margin_left + 3, width=2, height=3)
|
||||
.add(SeatPixel("D12", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D12")), row=block_d_margin_top + 8, column=block_d_margin_left + 3, width=2, height=3)
|
||||
)
|
||||
|
||||
# Block E
|
||||
block_e_margin_left = 28
|
||||
block_e_margin_top = 20
|
||||
(grid
|
||||
.add(SeatPixel("E01", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E01")), row=block_e_margin_top, column=block_e_margin_left, width=2, height=3)
|
||||
.add(SeatPixel("E02", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E02")), row=block_e_margin_top + 4, column=block_e_margin_left, width=2, height=3)
|
||||
.add(SeatPixel("E03", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E03")), row=block_e_margin_top + 8, column=block_e_margin_left, width=2, height=3)
|
||||
.add(SeatPixel("E10", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E10")), row=block_e_margin_top, column=block_e_margin_left + 3, width=2, height=3)
|
||||
.add(SeatPixel("E11", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E11")), row=block_e_margin_top + 4, column=block_e_margin_left + 3, width=2, height=3)
|
||||
.add(SeatPixel("E12", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E12")), row=block_e_margin_top + 8, column=block_e_margin_left + 3, width=2, height=3)
|
||||
)
|
||||
|
||||
# Middle Wall
|
||||
for y in range(0, 13):
|
||||
grid.add(WallPixel(), row=y, column=10)
|
||||
for y in range(19, MAX_GRID_HEIGHT_PIXELS):
|
||||
grid.add(WallPixel(), row=y, column=10)
|
||||
|
||||
# Stage
|
||||
for x in range(11, MAX_GRID_WIDTH_PIXELS):
|
||||
grid.add(WallPixel(), row=35, column=x)
|
||||
grid.add(TextPixel(text="Bühne"), row=36, column=11, width=24, height=9)
|
||||
|
||||
# Drinks
|
||||
grid.add(TextPixel(text="G\ne\nt\nr\nä\nn\nk\ne"), row=21, column=11, width=3, height=11)
|
||||
|
||||
# Sleeping
|
||||
grid.add(TextPixel(icon_name="material/bed"), row=1, column=1, width=4, height=11)
|
||||
|
||||
# Toilet
|
||||
grid.add(TextPixel(icon_name="material/floor", no_outline=True), row=1, column=7, width=3, height=2)
|
||||
grid.add(TextPixel(icon_name="material/north", no_outline=True), row=3, column=7, width=3, height=2)
|
||||
grid.add(TextPixel(icon_name="material/wc"), row=5, column=7, width=3, height=2)
|
||||
|
||||
# Entry/Helpdesk
|
||||
grid.add(TextPixel(text="Einlass\n &Orga"), row=19, column=3, width=7, height=5)
|
||||
|
||||
# Wall below Entry/Helpdesk
|
||||
for y in range(24, MAX_GRID_HEIGHT_PIXELS):
|
||||
grid.add(WallPixel(), row=y, column=3)
|
||||
|
||||
# Entry Arrow
|
||||
grid.add(TextPixel(icon_name="material/east", no_outline=True), row=15, column=1, width=2, height=2)
|
||||
|
||||
return Rectangle(
|
||||
content=grid,
|
||||
grow_x=True,
|
||||
grow_y=True,
|
||||
stroke_color=self.session.theme.neutral_color,
|
||||
stroke_width=0.1,
|
||||
fill=self.session.theme.primary_color,
|
||||
margin=0.5
|
||||
)
|
||||
|
||||
@ -1,11 +1,7 @@
|
||||
from decimal import Decimal
|
||||
from functools import partial
|
||||
from typing import Optional, Callable
|
||||
|
||||
from rio import Component, Column, Text, TextStyle, Button, Spacer, event
|
||||
|
||||
from src.ezgg_lan_manager import TicketingService
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from rio import Component, Column, Text, TextStyle, Button, Spacer
|
||||
|
||||
|
||||
class SeatingPlanInfoBox(Component):
|
||||
@ -16,30 +12,8 @@ class SeatingPlanInfoBox(Component):
|
||||
seat_occupant: Optional[str] = None
|
||||
seat_price: Decimal = Decimal("0")
|
||||
is_blocked: bool = False
|
||||
has_user_ticket: bool = False
|
||||
booking_button_text: str = ""
|
||||
override_text: str = "" # If this is set, all other functionality is disabled and the text is shown
|
||||
|
||||
@event.on_populate
|
||||
async def check_ticket(self) -> None:
|
||||
if self.session[SessionStorage].user_id:
|
||||
user_ticket = await self.session[TicketingService].get_user_ticket(self.session[SessionStorage].user_id)
|
||||
self.has_user_ticket = not (user_ticket is None)
|
||||
self.booking_button_text = "Buchen" if self.has_user_ticket else "Ticket kaufen"
|
||||
self.force_refresh()
|
||||
|
||||
async def purchase_clicked(self):
|
||||
if self.has_user_ticket:
|
||||
await self.purchase_cb()
|
||||
else:
|
||||
self.session.navigate_to("./buy_ticket")
|
||||
|
||||
def build(self) -> Component:
|
||||
if self.override_text:
|
||||
return Column(Text(self.override_text, margin=1,
|
||||
style=TextStyle(fill=self.session.theme.neutral_color, font_size=1.4), overflow="wrap",
|
||||
justify="center"), min_height=10)
|
||||
|
||||
if not self.show:
|
||||
return Spacer()
|
||||
if self.is_blocked:
|
||||
@ -62,7 +36,7 @@ class SeatingPlanInfoBox(Component):
|
||||
style=TextStyle(fill=self.session.theme.neutral_color), overflow="wrap", justify="center"),
|
||||
Button(
|
||||
Text(
|
||||
text=self.booking_button_text,
|
||||
f"Buchen",
|
||||
margin=1,
|
||||
style=TextStyle(fill=self.session.theme.neutral_color, font_size=1.1),
|
||||
overflow="wrap",
|
||||
@ -74,10 +48,7 @@ class SeatingPlanInfoBox(Component):
|
||||
margin=1,
|
||||
grow_y=False,
|
||||
is_sensitive=not self.is_booking_blocked,
|
||||
on_press=self.purchase_clicked
|
||||
) if self.session[SessionStorage].user_id else Text(f"Du musst eingeloggt sein um einen Sitzplatz zu buchen",
|
||||
margin=1,
|
||||
style=TextStyle(fill=self.session.theme.neutral_color),
|
||||
overflow="wrap", justify="center"),
|
||||
on_press=self.purchase_cb
|
||||
),
|
||||
min_height=10
|
||||
)
|
||||
@ -1,17 +1,16 @@
|
||||
from functools import partial
|
||||
|
||||
from rio import Component, Text, Icon, TextStyle, Rectangle, Spacer, Color, PointerEventListener, Column, Row, PointerEvent, Tooltip
|
||||
from typing import Optional, Callable, Literal
|
||||
from rio import Component, Text, Icon, TextStyle, Rectangle, Spacer, Color, PointerEventListener, Column
|
||||
from typing import Optional, Callable
|
||||
|
||||
from src.ezgg_lan_manager.types.Seat import Seat
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager.types.Seat import Seat
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
|
||||
|
||||
class SeatPixel(Component):
|
||||
seat_id: str
|
||||
on_press_cb: Callable
|
||||
seat: Seat
|
||||
seat_orientation: Literal["top", "bottom"]
|
||||
|
||||
def determine_color(self) -> Color:
|
||||
if self.seat.user is not None and self.seat.user.user_id == self.session[SessionStorage].user_id:
|
||||
@ -21,37 +20,24 @@ class SeatPixel(Component):
|
||||
return self.session.theme.success_color
|
||||
|
||||
def build(self) -> Component:
|
||||
text = Text(f"{self.seat_id}", style=TextStyle(fill=self.session.theme.primary_color, 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.from_hex("003300") if self.seat.category == "NORMAL" else Color.from_hex("66ff99"),
|
||||
grow_x=True,
|
||||
grow_y=True,
|
||||
hover_fill=self.session.theme.hud_color,
|
||||
transition_time=0.4,
|
||||
ripple=True
|
||||
)
|
||||
|
||||
if self.seat.user or self.seat.is_blocked:
|
||||
return PointerEventListener(
|
||||
content=Tooltip(
|
||||
anchor=rec,
|
||||
tip=self.seat.user.user_name if self.seat.user else "Gesperrt",
|
||||
position=self.seat_orientation,
|
||||
return PointerEventListener(
|
||||
content=Rectangle(
|
||||
content=Column(
|
||||
Text(f"{self.seat_id}", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.7), align_x=0.5, selectable=False),
|
||||
Text(f"{self.seat.category[0]}", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.9), align_x=0.5, selectable=False, overflow="wrap")
|
||||
),
|
||||
on_press=partial(self.on_press_cb, self.seat_id),
|
||||
)
|
||||
else:
|
||||
return PointerEventListener(
|
||||
content=rec,
|
||||
on_press=partial(self.on_press_cb, self.seat_id),
|
||||
)
|
||||
|
||||
min_width=1,
|
||||
min_height=1,
|
||||
fill=self.determine_color(),
|
||||
hover_stroke_width = 0.1,
|
||||
grow_x=True,
|
||||
grow_y=True,
|
||||
hover_fill=self.session.theme.hud_color,
|
||||
transition_time=0.4,
|
||||
ripple=True
|
||||
),
|
||||
on_press=partial(self.on_press_cb, self.seat_id)
|
||||
)
|
||||
|
||||
class TextPixel(Component):
|
||||
text: Optional[str] = None
|
||||
@ -72,14 +58,13 @@ class TextPixel(Component):
|
||||
fill=self.session.theme.primary_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,
|
||||
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(
|
||||
@ -90,7 +75,6 @@ class WallPixel(Component):
|
||||
grow_y=True,
|
||||
)
|
||||
|
||||
|
||||
class DebugPixel(Component):
|
||||
def build(self) -> Component:
|
||||
return Rectangle(
|
||||
@ -98,15 +82,14 @@ class DebugPixel(Component):
|
||||
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,
|
||||
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(
|
||||
@ -117,4 +100,4 @@ class InvisiblePixel(Component):
|
||||
hover_stroke_width=0.0,
|
||||
grow_x=True,
|
||||
grow_y=True
|
||||
)
|
||||
)
|
||||
@ -2,14 +2,14 @@ from asyncio import sleep, create_task
|
||||
from decimal import Decimal
|
||||
|
||||
import rio
|
||||
from rio import Component, Column, Text, TextStyle, Button, Row, ScrollContainer, Spacer, Popup, Table, event
|
||||
from rio import Component, Column, Text, TextStyle, Button, Row, ScrollContainer, Spacer, Popup, Table
|
||||
|
||||
from src.ezgg_lan_manager.components.CateringCartItem import CateringCartItem
|
||||
from src.ezgg_lan_manager.components.CateringOrderItem import CateringOrderItem
|
||||
from src.ezgg_lan_manager.services.AccountingService import AccountingService
|
||||
from src.ezgg_lan_manager.services.CateringService import CateringService, CateringError, CateringErrorType
|
||||
from src.ezgg_lan_manager.types.CateringOrder import CateringOrder, CateringMenuItemsWithAmount
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager.components.CateringCartItem import CateringCartItem
|
||||
from src.ez_lan_manager.components.CateringOrderItem import CateringOrderItem
|
||||
from src.ez_lan_manager.services.AccountingService import AccountingService
|
||||
from src.ez_lan_manager.services.CateringService import CateringService, CateringError, CateringErrorType
|
||||
from src.ez_lan_manager.types.CateringOrder import CateringOrder, CateringMenuItemsWithAmount
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
|
||||
POPUP_CLOSE_TIMEOUT_SECONDS = 3
|
||||
|
||||
@ -21,11 +21,6 @@ class ShoppingCartAndOrders(Component):
|
||||
popup_is_shown: bool = False
|
||||
popup_is_error: bool = True
|
||||
|
||||
@event.periodic(5)
|
||||
async def periodic_refresh_of_orders(self) -> None:
|
||||
if not self.show_cart and not self.popup_is_shown:
|
||||
self.orders = await self.session[CateringService].get_orders_for_user(self.session[SessionStorage].user_id)
|
||||
|
||||
async def switch(self) -> None:
|
||||
self.show_cart = not self.show_cart
|
||||
self.orders = await self.session[CateringService].get_orders_for_user(self.session[SessionStorage].user_id)
|
||||
@ -90,8 +85,7 @@ class ShoppingCartAndOrders(Component):
|
||||
show_popup_task = create_task(self.show_popup("Guthaben nicht ausreichend", True))
|
||||
else:
|
||||
show_popup_task = create_task(self.show_popup("Unbekannter Fehler", True))
|
||||
else:
|
||||
self.session[CateringService].save_cart(self.session[SessionStorage].user_id, [])
|
||||
self.session[CateringService].save_cart(self.session[SessionStorage].user_id, [])
|
||||
self.order_button_loading = False
|
||||
if not show_popup_task:
|
||||
show_popup_task = create_task(self.show_popup("Bestellung erfolgreich aufgegeben!", False))
|
||||
@ -130,7 +124,7 @@ class ShoppingCartAndOrders(Component):
|
||||
dialog = await self.session.show_custom_dialog(
|
||||
build=build_dialog_content,
|
||||
modal=True,
|
||||
user_closable=True,
|
||||
user_closeable=True,
|
||||
)
|
||||
await dialog.wait_for_close()
|
||||
|
||||
@ -5,9 +5,9 @@ from decimal import Decimal
|
||||
import rio
|
||||
from rio import Component, Card, Column, Text, Row, Button, TextStyle, ProgressBar, event, Spacer
|
||||
|
||||
from src.ezgg_lan_manager import TicketingService
|
||||
from src.ezgg_lan_manager.services.AccountingService import AccountingService
|
||||
from src.ezgg_lan_manager.types.Ticket import Ticket
|
||||
from src.ez_lan_manager import TicketingService
|
||||
from src.ez_lan_manager.services.AccountingService import AccountingService
|
||||
from src.ez_lan_manager.types.Ticket import Ticket
|
||||
|
||||
|
||||
class TicketBuyCard(Component):
|
||||
@ -7,10 +7,10 @@ from from_root import from_root
|
||||
from rio import Component, Column, Button, Color, TextStyle, Text, TextInput, Row, Image, event, Spacer, DateInput, \
|
||||
TextInputChangeEvent, NoFileSelectedError
|
||||
|
||||
from src.ezgg_lan_manager.services.UserService import UserService, NameNotAllowedError
|
||||
from src.ezgg_lan_manager.services.ConfigurationService import ConfigurationService
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager.services.UserService import UserService, NameNotAllowedError
|
||||
from src.ez_lan_manager.services.ConfigurationService import ConfigurationService
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
|
||||
class UserEditForm(Component):
|
||||
@ -122,7 +122,7 @@ class UserEditForm(Component):
|
||||
|
||||
def build(self) -> Component:
|
||||
pfp_image_container = Image(
|
||||
from_root("src/ezgg_lan_manager/assets/img/anon_pfp.png") if self.profile_picture is None else self.profile_picture,
|
||||
from_root("src/ez_lan_manager/assets/img/anon_pfp.png") if self.profile_picture is None else self.profile_picture,
|
||||
align_x=0.5,
|
||||
min_width=10,
|
||||
min_height=10,
|
||||
@ -1,9 +1,9 @@
|
||||
import logging
|
||||
|
||||
from rio import Component
|
||||
from src.ezgg_lan_manager.components.LoginBox import LoginBox
|
||||
from src.ezgg_lan_manager.components.UserInfoBox import UserInfoBox
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager.components.LoginBox import LoginBox
|
||||
from src.ez_lan_manager.components.UserInfoBox import UserInfoBox
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
@ -4,16 +4,16 @@ from decimal import Decimal
|
||||
|
||||
from rio import Component, TextStyle, Color, Button, Text, Rectangle, Column, Row, Spacer, Link, event, EventHandler
|
||||
|
||||
from src.ezgg_lan_manager.components.UserInfoBoxButton import UserInfoBoxButton
|
||||
from src.ezgg_lan_manager.services.LocalDataService import LocalData, LocalDataService
|
||||
from src.ezgg_lan_manager.services.UserService import UserService
|
||||
from src.ezgg_lan_manager.services.AccountingService import AccountingService
|
||||
from src.ezgg_lan_manager.services.TicketingService import TicketingService
|
||||
from src.ezgg_lan_manager.services.SeatingService import SeatingService
|
||||
from src.ezgg_lan_manager.types.Seat import Seat
|
||||
from src.ezgg_lan_manager.types.Ticket import Ticket
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager.components.UserInfoBoxButton import UserInfoBoxButton
|
||||
from src.ez_lan_manager.services.LocalDataService import LocalData, LocalDataService
|
||||
from src.ez_lan_manager.services.UserService import UserService
|
||||
from src.ez_lan_manager.services.AccountingService import AccountingService
|
||||
from src.ez_lan_manager.services.TicketingService import TicketingService
|
||||
from src.ez_lan_manager.services.SeatingService import SeatingService
|
||||
from src.ez_lan_manager.types.Seat import Seat
|
||||
from src.ez_lan_manager.types.Ticket import Ticket
|
||||
from src.ez_lan_manager.types.User import User
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
|
||||
|
||||
class StatusButton(Component):
|
||||
@ -73,8 +73,6 @@ class UserInfoBox(Component):
|
||||
async def update(self) -> None:
|
||||
if not self.user:
|
||||
self.user = await self.session[UserService].get_user(self.session[SessionStorage].user_id)
|
||||
if not self.user:
|
||||
return
|
||||
self.user_balance = await self.session[AccountingService].get_balance(self.user.user_id)
|
||||
self.user_ticket = await self.session[TicketingService].get_user_ticket(self.user.user_id)
|
||||
self.user_seat = await self.session[SeatingService].get_user_seat(self.user.user_id)
|
||||
@ -2,8 +2,8 @@ from typing import Optional
|
||||
|
||||
from rio import URL, GuardEvent
|
||||
|
||||
from src.ezgg_lan_manager.services.UserService import UserService
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager.services.UserService import UserService
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
|
||||
|
||||
# Guards pages against access from users that are NOT logged in
|
||||
@ -5,14 +5,17 @@ from decimal import Decimal
|
||||
|
||||
import sys
|
||||
|
||||
from src.ezgg_lan_manager import init_services
|
||||
from src.ezgg_lan_manager.types.CateringMenuItem import CateringMenuItemCategory
|
||||
from src.ezgg_lan_manager.types.News import News
|
||||
from src.ez_lan_manager import init_services
|
||||
from src.ez_lan_manager.types.CateringMenuItem import CateringMenuItemCategory
|
||||
from src.ez_lan_manager.types.Tournament import Tournament
|
||||
from src.ez_lan_manager.types.News import News
|
||||
|
||||
DEMO_USERS = [
|
||||
{"user_name": "manfred", "user_mail": "manfred@demomail.com", "password_clear_text": "manfred"}, # Gast
|
||||
{"user_name": "gustav", "user_mail": "gustav@demomail.com", "password_clear_text": "gustav"}, # Gast + Ticket(NORMAL)
|
||||
{"user_name": "jason", "user_mail": "juergen@demomail.com", "password_clear_text": "jason"}, # Gast + Ticket(NORMAL) + Sitzplatz
|
||||
{"user_name": "gustav", "user_mail": "gustav@demomail.com", "password_clear_text": "gustav"},
|
||||
# Gast + Ticket(NORMAL)
|
||||
{"user_name": "jason", "user_mail": "juergen@demomail.com", "password_clear_text": "jason"},
|
||||
# Gast + Ticket(NORMAL) + Sitzplatz
|
||||
{"user_name": "lisa", "user_mail": "lisa@demomail.com", "password_clear_text": "lisa"}, # Teamler
|
||||
{"user_name": "thomas", "user_mail": "thomas@demomail.com", "password_clear_text": "thomas"} # Teamler + Admin
|
||||
]
|
||||
@ -27,6 +30,7 @@ async def run() -> None:
|
||||
ticket_service = services[7]
|
||||
seating_service = services[6]
|
||||
news_service = services[5]
|
||||
tournament_service = services[10]
|
||||
|
||||
if input("Generate seating table? (y/N): ").lower() == "y":
|
||||
sys.exit("This part of the script is currently being reworked... :(")
|
||||
@ -71,37 +75,52 @@ async def run() -> None:
|
||||
CateringMenuItemCategory.MAIN_COURSE)
|
||||
await catering_service.add_menu_item("Tortellini in Käsesauce mit Fleischfüllung", "", Decimal("10.50"),
|
||||
CateringMenuItemCategory.MAIN_COURSE)
|
||||
await catering_service.add_menu_item("Tortellini in Käsesauce ohne Fleischfüllung", "Vegetarisch", Decimal("10.50"),
|
||||
await catering_service.add_menu_item("Tortellini in Käsesauce ohne Fleischfüllung", "Vegetarisch",
|
||||
Decimal("10.50"),
|
||||
CateringMenuItemCategory.MAIN_COURSE)
|
||||
|
||||
# SNACK
|
||||
await catering_service.add_menu_item("Käse Schinken Wrap", "", Decimal("5.00"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Puten Paprika Wrap", "", Decimal("7.00"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Tomate Mozzarella Wrap", "", Decimal("6.00"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Tomate Mozzarella Wrap", "", Decimal("6.00"),
|
||||
CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Portion Pommes", "", Decimal("4.00"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Rinds-Currywurst", "", Decimal("4.50"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Rinds-Currywurst mit Pommes", "", Decimal("6.50"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Rinds-Currywurst mit Pommes", "", Decimal("6.50"),
|
||||
CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Nudelsalat", "", Decimal("4.50"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Nudelsalat mit Bockwurst", "", Decimal("6.00"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Nudelsalat mit Bockwurst", "", Decimal("6.00"),
|
||||
CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Kartoffelsalat", "", Decimal("4.50"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Kartoffelsalat mit Bockwurst", "", Decimal("6.00"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Sandwichtoast - Schinken", "", Decimal("1.80"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Sandwichtoast - Käse", "", Decimal("1.80"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Sandwichtoast - Schinken/Käse", "", Decimal("2.10"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Sandwichtoast - Salami", "", Decimal("1.80"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Sandwichtoast - Salami/Käse", "", Decimal("2.10"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Chips - Western Style", "", Decimal("1.30"), CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Kartoffelsalat mit Bockwurst", "", Decimal("6.00"),
|
||||
CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Sandwichtoast - Schinken", "", Decimal("1.80"),
|
||||
CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Sandwichtoast - Käse", "", Decimal("1.80"),
|
||||
CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Sandwichtoast - Schinken/Käse", "", Decimal("2.10"),
|
||||
CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Sandwichtoast - Salami", "", Decimal("1.80"),
|
||||
CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Sandwichtoast - Salami/Käse", "", Decimal("2.10"),
|
||||
CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Chips - Western Style", "", Decimal("1.30"),
|
||||
CateringMenuItemCategory.SNACK)
|
||||
await catering_service.add_menu_item("Nachos - Salted", "", Decimal("1.30"), CateringMenuItemCategory.SNACK)
|
||||
|
||||
# DESSERT
|
||||
await catering_service.add_menu_item("Panna Cotta mit Erdbeersauce", "", Decimal("7.00"), CateringMenuItemCategory.DESSERT)
|
||||
await catering_service.add_menu_item("Panna Cotta mit Blaubeersauce", "", Decimal("7.00"), CateringMenuItemCategory.DESSERT)
|
||||
await catering_service.add_menu_item("Mousse au Chocolat", "", Decimal("7.00"), CateringMenuItemCategory.DESSERT)
|
||||
await catering_service.add_menu_item("Panna Cotta mit Erdbeersauce", "", Decimal("7.00"),
|
||||
CateringMenuItemCategory.DESSERT)
|
||||
await catering_service.add_menu_item("Panna Cotta mit Blaubeersauce", "", Decimal("7.00"),
|
||||
CateringMenuItemCategory.DESSERT)
|
||||
await catering_service.add_menu_item("Mousse au Chocolat", "", Decimal("7.00"),
|
||||
CateringMenuItemCategory.DESSERT)
|
||||
|
||||
# BREAKFAST
|
||||
await catering_service.add_menu_item("Fruit Loops", "", Decimal("1.50"), CateringMenuItemCategory.BREAKFAST)
|
||||
await catering_service.add_menu_item("Smacks", "", Decimal("1.50"), CateringMenuItemCategory.BREAKFAST)
|
||||
await catering_service.add_menu_item("Knuspermüsli", "Schoko", Decimal("2.00"), CateringMenuItemCategory.BREAKFAST)
|
||||
await catering_service.add_menu_item("Knuspermüsli", "Schoko", Decimal("2.00"),
|
||||
CateringMenuItemCategory.BREAKFAST)
|
||||
await catering_service.add_menu_item("Cini Minis", "", Decimal("2.50"), CateringMenuItemCategory.BREAKFAST)
|
||||
await catering_service.add_menu_item("Brötchen - Schinken", "mit Margarine", Decimal("1.20"),
|
||||
CateringMenuItemCategory.BREAKFAST)
|
||||
@ -133,12 +152,14 @@ async def run() -> None:
|
||||
CateringMenuItemCategory.BEVERAGE_NON_ALCOHOLIC)
|
||||
await catering_service.add_menu_item("Spezi", "von Paulaner, 0,5L Flasche", Decimal("1.50"),
|
||||
CateringMenuItemCategory.BEVERAGE_NON_ALCOHOLIC)
|
||||
await catering_service.add_menu_item("Red Bull", "", Decimal("2.00"), CateringMenuItemCategory.BEVERAGE_NON_ALCOHOLIC)
|
||||
await catering_service.add_menu_item("Red Bull", "", Decimal("2.00"),
|
||||
CateringMenuItemCategory.BEVERAGE_NON_ALCOHOLIC)
|
||||
await catering_service.add_menu_item("Energy", "Hausmarke", Decimal("1.50"),
|
||||
CateringMenuItemCategory.BEVERAGE_NON_ALCOHOLIC)
|
||||
|
||||
# BEVERAGE_ALCOHOLIC
|
||||
await catering_service.add_menu_item("Pils", "0,33L Flasche", Decimal("1.90"), CateringMenuItemCategory.BEVERAGE_ALCOHOLIC)
|
||||
await catering_service.add_menu_item("Pils", "0,33L Flasche", Decimal("1.90"),
|
||||
CateringMenuItemCategory.BEVERAGE_ALCOHOLIC)
|
||||
await catering_service.add_menu_item("Radler", "0,33L Flasche", Decimal("1.90"),
|
||||
CateringMenuItemCategory.BEVERAGE_ALCOHOLIC)
|
||||
await catering_service.add_menu_item("Diesel", "0,33L Flasche", Decimal("1.90"),
|
||||
@ -151,17 +172,24 @@ async def run() -> None:
|
||||
CateringMenuItemCategory.BEVERAGE_ALCOHOLIC)
|
||||
|
||||
# BEVERAGE_COCKTAIL
|
||||
await catering_service.add_menu_item("Vodka Energy", "", Decimal("4.00"), CateringMenuItemCategory.BEVERAGE_COCKTAIL)
|
||||
await catering_service.add_menu_item("Vodka O-Saft", "", Decimal("4.00"), CateringMenuItemCategory.BEVERAGE_COCKTAIL)
|
||||
await catering_service.add_menu_item("Vodka Energy", "", Decimal("4.00"),
|
||||
CateringMenuItemCategory.BEVERAGE_COCKTAIL)
|
||||
await catering_service.add_menu_item("Vodka O-Saft", "", Decimal("4.00"),
|
||||
CateringMenuItemCategory.BEVERAGE_COCKTAIL)
|
||||
await catering_service.add_menu_item("Whiskey Cola", "mit Bourbon", Decimal("4.00"),
|
||||
CateringMenuItemCategory.BEVERAGE_COCKTAIL)
|
||||
await catering_service.add_menu_item("Jägermeister Energy", "", Decimal("4.00"), CateringMenuItemCategory.BEVERAGE_COCKTAIL)
|
||||
await catering_service.add_menu_item("Sex on the Beach", "", Decimal("5.50"), CateringMenuItemCategory.BEVERAGE_COCKTAIL)
|
||||
await catering_service.add_menu_item("Long Island Ice Tea", "", Decimal("5.50"), CateringMenuItemCategory.BEVERAGE_COCKTAIL)
|
||||
await catering_service.add_menu_item("Caipirinha", "", Decimal("5.50"), CateringMenuItemCategory.BEVERAGE_COCKTAIL)
|
||||
await catering_service.add_menu_item("Jägermeister Energy", "", Decimal("4.00"),
|
||||
CateringMenuItemCategory.BEVERAGE_COCKTAIL)
|
||||
await catering_service.add_menu_item("Sex on the Beach", "", Decimal("5.50"),
|
||||
CateringMenuItemCategory.BEVERAGE_COCKTAIL)
|
||||
await catering_service.add_menu_item("Long Island Ice Tea", "", Decimal("5.50"),
|
||||
CateringMenuItemCategory.BEVERAGE_COCKTAIL)
|
||||
await catering_service.add_menu_item("Caipirinha", "", Decimal("5.50"),
|
||||
CateringMenuItemCategory.BEVERAGE_COCKTAIL)
|
||||
|
||||
# BEVERAGE_SHOT
|
||||
await catering_service.add_menu_item("Jägermeister", "", Decimal("2.00"), CateringMenuItemCategory.BEVERAGE_SHOT)
|
||||
await catering_service.add_menu_item("Jägermeister", "", Decimal("2.00"),
|
||||
CateringMenuItemCategory.BEVERAGE_SHOT)
|
||||
await catering_service.add_menu_item("Tequila", "", Decimal("2.00"), CateringMenuItemCategory.BEVERAGE_SHOT)
|
||||
await catering_service.add_menu_item("PfEZzi", "Getunter Pfefferminz-Schnaps", Decimal("1.99"),
|
||||
CateringMenuItemCategory.BEVERAGE_SHOT)
|
||||
@ -185,15 +213,23 @@ async def run() -> None:
|
||||
|
||||
await news_service.add_news(News(
|
||||
news_id=None,
|
||||
title="Der EZGG LAN Manager",
|
||||
title="Der EZ LAN Manager",
|
||||
subtitle="Eine Software des EZ GG e.V.",
|
||||
content="Dies ist eine WIP-Version des EZGG LAN Managers. Diese Software soll uns helfen in Zukunft die LAN "
|
||||
content="Dies ist eine WIP-Version des EZ LAN Managers. Diese Software soll uns helfen in Zukunft die LAN "
|
||||
"Parties des EZ GG e.V.'s zu organisieren. Wer Fehler findet darf sie behalten. (Oder er meldet "
|
||||
"sie)",
|
||||
author=user,
|
||||
news_date=date.today()
|
||||
))
|
||||
|
||||
if not input("Generate default tournament? (Y/n): ").lower() == "n":
|
||||
await tournament_service.add_tournament(
|
||||
name="League of Legends 1vs1",
|
||||
additional_info="Normal 1vs1, 100 cs, first blood, first tower, aram-map",
|
||||
start_time=date.today(),
|
||||
participants_limit=30
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
with asyncio.Runner() as loop:
|
||||
@ -1,19 +1,18 @@
|
||||
from decimal import Decimal
|
||||
from functools import partial
|
||||
from typing import Optional
|
||||
|
||||
from rio import Column, Component, event, Text, TextStyle, Button, Color, Revealer, Row, ProgressCircle, Link
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, UserService, AccountingService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ezgg_lan_manager.types.Transaction import Transaction
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager import ConfigurationService, UserService, AccountingService
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager.types.Transaction import Transaction
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
|
||||
class AccountPage(Component):
|
||||
user: Optional[User] = None
|
||||
balance: Optional[Decimal] = None
|
||||
balance: Optional[int] = None
|
||||
transaction_history: list[Transaction] = list()
|
||||
banking_info_revealer_open: bool = False
|
||||
paypal_info_revealer_open: bool = False
|
||||
@ -2,17 +2,14 @@ from __future__ import annotations
|
||||
|
||||
from typing import * # type: ignore
|
||||
|
||||
from rio import Component, event, Spacer, Card, Container, Column, Row, TextStyle, Color, Text, PageView, Button
|
||||
from rio import Component, event, Spacer, Card, Container, Column, Row, TextStyle, Color, Text, PageView
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, DatabaseService
|
||||
from src.ezgg_lan_manager.components.DesktopNavigation import DesktopNavigation
|
||||
from src.ez_lan_manager import ConfigurationService, DatabaseService
|
||||
from src.ez_lan_manager.components.DesktopNavigation import DesktopNavigation
|
||||
|
||||
class BasePage(Component):
|
||||
color = "secondary"
|
||||
corner_radius = (0, 0.5, 0, 0)
|
||||
footer_size = 53.1
|
||||
force_portrait_mode = False
|
||||
|
||||
@event.periodic(60)
|
||||
async def check_db_conn(self) -> None:
|
||||
is_healthy = await self.session[DatabaseService].is_healthy()
|
||||
@ -23,20 +20,6 @@ class BasePage(Component):
|
||||
async def on_window_size_change(self):
|
||||
self.force_refresh()
|
||||
|
||||
@event.on_page_change
|
||||
def check_needed_size(self):
|
||||
# ToDo: Low-Prio: Change layout, so the footer is always as wide as needed.
|
||||
# This is a workaround, bc the seating page needs more width
|
||||
if "/seating" in self.session.active_page_url.__str__():
|
||||
self.footer_size = 78.2
|
||||
else:
|
||||
self.footer_size = 53.1
|
||||
self.force_refresh()
|
||||
|
||||
def enforce_portrait_mode(self) -> None:
|
||||
self.force_portrait_mode = True
|
||||
self.force_refresh()
|
||||
|
||||
def build(self) -> Component:
|
||||
content = Card(
|
||||
PageView(),
|
||||
@ -44,7 +27,7 @@ class BasePage(Component):
|
||||
min_width=38,
|
||||
corner_radius=(0, 0.5, 0, 0)
|
||||
)
|
||||
if self.session.window_width > 28 or self.force_portrait_mode:
|
||||
if self.session.window_width > 28:
|
||||
return Container(
|
||||
content=Column(
|
||||
Column(
|
||||
@ -58,13 +41,13 @@ class BasePage(Component):
|
||||
Row(
|
||||
Spacer(grow_x=True, grow_y=False),
|
||||
Card(
|
||||
content=Text(f"EZGG LAN Manager Version {self.session[ConfigurationService].APP_VERSION} © EZ GG e.V.", align_x=0.5, align_y=0.5, fill=self.session.theme.primary_color, style=TextStyle(font_size=0.5)),
|
||||
content=Text(f"EZ LAN Manager Version {self.session[ConfigurationService].APP_VERSION} © EZ GG e.V.", align_x=0.5, align_y=0.5, style=TextStyle(fill=self.session.theme.primary_color, font_size=0.5)),
|
||||
color=self.session.theme.neutral_color,
|
||||
corner_radius=(0, 0, 0.5, 0.5),
|
||||
grow_x=False,
|
||||
grow_y=False,
|
||||
min_height=1.2,
|
||||
min_width=self.footer_size,
|
||||
min_width=53.1,
|
||||
margin_bottom=3
|
||||
),
|
||||
Spacer(grow_x=True, grow_y=False),
|
||||
@ -77,21 +60,10 @@ class BasePage(Component):
|
||||
grow_y=True
|
||||
)
|
||||
else:
|
||||
return Column(
|
||||
Text(
|
||||
"Wir empfehlen auf\nmobilen Endgeräten im\nQuerformat zu arbeiten.\n\nBitte drehe dein Gerät.",
|
||||
fill=Color.from_hex("FFFFFF"),
|
||||
align_x=0.5,
|
||||
align_y=0.5,
|
||||
style=TextStyle(font_size=0.8)
|
||||
),
|
||||
Button(
|
||||
content=Text("Ohne drehen fortfahren", margin=0.2),
|
||||
style="minor",
|
||||
shape="rounded",
|
||||
align_x=0.5,
|
||||
align_y=0,
|
||||
on_press=self.enforce_portrait_mode
|
||||
)
|
||||
return Text(
|
||||
"Der EZ LAN Manager wird\nauf mobilen Endgeräten nur\nim Querformat unterstützt.\nBitte drehe dein Gerät.",
|
||||
align_x=0.5,
|
||||
align_y=0.5,
|
||||
style=TextStyle(fill=Color.from_hex("FFFFFF"), font_size=0.8)
|
||||
)
|
||||
|
||||
@ -2,14 +2,14 @@ from typing import Optional
|
||||
|
||||
from rio import Text, Column, TextStyle, Component, event, Button, Popup
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, UserService, TicketingService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ezgg_lan_manager.components.TicketBuyCard import TicketBuyCard
|
||||
from src.ezgg_lan_manager.services.AccountingService import InsufficientFundsError
|
||||
from src.ezgg_lan_manager.services.TicketingService import TicketNotAvailableError, UserAlreadyHasTicketError
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ezgg_lan_manager.types.Ticket import Ticket
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager import ConfigurationService, UserService, TicketingService
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager.components.TicketBuyCard import TicketBuyCard
|
||||
from src.ez_lan_manager.services.AccountingService import InsufficientFundsError
|
||||
from src.ez_lan_manager.services.TicketingService import TicketNotAvailableError, UserAlreadyHasTicketError
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager.types.Ticket import Ticket
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
|
||||
class BuyTicketPage(Component):
|
||||
@ -2,12 +2,12 @@ from typing import Optional, Callable
|
||||
|
||||
from rio import Column, Component, event, TextStyle, Text, Spacer, Revealer, SwitcherBar, SwitcherBarChangeEvent, ProgressCircle
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, CateringService
|
||||
from src.ezgg_lan_manager.components.CateringSelectionItem import CateringSelectionItem
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ezgg_lan_manager.components.ShoppingCartAndOrders import ShoppingCartAndOrders
|
||||
from src.ezgg_lan_manager.types.CateringMenuItem import CateringMenuItemCategory, CateringMenuItem
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager import ConfigurationService, CateringService
|
||||
from src.ez_lan_manager.components.CateringSelectionItem import CateringSelectionItem
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager.components.ShoppingCartAndOrders import ShoppingCartAndOrders
|
||||
from src.ez_lan_manager.types.CateringMenuItem import CateringMenuItemCategory, CateringMenuItem
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
|
||||
|
||||
class CateringPage(Component):
|
||||
@ -3,25 +3,20 @@ from typing import Optional
|
||||
|
||||
from rio import Text, Column, TextStyle, Component, event, TextInput, MultiLineTextInput, Row, Button
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, UserService, MailingService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager import ConfigurationService, UserService, MailingService
|
||||
from src.ez_lan_manager.components.AnimatedText import AnimatedText
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
|
||||
class ContactPage(Component):
|
||||
# Workaround: Can not reassign this value without rio triggering refresh
|
||||
# Using list to bypass this behavior
|
||||
last_message_sent: list[datetime] = [datetime(day=1, month=1, year=2000)]
|
||||
display_printing: list[bool] = [False]
|
||||
user: Optional[User] = None
|
||||
|
||||
e_mail: str = ""
|
||||
subject: str = ""
|
||||
message: str = ""
|
||||
submit_button_is_loading: bool = False
|
||||
response_message: str = ""
|
||||
is_success: bool = True
|
||||
|
||||
@event.on_populate
|
||||
async def on_populate(self) -> None:
|
||||
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Kontakt")
|
||||
@ -29,67 +24,73 @@ class ContactPage(Component):
|
||||
self.user = await self.session[UserService].get_user(self.session[SessionStorage].user_id)
|
||||
else:
|
||||
self.user = None
|
||||
self.e_mail = "" if not self.user else self.user.user_mail
|
||||
|
||||
async def on_send_pressed(self) -> None:
|
||||
error_msg = ""
|
||||
self.submit_button_is_loading = True
|
||||
self.submit_button.is_loading = True
|
||||
self.submit_button.force_refresh()
|
||||
now = datetime.now()
|
||||
if not self.e_mail:
|
||||
if not self.email_input.text:
|
||||
error_msg = "E-Mail darf nicht leer sein!"
|
||||
elif not self.subject:
|
||||
elif not self.subject_input.text:
|
||||
error_msg = "Betreff darf nicht leer sein!"
|
||||
elif not self.message:
|
||||
elif not self.message_input.text:
|
||||
error_msg = "Nachricht darf nicht leer sein!"
|
||||
elif (now - self.last_message_sent[0]) < timedelta(minutes=1):
|
||||
error_msg = "Immer mit der Ruhe!"
|
||||
|
||||
if error_msg:
|
||||
self.submit_button_is_loading = False
|
||||
self.is_success = False
|
||||
self.response_message = error_msg
|
||||
self.submit_button.is_loading = False
|
||||
await self.animated_text.display_text(False, error_msg)
|
||||
return
|
||||
|
||||
mail_recipient = self.session[ConfigurationService].get_lan_info().organizer_mail
|
||||
msg = (f"Kontaktformular vom {now.strftime('%d.%m.%Y %H:%M')}:\n\n"
|
||||
f"Betreff: {self.subject}\n"
|
||||
f"Absender: {self.e_mail}\n\n"
|
||||
f"Betreff: {self.subject_input.text}\n"
|
||||
f"Absender: {self.email_input.text}\n\n"
|
||||
f"Inhalt:\n"
|
||||
f"{self.message}\n")
|
||||
f"{self.message_input.text}\n")
|
||||
|
||||
await self.session[MailingService].send_email("Kontaktformular-Mitteilung", msg, mail_recipient)
|
||||
self.last_message_sent[0] = datetime.now()
|
||||
self.submit_button_is_loading = False
|
||||
self.is_success = True
|
||||
self.response_message = "Nachricht erfolgreich gesendet!"
|
||||
self.submit_button.is_loading = False
|
||||
await self.animated_text.display_text(True, "Nachricht erfolgreich gesendet!")
|
||||
|
||||
def build(self) -> Component:
|
||||
email_input = TextInput(
|
||||
self.animated_text = AnimatedText(
|
||||
margin_top=2,
|
||||
margin_bottom=1,
|
||||
align_x=0.1
|
||||
)
|
||||
|
||||
self.email_input = TextInput(
|
||||
label="E-Mail Adresse",
|
||||
text=self.bind().e_mail,
|
||||
text="" if not self.user else self.user.user_mail,
|
||||
margin_left=1,
|
||||
margin_right=1,
|
||||
margin_bottom=1,
|
||||
grow_x=True
|
||||
)
|
||||
|
||||
subject_input = TextInput(
|
||||
self.subject_input = TextInput(
|
||||
label="Betreff",
|
||||
text=self.bind().subject,
|
||||
text="",
|
||||
margin_left=1,
|
||||
margin_right=1,
|
||||
margin_bottom=1,
|
||||
grow_x=True
|
||||
)
|
||||
|
||||
message_input = MultiLineTextInput(
|
||||
self.message_input = MultiLineTextInput(
|
||||
label="Deine Nachricht an uns",
|
||||
text=self.bind().message,
|
||||
text="",
|
||||
margin_left=1,
|
||||
margin_right=1,
|
||||
margin_bottom=1,
|
||||
min_height=5
|
||||
)
|
||||
|
||||
submit_button = Button(
|
||||
self.submit_button = Button(
|
||||
content=Text(
|
||||
"Absenden",
|
||||
style=TextStyle(fill=self.session.theme.success_color, font_size=0.9),
|
||||
@ -101,8 +102,7 @@ class ContactPage(Component):
|
||||
shape="rectangle",
|
||||
style="major",
|
||||
color="primary",
|
||||
on_press=self.on_send_pressed,
|
||||
is_loading=self.bind().submit_button_is_loading
|
||||
on_press=self.on_send_pressed
|
||||
)
|
||||
return Column(
|
||||
MainViewContentBox(
|
||||
@ -117,21 +117,12 @@ class ContactPage(Component):
|
||||
margin_bottom=1,
|
||||
align_x=0.5
|
||||
),
|
||||
email_input,
|
||||
subject_input,
|
||||
message_input,
|
||||
self.email_input,
|
||||
self.subject_input,
|
||||
self.message_input,
|
||||
Row(
|
||||
Text(
|
||||
text=self.bind().response_message,
|
||||
style=TextStyle(
|
||||
fill=self.session.theme.success_color if self.is_success else self.session.theme.danger_color,
|
||||
font_size=0.9
|
||||
),
|
||||
margin_top=2,
|
||||
margin_bottom=1,
|
||||
align_x=0.1
|
||||
),
|
||||
submit_button,
|
||||
self.animated_text,
|
||||
self.submit_button,
|
||||
)
|
||||
)
|
||||
),
|
||||
@ -5,9 +5,9 @@ from typing import * # type: ignore
|
||||
|
||||
from rio import Component, event, Spacer, Card, Container, Column, Row, TextStyle, Color, Text
|
||||
|
||||
from src.ezgg_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ezgg_lan_manager import ConfigurationService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ez_lan_manager import ConfigurationService
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
|
||||
|
||||
class DbErrorPage(Component):
|
||||
@ -62,7 +62,7 @@ class DbErrorPage(Component):
|
||||
Row(
|
||||
Spacer(grow_x=True, grow_y=False),
|
||||
Card(
|
||||
content=Text(f"EZGG LAN Manager Version {self.session[ConfigurationService].APP_VERSION} © EZ GG e.V.", align_x=0.5, align_y=0.5, style=TextStyle(fill=self.session.theme.primary_color, font_size=0.5)),
|
||||
content=Text(f"EZ LAN Manager Version {self.session[ConfigurationService].APP_VERSION} © EZ GG e.V.", align_x=0.5, align_y=0.5, style=TextStyle(fill=self.session.theme.primary_color, font_size=0.5)),
|
||||
color=self.session.theme.neutral_color,
|
||||
corner_radius=(0, 0, 0.5, 0.5),
|
||||
grow_x=False,
|
||||
@ -82,7 +82,7 @@ class DbErrorPage(Component):
|
||||
)
|
||||
else:
|
||||
return Text(
|
||||
"Der EZGG LAN Manager wird\nauf mobilen Endgeräten nur\nim Querformat unterstützt.\nBitte drehe dein Gerät.",
|
||||
"Der EZ LAN Manager wird\nauf mobilen Endgeräten nur\nim Querformat unterstützt.\nBitte drehe dein Gerät.",
|
||||
align_x=0.5,
|
||||
align_y=0.5,
|
||||
style=TextStyle(fill=Color.from_hex("FFFFFF"), font_size=0.8)
|
||||
@ -2,11 +2,11 @@ from typing import Optional
|
||||
|
||||
from rio import Column, Component, event, Spacer
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, UserService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ezgg_lan_manager.components.UserEditForm import UserEditForm
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager import ConfigurationService, UserService
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager.components.UserEditForm import UserEditForm
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
|
||||
class EditProfilePage(Component):
|
||||
@ -1,7 +1,7 @@
|
||||
from rio import Column, Component, event, TextStyle, Text, Revealer
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager import ConfigurationService
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
|
||||
FAQ: list[list[str]] = [
|
||||
["Wie melde ich mich für die LAN an?",
|
||||
@ -4,8 +4,8 @@ from random import choices
|
||||
from email_validator import validate_email, EmailNotValidError
|
||||
from rio import Column, Component, event, Text, TextStyle, TextInput, TextInputChangeEvent, Button
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, UserService, MailingService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager import ConfigurationService, UserService, MailingService
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
|
||||
|
||||
class ForgotPasswordPage(Component):
|
||||
@ -31,7 +31,7 @@ class ForgotPasswordPage(Component):
|
||||
await user_service.update_user(user)
|
||||
await mailing_service.send_email(
|
||||
subject=f"Dein neues Passwort für {lan_info.name}",
|
||||
body=f"Du hast für den EZGG-LAN Manager der {lan_info.name} ein neues Passwort angefragt. "
|
||||
body=f"Du hast für den EZ-LAN Manager der {lan_info.name} ein neues Passwort angefragt. "
|
||||
f"Und hier ist es schon:\n\n{new_password}\n\nSolltest du kein neues Passwort angefordert haben, "
|
||||
f"ignoriere diese E-Mail.\n\nLiebe Grüße\nDein {lan_info.name} - Team",
|
||||
receiver=self.email_input.text.strip()
|
||||
@ -2,10 +2,10 @@ from typing import Optional
|
||||
|
||||
from rio import Column, Component, event, TextStyle, Text, Button, Row, TextInput, Spacer, TextInputChangeEvent
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, UserService, TicketingService, SeatingService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ezgg_lan_manager.types.Seat import Seat
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager import ConfigurationService, UserService, TicketingService, SeatingService
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager.types.Seat import Seat
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
|
||||
class GuestsPage(Component):
|
||||
@ -1,7 +1,7 @@
|
||||
from rio import Text, Column, TextStyle, Component, event, Link, Color
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager import ConfigurationService
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
|
||||
|
||||
class ImprintPage(Component):
|
||||
@ -5,11 +5,11 @@ from typing import Optional, Callable
|
||||
|
||||
from rio import Column, Component, event, TextStyle, Text, Spacer, PointerEvent, Button, Popup, Card, Row
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, CateringService, SeatingService, AccountingService
|
||||
from src.ezgg_lan_manager.components.CateringManagementOrderDisplay import CateringManagementOrderDisplay
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ezgg_lan_manager.types.CateringOrder import CateringOrder, CateringOrderStatus
|
||||
from src.ezgg_lan_manager.types.Seat import Seat
|
||||
from src.ez_lan_manager import ConfigurationService, CateringService, SeatingService, AccountingService
|
||||
from src.ez_lan_manager.components.CateringManagementOrderDisplay import CateringManagementOrderDisplay
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager.types.CateringOrder import CateringOrder, CateringOrderStatus
|
||||
from src.ez_lan_manager.types.Seat import Seat
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
@ -5,11 +5,11 @@ from time import strptime
|
||||
|
||||
from rio import Column, Component, event, TextStyle, Text
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, UserService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ezgg_lan_manager.components.NewsPost import EditableNewsPost
|
||||
from src.ezgg_lan_manager.services.NewsService import NewsService
|
||||
from src.ezgg_lan_manager.types.News import News
|
||||
from src.ez_lan_manager import ConfigurationService, UserService
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager.components.NewsPost import EditableNewsPost
|
||||
from src.ez_lan_manager.services.NewsService import NewsService
|
||||
from src.ez_lan_manager.types.News import News
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
@ -78,8 +78,8 @@ class ManageNewsPage(Component):
|
||||
Column(
|
||||
Text(
|
||||
text="News Verwaltung",
|
||||
fill=self.session.theme.background_color,
|
||||
style=TextStyle(
|
||||
fill=self.session.theme.background_color,
|
||||
font_size=1.2
|
||||
),
|
||||
margin_top=2,
|
||||
@ -88,8 +88,8 @@ class ManageNewsPage(Component):
|
||||
),
|
||||
Text(
|
||||
text="Neuen News Post erstellen",
|
||||
fill=self.session.theme.background_color,
|
||||
style=TextStyle(
|
||||
fill=self.session.theme.background_color,
|
||||
font_size=1.1
|
||||
),
|
||||
margin_top=2,
|
||||
@ -106,8 +106,8 @@ class ManageNewsPage(Component):
|
||||
),
|
||||
Text(
|
||||
text="Post erfolgreich erstellt",
|
||||
fill=self.session.theme.success_color,
|
||||
style=TextStyle(
|
||||
fill=self.session.theme.success_color,
|
||||
font_size=0.7 if self.show_success_message else 0
|
||||
),
|
||||
margin_top=0.1,
|
||||
@ -116,8 +116,8 @@ class ManageNewsPage(Component):
|
||||
),
|
||||
Text(
|
||||
text="Bisherige Posts",
|
||||
fill=self.session.theme.background_color,
|
||||
style=TextStyle(
|
||||
fill=self.session.theme.background_color,
|
||||
font_size=1.1
|
||||
),
|
||||
margin_top=2,
|
||||
@ -2,8 +2,8 @@ import logging
|
||||
|
||||
from rio import Column, Component, event, TextStyle, Text, Spacer
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager import ConfigurationService
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
@ -6,14 +6,14 @@ from rio import Column, Component, event, TextStyle, Text, TextInput, ThemeConte
|
||||
PointerEventListener, PointerEvent, Rectangle, CursorStyle, Color, TextInputChangeEvent, Spacer, Row, Switch, \
|
||||
SwitchChangeEvent, EventHandler
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, UserService, AccountingService, SeatingService, MailingService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ezgg_lan_manager.components.NewTransactionForm import NewTransactionForm
|
||||
from src.ezgg_lan_manager.components.UserEditForm import UserEditForm
|
||||
from src.ezgg_lan_manager.services.AccountingService import InsufficientFundsError
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ezgg_lan_manager.types.Transaction import Transaction
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager import ConfigurationService, UserService, AccountingService, SeatingService
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager.components.NewTransactionForm import NewTransactionForm
|
||||
from src.ez_lan_manager.components.UserEditForm import UserEditForm
|
||||
from src.ez_lan_manager.services.AccountingService import InsufficientFundsError
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager.types.Transaction import Transaction
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
@ -104,17 +104,11 @@ class ManageUsersPage(Component):
|
||||
self.accounting_section_result_success = False
|
||||
return
|
||||
else:
|
||||
new_total_balance = await self.session[AccountingService].add_balance(
|
||||
await self.session[AccountingService].add_balance(
|
||||
transaction.user_id,
|
||||
transaction.value,
|
||||
transaction.reference
|
||||
)
|
||||
user = await self.session[UserService].get_user(transaction.user_id)
|
||||
await self.session[MailingService].send_email(
|
||||
"Dein Guthaben wurde aufgeladen",
|
||||
self.session[MailingService].generate_account_balance_added_mail_body(user, transaction.value, new_total_balance),
|
||||
user.user_mail
|
||||
)
|
||||
|
||||
self.accounting_section_result_text = f"Guthaben {'entfernt' if transaction.is_debit else 'hinzugefügt'}!"
|
||||
self.accounting_section_result_success = True
|
||||
@ -1,8 +1,8 @@
|
||||
from rio import Column, Component, event
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, NewsService
|
||||
from src.ezgg_lan_manager.components.NewsPost import NewsPost
|
||||
from src.ezgg_lan_manager.types.News import News
|
||||
from src.ez_lan_manager import ConfigurationService, NewsService
|
||||
from src.ez_lan_manager.components.NewsPost import NewsPost
|
||||
from src.ez_lan_manager.types.News import News
|
||||
|
||||
|
||||
class NewsPage(Component):
|
||||
@ -1,7 +1,7 @@
|
||||
from rio import Column, Component, event
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService
|
||||
from src.ezgg_lan_manager.components.NewsPost import NewsPost
|
||||
from src.ez_lan_manager import ConfigurationService
|
||||
from src.ez_lan_manager.components.NewsPost import NewsPost
|
||||
|
||||
|
||||
class PlaceholderPage(Component):
|
||||
@ -3,9 +3,9 @@ import logging
|
||||
from email_validator import validate_email, EmailNotValidError
|
||||
from rio import Column, Component, event, Text, TextStyle, TextInput, TextInputChangeEvent, Button
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, UserService, MailingService
|
||||
from src.ezgg_lan_manager.components.AnimatedText import AnimatedText
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager import ConfigurationService, UserService, MailingService
|
||||
from src.ez_lan_manager.components.AnimatedText import AnimatedText
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
|
||||
MINIMUM_PASSWORD_LENGTH = 6
|
||||
|
||||
@ -13,7 +13,7 @@ logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
|
||||
class RegisterPage(Component):
|
||||
def on_pw_focus_loss(self, _: TextInputChangeEvent) -> None:
|
||||
def on_pw_change(self, _: TextInputChangeEvent) -> None:
|
||||
if not (self.pw_1.text == self.pw_2.text) or len(self.pw_1.text) < MINIMUM_PASSWORD_LENGTH:
|
||||
self.pw_1.is_valid = False
|
||||
self.pw_2.is_valid = False
|
||||
@ -21,14 +21,14 @@ class RegisterPage(Component):
|
||||
self.pw_1.is_valid = True
|
||||
self.pw_2.is_valid = True
|
||||
|
||||
def on_email_focus_loss(self, change_event: TextInputChangeEvent) -> None:
|
||||
def on_email_changed(self, change_event: TextInputChangeEvent) -> None:
|
||||
try:
|
||||
validate_email(change_event.text, check_deliverability=False)
|
||||
self.email_input.is_valid = True
|
||||
except EmailNotValidError:
|
||||
self.email_input.is_valid = False
|
||||
|
||||
def on_user_name_focus_loss(self, _: TextInputChangeEvent) -> None:
|
||||
def on_user_name_input_change(self, _: TextInputChangeEvent) -> None:
|
||||
current_text = self.user_name_input.text
|
||||
if len(current_text) > UserService.MAX_USERNAME_LENGTH:
|
||||
self.user_name_input.text = current_text[:UserService.MAX_USERNAME_LENGTH]
|
||||
@ -69,7 +69,7 @@ class RegisterPage(Component):
|
||||
try:
|
||||
new_user = await user_service.create_user(self.user_name_input.text, self.email_input.text, self.pw_1.text)
|
||||
if not new_user:
|
||||
logger.warning(f"UserService.create_user returned: {new_user}") # ToDo: Seems like the user is created fine, even if not returned #FixMe
|
||||
raise RuntimeError("User could not be created")
|
||||
except Exception as e:
|
||||
logger.error(f"Unknown error during new user registration: {e}")
|
||||
await self.animated_text.display_text(False, "Es ist ein unbekannter Fehler aufgetreten :(")
|
||||
@ -79,7 +79,7 @@ class RegisterPage(Component):
|
||||
await mailing_service.send_email(
|
||||
subject="Erfolgreiche Registrierung",
|
||||
body=f"Hallo {self.user_name_input.text},\n\n"
|
||||
f"Du hast dich erfolgreich beim EZGG-LAN Manager für {lan_info.name} {lan_info.iteration} registriert.\n\n"
|
||||
f"Du hast dich erfolgreich beim EZ-LAN Manager für {lan_info.name} {lan_info.iteration} registriert.\n\n"
|
||||
f"Wenn du dich nicht registriert hast, kontaktiere bitte unser Team über unsere Homepage.\n\n"
|
||||
f"Liebe Grüße\nDein {lan_info.name} - Team",
|
||||
receiver=self.email_input.text
|
||||
@ -100,7 +100,7 @@ class RegisterPage(Component):
|
||||
margin_right=1,
|
||||
margin_bottom=1,
|
||||
grow_x=True,
|
||||
on_lose_focus=self.on_user_name_focus_loss
|
||||
on_change=self.on_user_name_input_change
|
||||
)
|
||||
self.email_input = TextInput(
|
||||
label="E-Mail Adresse",
|
||||
@ -109,7 +109,7 @@ class RegisterPage(Component):
|
||||
margin_right=1,
|
||||
margin_bottom=1,
|
||||
grow_x=True,
|
||||
on_lose_focus=self.on_email_focus_loss
|
||||
on_change=self.on_email_changed
|
||||
)
|
||||
self.pw_1 = TextInput(
|
||||
label="Passwort",
|
||||
@ -119,7 +119,7 @@ class RegisterPage(Component):
|
||||
margin_bottom=1,
|
||||
grow_x=True,
|
||||
is_secret=True,
|
||||
on_lose_focus=self.on_pw_focus_loss
|
||||
on_change=self.on_pw_change
|
||||
)
|
||||
self.pw_2 = TextInput(
|
||||
label="Passwort wiederholen",
|
||||
@ -129,7 +129,7 @@ class RegisterPage(Component):
|
||||
margin_bottom=1,
|
||||
grow_x=True,
|
||||
is_secret=True,
|
||||
on_lose_focus=self.on_pw_focus_loss
|
||||
on_change=self.on_pw_change
|
||||
)
|
||||
self.submit_button = Button(
|
||||
content=Text(
|
||||
@ -1,7 +1,7 @@
|
||||
from rio import Column, Component, event, TextStyle, Text, Revealer
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager import ConfigurationService
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
|
||||
RULES: list[str] = [
|
||||
"Respektvolles Verhalten: Sei höflich und respektvoll gegenüber anderen Gästen und dem Team.",
|
||||
@ -5,15 +5,15 @@ from typing import Optional
|
||||
|
||||
from rio import Text, Column, TextStyle, Component, event, PressEvent, ProgressCircle
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, SeatingService, TicketingService, UserService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ezgg_lan_manager.components.SeatingPlan import SeatingPlan, SeatingPlanLegend
|
||||
from src.ezgg_lan_manager.components.SeatingPlanInfoBox import SeatingPlanInfoBox
|
||||
from src.ezgg_lan_manager.components.SeatingPurchaseBox import SeatingPurchaseBox
|
||||
from src.ezgg_lan_manager.services.SeatingService import NoTicketError, SeatNotFoundError, WrongCategoryError, SeatAlreadyTakenError
|
||||
from src.ezgg_lan_manager.types.Seat import Seat
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager import ConfigurationService, SeatingService, TicketingService, UserService
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager.components.SeatingPlan import SeatingPlan, SeatingPlanLegend
|
||||
from src.ez_lan_manager.components.SeatingPlanInfoBox import SeatingPlanInfoBox
|
||||
from src.ez_lan_manager.components.SeatingPurchaseBox import SeatingPurchaseBox
|
||||
from src.ez_lan_manager.services.SeatingService import NoTicketError, SeatNotFoundError, WrongCategoryError, SeatAlreadyTakenError
|
||||
from src.ez_lan_manager.types.Seat import Seat
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
@ -30,7 +30,6 @@ class SeatingPlanPage(Component):
|
||||
purchase_box_loading: bool = False
|
||||
purchase_box_success_msg: Optional[str] = None
|
||||
purchase_box_error_msg: Optional[str] = None
|
||||
seating_info_text = ""
|
||||
is_booking_blocked: bool = False
|
||||
|
||||
@event.on_populate
|
||||
@ -48,7 +47,6 @@ class SeatingPlanPage(Component):
|
||||
self.is_booking_blocked = True
|
||||
|
||||
async def on_seat_clicked(self, seat_id: str, _: PressEvent) -> None:
|
||||
self.seating_info_text = ""
|
||||
self.show_info_box = True
|
||||
self.show_purchase_box = False
|
||||
seat = next(filter(lambda s: s.seat_id == seat_id, self.seating_info), None)
|
||||
@ -64,12 +62,6 @@ class SeatingPlanPage(Component):
|
||||
else:
|
||||
self.current_seat_occupant = None
|
||||
|
||||
async def on_info_clicked(self, text: str) -> None:
|
||||
self.show_info_box = True
|
||||
self.show_purchase_box = False
|
||||
self.current_seat_id = None
|
||||
self.seating_info_text = text
|
||||
|
||||
def set_error(self, msg: str) -> None:
|
||||
self.purchase_box_error_msg = msg
|
||||
self.purchase_box_success_msg = None
|
||||
@ -127,7 +119,7 @@ class SeatingPlanPage(Component):
|
||||
Column(
|
||||
SeatingPlanInfoBox(seat_id=self.current_seat_id, seat_occupant=self.current_seat_occupant, seat_price=self.current_seat_price,
|
||||
is_blocked=self.current_seat_is_blocked, is_booking_blocked=self.is_booking_blocked, show=self.show_info_box,
|
||||
purchase_cb=self.on_purchase_clicked, override_text=self.seating_info_text),
|
||||
purchase_cb=self.on_purchase_clicked),
|
||||
SeatingPurchaseBox(
|
||||
show=self.show_purchase_box,
|
||||
seat_id=self.current_seat_id,
|
||||
@ -140,7 +132,7 @@ class SeatingPlanPage(Component):
|
||||
)
|
||||
),
|
||||
MainViewContentBox(
|
||||
SeatingPlan(seat_clicked_cb=self.on_seat_clicked, seating_info=self.seating_info, info_clicked_cb=self.on_info_clicked) if self.seating_info else
|
||||
SeatingPlan(seat_clicked_cb=self.on_seat_clicked, seating_info=self.seating_info) if self.seating_info else
|
||||
Column(ProgressCircle(color=self.session.theme.secondary_color, margin=3),
|
||||
Text("Sitzplan wird geladen", style=TextStyle(fill=self.session.theme.neutral_color), align_x=0.5, margin=1))
|
||||
),
|
||||
@ -1,7 +1,7 @@
|
||||
from rio import Column, Component, event, TextStyle, Text
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager import ConfigurationService
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
|
||||
|
||||
class PAGENAME(Component):
|
||||
@ -1,7 +1,7 @@
|
||||
from rio import Column, Component, event, TextStyle, Text
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
from src.ez_lan_manager import ConfigurationService
|
||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
|
||||
|
||||
class TournamentsPage(Component):
|
||||
@ -19,4 +19,3 @@ from .ManageNewsPage import ManageNewsPage
|
||||
from .ManageUsersPage import ManageUsersPage
|
||||
from .ManageCateringPage import ManageCateringPage
|
||||
from .ManageTournamentsPage import ManageTournamentsPage
|
||||
from .OverviewPage import OverviewPage
|
||||
@ -2,10 +2,9 @@ import logging
|
||||
from collections.abc import Callable
|
||||
from datetime import datetime
|
||||
from decimal import Decimal, ROUND_DOWN
|
||||
from typing import Optional
|
||||
|
||||
from src.ezgg_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ezgg_lan_manager.types.Transaction import Transaction
|
||||
from src.ez_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ez_lan_manager.types.Transaction import Transaction
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
@ -66,11 +65,9 @@ class AccountingService:
|
||||
return await self._db_service.get_all_transactions_for_user(user_id)
|
||||
|
||||
@staticmethod
|
||||
def make_euro_string_from_decimal(euros: Optional[Decimal]) -> str:
|
||||
def make_euro_string_from_decimal(euros: Decimal) -> str:
|
||||
"""
|
||||
Internally, all money values are euros as decimal. Only when showing them to the user we generate a string.
|
||||
"""
|
||||
if euros is None:
|
||||
return "0.00 €"
|
||||
rounded_decimal = str(euros.quantize(Decimal(".01"), rounding=ROUND_DOWN))
|
||||
return f"{rounded_decimal} €"
|
||||
@ -3,12 +3,11 @@ from decimal import Decimal
|
||||
from enum import Enum
|
||||
from typing import Optional
|
||||
|
||||
from src.ezgg_lan_manager.services.AccountingService import AccountingService
|
||||
from src.ezgg_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ezgg_lan_manager.services.UserService import UserService
|
||||
from src.ezgg_lan_manager.services.ReceiptPrintingService import ReceiptPrintingService
|
||||
from src.ezgg_lan_manager.types.CateringOrder import CateringOrder, CateringOrderStatus, CateringMenuItemsWithAmount
|
||||
from src.ezgg_lan_manager.types.CateringMenuItem import CateringMenuItem, CateringMenuItemCategory
|
||||
from src.ez_lan_manager.services.AccountingService import AccountingService
|
||||
from src.ez_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ez_lan_manager.services.UserService import UserService
|
||||
from src.ez_lan_manager.types.CateringOrder import CateringOrder, CateringOrderStatus, CateringMenuItemsWithAmount
|
||||
from src.ez_lan_manager.types.CateringMenuItem import CateringMenuItem, CateringMenuItemCategory
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
@ -26,11 +25,10 @@ class CateringError(Exception):
|
||||
|
||||
|
||||
class CateringService:
|
||||
def __init__(self, db_service: DatabaseService, accounting_service: AccountingService, user_service: UserService, receipt_printing_service: ReceiptPrintingService) -> None:
|
||||
def __init__(self, db_service: DatabaseService, accounting_service: AccountingService, user_service: UserService):
|
||||
self._db_service = db_service
|
||||
self._accounting_service = accounting_service
|
||||
self._user_service = user_service
|
||||
self._receipt_printing_service = receipt_printing_service
|
||||
self.cached_cart: dict[int, list[CateringMenuItem]] = {}
|
||||
|
||||
# ORDERS
|
||||
@ -54,7 +52,6 @@ class CateringService:
|
||||
await self._accounting_service.remove_balance(user_id, total_price, f"CATERING - {order.order_id}")
|
||||
logger.info(
|
||||
f"User '{order.customer.user_name}' (ID:{order.customer.user_id}) ordered from catering for {self._accounting_service.make_euro_string_from_decimal(total_price)}")
|
||||
await self._receipt_printing_service.print_order(user, order)
|
||||
# await self.cancel_order(order) # ToDo: Check if commented out before commit. Un-comment to auto-cancel every placed order
|
||||
return order
|
||||
|
||||
@ -7,8 +7,8 @@ import tomllib
|
||||
|
||||
from from_root import from_root
|
||||
|
||||
from src.ezgg_lan_manager.types.ConfigurationTypes import DatabaseConfiguration, MailingServiceConfiguration, LanInfo, \
|
||||
SeatingConfiguration, TicketInfo, ReceiptPrintingConfiguration
|
||||
from src.ez_lan_manager.types.ConfigurationTypes import DatabaseConfiguration, MailingServiceConfiguration, LanInfo, \
|
||||
SeatingConfiguration, TicketInfo
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
@ -71,6 +71,15 @@ class ConfigurationService:
|
||||
logger.fatal("Error loading LAN Info, exiting...")
|
||||
sys.exit(1)
|
||||
|
||||
def get_seating_configuration(self) -> SeatingConfiguration:
|
||||
try:
|
||||
return SeatingConfiguration(
|
||||
seats=self._config["seating"]
|
||||
)
|
||||
except KeyError:
|
||||
logger.fatal("Error loading seating configuration, exiting...")
|
||||
sys.exit(1)
|
||||
|
||||
def get_ticket_info(self) -> tuple[TicketInfo, ...]:
|
||||
try:
|
||||
return tuple([TicketInfo(
|
||||
@ -86,19 +95,6 @@ class ConfigurationService:
|
||||
logger.fatal("Error loading seating configuration, exiting...")
|
||||
sys.exit(1)
|
||||
|
||||
def get_receipt_printing_configuration(self) -> ReceiptPrintingConfiguration:
|
||||
try:
|
||||
receipt_printing_configuration = self._config["receipt_printing"]
|
||||
return ReceiptPrintingConfiguration(
|
||||
host=receipt_printing_configuration["host"],
|
||||
port=receipt_printing_configuration["port"],
|
||||
order_print_endpoint=receipt_printing_configuration["order_print_endpoint"],
|
||||
password=receipt_printing_configuration["password"]
|
||||
)
|
||||
except KeyError:
|
||||
logger.fatal("Error loading Receipt Printing Configuration, exiting...")
|
||||
sys.exit(1)
|
||||
|
||||
@property
|
||||
def APP_VERSION(self) -> str:
|
||||
return self._version
|
||||
@ -6,15 +6,16 @@ from decimal import Decimal
|
||||
|
||||
import aiomysql
|
||||
|
||||
from src.ezgg_lan_manager.types.CateringOrder import CateringOrder
|
||||
from src.ezgg_lan_manager.types.CateringMenuItem import CateringMenuItem, CateringMenuItemCategory
|
||||
from src.ezgg_lan_manager.types.CateringOrder import CateringMenuItemsWithAmount, CateringOrderStatus
|
||||
from src.ezgg_lan_manager.types.ConfigurationTypes import DatabaseConfiguration
|
||||
from src.ezgg_lan_manager.types.News import News
|
||||
from src.ezgg_lan_manager.types.Seat import Seat
|
||||
from src.ezgg_lan_manager.types.Ticket import Ticket
|
||||
from src.ezgg_lan_manager.types.Transaction import Transaction
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager.types.CateringOrder import CateringOrder
|
||||
from src.ez_lan_manager.types.CateringMenuItem import CateringMenuItem, CateringMenuItemCategory
|
||||
from src.ez_lan_manager.types.CateringOrder import CateringMenuItemsWithAmount, CateringOrderStatus
|
||||
from src.ez_lan_manager.types.ConfigurationTypes import DatabaseConfiguration
|
||||
from src.ez_lan_manager.types.Tournament import Tournament
|
||||
from src.ez_lan_manager.types.News import News
|
||||
from src.ez_lan_manager.types.Seat import Seat
|
||||
from src.ez_lan_manager.types.Ticket import Ticket
|
||||
from src.ez_lan_manager.types.Transaction import Transaction
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
@ -81,6 +82,18 @@ class DatabaseService:
|
||||
last_updated_at=data[11]
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _map_db_result_to_tournament(data: tuple) -> Tournament:
|
||||
return Tournament(
|
||||
tournament_id=data[0],
|
||||
tournament_name=data[1],
|
||||
tournament_info=data[2],
|
||||
participants_limit=data[3],
|
||||
start_time=data[4],
|
||||
created_at=data[5],
|
||||
can_register=data[6]
|
||||
)
|
||||
|
||||
async def get_user_by_name(self, user_name: str) -> Optional[User]:
|
||||
async with self._connection_pool.acquire() as conn:
|
||||
async with conn.cursor(aiomysql.Cursor) as cursor:
|
||||
@ -232,6 +245,7 @@ class DatabaseService:
|
||||
except aiomysql.InterfaceError:
|
||||
pool_init_result = await self.init_db_pool()
|
||||
if not pool_init_result:
|
||||
print(self._connection_pool)
|
||||
raise NoDatabaseConnectionError
|
||||
return await self.get_news(dt_start, dt_end)
|
||||
except Exception as e:
|
||||
@ -787,3 +801,73 @@ class DatabaseService:
|
||||
return await self.remove_profile_picture(user_id)
|
||||
except Exception as e:
|
||||
logger.warning(f"Error deleting user profile picture: {e}")
|
||||
|
||||
async def get_all_tournaments(self):
|
||||
async with self._connection_pool.acquire() as conn:
|
||||
async with conn.cursor(aiomysql.Cursor) as cursor:
|
||||
results = []
|
||||
try:
|
||||
await cursor.execute("SELECT * FROM tournaments;")
|
||||
await conn.commit()
|
||||
except aiomysql.InterfaceError:
|
||||
pool_init_result = await self.init_db_pool()
|
||||
if not pool_init_result:
|
||||
raise NoDatabaseConnectionError
|
||||
return await self.get_all_users()
|
||||
except Exception as e:
|
||||
logger.warning(f"Error getting all tournaments: {e}")
|
||||
return results
|
||||
|
||||
for tournament_raw in await cursor.fetchall():
|
||||
results.append(self._map_db_result_to_tournament(tournament_raw))
|
||||
|
||||
return results
|
||||
|
||||
async def get_tournament(self, tournament_id: int) -> Optional[Tournament]:
|
||||
async with self._connection_pool.acquire() as conn:
|
||||
async with conn.cursor(aiomysql.Cursor) as cursor:
|
||||
await cursor.execute("SELECT * FROM tournaments WHERE tournament_id=%s", (tournament_id,))
|
||||
result = await cursor.fetchone()
|
||||
if not result:
|
||||
return
|
||||
return self._map_db_result_to_tournament(result)
|
||||
|
||||
async def get_all_registered_users_for_tournament(self, tournament_id: id) -> Optional[list[User]]:
|
||||
async with self._connection_pool.acquire() as conn:
|
||||
async with conn.cursor(aiomysql.Cursor) as cursor:
|
||||
await cursor.execute("SELECT * FROM tournaments_participants WHERE tournament_id=%s", (tournament_id,))
|
||||
result = await cursor.fetchone()
|
||||
result = [self.get_user_by_id(user_id[1]) for user_id in result]
|
||||
if not result:
|
||||
return
|
||||
return result
|
||||
|
||||
|
||||
async def set_tournament_info(self, tournament_id, tournament_info):
|
||||
pass
|
||||
|
||||
async def register_to_tournament(self, tournament_id, user_id):
|
||||
pass
|
||||
|
||||
async def unregister_to_tournament(self, tournament_id, user_id):
|
||||
pass
|
||||
|
||||
async def add_tournament(self, name, additional_info, start_time, participants_limit) -> None:
|
||||
async with self._connection_pool.acquire() as conn:
|
||||
async with conn.cursor(aiomysql.Cursor) as cursor:
|
||||
try:
|
||||
await cursor.execute(
|
||||
"INSERT INTO tournaments (name, additional_info, start_time, participants_limit) "
|
||||
"VALUES (%s, %s, %s, %s)",
|
||||
(name, additional_info, start_time, participants_limit)
|
||||
)
|
||||
await conn.commit()
|
||||
except aiomysql.InterfaceError:
|
||||
pool_init_result = await self.init_db_pool()
|
||||
if not pool_init_result:
|
||||
raise NoDatabaseConnectionError
|
||||
return await self.add_tournament(name, additional_info, start_time, participants_limit)
|
||||
except Exception as e:
|
||||
logger.warning(f"Error adding Tournament: {e}")
|
||||
return
|
||||
|
||||
@ -3,7 +3,7 @@ from typing import Optional
|
||||
|
||||
from rio import UserSettings
|
||||
|
||||
from src.ezgg_lan_manager.types.SessionStorage import SessionStorage
|
||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||
|
||||
|
||||
class LocalData(UserSettings):
|
||||
@ -1,12 +1,10 @@
|
||||
import logging
|
||||
from decimal import Decimal
|
||||
from email.message import EmailMessage
|
||||
from asyncio import sleep
|
||||
|
||||
import aiosmtplib
|
||||
|
||||
from src.ezgg_lan_manager.services.ConfigurationService import ConfigurationService
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager.services.ConfigurationService import ConfigurationService
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
@ -18,9 +16,6 @@ class MailingService:
|
||||
async def send_email(self, subject: str, body: str, receiver: str) -> None:
|
||||
if self._configuration_service.DEV_MODE_ACTIVE:
|
||||
logger.info(f"Skipped sending mail to {receiver} because demo mode is active.")
|
||||
logger.info(f"Subject: {subject}")
|
||||
logger.info(f"Receiver: {receiver}")
|
||||
logger.info(f"Body: {body}")
|
||||
await sleep(1)
|
||||
return
|
||||
|
||||
@ -40,15 +35,3 @@ class MailingService:
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to send email: {e}")
|
||||
|
||||
def generate_account_balance_added_mail_body(self, user: User, added_balance: Decimal, total_balance: Decimal) -> str:
|
||||
return f"""
|
||||
Hallo {user.user_name},
|
||||
|
||||
deinem Account wurden {added_balance} € hinzugefügt. Dein neues Guthaben beträgt nun {total_balance} €.
|
||||
|
||||
Wenn du zu dieser Aufladung Fragen hast, stehen wir dir in unserem Discord Server oder per Mail an {self._configuration_service.get_lan_info().organizer_mail} zur Verfügung.
|
||||
|
||||
Liebe Grüße
|
||||
Dein {self._configuration_service.get_lan_info().name} Team
|
||||
"""
|
||||
@ -2,8 +2,8 @@ import logging
|
||||
from datetime import date
|
||||
from typing import Optional
|
||||
|
||||
from src.ezgg_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ezgg_lan_manager.types.News import News
|
||||
from src.ez_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ez_lan_manager.types.News import News
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
@ -2,10 +2,10 @@ import logging
|
||||
from typing import Optional
|
||||
|
||||
|
||||
from src.ezgg_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ezgg_lan_manager.services.TicketingService import TicketingService
|
||||
from src.ezgg_lan_manager.types.ConfigurationTypes import LanInfo, SeatingConfiguration
|
||||
from src.ezgg_lan_manager.types.Seat import Seat
|
||||
from src.ez_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ez_lan_manager.services.TicketingService import TicketingService
|
||||
from src.ez_lan_manager.types.ConfigurationTypes import LanInfo, SeatingConfiguration
|
||||
from src.ez_lan_manager.types.Seat import Seat
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
@ -22,7 +22,8 @@ class SeatAlreadyTakenError(Exception):
|
||||
pass
|
||||
|
||||
class SeatingService:
|
||||
def __init__(self, lan_info: LanInfo, db_service: DatabaseService, ticketing_service: TicketingService) -> None:
|
||||
def __init__(self, seating_configuration: SeatingConfiguration, lan_info: LanInfo, db_service: DatabaseService, ticketing_service: TicketingService) -> None:
|
||||
self._seating_configuration = seating_configuration
|
||||
self._lan_info = lan_info
|
||||
self._db_service = db_service
|
||||
self._ticketing_service = ticketing_service
|
||||
@ -1,10 +1,10 @@
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from src.ezgg_lan_manager.services.AccountingService import AccountingService, InsufficientFundsError
|
||||
from src.ezgg_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ezgg_lan_manager.types.ConfigurationTypes import TicketInfo
|
||||
from src.ezgg_lan_manager.types.Ticket import Ticket
|
||||
from src.ez_lan_manager.services.AccountingService import AccountingService, InsufficientFundsError
|
||||
from src.ez_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ez_lan_manager.types.ConfigurationTypes import TicketInfo
|
||||
from src.ez_lan_manager.types.Ticket import Ticket
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
38
src/ez_lan_manager/services/TournamentService.py
Normal file
38
src/ez_lan_manager/services/TournamentService.py
Normal file
@ -0,0 +1,38 @@
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from src.ez_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ez_lan_manager.types.Tournament import Tournament
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
|
||||
class AlreadyRegisteredToTournamentError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class TournamentService:
|
||||
def __init__(self, db_service: DatabaseService):
|
||||
self._db_service = db_service
|
||||
|
||||
async def add_tournament(self, name, additional_info, start_time, participants_limit) -> None:
|
||||
await self._db_service.add_tournament(name, additional_info, start_time, participants_limit)
|
||||
|
||||
async def get_all_tournaments(self) -> list[Tournament]:
|
||||
return await self._db_service.get_all_tournaments()
|
||||
|
||||
async def get_tournament(self, tournament_id: int) -> Tournament:
|
||||
return await self._db_service.get_tournament()
|
||||
|
||||
async def get_all_registered_users_for_tournament(self, tournament_id: int) -> list[User]:
|
||||
return await self._db_service.get_all_registered_users_for_tournament(tournament_id)
|
||||
|
||||
async def register_to_tournament(self, tournament_id: int, user_id: int) -> None:
|
||||
await self._db_service.register_to_tournament(tournament_id, user_id)
|
||||
|
||||
async def unregister_to_tournament(self, tournament_id: int, user_id: int) -> None:
|
||||
await self._db_service.unregister_to_tournament(tournament_id, user_id)
|
||||
|
||||
async def set_tournament_info(self, tournament_id: int, tournament_info: str) -> None:
|
||||
await self._db_service.set_tournament_info(tournament_id, tournament_info)
|
||||
@ -2,8 +2,8 @@ from hashlib import sha256
|
||||
from typing import Union, Optional
|
||||
from string import ascii_letters, digits
|
||||
|
||||
from src.ezgg_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
|
||||
class NameNotAllowedError(Exception):
|
||||
@ -47,8 +47,7 @@ class UserService:
|
||||
user_name = user_name.lower()
|
||||
|
||||
hashed_pw = sha256(password_clear_text.encode(encoding="utf-8")).hexdigest()
|
||||
created_user = await self._db_service.create_user(user_name, user_mail, hashed_pw)
|
||||
return created_user
|
||||
return await self._db_service.create_user(user_name, user_mail, hashed_pw)
|
||||
|
||||
async def update_user(self, user: User) -> User:
|
||||
disallowed_char = self._check_for_disallowed_char(user.user_name)
|
||||
@ -4,8 +4,8 @@ from decimal import Decimal
|
||||
from enum import StrEnum
|
||||
from typing import Optional, Iterable, Self
|
||||
|
||||
from src.ezgg_lan_manager.types.CateringMenuItem import CateringMenuItem, CateringMenuItemCategory
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager.types.CateringMenuItem import CateringMenuItem, CateringMenuItemCategory
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
CateringMenuItemsWithAmount = dict[CateringMenuItem, int]
|
||||
|
||||
@ -48,10 +48,3 @@ class LanInfo:
|
||||
@dataclass(frozen=True)
|
||||
class SeatingConfiguration:
|
||||
seats: dict[str, str]
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ReceiptPrintingConfiguration:
|
||||
host: str
|
||||
port: int
|
||||
order_print_endpoint: str
|
||||
password: str
|
||||
@ -2,7 +2,7 @@ from dataclasses import dataclass
|
||||
from datetime import date
|
||||
from typing import Optional
|
||||
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@ -1,7 +1,7 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@ -2,7 +2,7 @@ from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
18
src/ez_lan_manager/types/Tournament.py
Normal file
18
src/ez_lan_manager/types/Tournament.py
Normal file
@ -0,0 +1,18 @@
|
||||
from dataclasses import dataclass
|
||||
from datetime import date, datetime
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
class Tournament:
|
||||
tournament_id: int
|
||||
tournament_name: str
|
||||
tournament_info: str
|
||||
participants_limit: int
|
||||
start_time: datetime
|
||||
created_at: datetime
|
||||
can_register: bool = True
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(str(self.tournament_id))
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
import logging
|
||||
|
||||
from from_root import from_root
|
||||
|
||||
from src.ezgg_lan_manager.services import *
|
||||
from src.ezgg_lan_manager.services.AccountingService import AccountingService
|
||||
from src.ezgg_lan_manager.services.CateringService import CateringService
|
||||
from src.ezgg_lan_manager.services.ConfigurationService import ConfigurationService
|
||||
from src.ezgg_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ezgg_lan_manager.services.LocalDataService import LocalDataService
|
||||
from src.ezgg_lan_manager.services.MailingService import MailingService
|
||||
from src.ezgg_lan_manager.services.NewsService import NewsService
|
||||
from src.ezgg_lan_manager.services.ReceiptPrintingService import ReceiptPrintingService
|
||||
from src.ezgg_lan_manager.services.SeatingService import SeatingService
|
||||
from src.ezgg_lan_manager.services.TicketingService import TicketingService
|
||||
from src.ezgg_lan_manager.services.UserService import UserService
|
||||
from src.ezgg_lan_manager.types import *
|
||||
|
||||
# Inits services in the correct order
|
||||
def init_services() -> tuple[AccountingService, CateringService, ConfigurationService, DatabaseService, MailingService, NewsService, SeatingService, TicketingService, UserService, LocalDataService, ReceiptPrintingService]:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
configuration_service = ConfigurationService(from_root("config.toml"))
|
||||
db_service = DatabaseService(configuration_service.get_database_configuration())
|
||||
user_service = UserService(db_service)
|
||||
accounting_service = AccountingService(db_service)
|
||||
news_service = NewsService(db_service)
|
||||
mailing_service = MailingService(configuration_service)
|
||||
ticketing_service = TicketingService(configuration_service.get_ticket_info(), db_service, accounting_service)
|
||||
seating_service = SeatingService(configuration_service.get_lan_info(), db_service, ticketing_service)
|
||||
receipt_printing_service = ReceiptPrintingService(seating_service, configuration_service.get_receipt_printing_configuration(), configuration_service.DEV_MODE_ACTIVE)
|
||||
catering_service = CateringService(db_service, accounting_service, user_service, receipt_printing_service)
|
||||
local_data_service = LocalDataService()
|
||||
|
||||
|
||||
return accounting_service, catering_service, configuration_service, db_service, mailing_service, news_service, seating_service, ticketing_service, user_service, local_data_service, receipt_printing_service
|
||||
@ -1,274 +0,0 @@
|
||||
from typing import Callable
|
||||
|
||||
from rio import Component, Rectangle, Grid, Column, Row, Text, TextStyle, Color, PointerEventListener, Spacer
|
||||
|
||||
from src.ezgg_lan_manager.components.SeatingPlanPixels import SeatPixel, WallPixel, InvisiblePixel, TextPixel
|
||||
from src.ezgg_lan_manager.types.Seat import Seat
|
||||
|
||||
MAX_GRID_WIDTH_PIXELS = 60
|
||||
MAX_GRID_HEIGHT_PIXELS = 60
|
||||
|
||||
class SeatingPlanLegend(Component):
|
||||
def build(self) -> Component:
|
||||
return Column(
|
||||
Text("Legende", style=TextStyle(fill=self.session.theme.neutral_color), justify="center", margin=1),
|
||||
Row(
|
||||
Spacer(),
|
||||
Rectangle(
|
||||
content=Text("Normaler Platz", style=TextStyle(fill=self.session.theme.neutral_color, font_size=0.7), margin=0.2, justify="center"),
|
||||
fill=Color.TRANSPARENT,
|
||||
stroke_width=0.2,
|
||||
stroke_color=Color.from_hex("003300"),
|
||||
min_width=20,
|
||||
margin_right=1
|
||||
),
|
||||
Rectangle(
|
||||
content=Text("Deluxe Platz", style=TextStyle(fill=self.session.theme.neutral_color, font_size=0.7), margin=0.2, justify="center"),
|
||||
fill=Color.TRANSPARENT,
|
||||
stroke_width=0.2,
|
||||
stroke_color=Color.from_hex("66ff99"),
|
||||
min_width=20
|
||||
),
|
||||
Spacer()
|
||||
),
|
||||
Row(
|
||||
Rectangle(
|
||||
content=Column(
|
||||
Text(f"Freier Platz", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.7), align_x=0.5, selectable=False),
|
||||
Text(f"", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.9), align_x=0.5,
|
||||
selectable=False, overflow="wrap")
|
||||
),
|
||||
min_width=1,
|
||||
min_height=1,
|
||||
fill=self.session.theme.success_color,
|
||||
grow_x=False,
|
||||
grow_y=False,
|
||||
hover_fill=self.session.theme.success_color,
|
||||
transition_time=0.4,
|
||||
ripple=True
|
||||
),
|
||||
Rectangle(
|
||||
content=Column(
|
||||
Text(f"Belegter Platz", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.7), align_x=0.5, selectable=False),
|
||||
Text(f"", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.9), align_x=0.5,
|
||||
selectable=False, overflow="wrap")
|
||||
),
|
||||
min_width=1,
|
||||
min_height=1,
|
||||
fill=self.session.theme.danger_color,
|
||||
grow_x=False,
|
||||
grow_y=False,
|
||||
hover_fill=self.session.theme.danger_color,
|
||||
transition_time=0.4,
|
||||
ripple=True
|
||||
),
|
||||
Rectangle(
|
||||
content=Column(
|
||||
Text(f"Eigener Platz", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.7), align_x=0.5, selectable=False),
|
||||
Text(f"", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.9), align_x=0.5,
|
||||
selectable=False, overflow="wrap")
|
||||
),
|
||||
min_width=1,
|
||||
min_height=1,
|
||||
fill=Color.from_hex("800080"),
|
||||
grow_x=False,
|
||||
grow_y=False,
|
||||
hover_fill=Color.from_hex("800080"),
|
||||
transition_time=0.4,
|
||||
ripple=True
|
||||
),
|
||||
margin=1,
|
||||
spacing=1
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class SeatingPlan(Component):
|
||||
seat_clicked_cb: Callable
|
||||
seating_info: list[Seat]
|
||||
info_clicked_cb: Callable
|
||||
|
||||
def get_seat(self, seat_id: str) -> Seat:
|
||||
seat = next(filter(lambda seat_: seat_.seat_id == seat_id, self.seating_info), None)
|
||||
return seat if seat else Seat(seat_id="Z99", is_blocked=True, category="LUXUS", user=None)
|
||||
|
||||
"""
|
||||
This seating plan is for the community center "Donsbach"
|
||||
"""
|
||||
def build(self) -> Component:
|
||||
grid = Grid()
|
||||
# Outlines
|
||||
for x in range(0, MAX_GRID_WIDTH_PIXELS):
|
||||
grid.add(WallPixel(), row=0, column=x)
|
||||
|
||||
for y in range(0, MAX_GRID_HEIGHT_PIXELS):
|
||||
grid.add(WallPixel(), row=y, column=0)
|
||||
|
||||
for x in range(0, MAX_GRID_WIDTH_PIXELS):
|
||||
grid.add(WallPixel(), row=MAX_GRID_HEIGHT_PIXELS, column=x)
|
||||
|
||||
for x in range(0, 31):
|
||||
grid.add(WallPixel(), row=15, column=x)
|
||||
|
||||
for x in range(41, MAX_GRID_WIDTH_PIXELS):
|
||||
grid.add(WallPixel(), row=32, column=x)
|
||||
|
||||
for x in range(31, 34):
|
||||
grid.add(WallPixel(), row=32, column=x)
|
||||
grid.add(WallPixel(), row=19, column=x)
|
||||
|
||||
for x in range(42, MAX_GRID_WIDTH_PIXELS):
|
||||
grid.add(WallPixel(), row=11, column=x)
|
||||
grid.add(WallPixel(), row=22, column=x)
|
||||
|
||||
for x in range(22, 30):
|
||||
grid.add(WallPixel(), row=5, column=x)
|
||||
grid.add(WallPixel(), row=10, column=x)
|
||||
|
||||
for y in range(5, 11):
|
||||
grid.add(WallPixel(), row=y, column=21)
|
||||
grid.add(WallPixel(), row=y, column=30)
|
||||
|
||||
|
||||
for y in range(40, MAX_GRID_HEIGHT_PIXELS):
|
||||
grid.add(WallPixel(), row=y, column=30)
|
||||
|
||||
for y in range(32, 36):
|
||||
grid.add(WallPixel(), row=y, column=30)
|
||||
|
||||
for y in range(19, 33):
|
||||
grid.add(WallPixel(), row=y, column=34)
|
||||
|
||||
for y in range(16, 20):
|
||||
grid.add(WallPixel(), row=y, column=30)
|
||||
|
||||
for y in range(0, 5):
|
||||
grid.add(WallPixel(), row=y, column=41)
|
||||
|
||||
for y in range(9, 15):
|
||||
grid.add(WallPixel(), row=y, column=41)
|
||||
|
||||
for y in range(19, 33):
|
||||
grid.add(WallPixel(), row=y, column=41)
|
||||
|
||||
|
||||
# Block A
|
||||
grid.add(SeatPixel("A01", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A01"), seat_orientation="bottom"), row=57, column=1, width=5, height=2)
|
||||
grid.add(SeatPixel("A02", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A02"), seat_orientation="bottom"), row=57, column=6, width=5, height=2)
|
||||
grid.add(SeatPixel("A03", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A03"), seat_orientation="bottom"), row=57, column=11, width=5, height=2)
|
||||
grid.add(SeatPixel("A04", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A04"), seat_orientation="bottom"), row=57, column=16, width=5, height=2)
|
||||
grid.add(SeatPixel("A05", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A05"), seat_orientation="bottom"), row=57, column=21, width=5, height=2)
|
||||
|
||||
grid.add(SeatPixel("A10", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A10"), seat_orientation="top"), row=55, column=1, width=5, height=2)
|
||||
grid.add(SeatPixel("A11", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A11"), seat_orientation="top"), row=55, column=6, width=5, height=2)
|
||||
grid.add(SeatPixel("A12", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A12"), seat_orientation="top"), row=55, column=11, width=5, height=2)
|
||||
grid.add(SeatPixel("A13", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A13"), seat_orientation="top"), row=55, column=16, width=5, height=2)
|
||||
grid.add(SeatPixel("A14", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A14"), seat_orientation="top"), row=55, column=21, width=5, height=2)
|
||||
|
||||
# Block B
|
||||
grid.add(SeatPixel("B01", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B01"), seat_orientation="bottom"), row=50, column=1, width=3, height=2)
|
||||
grid.add(SeatPixel("B02", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B02"), seat_orientation="bottom"), row=50, column=4, width=3, height=2)
|
||||
grid.add(SeatPixel("B03", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B03"), seat_orientation="bottom"), row=50, column=7, width=3, height=2)
|
||||
grid.add(SeatPixel("B04", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B04"), seat_orientation="bottom"), row=50, column=10, width=3, height=2)
|
||||
grid.add(SeatPixel("B05", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B05"), seat_orientation="bottom"), row=50, column=13, width=3, height=2)
|
||||
grid.add(SeatPixel("B06", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B06"), seat_orientation="bottom"), row=50, column=16, width=3, height=2)
|
||||
|
||||
grid.add(SeatPixel("B10", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B10"), seat_orientation="top"), row=48, column=1, width=3, height=2)
|
||||
grid.add(SeatPixel("B11", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B11"), seat_orientation="top"), row=48, column=4, width=3, height=2)
|
||||
grid.add(SeatPixel("B12", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B12"), seat_orientation="top"), row=48, column=7, width=3, height=2)
|
||||
grid.add(SeatPixel("B13", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B13"), seat_orientation="top"), row=48, column=10, width=3, height=2)
|
||||
grid.add(SeatPixel("B14", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B14"), seat_orientation="top"), row=48, column=13, width=3, height=2)
|
||||
grid.add(SeatPixel("B15", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B15"), seat_orientation="top"), row=48, column=16, width=3, height=2)
|
||||
|
||||
# Block C
|
||||
grid.add(SeatPixel("C01", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C01"), seat_orientation="bottom"), row=43, column=1, width=3, height=2)
|
||||
grid.add(SeatPixel("C02", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C02"), seat_orientation="bottom"), row=43, column=4, width=3, height=2)
|
||||
grid.add(SeatPixel("C03", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C03"), seat_orientation="bottom"), row=43, column=7, width=3, height=2)
|
||||
grid.add(SeatPixel("C04", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C04"), seat_orientation="bottom"), row=43, column=10, width=3, height=2)
|
||||
grid.add(SeatPixel("C05", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C05"), seat_orientation="bottom"), row=43, column=13, width=3, height=2)
|
||||
grid.add(SeatPixel("C06", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C06"), seat_orientation="bottom"), row=43, column=16, width=3, height=2)
|
||||
|
||||
grid.add(SeatPixel("C10", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C10"), seat_orientation="top"), row=41, column=1, width=3, height=2)
|
||||
grid.add(SeatPixel("C11", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C11"), seat_orientation="top"), row=41, column=4, width=3, height=2)
|
||||
grid.add(SeatPixel("C12", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C12"), seat_orientation="top"), row=41, column=7, width=3, height=2)
|
||||
grid.add(SeatPixel("C13", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C13"), seat_orientation="top"), row=41, column=10, width=3, height=2)
|
||||
grid.add(SeatPixel("C14", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C14"), seat_orientation="top"), row=41, column=13, width=3, height=2)
|
||||
grid.add(SeatPixel("C15", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C15"), seat_orientation="top"), row=41, column=16, width=3, height=2)
|
||||
|
||||
# Block D
|
||||
grid.add(SeatPixel("D01", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D01"), seat_orientation="bottom"), row=34, column=1, width=5, height=2)
|
||||
grid.add(SeatPixel("D02", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D02"), seat_orientation="bottom"), row=34, column=6, width=5, height=2)
|
||||
grid.add(SeatPixel("D03", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D03"), seat_orientation="bottom"), row=34, column=11, width=5, height=2)
|
||||
grid.add(SeatPixel("D04", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D04"), seat_orientation="bottom"), row=34, column=16, width=5, height=2)
|
||||
grid.add(SeatPixel("D05", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D05"), seat_orientation="bottom"), row=34, column=21, width=5, height=2)
|
||||
|
||||
grid.add(SeatPixel("D10", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D10"), seat_orientation="top"), row=32, column=1, width=5, height=2)
|
||||
grid.add(SeatPixel("D11", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D11"), seat_orientation="top"), row=32, column=6, width=5, height=2)
|
||||
grid.add(SeatPixel("D12", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D12"), seat_orientation="top"), row=32, column=11, width=5, height=2)
|
||||
grid.add(SeatPixel("D13", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D13"), seat_orientation="top"), row=32, column=16, width=5, height=2)
|
||||
grid.add(SeatPixel("D14", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D14"), seat_orientation="top"), row=32, column=21, width=5, height=2)
|
||||
|
||||
# Block E
|
||||
grid.add(SeatPixel("E01", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E01"), seat_orientation="bottom"), row=27, column=1, width=5, height=2)
|
||||
grid.add(SeatPixel("E02", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E02"), seat_orientation="bottom"), row=27, column=6, width=5, height=2)
|
||||
grid.add(SeatPixel("E03", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E03"), seat_orientation="bottom"), row=27, column=11, width=5, height=2)
|
||||
grid.add(SeatPixel("E04", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E04"), seat_orientation="bottom"), row=27, column=16, width=5, height=2)
|
||||
grid.add(SeatPixel("E05", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E05"), seat_orientation="bottom"), row=27, column=21, width=5, height=2)
|
||||
|
||||
grid.add(SeatPixel("E10", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E10"), seat_orientation="top"), row=25, column=1, width=5, height=2)
|
||||
grid.add(SeatPixel("E11", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E11"), seat_orientation="top"), row=25, column=6, width=5, height=2)
|
||||
grid.add(SeatPixel("E12", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E12"), seat_orientation="top"), row=25, column=11, width=5, height=2)
|
||||
grid.add(SeatPixel("E13", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E13"), seat_orientation="top"), row=25, column=16, width=5, height=2)
|
||||
grid.add(SeatPixel("E14", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E14"), seat_orientation="top"), row=25, column=21, width=5, height=2)
|
||||
|
||||
# Stage
|
||||
grid.add(PointerEventListener(
|
||||
TextPixel(text="Bühne"),
|
||||
on_press=lambda _: self.info_clicked_cb("Hier darf ab Freitag 20 Uhr ebenfalls geschlafen werden.")
|
||||
), row=16, column=1, width=29, height=4)
|
||||
|
||||
# Drinks
|
||||
grid.add(PointerEventListener(
|
||||
TextPixel(text="G\ne\nt\nr\nä\nn\nk\ne"),
|
||||
on_press=lambda _: self.info_clicked_cb("Ich mag Bier, B - I - R")
|
||||
), row=20, column=30, width=4, height=12)
|
||||
|
||||
# Main Entrance
|
||||
grid.add(PointerEventListener(
|
||||
TextPixel(text="H\na\nl\nl\ne\nn\n\ne\ni\nn\ng\na\nn\ng"),
|
||||
on_press=lambda _: self.info_clicked_cb("Hallo, ich bin ein Haupteingang")
|
||||
), row=33, column=56, width=4, height=27)
|
||||
|
||||
# Sleeping
|
||||
grid.add(PointerEventListener(
|
||||
TextPixel(icon_name="material/bed"),
|
||||
on_press=lambda _: self.info_clicked_cb("In diesem Raum kann geschlafen werden.\nAchtung: Hier werden nicht alle Teilnehmer Platz finden.")
|
||||
), row=1, column=1, width=20, height=14)
|
||||
|
||||
# Toilet
|
||||
grid.add(PointerEventListener(
|
||||
TextPixel(icon_name="material/wc"),
|
||||
on_press=lambda _: self.info_clicked_cb("Damen Toilette")
|
||||
), row=1, column=42, width=19, height=10)
|
||||
grid.add(PointerEventListener(
|
||||
TextPixel(icon_name="material/wc"),
|
||||
on_press=lambda _: self.info_clicked_cb("Herren Toilette")
|
||||
), row=12, column=42, width=19, height=10)
|
||||
|
||||
# Entry/Helpdesk
|
||||
grid.add(PointerEventListener(
|
||||
TextPixel(text="Einlass\n &Orga"),
|
||||
on_press=lambda _: self.info_clicked_cb("Für alle Anliegen findest du hier rund um die Uhr jemanden vom Team.")
|
||||
), row=40, column=22, width=8, height=12)
|
||||
|
||||
|
||||
return Rectangle(
|
||||
content=grid,
|
||||
grow_x=True,
|
||||
grow_y=True,
|
||||
stroke_color=self.session.theme.neutral_color,
|
||||
stroke_width=0.1,
|
||||
fill=self.session.theme.primary_color,
|
||||
margin=0.5
|
||||
)
|
||||
|
||||
@ -1,141 +0,0 @@
|
||||
from rio import Column, Component, event, Text, Spacer, Row, Link
|
||||
|
||||
from src.ezgg_lan_manager import ConfigurationService, TicketingService
|
||||
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||
|
||||
|
||||
class OverviewPage(Component):
|
||||
@event.on_populate
|
||||
async def on_populate(self) -> None:
|
||||
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Übersicht")
|
||||
|
||||
def build(self) -> Component:
|
||||
lan_info = self.session[ConfigurationService].get_lan_info()
|
||||
return Column(
|
||||
MainViewContentBox(
|
||||
Column(
|
||||
Text(lan_info.name, font_size=2, justify="center", fill=self.session.theme.neutral_color, margin_top=0.5),
|
||||
Text(f"Edition {lan_info.iteration}", font_size=0.9, justify="center", fill=self.session.theme.neutral_color, margin_bottom=1.5)
|
||||
)
|
||||
),
|
||||
MainViewContentBox(
|
||||
Column(
|
||||
Text("Allgemeines", font_size=2, justify="center", fill=self.session.theme.neutral_color, margin_top=0.5, margin_bottom=1),
|
||||
Column(
|
||||
Row(
|
||||
Text("Wann?", fill=self.session.theme.neutral_color, margin_left=1),
|
||||
Spacer(),
|
||||
Text(f"{lan_info.date_from.strftime("%d.%m.")} bis {lan_info.date_till.strftime("%d.%m.%Y")}", fill=self.session.theme.neutral_color, margin_right=1),
|
||||
margin_bottom=0.3
|
||||
),
|
||||
Row(
|
||||
Text("Wo?", fill=self.session.theme.neutral_color, margin_left=1),
|
||||
Spacer(),
|
||||
Link(Text(f"DGH Donsbach", fill=self.session.theme.secondary_color, margin_right=1), target_url="https://maps.app.goo.gl/3Zyue776A22jdoxz5", open_in_new_tab=True),
|
||||
margin_bottom=0.3
|
||||
),
|
||||
Row(
|
||||
Text("Einlass", fill=self.session.theme.neutral_color, margin_left=1),
|
||||
Spacer(),
|
||||
Text(lan_info.date_from.strftime("Freitag %H:%M Uhr"), fill=self.session.theme.neutral_color, margin_right=1),
|
||||
margin_bottom=0.3
|
||||
),
|
||||
Row(
|
||||
Text("Ende", fill=self.session.theme.neutral_color, margin_left=1),
|
||||
Spacer(),
|
||||
Text(lan_info.date_till.strftime("Sonntag %H:%M Uhr"), fill=self.session.theme.neutral_color, margin_right=1),
|
||||
margin_bottom=0.3
|
||||
),
|
||||
Row(
|
||||
Text("Anmeldung", fill=self.session.theme.neutral_color, margin_left=1),
|
||||
Spacer(),
|
||||
Text("Geöffnet", fill=self.session.theme.success_color, margin_right=1),
|
||||
margin_bottom=0.3
|
||||
),
|
||||
Row(
|
||||
Text("Teilnehmer", fill=self.session.theme.neutral_color, margin_left=1),
|
||||
Spacer(),
|
||||
Text(str(self.session[TicketingService].get_total_tickets()), fill=self.session.theme.neutral_color, margin_right=1),
|
||||
margin_bottom=0.3
|
||||
)
|
||||
,
|
||||
Row(
|
||||
Text("Ticket Preise", fill=self.session.theme.neutral_color, margin_left=1),
|
||||
Spacer(),
|
||||
Link(Text(f"Preisliste", fill=self.session.theme.secondary_color, margin_right=1), target_url="./buy_ticket", open_in_new_tab=False),
|
||||
margin_bottom=0.3
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
MainViewContentBox(
|
||||
Column(
|
||||
Text("Technisches", font_size=2, justify="center", fill=self.session.theme.neutral_color, margin_top=0.5, margin_bottom=1),
|
||||
Column(
|
||||
Row(
|
||||
Text("Internet", fill=self.session.theme.neutral_color, margin_left=1),
|
||||
Spacer(),
|
||||
Text(f"60/20 Mbit/s (down/up)", fill=self.session.theme.neutral_color, margin_right=1),
|
||||
margin_bottom=0.3
|
||||
),
|
||||
Row(
|
||||
Text("Routing", fill=self.session.theme.neutral_color, margin_left=1),
|
||||
Spacer(),
|
||||
Text(f"Flaches Netz", fill=self.session.theme.neutral_color, margin_right=1),
|
||||
margin_bottom=0.3
|
||||
),
|
||||
Row(
|
||||
Text("WLAN", fill=self.session.theme.neutral_color, margin_left=1),
|
||||
Spacer(),
|
||||
Text(f"vorhanden", fill=self.session.theme.neutral_color, margin_right=1),
|
||||
margin_bottom=0.3
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
MainViewContentBox(
|
||||
Column(
|
||||
Text("Sonstiges", font_size=2, justify="center", fill=self.session.theme.neutral_color, margin_top=0.5, margin_bottom=1),
|
||||
Column(
|
||||
Row(
|
||||
Text("Schlafen", fill=self.session.theme.neutral_color, margin_left=1, justify="center"),
|
||||
margin_bottom=0.3
|
||||
),
|
||||
Row(
|
||||
Text("Es steht ein Schlafsaal zur Verfügung. Nach der Eröffnung steht auch die Bühne als Schlafbereich zur Verfügung.", font_size=0.7,
|
||||
fill=self.session.theme.neutral_color, margin_left=1, overflow="wrap"),
|
||||
margin_bottom=0.3
|
||||
),
|
||||
Row(
|
||||
Text("Essen & Trinken", fill=self.session.theme.neutral_color, margin_left=1, justify="center"),
|
||||
margin_bottom=0.3
|
||||
),
|
||||
Row(
|
||||
Text("Wir sorgen für euer leibliches Wohl, ihr dürft aber auch eure eigenen Speißen und Getränke mitbringen.", font_size=0.7, fill=self.session.theme.neutral_color, margin_left=1, overflow="wrap"),
|
||||
margin_bottom=0.3
|
||||
),
|
||||
Row(
|
||||
Text("Parken", fill=self.session.theme.neutral_color, margin_left=1, justify="center"),
|
||||
margin_bottom=0.3
|
||||
),
|
||||
Row(
|
||||
Text("Vor der Halle sind ausreichend Parkplätze vorhanden.", font_size=0.7, fill=self.session.theme.neutral_color, margin_left=1, overflow="wrap"),
|
||||
margin_bottom=0.3
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
MainViewContentBox(
|
||||
Column(
|
||||
Text("Turniere & Ablauf", font_size=2, justify="center", fill=self.session.theme.neutral_color, margin_top=0.5, margin_bottom=1),
|
||||
Column(
|
||||
Row(
|
||||
Text("Zum aktuellen Zeitpunkt steht noch nicht fest welche Turniere gespielt werden. Wir planen diverse Online- und Offline Turniere mit Preisen durchzuführen. Weitere Informationen gibt es, sobald sie kommen, auf der NEWS- und Turnier-Seite.", font_size=0.7,
|
||||
fill=self.session.theme.neutral_color, margin_left=1, overflow="wrap"),
|
||||
margin_bottom=0.3
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
Spacer()
|
||||
)
|
||||
@ -1,48 +0,0 @@
|
||||
import logging
|
||||
|
||||
import requests
|
||||
|
||||
from src.ezgg_lan_manager.services.SeatingService import SeatingService
|
||||
from src.ezgg_lan_manager.types.CateringOrder import CateringOrder
|
||||
from src.ezgg_lan_manager.types.ConfigurationTypes import ReceiptPrintingConfiguration
|
||||
from src.ezgg_lan_manager.types.User import User
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
logging.getLogger("urllib3").setLevel(logging.FATAL) # Disable logging for urllib3
|
||||
|
||||
class ReceiptPrintingService:
|
||||
def __init__(self, seating_service: SeatingService, config: ReceiptPrintingConfiguration, dev_mode_enabled: bool) -> None:
|
||||
self._seating_service = seating_service
|
||||
self._config = config
|
||||
self._dev_mode_enabled = dev_mode_enabled
|
||||
|
||||
async def print_order(self, user: User, order: CateringOrder) -> None:
|
||||
seat_id = await self._seating_service.get_user_seat(user.user_id)
|
||||
if not seat_id:
|
||||
seat_id = " - "
|
||||
|
||||
menu_items_payload = []
|
||||
for item, amount in order.items.items():
|
||||
menu_items_payload.append({
|
||||
"menu_item_name": item.name,
|
||||
"amount": amount
|
||||
})
|
||||
|
||||
payload = {
|
||||
"order_id": str(order.order_id),
|
||||
"order_date": order.order_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z',
|
||||
"customer_name": user.user_name,
|
||||
"seat_id": seat_id,
|
||||
"items": menu_items_payload
|
||||
}
|
||||
try:
|
||||
requests.post(
|
||||
f"http://{self._config.host}:{self._config.port}/{self._config.order_print_endpoint}",
|
||||
json=payload,
|
||||
headers={"x-password": self._config.password}
|
||||
)
|
||||
except Exception as e:
|
||||
if self._dev_mode_enabled:
|
||||
logger.info("An error occurred trying to print a receipt:", e)
|
||||
return
|
||||
logger.error("An error occurred trying to print a receipt:", e)
|
||||
@ -3,8 +3,8 @@ from datetime import datetime
|
||||
from unittest.mock import MagicMock, AsyncMock
|
||||
from decimal import Decimal
|
||||
|
||||
from src.ezgg_lan_manager.services.AccountingService import AccountingService, InsufficientFundsError
|
||||
from src.ezgg_lan_manager.types.Transaction import Transaction
|
||||
from src.ez_lan_manager.services.AccountingService import AccountingService, InsufficientFundsError
|
||||
from src.ez_lan_manager.types.Transaction import Transaction
|
||||
|
||||
|
||||
class AccountingServiceTests(unittest.IsolatedAsyncioTestCase):
|
||||
|
||||
12
testing/unittests/TournamentServiceTests.py
Normal file
12
testing/unittests/TournamentServiceTests.py
Normal file
@ -0,0 +1,12 @@
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, AsyncMock
|
||||
|
||||
from src.ez_lan_manager.services.TournamentService import TournamentService
|
||||
|
||||
|
||||
class TournamentServiceTests(unittest.IsolatedAsyncioTestCase):
|
||||
|
||||
def setUp(self) -> None:
|
||||
self.mock_database_service = MagicMock()
|
||||
self.mock_database_service.add_transaction = AsyncMock()
|
||||
self.accounting_service = TournamentService(self.mock_database_service)
|
||||
Loading…
Reference in New Issue
Block a user