diff --git a/Cargo.toml b/Cargo.toml index 8845d5a..72cc281 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,3 +41,4 @@ sea-orm = { version = "0.12.0", features = [ [target.'cfg(client)'.dependencies] wasm-bindgen = "0.2" reqwest = { version = "0.11", features = ["json"] } +sea-orm = { version = "0.12.0" } diff --git a/README.md b/README.md index c57eb6d..1eaca27 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ To set up the database, run: `$env:DATABASE_URL = "postgres://elo:elo@localhost:5432/elo_app"; sea-orm-cli migrate up` Updating entities after updating database: -`$env:DATABASE_URL = "postgres://elo:elo@localhost:5432/elo_app"; sea-orm-cli generate entity -o entity/src --with-serde both` +`$env:DATABASE_URL = "postgres://elo:elo@localhost:5432/elo_app"; sea-orm-cli generate entity -o src/entity --with-serde both` To build CSS run: `npm run build` diff --git a/entity/src/prelude.rs b/entity/src/prelude.rs deleted file mode 100644 index f412b60..0000000 --- a/entity/src/prelude.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.0 - -pub use super::game::Entity as Game; -pub use super::one_vs_one::Entity as OneVsOne; -pub use super::user::Entity as User; diff --git a/entity/src/user.rs b/entity/src/user.rs deleted file mode 100644 index aa72e13..0000000 --- a/entity/src/user.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.0 - -use sea_orm::entity::prelude::*; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] -#[sea_orm(table_name = "user")] -pub struct Model { - #[sea_orm(primary_key)] - pub id: i32, - pub username: String, - pub password: String, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation {} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/migration/src/m20240813_000001_create_users.rs b/migration/src/m20240813_000001_create_users.rs index 60a3819..dbfe201 100644 --- a/migration/src/m20240813_000001_create_users.rs +++ b/migration/src/m20240813_000001_create_users.rs @@ -3,23 +3,25 @@ use sea_orm_migration::{prelude::*, schema::*}; #[derive(DeriveMigrationName)] pub struct Migration; +// https://github.com/SeaQL/sea-orm/blob/368b1126f73f47c7ec30fe523834f6a0962a193b/sea-orm-migration/src/schema.rs + #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + // User table manager .create_table( Table::create() .table(User::Table) - .if_not_exists() - .col( - ColumnDef::new(User::Id) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) + .col(pk_auto(User::Id)) .col(string(User::Username)) .col(string(User::Password)) + .col(string(User::Salt)) + .col(timestamp_with_time_zone(User::CreationTime)) + .col(timestamp_with_time_zone(User::LastActiveTime)) + .col(boolean(User::IsAdmin)) + .col(string_null(User::Email)) + .col(string_null(User::Avatar)) .to_owned(), ) .await @@ -37,6 +39,11 @@ pub enum User { Table, Id, Username, - // Hash Password, + Salt, + CreationTime, + LastActiveTime, + IsAdmin, + Email, + Avatar, } diff --git a/migration/src/m20240813_000002_create_game.rs b/migration/src/m20240813_000002_create_game.rs index 0dc83ee..f139e01 100644 --- a/migration/src/m20240813_000002_create_game.rs +++ b/migration/src/m20240813_000002_create_game.rs @@ -12,114 +12,112 @@ impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { let schema = Schema::new(DbBackend::Postgres); - manager - .create_type(schema.create_enum_from_active_enum::()) - .await?; + // Game type enum manager .create_type(schema.create_enum_from_active_enum::()) .await?; + // Game table manager .create_table( Table::create() .table(Game::Table) - .if_not_exists() - .col( - ColumnDef::new(Game::Id) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col(ColumnDef::new(Game::PlayerSetupType).custom(PlayerSetupType::name())) - .col(ColumnDef::new(Game::GameType).custom(GameType::name())) - .col( - ColumnDef::new(Game::Time) - .timestamp_with_time_zone() - .not_null(), - ) - .to_owned(), - ) - .await?; - manager - .create_table( - Table::create() - .table(Game::Table) - .if_not_exists() - .col( - ColumnDef::new(Game::Id) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col(ColumnDef::new(Game::PlayerSetupType).custom(PlayerSetupType::name())) + .col(pk_auto(Game::Id)) + .col(timestamp_with_time_zone(Game::Time)) .col(ColumnDef::new(Game::GameType).custom(GameType::name())) .to_owned(), ) .await?; + // TeamResult table manager .create_table( Table::create() - .table(OneVsOne::Table) - .if_not_exists() - .col( - ColumnDef::new(OneVsOne::Id) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col(ColumnDef::new(OneVsOne::PlayerOne).integer().not_null()) - .col(ColumnDef::new(OneVsOne::PlayerTwo).integer().not_null()) - .col(ColumnDef::new(OneVsOne::GameId).integer().not_null()) - .foreign_key( - ForeignKey::create() - .name("fk-user-one_vs_one-player_one_id") - .from(OneVsOne::Table, OneVsOne::PlayerOne) - .to(User::Table, User::Id), + .table(TeamResult::Table) + .col(pk_auto(TeamResult::Id)) + .col(integer(TeamResult::Place)) + .col(integer_null(TeamResult::Score)) + .to_owned(), + ) + .await?; + // Game to TeamResult assoc + manager + .create_table( + Table::create() + .table(GameToTeamResult::Table) + .col(integer(GameToTeamResult::GameId)) + .col(integer(GameToTeamResult::TeamResultId)) + .primary_key( + Index::create() + .name("pk-game_to_team_result") + .col(GameToTeamResult::GameId) + .col(GameToTeamResult::TeamResultId), ) .foreign_key( ForeignKey::create() - .name("fk-user-one_vs_one-player_two_id") - .from(OneVsOne::Table, OneVsOne::PlayerTwo) - .to(User::Table, User::Id), - ) - .foreign_key( - ForeignKey::create() - .name("fk-game-one_vs_one-game_id") - .from(OneVsOne::Table, OneVsOne::GameId) + .name("fk-game_to_team_result-game_id") + .from(GameToTeamResult::Table, GameToTeamResult::GameId) .to(Game::Table, Game::Id), ) + .foreign_key( + ForeignKey::create() + .name("fk-game_to_team_result-team_result_id") + .from(GameToTeamResult::Table, GameToTeamResult::TeamResultId) + .to(TeamResult::Table, TeamResult::Id), + ) + .to_owned(), + ) + .await?; + // TeamResult to User assoc + manager + .create_table( + Table::create() + .table(TeamResultToUser::Table) + .col(integer(TeamResultToUser::TeamResultId)) + .col(integer(TeamResultToUser::UserId)) + .primary_key( + Index::create() + .name("pk-team_result_to_user") + .col(TeamResultToUser::TeamResultId) + .col(TeamResultToUser::UserId), + ) + .foreign_key( + ForeignKey::create() + .name("fk-team_result_to_user-team_result_id") + .from(TeamResultToUser::Table, TeamResultToUser::TeamResultId) + .to(TeamResult::Table, TeamResult::Id), + ) + .foreign_key( + ForeignKey::create() + .name("fk-team_result_to_user-user_id") + .from(TeamResultToUser::Table, TeamResultToUser::UserId) + .to(User::Table, User::Id), + ) .to_owned(), ) .await } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + // Drop tables in reverse manager - .drop_type(Type::drop().name(PlayerSetupType::name()).to_owned()) + .drop_table(Table::drop().table(TeamResultToUser::Table).to_owned()) .await?; manager - .drop_type(Type::drop().name(GameType::name()).to_owned()) + .drop_table(Table::drop().table(GameToTeamResult::Table).to_owned()) + .await?; + manager + .drop_table(Table::drop().table(TeamResult::Table).to_owned()) .await?; manager .drop_table(Table::drop().table(Game::Table).to_owned()) .await?; + // Drop types manager - .drop_table(Table::drop().table(OneVsOne::Table).to_owned()) + .drop_type(Type::drop().name(GameType::name()).to_owned()) .await } } // Enums -#[derive(EnumIter, DeriveActiveEnum)] -#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "player_setup_type")] -enum PlayerSetupType { - #[sea_orm(string_value = "OneVsOne")] - OneVsOne, - #[sea_orm(string_value = "TwoVsTwo")] - TwoVsTwo, -} #[derive(EnumIter, DeriveActiveEnum)] #[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "game_type")] @@ -138,15 +136,28 @@ enum Game { Table, Id, Time, - PlayerSetupType, GameType, } #[derive(DeriveIden)] -enum OneVsOne { +enum TeamResult { Table, Id, - GameId, - PlayerOne, - PlayerTwo, + Place, + Score, +} + +// Assoc +#[derive(DeriveIden)] +enum GameToTeamResult { + Table, + GameId, + TeamResultId, +} + +#[derive(DeriveIden)] +enum TeamResultToUser { + Table, + TeamResultId, + UserId, } diff --git a/src/auth.rs b/src/auth.rs new file mode 100644 index 0000000..6f79b1a --- /dev/null +++ b/src/auth.rs @@ -0,0 +1,19 @@ +use crate::user; +use axum_login::{AuthUser, AuthnBackend, UserId}; +use serde::{Deserialize, Serialize}; + +// References +// https://github.com/maxcountryman/axum-login/tree/main/examples/sqlite/src +// https://framesurge.sh/perseus/en-US/docs/0.4.x/state/intro + +impl AuthUser for user::Model { + type Id = i32; + + fn id(&self) -> Self::Id { + self.id + } + + fn session_auth_hash(&self) -> &[u8] { + self.password.as_bytes() + } +} diff --git a/src/data/mod.rs b/src/data/mod.rs deleted file mode 100644 index 68c233a..0000000 --- a/src/data/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod pool_match; -pub mod user; - -#[cfg(engine)] -pub mod store; diff --git a/src/data/pool_match.rs b/src/data/pool_match.rs deleted file mode 100644 index b2ba79c..0000000 --- a/src/data/pool_match.rs +++ /dev/null @@ -1,74 +0,0 @@ -use crate::data::user::PlayerId; -use chrono::serde::ts_seconds; -use chrono::{DateTime, Utc}; -use serde::{Deserialize, Serialize}; - -pub type MatchId = u32; - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub enum MatchType { - Standard8Ball, - Standard9Ball, - CutThroat, -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct MatchData { - pub type_: MatchType, - pub winners: Vec, - pub losers: Vec, -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct PoolMatch { - pub id: MatchId, - pub data: MatchData, - #[serde(with = "ts_seconds")] - pub time: DateTime, -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct PoolMatchList { - pub pool_matches: Vec, - pub max_id: MatchId, -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct UserList{ - pub users: Vec, -} - -impl PoolMatch { - pub fn new(data: MatchData, time: DateTime) -> PoolMatch { - PoolMatch { id: 0, data, time } - } -} - -impl PoolMatchList { - pub fn new() -> PoolMatchList { - PoolMatchList { - pool_matches: vec![], - max_id: 0, - } - } - - pub fn add_pool_match(&mut self, mut pool_match: PoolMatch) { - pool_match.id = self.max_id + 1; - self.max_id += 1; - self.pool_matches.push(pool_match); - } -} - -impl UserList { - pub fn new() -> UserList { - UserList { - users: vec![], - } - } - - pub fn add_user(&mut self, user: String) -> usize { - let user_id = self.users.len(); - self.users.push(user); - user_id - } -} diff --git a/src/data/store.rs b/src/data/store.rs deleted file mode 100644 index 4069df9..0000000 --- a/src/data/store.rs +++ /dev/null @@ -1,37 +0,0 @@ -// (Server only) In-memory data storage and persistent storage - -use crate::data::pool_match::PoolMatchList; -use crate::data::pool_match::UserList; -use once_cell::sync::Lazy; -use serde::{Deserialize, Serialize}; -use std::{fs, path::Path, sync::Mutex}; - -#[derive(Serialize, Deserialize, Clone)] -pub struct Store { - pub matches: PoolMatchList, - pub users: UserList, -} - -impl Store { - fn new() -> Store { - fs::create_dir_all("data").unwrap(); - match Path::new("data/store.json").exists() { - false => Store { - matches: PoolMatchList::new(), - users: UserList::new(), - }, - true => { - let contents = fs::read_to_string("data/store.json").unwrap(); - serde_json::from_str(&contents).unwrap() - } - } - } - // TODO -> Store data - #[allow(dead_code)] - pub fn write(&self) { - let contents = serde_json::to_string(&self).unwrap(); - fs::write("data/store.json", contents).unwrap(); - } -} - -pub static DATA: Lazy> = Lazy::new(|| Mutex::new(Store::new())); diff --git a/src/data/user.rs b/src/data/user.rs deleted file mode 100644 index 0124a63..0000000 --- a/src/data/user.rs +++ /dev/null @@ -1,38 +0,0 @@ -use axum_login::{AuthUser, AuthnBackend, UserId}; -use serde::{Deserialize, Serialize}; - -pub type PlayerId = u32; - -// References -// https://github.com/maxcountryman/axum-login/tree/main/examples/sqlite/src -// https://framesurge.sh/perseus/en-US/docs/0.4.x/state/intro - -#[derive(Clone, Serialize, Deserialize)] -pub struct User { - id: u64, - pub username: String, - password: String, -} - -// Override debug to prevent logging password hash -impl std::fmt::Debug for User { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("User") - .field("id", &self.id) - .field("username", &self.username) - .field("password", &"[hidden]") - .finish() - } -} - -impl AuthUser for User { - type Id = u64; - - fn id(&self) -> Self::Id { - self.id - } - - fn session_auth_hash(&self) -> &[u8] { - self.password.as_bytes() - } -} diff --git a/entity/src/game.rs b/src/entity/game.rs similarity index 56% rename from entity/src/game.rs rename to src/entity/game.rs index a739bc7..18c89a5 100644 --- a/entity/src/game.rs +++ b/src/entity/game.rs @@ -1,7 +1,6 @@ //! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.0 use super::sea_orm_active_enums::GameType; -use super::sea_orm_active_enums::PlayerSetupType; use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; @@ -10,20 +9,28 @@ use serde::{Deserialize, Serialize}; pub struct Model { #[sea_orm(primary_key)] pub id: i32, - pub player_setup_type: Option, - pub game_type: Option, pub time: DateTimeWithTimeZone, + pub game_type: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { - #[sea_orm(has_many = "super::one_vs_one::Entity")] - OneVsOne, + #[sea_orm(has_many = "super::game_to_team_result::Entity")] + GameToTeamResult, } -impl Related for Entity { +impl Related for Entity { fn to() -> RelationDef { - Relation::OneVsOne.def() + Relation::GameToTeamResult.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::game_to_team_result::Relation::TeamResult.def() + } + fn via() -> Option { + Some(super::game_to_team_result::Relation::Game.def().rev()) } } diff --git a/entity/src/one_vs_one.rs b/src/entity/game_to_team_result.rs similarity index 62% rename from entity/src/one_vs_one.rs rename to src/entity/game_to_team_result.rs index 550cda4..52040a4 100644 --- a/entity/src/one_vs_one.rs +++ b/src/entity/game_to_team_result.rs @@ -4,13 +4,12 @@ use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] -#[sea_orm(table_name = "one_vs_one")] +#[sea_orm(table_name = "game_to_team_result")] pub struct Model { - #[sea_orm(primary_key)] - pub id: i32, - pub player_one: i32, - pub player_two: i32, + #[sea_orm(primary_key, auto_increment = false)] pub game_id: i32, + #[sea_orm(primary_key, auto_increment = false)] + pub team_result_id: i32, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] @@ -24,21 +23,13 @@ pub enum Relation { )] Game, #[sea_orm( - belongs_to = "super::user::Entity", - from = "Column::PlayerOne", - to = "super::user::Column::Id", + belongs_to = "super::team_result::Entity", + from = "Column::TeamResultId", + to = "super::team_result::Column::Id", on_update = "NoAction", on_delete = "NoAction" )] - User2, - #[sea_orm( - belongs_to = "super::user::Entity", - from = "Column::PlayerTwo", - to = "super::user::Column::Id", - on_update = "NoAction", - on_delete = "NoAction" - )] - User1, + TeamResult, } impl Related for Entity { @@ -47,4 +38,10 @@ impl Related for Entity { } } +impl Related for Entity { + fn to() -> RelationDef { + Relation::TeamResult.def() + } +} + impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/mod.rs b/src/entity/mod.rs similarity index 62% rename from entity/src/mod.rs rename to src/entity/mod.rs index f22ac25..8a33116 100644 --- a/entity/src/mod.rs +++ b/src/entity/mod.rs @@ -3,6 +3,8 @@ pub mod prelude; pub mod game; -pub mod one_vs_one; +pub mod game_to_team_result; pub mod sea_orm_active_enums; +pub mod team_result; +pub mod team_result_to_user; pub mod user; diff --git a/src/entity/prelude.rs b/src/entity/prelude.rs new file mode 100644 index 0000000..6f116a3 --- /dev/null +++ b/src/entity/prelude.rs @@ -0,0 +1,7 @@ +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.0 + +pub use super::game::Entity as Game; +pub use super::game_to_team_result::Entity as GameToTeamResult; +pub use super::team_result::Entity as TeamResult; +pub use super::team_result_to_user::Entity as TeamResultToUser; +pub use super::user::Entity as User; diff --git a/entity/src/sea_orm_active_enums.rs b/src/entity/sea_orm_active_enums.rs similarity index 60% rename from entity/src/sea_orm_active_enums.rs rename to src/entity/sea_orm_active_enums.rs index 631fc29..25dba9d 100644 --- a/entity/src/sea_orm_active_enums.rs +++ b/src/entity/sea_orm_active_enums.rs @@ -13,11 +13,3 @@ pub enum GameType { #[sea_orm(string_value = "TableTennis")] TableTennis, } -#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)] -#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "player_setup_type")] -pub enum PlayerSetupType { - #[sea_orm(string_value = "OneVsOne")] - OneVsOne, - #[sea_orm(string_value = "TwoVsTwo")] - TwoVsTwo, -} diff --git a/src/entity/team_result.rs b/src/entity/team_result.rs new file mode 100644 index 0000000..d3bfadc --- /dev/null +++ b/src/entity/team_result.rs @@ -0,0 +1,53 @@ +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.0 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "team_result")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub place: i32, + pub score: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::game_to_team_result::Entity")] + GameToTeamResult, + #[sea_orm(has_many = "super::team_result_to_user::Entity")] + TeamResultToUser, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::GameToTeamResult.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::TeamResultToUser.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::game_to_team_result::Relation::Game.def() + } + fn via() -> Option { + Some(super::game_to_team_result::Relation::TeamResult.def().rev()) + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::team_result_to_user::Relation::User.def() + } + fn via() -> Option { + Some(super::team_result_to_user::Relation::TeamResult.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/entity/team_result_to_user.rs b/src/entity/team_result_to_user.rs new file mode 100644 index 0000000..7e73bed --- /dev/null +++ b/src/entity/team_result_to_user.rs @@ -0,0 +1,47 @@ +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.0 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "team_result_to_user")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub team_result_id: i32, + #[sea_orm(primary_key, auto_increment = false)] + pub user_id: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::team_result::Entity", + from = "Column::TeamResultId", + to = "super::team_result::Column::Id", + on_update = "NoAction", + on_delete = "NoAction" + )] + TeamResult, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "NoAction" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::TeamResult.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/entity/user.rs b/src/entity/user.rs new file mode 100644 index 0000000..36b32b0 --- /dev/null +++ b/src/entity/user.rs @@ -0,0 +1,42 @@ +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.0 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "user")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub username: String, + pub password: String, + pub salt: String, + pub creation_time: DateTimeWithTimeZone, + pub last_active_time: DateTimeWithTimeZone, + pub is_admin: bool, + pub email: Option, + pub avatar: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::team_result_to_user::Entity")] + TeamResultToUser, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::TeamResultToUser.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::team_result_to_user::Relation::TeamResult.def() + } + fn via() -> Option { + Some(super::team_result_to_user::Relation::User.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/main.rs b/src/main.rs index b7289a1..25f1752 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ mod components; -mod data; mod endpoints; +mod entity; mod error_views; #[cfg(engine)] mod server; diff --git a/src/server/routes.rs b/src/server/routes.rs index df2cc88..f343cbf 100644 --- a/src/server/routes.rs +++ b/src/server/routes.rs @@ -1,52 +1,16 @@ // (Server only) Routes - -use crate::{ - data::{ - pool_match::{PoolMatch, PoolMatchList, UserList}, - store::DATA, - }, - endpoints::MATCH, - endpoints::USER, -}; +use crate::{endpoints::USER, entity::user}; use axum::{ extract::Json, routing::{post, Router}, }; -use std::thread; pub fn register_routes(app: Router) -> Router { - let app = app.route(MATCH, post(post_match)); let app = app.route(USER, post(post_user)); app } -async fn post_match(Json(pool_match): Json) -> Json { +async fn post_user(user: String) -> Json { // Update the store with the new match - let matches = thread::spawn(move || { - // Get the store - let mut data = DATA.lock().unwrap(); - (*data).matches.add_pool_match(pool_match); - println!("{:?}", (*data).matches.pool_matches); - (*data).matches.clone() - }) - .join() - .unwrap(); - - Json(matches) + todo!() } - -async fn post_user(user: String) -> Json { - // Update the store with the new match - let users = thread::spawn(move || { - // Get the store - let mut data = DATA.lock().unwrap(); - let user_id = (*data).users.add_user(user); - println!("Added new user id: {}\nAll users: {:?}", user_id, (*data).users); - (*data).users.clone() - }) - .join() - .unwrap(); - - Json(users) -} - diff --git a/src/templates/add_game_form.rs b/src/templates/add_game_form.rs index d89de31..d7f20b6 100644 --- a/src/templates/add_game_form.rs +++ b/src/templates/add_game_form.rs @@ -1,5 +1,4 @@ -use crate::data::pool_match::MatchType; -use crate::{components::layout::Layout, data::pool_match::MatchData}; +use crate::components::layout::Layout; use perseus::prelude::*; use serde::{Deserialize, Serialize}; use sycamore::prelude::*; @@ -7,7 +6,6 @@ use web_sys::Event; cfg_if::cfg_if! { if #[cfg(client)] { - use crate::data::pool_match::{PoolMatch, PoolMatchList, UserList}; use crate::templates::global_state::AppStateRx; use crate::endpoints::{MATCH, USER}; use crate::templates::get_api_path; @@ -29,28 +27,7 @@ fn add_game_form_page<'a, G: Html>(cx: BoundedScope<'_, 'a>, state: &'a PageStat #[cfg(client)] { // state.winner.get().as_ref().clone() - spawn_local_scoped(cx, async move { - let new_match = PoolMatch::new( - MatchData { - type_: MatchType::Standard8Ball, - winners: vec![1], - losers: vec![2, 3, 4], - }, - Utc::now(), - ); - let client = reqwest::Client::new(); - let new_matches = client - .post(get_api_path(MATCH).as_str()) - .json(&new_match) - .send() - .await - .unwrap() - .json::() - .await - .unwrap(); - let global_state = Reactor::::from_cx(cx).get_global_state::(cx); - global_state.matches.set(new_matches); - }) + spawn_local_scoped(cx, async move {}) } }; @@ -58,20 +35,7 @@ fn add_game_form_page<'a, G: Html>(cx: BoundedScope<'_, 'a>, state: &'a PageStat #[cfg(client)] { // state.winner.get().as_ref().clone() - spawn_local_scoped(cx, async move { - let client = reqwest::Client::new(); - let new_users = client - .post(get_api_path(USER).as_str()) - .body(state.new_user.get().as_ref().clone()) - .send() - .await - .unwrap() - .json::() - .await - .unwrap(); - let global_state = Reactor::::from_cx(cx).get_global_state::(cx); - global_state.users.set(new_users); - }) + spawn_local_scoped(cx, async move {}) } }; diff --git a/src/templates/global_state.rs b/src/templates/global_state.rs index 8658355..5fd4e1f 100644 --- a/src/templates/global_state.rs +++ b/src/templates/global_state.rs @@ -1,8 +1,5 @@ // Not a page, global state that is shared between all pages -use crate::data::pool_match::PoolMatchList; -use crate::data::pool_match::UserList; - use perseus::{prelude::*, state::GlobalStateCreator}; use serde::{Deserialize, Serialize}; @@ -10,16 +7,12 @@ cfg_if::cfg_if! { if #[cfg(engine)] { use std::thread; use std::ops::Deref; - use crate::data::store::DATA; } } #[derive(Serialize, Deserialize, ReactiveState, Clone)] #[rx(alias = "AppStateRx")] -pub struct AppState { - pub matches: PoolMatchList, - pub users: UserList, -} +pub struct AppState {} pub fn get_global_state_creator() -> GlobalStateCreator { GlobalStateCreator::new() @@ -29,15 +22,7 @@ pub fn get_global_state_creator() -> GlobalStateCreator { #[engine_only_fn] fn get_state() -> AppState { - let matches = thread::spawn(move || DATA.lock().unwrap().deref().matches.clone()) - .join() - .unwrap(); - - let users = thread::spawn(move || DATA.lock().unwrap().deref().users.clone()) - .join() - .unwrap(); - - AppState { matches, users } + AppState {} } #[engine_only_fn] diff --git a/src/templates/overall_board.rs b/src/templates/overall_board.rs index 5bc0f26..db45c2d 100644 --- a/src/templates/overall_board.rs +++ b/src/templates/overall_board.rs @@ -1,22 +1,13 @@ -use crate::{components::layout::Layout, templates::global_state::AppStateRx, data::user::PlayerId}; +use crate::{components::layout::Layout, templates::global_state::AppStateRx}; use perseus::prelude::*; use serde::{Deserialize, Serialize}; use sycamore::prelude::*; -use crate::data::pool_match::PoolMatch; - #[derive(Serialize, Deserialize, Clone, ReactiveState)] #[rx(alias = "PageStateRx")] struct PageState {} -fn format_list_or_single(to_format: &Vec) -> String{ - match to_format.len() { - 1 => to_format[0].to_string(), - _ => format!("{:?}", to_format), - } -} - fn overall_board_page<'a, G: Html>(cx: BoundedScope<'_, 'a>, _state: &'a PageStateRx) -> View { let global_state = Reactor::::from_cx(cx).get_global_state::(cx); @@ -24,24 +15,7 @@ fn overall_board_page<'a, G: Html>(cx: BoundedScope<'_, 'a>, _state: &'a PageSta Layout(title = "Overall Leaderboard") { ul { (View::new_fragment( - global_state.matches.get() - .pool_matches - .iter() - .rev() - .map(|item: &PoolMatch| { - let game = item.clone(); - - view! { cx, - li (class = "text-blue-700", id = "ha",) { - (game.id) - (" ") - (format_list_or_single(&game.data.winners)) - (" ") - (format_list_or_single(&game.data.losers)) - } - } - }) - .collect(), + vec![], )) } }