Added the ability to fetch multiple members on register

This commit is contained in:
xeovalyte 2024-09-24 21:17:49 +02:00
parent 91824dc82b
commit a503726b42
Signed by: xeovalyte
SSH Key Fingerprint: SHA256:kSQDrQDmKzljJzfGYcd3m9RqHi4h8rSwkZ3sQ9kBURo
7 changed files with 729 additions and 566 deletions

1198
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@ dioxus = { version = "0.5", features = ["fullstack", "router"] }
tokio = { version = "1.38", features = ["macros", "rt-multi-thread"], optional = true } tokio = { version = "1.38", features = ["macros", "rt-multi-thread"], optional = true }
axum = { version = "0.7", optional = true } axum = { version = "0.7", optional = true }
once_cell = { version = "1.19", optional = true } once_cell = { version = "1.19", optional = true }
surrealdb = { version = "1.5", features = ["kv-speedb"], optional = true } surrealdb = { version = "2.0", features = ["kv-rocksdb"], optional = true }
csv = { version = "1.3", optional = true } csv = { version = "1.3", optional = true }

View File

@ -2188,12 +2188,12 @@ input.tab:checked + .tab-content,
} }
} }
.badge-lg { .badge-md {
height: 1.5rem; height: 1.25rem;
font-size: 1rem; font-size: 0.875rem;
line-height: 1.5rem; line-height: 1.25rem;
padding-left: 0.688rem; padding-left: 0.563rem;
padding-right: 0.688rem; padding-right: 0.563rem;
} }
.btn-wide { .btn-wide {
@ -2547,11 +2547,6 @@ input.tab:checked + .tab-content,
gap: 1.25rem; gap: 1.25rem;
} }
.gap-x-2 {
-moz-column-gap: 0.5rem;
column-gap: 0.5rem;
}
.overflow-auto { .overflow-auto {
overflow: auto; overflow: auto;
} }

View File

