feat(dash): improved frontend dashboard (#6)
All checks were successful
CI / Format (push) Successful in 6m30s
CI / Clippy (push) Successful in 2m25s
CI / Security Audit (push) Successful in 1m53s
CI / Tests (push) Successful in 2m50s
CI / Deploy (push) Successful in 4s

Co-authored-by: Sharang Parnerkar <parnerkarsharang@gmail.com>
Reviewed-on: #6
This commit was merged in pull request #6.
This commit is contained in:
2026-02-19 11:52:41 +00:00
parent f699976f4d
commit a588be306a
46 changed files with 4960 additions and 261 deletions

View File

@@ -0,0 +1,24 @@
use dioxus::prelude::*;
/// Agents page placeholder for the LangGraph agent builder.
///
/// Shows a "Coming Soon" card with a disabled launch button.
/// Will eventually integrate with the LangGraph framework.
#[component]
pub fn AgentsPage() -> Element {
rsx! {
section { class: "placeholder-page",
div { class: "placeholder-card",
div { class: "placeholder-icon", "A" }
h2 { "Agent Builder" }
p { class: "placeholder-desc",
"Build and manage AI agents with LangGraph. \
Create multi-step reasoning pipelines, tool-using agents, \
and autonomous workflows."
}
button { class: "btn-primary", disabled: true, "Launch Agent Builder" }
span { class: "placeholder-badge", "Coming Soon" }
}
}
}
}

View File

@@ -0,0 +1,65 @@
use dioxus::prelude::*;
use crate::models::AnalyticsMetric;
/// Analytics page placeholder for LangFuse integration.
///
/// Shows a "Coming Soon" card with a disabled launch button,
/// plus a mock stats bar showing sample metrics.
#[component]
pub fn AnalyticsPage() -> Element {
let metrics = mock_metrics();
rsx! {
section { class: "placeholder-page",
div { class: "analytics-stats-bar",
for metric in &metrics {
div { class: "analytics-stat",
span { class: "analytics-stat-value", "{metric.value}" }
span { class: "analytics-stat-label", "{metric.label}" }
span { class: if metric.change_pct >= 0.0 { "analytics-stat-change analytics-stat-change--up" } else { "analytics-stat-change analytics-stat-change--down" },
"{metric.change_pct:+.1}%"
}
}
}
}
div { class: "placeholder-card",
div { class: "placeholder-icon", "L" }
h2 { "Analytics & Observability" }
p { class: "placeholder-desc",
"Monitor and analyze your AI pipelines with LangFuse. \
Track token usage, latency, costs, and quality metrics \
across all your deployments."
}
button { class: "btn-primary", disabled: true, "Launch LangFuse" }
span { class: "placeholder-badge", "Coming Soon" }
}
}
}
}
/// Returns mock analytics metrics for the stats bar.
fn mock_metrics() -> Vec<AnalyticsMetric> {
vec![
AnalyticsMetric {
label: "Total Requests".into(),
value: "12,847".into(),
change_pct: 14.2,
},
AnalyticsMetric {
label: "Avg Latency".into(),
value: "245ms".into(),
change_pct: -8.5,
},
AnalyticsMetric {
label: "Tokens Used".into(),
value: "2.4M".into(),
change_pct: 22.1,
},
AnalyticsMetric {
label: "Error Rate".into(),
value: "0.3%".into(),
change_pct: -12.0,
},
]
}

View File

@@ -0,0 +1,24 @@
use dioxus::prelude::*;
/// Flow page placeholder for the LangFlow visual workflow builder.
///
/// Shows a "Coming Soon" card with a disabled launch button.
/// Will eventually integrate with LangFlow for visual flow design.
#[component]
pub fn FlowPage() -> Element {
rsx! {
section { class: "placeholder-page",
div { class: "placeholder-card",
div { class: "placeholder-icon", "F" }
h2 { "Flow Builder" }
p { class: "placeholder-desc",
"Design visual AI workflows with LangFlow. \
Drag-and-drop nodes to create data processing pipelines, \
prompt chains, and integration flows."
}
button { class: "btn-primary", disabled: true, "Launch Flow Builder" }
span { class: "placeholder-badge", "Coming Soon" }
}
}
}
}

View File

@@ -0,0 +1,41 @@
mod agents;
mod analytics;
mod flow;
pub use agents::*;
pub use analytics::*;
pub use flow::*;
use dioxus::prelude::*;
use crate::app::Route;
use crate::components::sub_nav::{SubNav, SubNavItem};
/// Shell layout for the Developer section.
///
/// Renders a horizontal tab bar (Agents, Flow, Analytics) above
/// the child route outlet. Sits inside the main `AppShell` layout.
#[component]
pub fn DeveloperShell() -> Element {
let tabs = vec![
SubNavItem {
label: "Agents",
route: Route::AgentsPage {},
},
SubNavItem {
label: "Flow",
route: Route::FlowPage {},
},
SubNavItem {
label: "Analytics",
route: Route::AnalyticsPage {},
},
];
rsx! {
div { class: "developer-shell",
SubNav { items: tabs }
div { class: "shell-content", Outlet::<Route> {} }
}
}
}