From 1f96cbcba6f4eea70758858031963542839d3fa3 Mon Sep 17 00:00:00 2001 From: xeovalyte Date: Thu, 11 Apr 2024 08:48:11 +0200 Subject: [PATCH] Added live updating timings --- application/src/components/participants.rs | 77 +++++++++++++--------- application/src/pages/add_participant.rs | 2 +- application/src/pages/add_time.rs | 50 +------------- application/src/util/surrealdb.rs | 1 + application/src/util/surrealdb/client.rs | 57 ++++++++++++++++ application/src/util/surrealdb/schemas.rs | 2 +- application/src/util/websocket/client.rs | 33 ++++------ application/style/index.scss | 31 +++++++++ 8 files changed, 151 insertions(+), 102 deletions(-) create mode 100644 application/src/util/surrealdb/client.rs diff --git a/application/src/components/participants.rs b/application/src/components/participants.rs index 77c4108..31c7c44 100644 --- a/application/src/components/participants.rs +++ b/application/src/components/participants.rs @@ -1,4 +1,4 @@ -use crate::util::surrealdb::schemas; +use crate::util::surrealdb::{client::sort_participants, client::Time, schemas}; use leptos::*; /// Renders the home page of your application. @@ -6,40 +6,53 @@ use leptos::*; pub fn Participants() -> impl IntoView { let participants_context = use_context::().unwrap(); + let name = create_rw_signal("".to_string()); + + let participants_sorted = + create_memo(move |_| sort_participants(participants_context.get(), name.get())); + view! { -
- + +
+ + + + + + + + - - - - - - - - - - - { move || match child.value.get().events { - Some(events) => view! { - - - - }, - None => view! { - - - - } + + + { move || match child.value.get().events { + Some(events) => view! { + + + + }, + None => view! { + + + } } - - -
"Naam""Groep""Lifesaver""Hindernis""Popduiken"
"Naam""Groep""Lifesaver""Hindernis""Popduiken"
{ move || child.value.get().name }{ move || child.value.get().group }{ events.lifesaver.unwrap_or(0) }{ events.hindernis.unwrap_or(0) }{ events.popduiken.unwrap_or(0) }"0""0""0"{ move || child.value.get().name }{ move || child.value.get().group }{ Time::from_milliseconds_to_string(events.lifesaver.unwrap_or(0)) }{ Time::from_milliseconds_to_string(events.hindernis.unwrap_or(0)) }{ Time::from_milliseconds_to_string(events.popduiken.unwrap_or(0)) }"0""0""0"
-
+ } + + + } } diff --git a/application/src/pages/add_participant.rs b/application/src/pages/add_participant.rs index c0e196e..c59af0b 100644 --- a/application/src/pages/add_participant.rs +++ b/application/src/pages/add_participant.rs @@ -30,7 +30,7 @@ async fn add_participant(name: String, group: String) -> Result<(), ServerFnErro participant: schemas::Participant { name: participant.name.clone(), group: participant.group.clone(), - id: participant.id.to_string(), + id: participant.id.id.to_string(), events: participant.events.clone(), }, }; diff --git a/application/src/pages/add_time.rs b/application/src/pages/add_time.rs index a0bb117..d0aa737 100644 --- a/application/src/pages/add_time.rs +++ b/application/src/pages/add_time.rs @@ -1,7 +1,6 @@ -use crate::util::surrealdb::schemas; +use crate::util::surrealdb::{client::sort_participants, client::Time, schemas}; use leptos::{ev::keydown, *}; use leptos_use::*; -use strsim::normalized_damerau_levenshtein; use web_sys::ScrollIntoViewOptions; cfg_if::cfg_if! { @@ -13,19 +12,6 @@ cfg_if::cfg_if! { } } -#[derive(Clone)] -struct Time { - minutes: u32, - seconds: u32, - milliseconds: u32, -} - -impl Time { - fn as_milliseconds(&self) -> u32 { - self.minutes * 60 * 1000 + self.seconds * 1000 + self.milliseconds * 10 - } -} - #[server(AddTime)] async fn add_time( mut participant: schemas::Participant, @@ -96,7 +82,7 @@ pub fn AddTime() -> impl IntoView { let participant = &participants_sorted.get()[selected_index.get()]; add_time_action.dispatch(( - participant.clone(), + participant.value.get(), event.get(), time.get().as_milliseconds(), )); @@ -165,7 +151,7 @@ pub fn AddTime() -> impl IntoView { /> @@ -227,33 +213,3 @@ pub fn SelectOption(is: &'static str, value: ReadSignal) -> impl IntoVie } } -fn sort_participants( - participants: Vec, - search: String, -) -> Vec { - let mut filtered_sorted_list: Vec<(schemas::Participant, f64)> = participants - .into_iter() - .map(|participant| { - ( - participant.value.get(), - normalized_damerau_levenshtein( - &participant.value.get().name.to_lowercase(), - &search.to_lowercase(), - ), - ) - }) - .collect(); - - filtered_sorted_list.sort_by(|a, b| { - let (_, sim_score_a) = a; - let (_, sim_score_b) = b; - sim_score_b - .partial_cmp(sim_score_a) - .unwrap_or(std::cmp::Ordering::Equal) - }); - - filtered_sorted_list - .into_iter() - .map(|(item, _)| item) - .collect() -} diff --git a/application/src/util/surrealdb.rs b/application/src/util/surrealdb.rs index 0fe1718..4cad407 100644 --- a/application/src/util/surrealdb.rs +++ b/application/src/util/surrealdb.rs @@ -1,5 +1,6 @@ use leptos::*; +pub mod client; pub mod schemas; cfg_if::cfg_if! { diff --git a/application/src/util/surrealdb/client.rs b/application/src/util/surrealdb/client.rs new file mode 100644 index 0000000..ece0cb3 --- /dev/null +++ b/application/src/util/surrealdb/client.rs @@ -0,0 +1,57 @@ +use crate::util::surrealdb::schemas; +use leptos::*; +use strsim::normalized_damerau_levenshtein; + +#[derive(Clone)] +pub struct Time { + pub minutes: u32, + pub seconds: u32, + pub milliseconds: u32, +} + +impl Time { + pub fn as_milliseconds(&self) -> u32 { + self.minutes * 60 * 1000 + self.seconds * 1000 + self.milliseconds * 10 + } + + pub fn from_milliseconds_to_string(mut time: u32) -> String { + let milliseconds = (time % 1000) / 10; + time /= 1000; + let seconds = time % 60; + time /= 60; + let minutes = time; + + format!("{minutes}:{seconds}:{milliseconds}") + } +} + +pub fn sort_participants( + participants: Vec, + search: String, +) -> Vec { + let mut filtered_sorted_list: Vec<(schemas::ParticipantSignal, f64)> = participants + .into_iter() + .map(|participant| { + ( + participant.clone(), + normalized_damerau_levenshtein( + &participant.value.get().name.to_lowercase(), + &search.to_lowercase(), + ), + ) + }) + .collect(); + + filtered_sorted_list.sort_by(|a, b| { + let (_, sim_score_a) = a; + let (_, sim_score_b) = b; + sim_score_b + .partial_cmp(sim_score_a) + .unwrap_or(std::cmp::Ordering::Equal) + }); + + filtered_sorted_list + .into_iter() + .map(|(item, _)| item) + .collect() +} diff --git a/application/src/util/surrealdb/schemas.rs b/application/src/util/surrealdb/schemas.rs index 2ccd416..cbd9dd5 100644 --- a/application/src/util/surrealdb/schemas.rs +++ b/application/src/util/surrealdb/schemas.rs @@ -31,7 +31,7 @@ pub struct Participant { pub events: Option, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct ParticipantSignal { pub id: String, pub value: RwSignal, diff --git a/application/src/util/websocket/client.rs b/application/src/util/websocket/client.rs index 3a8f077..cacda51 100644 --- a/application/src/util/websocket/client.rs +++ b/application/src/util/websocket/client.rs @@ -12,22 +12,17 @@ pub fn init_websocket() { } = use_websocket("ws://localhost:3000/ws"); provide_context(ready_state); + let participants_context = use_context::().unwrap(); + let owner = Owner::current().unwrap(); - create_effect(move |prev_value| { - let msg = message.get(); - - if prev_value != Some(msg.clone()) { - match msg { - Some(ref text) => handle_message(text), - None => (), - } + create_effect(move |_| { + if let Some(m) = message.get() { + with_owner(owner, || handle_message(&participants_context, &m)); } - - msg }); } -fn handle_message(message: &str) { +fn handle_message(&participants_context: &schemas::ParticipantsContext, message: &str) { let action: ParticipantsAction = match serde_json::from_str(message) { Ok(res) => res, Err(_err) => { @@ -37,8 +32,6 @@ fn handle_message(message: &str) { logging::log!("Recieved action: {:?}", action); - let participants_context = use_context::().unwrap(); - match action { ParticipantsAction::Add { participant } => participants_context.update(|participants| { participants.push(schemas::ParticipantSignal { @@ -49,15 +42,13 @@ fn handle_message(message: &str) { ParticipantsAction::Remove { id } => participants_context .update(|participants| participants.retain(|participant| participant.id != id)), ParticipantsAction::Replace { participant } => { - participants_context.with(|participants| { - for participant_signal in participants { - if participant_signal.id == participant.id { - participant_signal.value.update(|value| { - *value = participant.clone(); - }) - } + let participants = participants_context.get(); + for participant_signal in participants { + if participant_signal.id == participant.id { + participant_signal.value.set(participant); + break; } - }); + } } } } diff --git a/application/style/index.scss b/application/style/index.scss index 425d60a..c9c58f2 100644 --- a/application/style/index.scss +++ b/application/style/index.scss @@ -24,3 +24,34 @@ a { background-color: $secondary-bg-color-light; } +.participants-search { + margin-top: 40px; + width: 100%; +} + +.participants-table { + margin-top: 0px; + width: 100%; + border-collapse: collapse; +} + +.participants-table th { + position: sticky; + background-color: $secondary-bg-color-lighter; + z-index: 100; + top: 0; +} + +.participants-table th,td { + text-align: left; + padding: 8px 8px; +} + +.participants-table tr:hover { + background-color: $secondary-color !important; + cursor: pointer; +} + +.participants-table tr:nth-child(odd) { + background-color: $secondary-bg-color-light; +}