Add card table loading
This commit is contained in:
@@ -39,9 +39,9 @@ polars = { version = "0.39.2", default-features = false, features = [
|
||||
fantoccini = "0.19"
|
||||
|
||||
[target.'cfg(engine)'.dependencies]
|
||||
axum = { version = "0.6", features = ["macros"] }
|
||||
tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread"] }
|
||||
perseus-axum = { version = "0.4.2" }
|
||||
axum = "0.6"
|
||||
futures = "0.3.28"
|
||||
sea-orm = { version = "1.0", features = [
|
||||
"sqlx-postgres",
|
||||
@@ -60,3 +60,6 @@ sea-orm = { version = "1.0" }
|
||||
|
||||
[lints.rust]
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(engine)', 'cfg(client)'] }
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
||||
@@ -11,6 +11,14 @@ use crate::{
|
||||
use perseus::prelude::*;
|
||||
use sycamore::prelude::*;
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(client)] {
|
||||
use crate::endpoints::CARD_INFO;
|
||||
use crate::templates::get_api_path;
|
||||
use crate::models::card::CardTable;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Prop)]
|
||||
pub struct LayoutProps<'a, G: Html> {
|
||||
pub content_state: ContentState,
|
||||
@@ -51,12 +59,42 @@ pub fn Layout<'a, G: Html>(
|
||||
|
||||
let content_state_header = content_state.clone();
|
||||
|
||||
#[cfg(client)]
|
||||
{
|
||||
// TODO -> try to use suspense
|
||||
spawn_local_scoped(cx, async move {
|
||||
let global_state = Reactor::<G>::from_cx(cx).get_global_state::<AppStateRx>(cx);
|
||||
|
||||
let card_table_loaded = (*global_state.constants.is_loaded.get()).clone();
|
||||
if !card_table_loaded {
|
||||
let client = reqwest::Client::new();
|
||||
let response = client
|
||||
.get(get_api_path(CARD_INFO).as_str())
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// TODO add error handling
|
||||
let response = response.json::<CardTable>().await.unwrap();
|
||||
global_state.constants.card_table.set(Some(response));
|
||||
global_state.constants.is_loaded.set(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
view! { cx,
|
||||
// Main page header, including login functionality
|
||||
Header(content_state = content_state_header)
|
||||
|
||||
// Modals
|
||||
section(class = "flex-2") {
|
||||
(match (*global_state.constants.card_table.get()).clone() {
|
||||
Some(card_table) => { view!{ cx,
|
||||
p { "DONE" }
|
||||
} },
|
||||
None => { view!{ cx, p { "Loading cards" } } },
|
||||
})
|
||||
|
||||
(match *global_state.modals_open.login.get() {
|
||||
OpenState::Open => {
|
||||
view! { cx,
|
||||
|
||||
@@ -4,3 +4,4 @@ pub const LOGIN: &str = "/api/login";
|
||||
#[cfg(engine)]
|
||||
pub const LOGIN_TEST: &str = "/api/login-test";
|
||||
pub const FORGOT_PASSWORD: &str = "/api/forgot-password";
|
||||
pub const CARD_INFO: &str = "/api/card-info";
|
||||
|
||||
@@ -4,13 +4,16 @@ use perseus::{prelude::*, state::GlobalStateCreator};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
models::auth::WebAuthInfo,
|
||||
models::{auth::WebAuthInfo, card::CardTable},
|
||||
state_enums::{LoginState, OpenState},
|
||||
};
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize, ReactiveState, Clone)]
|
||||
#[rx(alias = "AppStateRx")]
|
||||
pub struct AppState {
|
||||
#[rx(nested)]
|
||||
pub constants: ConstData,
|
||||
#[rx(nested)]
|
||||
pub auth: AuthData,
|
||||
#[rx(nested)]
|
||||
@@ -19,6 +22,13 @@ pub struct AppState {
|
||||
pub style: StyleData,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ReactiveState, Clone)]
|
||||
#[rx(alias = "ConstDataRx")]
|
||||
pub struct ConstData {
|
||||
pub is_loaded: bool,
|
||||
pub card_table: Option<CardTable>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ReactiveState, Clone)]
|
||||
#[rx(alias = "AuthDataRx")]
|
||||
pub struct AuthData {
|
||||
@@ -58,6 +68,10 @@ pub fn get_global_state_creator() -> GlobalStateCreator {
|
||||
#[engine_only_fn]
|
||||
pub async fn get_build_state() -> AppState {
|
||||
AppState {
|
||||
constants: ConstData {
|
||||
is_loaded: false,
|
||||
card_table: None
|
||||
},
|
||||
auth: AuthData {
|
||||
state: LoginState::Unknown,
|
||||
pending_username: String::new(),
|
||||
|
||||
@@ -34,6 +34,7 @@ pub enum MonsterAttribute {
|
||||
Light,
|
||||
Water,
|
||||
Wind,
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
@@ -51,13 +52,14 @@ pub enum TrapType {
|
||||
Normal,
|
||||
Continuous,
|
||||
Counter,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub enum CardTypeInfo {
|
||||
Monster {
|
||||
level: u32, // level/rank/link rating
|
||||
atk: u32,
|
||||
level: Option<u32>, // level/rank/link rating
|
||||
atk: Option<u32>,
|
||||
def: Option<u32>,
|
||||
pendulum_scale: Option<u32>,
|
||||
attribute: MonsterAttribute,
|
||||
@@ -170,16 +172,16 @@ impl CardTable {
|
||||
"Continuous" => TrapType::Continuous,
|
||||
"Counter" => TrapType::Counter,
|
||||
"Normal" => TrapType::Normal,
|
||||
unknown => panic!("Unknown trap type {}", unknown),
|
||||
_ => TrapType::Unknown,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
CardTypeInfo::Monster {
|
||||
level: row[level_idx].try_extract().unwrap(),
|
||||
atk: row[atk_idx].try_extract().unwrap(),
|
||||
level: row[level_idx].try_extract().ok(),
|
||||
atk: row[atk_idx].try_extract().ok(),
|
||||
def: row[def_idx].try_extract().ok(),
|
||||
pendulum_scale: row[pendulum_scale_idx].try_extract().ok(),
|
||||
attribute: match row[attribute_idx].get_str().unwrap() {
|
||||
attribute: match row[attribute_idx].get_str().unwrap_or("NONE") {
|
||||
"DARK" => MonsterAttribute::Dark,
|
||||
"DIVINE" => MonsterAttribute::Divine,
|
||||
"EARTH" => MonsterAttribute::Earth,
|
||||
@@ -187,6 +189,7 @@ impl CardTable {
|
||||
"LIGHT" => MonsterAttribute::Light,
|
||||
"WATER" => MonsterAttribute::Water,
|
||||
"WIND" => MonsterAttribute::Wind,
|
||||
"NONE" => MonsterAttribute::None,
|
||||
unknown => panic!("Unknown attribute {}", unknown),
|
||||
},
|
||||
monster_type: row[monster_type_idx]
|
||||
@@ -390,18 +393,14 @@ impl CardTable {
|
||||
"frameType",
|
||||
"ygoprodeck_url",
|
||||
"linkval",
|
||||
"race"
|
||||
"race",
|
||||
])])
|
||||
// Remove link markers, unless it's needed later
|
||||
.select([col("*").exclude(["linkmarkers"])])
|
||||
// TODO add banlist support
|
||||
.select([col("*").exclude(["banlist_info"])])
|
||||
// TODO readd
|
||||
.select([col("*").exclude([
|
||||
"card_sets",
|
||||
"card_images",
|
||||
"card_prices",
|
||||
])])
|
||||
.select([col("*").exclude(["card_sets", "card_images", "card_prices"])])
|
||||
// Filter out "Skill Card"
|
||||
.filter(col("type").str().contains(lit("Skill Card"), false).not())
|
||||
// Filters for testing
|
||||
|
||||
18
src/server/constants/card_table.rs
Normal file
18
src/server/constants/card_table.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
use std::path::Path;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::server::server_state::ServerState;
|
||||
use axum::{debug_handler, extract::State, http::StatusCode, Json};
|
||||
|
||||
use crate::models::card::CardTable;
|
||||
|
||||
lazy_static! {
|
||||
static ref CARD_TABLE: CardTable =
|
||||
CardTable::new_from_server_json(Path::new("./data/cardinfo.json"));
|
||||
}
|
||||
|
||||
#[debug_handler]
|
||||
pub async fn get_card_table(State(_): State<ServerState>) -> Result<Json<CardTable>, StatusCode> {
|
||||
Ok(Json(CARD_TABLE.clone()))
|
||||
}
|
||||
1
src/server/constants/mod.rs
Normal file
1
src/server/constants/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod card_table;
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod auth;
|
||||
pub mod constants;
|
||||
pub mod routes;
|
||||
pub mod server_state;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// (Server only) Routes
|
||||
use crate::endpoints::{FORGOT_PASSWORD, LOGIN, LOGIN_TEST, REGISTER};
|
||||
use axum::routing::{post, Router};
|
||||
use crate::endpoints::{CARD_INFO, FORGOT_PASSWORD, LOGIN, LOGIN_TEST, REGISTER};
|
||||
use axum::routing::{get, post, Router};
|
||||
|
||||
use super::{
|
||||
auth::{
|
||||
@@ -8,6 +8,7 @@ use super::{
|
||||
login::{post_login_user, post_test_login},
|
||||
register::post_register_user,
|
||||
},
|
||||
constants::card_table::get_card_table,
|
||||
server_state::ServerState,
|
||||
};
|
||||
|
||||
@@ -17,5 +18,6 @@ pub fn get_api_router(state: ServerState) -> Router {
|
||||
.route(LOGIN, post(post_login_user))
|
||||
.route(LOGIN_TEST, post(post_test_login))
|
||||
.route(FORGOT_PASSWORD, post(post_forgot_password))
|
||||
.route(CARD_INFO, get(get_card_table))
|
||||
.with_state(state)
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
// Not a page, global state that is shared between all pages
|
||||
|
||||
use perseus::{prelude::*, state::GlobalStateCreator};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::data::card::CardTable;
|
||||
|
||||
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 card_table: CardTable,
|
||||
}
|
||||
|
||||
pub fn get_global_state_creator() -> GlobalStateCreator {
|
||||
GlobalStateCreator::new()
|
||||
.build_state_fn(get_build_state)
|
||||
.request_state_fn(get_request_state)
|
||||
}
|
||||
|
||||
#[engine_only_fn]
|
||||
fn get_state() -> AppState {
|
||||
let card_table = thread::spawn(move || DATA.lock().unwrap().deref().card_table.clone())
|
||||
.join()
|
||||
.unwrap();
|
||||
|
||||
AppState { card_table }
|
||||
}
|
||||
|
||||
#[engine_only_fn]
|
||||
pub async fn get_build_state() -> AppState {
|
||||
get_state()
|
||||
}
|
||||
|
||||
#[engine_only_fn]
|
||||
pub async fn get_request_state(_req: Request) -> AppState {
|
||||
get_state()
|
||||
}
|
||||
Reference in New Issue
Block a user