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"
web-sys = "0.3.77"
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]
default = ["web"]
web = ["dioxus/web"]
desktop = ["dioxus/desktop"]
mobile = ["dioxus/mobile"]
server = ["dioxus/server", "dep:mongodb"]
[profile.wasm-dev]
inherits = "dev"
+2 -1
View File
@@ -82,10 +82,11 @@
border-radius: 7px;
margin-top: auto;
margin-bottom: auto;
color: var(--fg);
}
.server-heading button:hover {
background-color: #f1f5f9;
background-color: var(--bg);
}
.server-monitor h2 {
+1 -1
View File
@@ -99,7 +99,7 @@
/* Misc */
--bg: #000000; /* pure black */
--fg: #ffffff; /* pure white */
--card-bg: #0e0e0e; /* almost black card */
--card-bg: #141414; /* almost black card */
--progress-bg: #1a1a1a; /* very dark grey */
--server-icon-bg: #111111; /* dark grey */
--fg-selected: #f8fafc;
+63 -40
View File
@@ -1,6 +1,49 @@
use crate::components::server::Server;
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]
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]
pub async fn get_servers() -> Result<Vec<Server>, ServerFnError> {
Ok(vec![
Server {
name: "Main Server".to_string(),
status: crate::components::server::Status::Online,
ip: "10.0.0.5".to_string(),
cpu: 95,
memory: 60,
storage: 43,
network: 88,
},
Server {
name: "Cache Node".to_string(),
status: crate::components::server::Status::Warning,
ip: "192.168.1.12".to_string(),
cpu: 47,
memory: 72,
storage: 81,
network: 34,
},
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,
},
])
pub async fn get_servers(search: String) -> Result<Vec<Server>, ServerFnError> {
let servers = get_mongo::<Server>("servers").await?;
let filter = if search.trim().is_empty() {
mongodb::bson::doc! {}
} else {
build_or_filter(&search, &["name", "ip"])
};
let mut cursor = servers.find(filter).await?;
let mut svo = Vec::new();
while let Some(doc) = cursor.try_next().await? {
svo.push(doc);
}
Ok(svo)
}
+1 -1
View File
@@ -91,7 +91,7 @@ pub fn ServerComponent(server: Server) -> Element {
fn get_level(i: u8) -> String {
if i > 80 {
String::from("high")
} else if i > 30 {
} else if i > 50 {
String::from("medium")
} else {
String::from("low")
+27 -9
View File
@@ -10,13 +10,16 @@ const DASHBOARD_CSS: Asset = asset!("/assets/styles/dashboard.css");
#[component]
pub fn Dashboard() -> Element {
let servers = use_resource(move || async move {
if let Ok(v) = backend::get_servers().await {
v
} else {
Vec::new()
let mut servers = use_signal(|| Vec::new());
let server_search = use_signal(|| String::new());
use_effect(move || {
spawn(async move {
if let Ok(v) = backend::get_servers(String::new()).await {
servers.set(v);
}
});
});
rsx! {
document::Link { rel: "stylesheet", href: DASHBOARD_CSS }
@@ -101,7 +104,24 @@ pub fn Dashboard() -> Element {
div { class: "search-container",
div { class: "search-input",
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: "online", "Online (3)" }
@@ -111,13 +131,11 @@ pub fn Dashboard() -> Element {
}
div { class: "server-container",
if let Some(ss) = servers.read().clone() {
for s in ss {
for s in (*servers.read()).clone() {
ServerComponent { server: s }
}
}
}
}
}
}
}