@ -2,6 +2,7 @@ use dioxus::prelude::*;
use crate::components::layout::icons; use crate::components::layout::icons;
use crate::util::model::member::Member; use crate::util::model::member::Member;
use std::collections::HashMap;
pub fn Auth() -> Element { pub fn Auth() -> Element {
let mut register = use_signal(|| false); let mut register = use_signal(|| false);
@ -80,7 +81,7 @@ fn Login() -> Element {
} }
fn Register() -> Element { fn Register() -> Element {
let mut members: Signal<Vec<Member>> = use_signal(|| vec![]); let mut members: Signal<HashMap<String, Member>> = use_signal(|| HashMap::new());
let mut input_registration_token = use_signal(|| "".to_string()); let mut input_registration_token = use_signal(|| "".to_string());
rsx! { rsx! {
@ -102,7 +103,7 @@ fn Register() -> Element {
class: "btn join-item btn-neutral", class: "btn join-item btn-neutral",
onclick: move |_| async move { onclick: move |_| async move {
if let Ok(res) = fetch_member(input_registration_token()).await { if let Ok(res) = fetch_member(input_registration_token()).await {
members.push(res); members.write().insert(res.id.clone(), res);
input_registration_token.set("".to_string()); input_registration_token.set("".to_string());
} }
}, },
@ -111,10 +112,13 @@ fn Register() -> Element {
} }
} }
div { div {
class: "flex gap-x-2 mt-2 overflow-x-auto pb-3", class: "flex gap-1 mt-2 flex-wrap pb-3",
for member in &*members.read() { for (id, member) in members() {
div { div {
class: "badge badge-lg badge-neutral h-8 gap-1 hover:cursor-pointer hover:line-through whitespace-nowrap", class: "badge badge-md badge-neutral h-8 gap-1 hover:cursor-pointer hover:line-through whitespace-nowrap",
onclick: move |_| {
members.write().remove(&id);
},
"{member.name.full}" "{member.name.full}"
icons::XMark {}, icons::XMark {},
} }

View File

@ -31,7 +31,7 @@ pub struct MembersMigration {
#[cfg(feature = "server")] #[cfg(feature = "server")]
impl Member { impl Member {
pub async fn fetch_all() -> Result<Vec<Self>, surrealdb::Error> { pub async fn fetch_all() -> Result<Vec<Self>, surrealdb::Error> {
let mut res = DB.query("SELECT meta::id(id) as id, name.first, name.full, hours, groups, diploma, registration_token FROM member").await?; let mut res = DB.query("SELECT record::id(id) as id, name.first, name.full, hours, groups, diploma, registration_token FROM member").await?;
let members: Vec<Self> = res.take(0)?; let members: Vec<Self> = res.take(0)?;
@ -43,11 +43,12 @@ impl Member {
pub async fn fetch_from_registration_token( pub async fn fetch_from_registration_token(
registration_token: String, registration_token: String,
) -> Result<Option<Self>, surrealdb::Error> { ) -> Result<Option<Self>, surrealdb::Error> {
let _ = Self::fetch_all().await?; let query = format!("SELECT record::id(id) as id, name.first, name.full, hours, groups, diploma, registration_token FROM ONLY member WHERE registration_token = $registration_token LIMIT 1");
let query = format!("SELECT meta::id(id) as id, name.first, name.full, hours, groups, diploma, registration_token FROM ONLY member WHERE registration_token = {} LIMIT 1", registration_token); let mut res = DB
.query(query)
let mut res = DB.query(query).await?; .bind(("registration_token", registration_token))
.await?;
let member: Option<Self> = res.take(0)?; let member: Option<Self> = res.take(0)?;

View File

@ -4,6 +4,7 @@ use super::{Member, MembersMigration};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::collections::HashMap; use std::collections::HashMap;
use surrealdb::sql::statements::{BeginStatement, CommitStatement};
use tokio::sync::Mutex; use tokio::sync::Mutex;
// Create a store for saving information when migrating to a new members list // Create a store for saving information when migrating to a new members list
@ -135,12 +136,6 @@ impl MembersMigration {
new_members_list: Vec<Member>, new_members_list: Vec<Member>,
current_members_list: Vec<Member>, current_members_list: Vec<Member>,
) -> MembersMigration { ) -> MembersMigration {
tracing::info!(
"Current: {}, New: {}",
current_members_list.len(),
new_members_list.len()
);
let current_members_map: HashMap<String, Member> = current_members_list let current_members_map: HashMap<String, Member> = current_members_list
.clone() .clone()
.into_iter() .into_iter()
@ -214,37 +209,45 @@ impl MembersMigration {
None => return Err("Could not get members from store".into()), None => return Err("Could not get members from store".into()),
}; };
let mut query = String::from("BEGIN TRANSACTION;"); let mut transaction = DB.query(BeginStatement::default());
for member in members_migration.updated.clone() { for member in members_migration.updated.clone() {
// TODO add hours and diploma support // TODO add hours and diploma support
query = query let id = member.id.clone();
+ format!(
"UPDATE member:{} SET name.first = \"{}\", name.full = \"{}\", hours = {:?}, groups = {:?};", transaction = transaction.query(format!("UPDATE type::thing('member', $id_{id}) SET name.first = $name_first_{id}, name.full = $name_full_{id}, hours = $hours_{id}, groups = $groups_{id};"))
member.id, member.name.first, member.name.full, member.hours, member.groups .bind((format!("id_{id}"), member.id))
) .bind((format!("name_first_{id}"), member.name.first))
.as_str(); .bind((format!("name_full_{id}"), member.name.full))
.bind((format!("hours_{id}"), member.hours))
.bind((format!("groups_{id}"), member.groups));
} }
for member in members_migration.inserted.clone() { for member in members_migration.inserted.clone() {
// TODO add hours and diploma support // TODO add hours and diploma support
let id = member.id.clone();
query = query transaction = transaction.query(format!("CREATE type::thing('member', $id_{id}) SET name.first = $name_first_{id}, name.full = $name_full_{id}, hours = $hours_{id}, groups = $groups_{id}, registration_token = rand::string(16);"))
+ format!( .bind((format!("id_{id}"), member.id))
"CREATE member:{} SET name.first = \"{}\", name.full = \"{}\", hours = {:?}, groups = {:?}, registration_token = rand::string(16);", .bind((format!("name_first_{id}"), member.name.first))
member.id, member.name.first, member.name.full, member.hours, member.groups .bind((format!("name_full_{id}"), member.name.full))
) .bind((format!("hours_{id}"), member.hours))
.as_str(); .bind((format!("groups_{id}"), member.groups));
} }
for member in members_migration.removed.clone() { for member in members_migration.removed.clone() {
// TODO add hours and diploma support // TODO add hours and diploma support
query = query + format!("DELETE member:{};", member.id).as_str(); let id = member.id.clone();
transaction = transaction
.query(format!("DELETE type::thing('member', $id_{id});"))
.bind((format!("id_{id}"), member.id));
} }
query = query + "COMMIT TRANSACTION;"; transaction
.query(CommitStatement::default())
DB.query(query).await?; .await?
.check()?;
Ok(()) Ok(())
} }

View File

@ -1,11 +1,11 @@
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use surrealdb::engine::local::{Db, SpeeDb}; use surrealdb::engine::local::{Db, RocksDb};
use surrealdb::Surreal; use surrealdb::Surreal;
pub static DB: Lazy<Surreal<Db>> = Lazy::new(|| Surreal::init()); pub static DB: Lazy<Surreal<Db>> = Lazy::new(|| Surreal::init());
pub async fn initialize() -> surrealdb::Result<()> { pub async fn initialize() -> surrealdb::Result<()> {
DB.connect::<SpeeDb>("./database").await?; DB.connect::<RocksDb>("./database").await?;
DB.use_ns("xvmcmm").use_db("xvmcmm").await?; DB.use_ns("xvmcmm").use_db("xvmcmm").await?;