mongodb on backend

This commit is contained in:
2025-07-14 12:40:14 +02:00
parent 9ec2b535b8
commit 2da5c1e9e2
7 changed files with 1419 additions and 68 deletions
Generated
+1318 -14
View File
File diff suppressed because it is too large Load Diff
+5
View File
@@ -13,12 +13,17 @@ lucide-dioxus = { version = "2.15.0", features = ["all-icons"] }
wasm-bindgen = "0.2.100" wasm-bindgen = "0.2.100"
web-sys = "0.3.77" web-sys = "0.3.77"
serde = { version = "1.0.61", features = ["derive"]} serde = { version = "1.0.61", features = ["derive"]}
mongodb = {version = "3.2.4", optional = true}
features = "0.10.0"
futures-util = "0.3.31"
regex = "1.11.1"
[features] [features]
default = ["web"] default = ["web"]
web = ["dioxus/web"] web = ["dioxus/web"]
desktop = ["dioxus/desktop"] desktop = ["dioxus/desktop"]
mobile = ["dioxus/mobile"] mobile = ["dioxus/mobile"]
server = ["dioxus/server", "dep:mongodb"]
[profile.wasm-dev] [profile.wasm-dev]
inherits = "dev" inherits = "dev"
+2 -1
View File
@@ -82,10 +82,11 @@
border-radius: 7px; border-radius: 7px;
margin-top: auto; margin-top: auto;
margin-bottom: auto; margin-bottom: auto;
color: var(--fg);
} }
.server-heading button:hover { .server-heading button:hover {
background-color: #f1f5f9; background-color: var(--bg);
} }
.server-monitor h2 { .server-monitor h2 {
+1 -1
View File
@@ -99,7 +99,7 @@
/* Misc */ /* Misc */
--bg: #000000; /* pure black */ --bg: #000000; /* pure black */
--fg: #ffffff; /* pure white */ --fg: #ffffff; /* pure white */
--card-bg: #0e0e0e; /* almost black card */ --card-bg: #141414; /* almost black card */
--progress-bg: #1a1a1a; /* very dark grey */ --progress-bg: #1a1a1a; /* very dark grey */
--server-icon-bg: #111111; /* dark grey */ --server-icon-bg: #111111; /* dark grey */
--fg-selected: #f8fafc; --fg-selected: #f8fafc;
+63 -40
View File
@@ -1,6 +1,49 @@
use crate::components::server::Server;
use dioxus::prelude::*; use dioxus::prelude::*;
use crate::components::server::Server; #[cfg(feature = "server")]
use futures_util::stream::TryStreamExt;
#[cfg(feature = "server")]
const DB_URL: &'static str = "mongodb://admin:admin@localhost/";
#[cfg(feature = "server")]
pub async fn get_mongo<T: Send + Sync>(
collection: &str,
) -> Result<mongodb::Collection<T>, mongodb::error::Error> {
let client = mongodb::Client::with_uri_str(DB_URL).await?;
Ok(client.database("sentryx").collection(collection))
}
#[cfg(feature = "server")]
fn parse_search_query(input: &str) -> Vec<String> {
let re = regex::Regex::new(r#""([^"]+)"|(\S+)"#).unwrap();
re.captures_iter(input)
.filter_map(|cap| cap.get(1).or_else(|| cap.get(2)))
.map(|m| m.as_str().to_string())
.collect()
}
#[cfg(feature = "server")]
fn build_or_filter(input: &str, fields: &[&str]) -> mongodb::bson::Document {
let phrases = parse_search_query(input);
let mut or_clauses = Vec::new();
for phrase in phrases {
for &field in fields {
or_clauses.push(mongodb::bson::doc! {
field: mongodb::bson::Regex {
pattern: phrase.clone(),
options: "i".into(), // case-insensitive
}
});
}
}
mongodb::bson::doc! { "$or": or_clauses }
}
#[server] #[server]
pub async fn log_in(username: String, password: String) -> Result<String, ServerFnError> { pub async fn log_in(username: String, password: String) -> Result<String, ServerFnError> {
@@ -8,43 +51,23 @@ pub async fn log_in(username: String, password: String) -> Result<String, Server
} }
#[server] #[server]
pub async fn get_servers() -> Result<Vec<Server>, ServerFnError> { pub async fn get_servers(search: String) -> Result<Vec<Server>, ServerFnError> {
Ok(vec![ let servers = get_mongo::<Server>("servers").await?;
Server {
name: "Main Server".to_string(), let filter = if search.trim().is_empty() {
status: crate::components::server::Status::Online, mongodb::bson::doc! {}
ip: "10.0.0.5".to_string(), } else {
cpu: 95, build_or_filter(&search, &["name", "ip"])
memory: 60, };
storage: 43,
network: 88,
}, let mut cursor = servers.find(filter).await?;
Server {
name: "Cache Node".to_string(), let mut svo = Vec::new();
status: crate::components::server::Status::Warning,
ip: "192.168.1.12".to_string(), while let Some(doc) = cursor.try_next().await? {
cpu: 47, svo.push(doc);
memory: 72, }
storage: 81,
network: 34, Ok(svo)
},
Server {
name: "Database".to_string(),
status: crate::components::server::Status::Offline,
ip: "172.16.254.3".to_string(),
cpu: 12,
memory: 90,
storage: 22,
network: 10,
},
Server {
name: "Backup Node".to_string(),
status: crate::components::server::Status::Maintenance,
ip: "192.168.100.22".to_string(),
cpu: 83,
memory: 41,
storage: 96,
network: 70,
},
])
} }
+1 -1
View File
@@ -91,7 +91,7 @@ pub fn ServerComponent(server: Server) -> Element {
fn get_level(i: u8) -> String { fn get_level(i: u8) -> String {
if i > 80 { if i > 80 {
String::from("high") String::from("high")
} else if i > 30 { } else if i > 50 {
String::from("medium") String::from("medium")
} else { } else {
String::from("low") String::from("low")
+27 -9
View File
@@ -10,13 +10,16 @@ const DASHBOARD_CSS: Asset = asset!("/assets/styles/dashboard.css");
#[component] #[component]
pub fn Dashboard() -> Element { pub fn Dashboard() -> Element {
let servers = use_resource(move || async move { let mut servers = use_signal(|| Vec::new());
if let Ok(v) = backend::get_servers().await { let server_search = use_signal(|| String::new());
v
} else { use_effect(move || {
Vec::new() spawn(async move {
if let Ok(v) = backend::get_servers(String::new()).await {
servers.set(v);
} }
}); });
});
rsx! { rsx! {
document::Link { rel: "stylesheet", href: DASHBOARD_CSS } document::Link { rel: "stylesheet", href: DASHBOARD_CSS }
@@ -101,7 +104,24 @@ pub fn Dashboard() -> Element {
div { class: "search-container", div { class: "search-container",
div { class: "search-input", div { class: "search-input",
lucide_dioxus::Search { size: 16, color: "currentColor" } lucide_dioxus::Search { size: 16, color: "currentColor" }
input { placeholder: "Search servers by name, location, or IP..." } input {
onchange: {let mut server_search = server_search.clone(); move |e: Event<FormData>| {server_search.set(e.value())}},
onkeypress: {
let server_search = server_search.clone();
let mut servers = servers.clone();
move |e: Event<KeyboardData>| {
let query = (*server_search.read()).clone();
async move {
if e.key() == Key::Enter {
if let Ok(v) = backend::get_servers(query).await {
servers.set(v);
}
}
}
}
},
placeholder: "Search servers by name, location, or IP..." }
} }
button { class: "fg", "All (4)" } button { class: "fg", "All (4)" }
button { class: "online", "Online (3)" } button { class: "online", "Online (3)" }
@@ -111,8 +131,7 @@ pub fn Dashboard() -> Element {
} }
div { class: "server-container", div { class: "server-container",
if let Some(ss) = servers.read().clone() { for s in (*servers.read()).clone() {
for s in ss {
ServerComponent { server: s } ServerComponent { server: s }
} }
} }
@@ -120,4 +139,3 @@ pub fn Dashboard() -> Element {
} }
} }
} }
}