From 20c732477decbafe0f06e8d731aaaae0f5343a04 Mon Sep 17 00:00:00 2001 From: Maxime Van Hees Date: Thu, 25 Jul 2024 10:43:20 +0200 Subject: [PATCH] Searching functionality for peers --- mycelium-ui/assets/styles.css | 24 +++++++++++++++ mycelium-ui/src/main.rs | 58 +++++++++++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/mycelium-ui/assets/styles.css b/mycelium-ui/assets/styles.css index 9002107..8a2ba0c 100644 --- a/mycelium-ui/assets/styles.css +++ b/mycelium-ui/assets/styles.css @@ -283,3 +283,27 @@ h2 { color: #f39c12; margin-bottom: 1rem; } + +/* Searching */ +.search-container { + display: flex; + margin-bottom: 1rem; +} + +.search-container input { + flex-grow: 1; + padding: 0.5rem; + font-size: 1rem; + border: 1px solid var(--border-color); + border-radius: 4px 0 0 4px; +} + +.search-container select { + padding: 0.5rem; + font-size: 1rem; + border: 1px solid var(--border-color); + border-left: none; + border-radius: 0 4px 4px 0; + background-color: white; +} + diff --git a/mycelium-ui/src/main.rs b/mycelium-ui/src/main.rs index 8dcc9ad..d6ebda2 100644 --- a/mycelium-ui/src/main.rs +++ b/mycelium-ui/src/main.rs @@ -6,6 +6,7 @@ use dioxus::prelude::*; use dioxus_free_icons::icons::fa_solid_icons::FaChevronLeft; use dioxus_free_icons::Icon; use mycelium::peer_manager::PeerType; +use std::collections::HashMap; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::{cmp::Ordering, str::FromStr}; use tracing::Level; @@ -30,6 +31,12 @@ pub enum Route { PageNotFound { route: Vec }, } +#[derive(Clone, PartialEq)] +struct SearchState { + query: String, + column: String, +} + fn main() { // Init logger dioxus_logger::init(Level::INFO).expect("failed to init logger"); @@ -105,7 +112,6 @@ fn Sidebar(collapsed: Signal) -> Element { #[component] fn Home() -> Element { - // let mut server_state = use_context::>(); let mut server_state_addr = use_signal(|| DEFAULT_SERVER_ADDR.to_string()); let mut server_state_connected = use_signal(|| false); let mut new_address = use_signal(|| DEFAULT_SERVER_ADDR.to_string()); @@ -134,7 +140,7 @@ fn Home() -> Element { } }); - // Executed when we press the connect button + // Executed when connect button is clicked let try_connect = move |_| { let new_addr = new_address.read().to_string(); server_state_addr.write().clone_from(&new_addr); // will trigger fetch_node_info @@ -295,13 +301,59 @@ fn PeersTable(peers: Vec) -> Element { sorted }); + // Searching + let mut search_state = use_signal(|| SearchState { + query: String::new(), + column: "Endpoint".to_string(), + }); + + let filtered_peers = use_memo(move || { + let query = search_state.read().query.to_lowercase(); + let column = &search_state.read().column; + sorted_peers + .read() + .iter() + .filter(|peer| match column.as_str() { + "Endpoint" => peer.endpoint.to_string().to_lowercase().contains(&query), + "Type" => peer.pt.to_string().to_lowercase().contains(&query), + "Connection State" => peer + .connection_state + .to_string() + .to_lowercase() + .contains(&query), + "Tx bytes" => peer.tx_bytes.to_string().to_lowercase().contains(&query), + "Rx bytes" => peer.rx_bytes.to_string().to_lowercase().contains(&query), + _ => false, + }) + .cloned() + .collect::>() + }); + + let peers_len = filtered_peers.read().len(); + let start = current_page * items_per_page; let end = (start + items_per_page).min(peers_len); - let current_peers = &sorted_peers.read()[start..end]; + let current_peers = &filtered_peers.read()[start..end]; rsx! { div { class: "peers-table", h2 { "Peers" } + div { class: "search-container", + input { + placeholder: "Search...", + value: "{search_state.read().query}", + oninput: move |evt| search_state.write().query.clone_from(&evt.value()), + } + select { + value: "{search_state.read().column}", + onchange: move |evt| search_state.write().column.clone_from(&evt.value()), + option { value: "Endpoint", "Endpoint" } + option { value: "Type", "Type" } + option { value: "Connection State", "Connection State" } + option { value: "Tx bytes", "Tx bytes" } + option { value: "Rx bytes", "Rx bytes" } + } + } div { class: "table-container", table { thead {