mongodb on backend
This commit is contained in:
Generated
+1318
-14
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
@@ -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,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user