All checks were successful
Use dioxus_free_icons Bootstrap icons: BsCpu for hero, BsBook for docs, BsLightningCharge for getting started, BsGithub for GitHub, BsCodeSquare for examples, BsBoxArrowUpRight for API reference. Also fix conditional serde import for server feature. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
241 lines
9.9 KiB
Rust
241 lines
9.9 KiB
Rust
use dioxus::prelude::*;
|
|
use dioxus_free_icons::icons::bs_icons::{
|
|
BsBook, BsBoxArrowUpRight, BsCodeSquare, BsCpu, BsGithub, BsLightningCharge,
|
|
};
|
|
use dioxus_free_icons::Icon;
|
|
|
|
use crate::i18n::{t, Locale};
|
|
use crate::models::ServiceUrlsContext;
|
|
|
|
/// Agents informational landing page for LangGraph.
|
|
///
|
|
/// Since LangGraph is API-only (no web UI), this page displays a hero section
|
|
/// explaining its role, a connection status indicator, a card grid linking
|
|
/// to documentation, and a live table of registered agents fetched from the
|
|
/// LangGraph assistants API.
|
|
#[component]
|
|
pub fn AgentsPage() -> Element {
|
|
let locale = use_context::<Signal<Locale>>();
|
|
let svc = use_context::<Signal<ServiceUrlsContext>>();
|
|
let l = *locale.read();
|
|
let url = svc.read().langgraph_url.clone();
|
|
|
|
// Derive whether a LangGraph URL is configured
|
|
let connected = !url.is_empty();
|
|
// Build the API reference URL from the configured base, falling back to "#"
|
|
let api_ref_href = if connected {
|
|
format!("{}/docs", url)
|
|
} else {
|
|
"#".to_string()
|
|
};
|
|
|
|
// Fetch agents from LangGraph when connected
|
|
let agents_resource = use_resource(move || async move {
|
|
match crate::infrastructure::langgraph::list_langgraph_agents().await {
|
|
Ok(agents) => agents,
|
|
Err(e) => {
|
|
tracing::error!("Failed to fetch agents: {e}");
|
|
Vec::new()
|
|
}
|
|
}
|
|
});
|
|
|
|
rsx! {
|
|
div { class: "agents-page",
|
|
// -- Hero section --
|
|
div { class: "agents-hero",
|
|
div { class: "agents-hero-row",
|
|
div { class: "agents-hero-icon",
|
|
Icon { icon: BsCpu, width: 24, height: 24 }
|
|
}
|
|
h2 { class: "agents-hero-title",
|
|
{t(l, "developer.agents_title")}
|
|
}
|
|
}
|
|
p { class: "agents-hero-desc",
|
|
{t(l, "developer.agents_desc")}
|
|
}
|
|
|
|
// -- Connection status --
|
|
if connected {
|
|
div { class: "agents-status",
|
|
span {
|
|
class: "agents-status-dot agents-status-dot--on",
|
|
}
|
|
span { {t(l, "developer.agents_status_connected")} }
|
|
code { class: "agents-status-url", {url.clone()} }
|
|
}
|
|
} else {
|
|
div { class: "agents-status",
|
|
span {
|
|
class: "agents-status-dot agents-status-dot--off",
|
|
}
|
|
span { {t(l, "developer.agents_status_not_connected")} }
|
|
span { class: "agents-status-hint",
|
|
{t(l, "developer.agents_config_hint")}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// -- Running Agents table --
|
|
div { class: "agents-table-section",
|
|
h3 { class: "agents-section-title",
|
|
{t(l, "developer.agents_running_title")}
|
|
}
|
|
|
|
match agents_resource.read().as_ref() {
|
|
None => {
|
|
rsx! {
|
|
p { class: "agents-table-loading",
|
|
{t(l, "common.loading")}
|
|
}
|
|
}
|
|
}
|
|
Some(agents) if agents.is_empty() => {
|
|
rsx! {
|
|
p { class: "agents-table-empty",
|
|
{t(l, "developer.agents_none")}
|
|
}
|
|
}
|
|
}
|
|
Some(agents) => {
|
|
rsx! {
|
|
div { class: "agents-table-wrap",
|
|
table { class: "agents-table",
|
|
thead {
|
|
tr {
|
|
th { {t(l, "developer.agents_col_name")} }
|
|
th { {t(l, "developer.agents_col_id")} }
|
|
th { {t(l, "developer.agents_col_description")} }
|
|
th { {t(l, "developer.agents_col_status")} }
|
|
}
|
|
}
|
|
tbody {
|
|
for agent in agents.iter() {
|
|
tr { key: "{agent.id}",
|
|
td { class: "agents-cell-name",
|
|
{agent.name.clone()}
|
|
}
|
|
td {
|
|
code { class: "agents-cell-id",
|
|
{agent.id.clone()}
|
|
}
|
|
}
|
|
td { class: "agents-cell-desc",
|
|
if agent.description.is_empty() {
|
|
span { class: "agents-cell-none", "--" }
|
|
} else {
|
|
{agent.description.clone()}
|
|
}
|
|
}
|
|
td {
|
|
span { class: "agents-badge agents-badge--active",
|
|
{agent.status.clone()}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// -- Quick Start card grid --
|
|
h3 { class: "agents-section-title",
|
|
{t(l, "developer.agents_quick_start")}
|
|
}
|
|
|
|
div { class: "agents-grid",
|
|
// Documentation
|
|
a {
|
|
class: "agents-card",
|
|
href: "https://langchain-ai.github.io/langgraph/",
|
|
target: "_blank",
|
|
rel: "noopener noreferrer",
|
|
div { class: "agents-card-icon",
|
|
Icon { icon: BsBook, width: 18, height: 18 }
|
|
}
|
|
div { class: "agents-card-title",
|
|
{t(l, "developer.agents_docs")}
|
|
}
|
|
div { class: "agents-card-desc",
|
|
{t(l, "developer.agents_docs_desc")}
|
|
}
|
|
}
|
|
|
|
// Getting Started
|
|
a {
|
|
class: "agents-card",
|
|
href: "https://langchain-ai.github.io/langgraph/tutorials/introduction/",
|
|
target: "_blank",
|
|
rel: "noopener noreferrer",
|
|
div { class: "agents-card-icon",
|
|
Icon { icon: BsLightningCharge, width: 18, height: 18 }
|
|
}
|
|
div { class: "agents-card-title",
|
|
{t(l, "developer.agents_getting_started")}
|
|
}
|
|
div { class: "agents-card-desc",
|
|
{t(l, "developer.agents_getting_started_desc")}
|
|
}
|
|
}
|
|
|
|
// GitHub
|
|
a {
|
|
class: "agents-card",
|
|
href: "https://github.com/langchain-ai/langgraph",
|
|
target: "_blank",
|
|
rel: "noopener noreferrer",
|
|
div { class: "agents-card-icon",
|
|
Icon { icon: BsGithub, width: 18, height: 18 }
|
|
}
|
|
div { class: "agents-card-title",
|
|
{t(l, "developer.agents_github")}
|
|
}
|
|
div { class: "agents-card-desc",
|
|
{t(l, "developer.agents_github_desc")}
|
|
}
|
|
}
|
|
|
|
// Examples
|
|
a {
|
|
class: "agents-card",
|
|
href: "https://github.com/langchain-ai/langgraph/tree/main/examples",
|
|
target: "_blank",
|
|
rel: "noopener noreferrer",
|
|
div { class: "agents-card-icon",
|
|
Icon { icon: BsCodeSquare, width: 18, height: 18 }
|
|
}
|
|
div { class: "agents-card-title",
|
|
{t(l, "developer.agents_examples")}
|
|
}
|
|
div { class: "agents-card-desc",
|
|
{t(l, "developer.agents_examples_desc")}
|
|
}
|
|
}
|
|
|
|
// API Reference (disabled when URL is empty)
|
|
a {
|
|
class: if connected { "agents-card" } else { "agents-card agents-card--disabled" },
|
|
href: "{api_ref_href}",
|
|
target: "_blank",
|
|
rel: "noopener noreferrer",
|
|
div { class: "agents-card-icon",
|
|
Icon { icon: BsBoxArrowUpRight, width: 18, height: 18 }
|
|
}
|
|
div { class: "agents-card-title",
|
|
{t(l, "developer.agents_api_ref")}
|
|
}
|
|
div { class: "agents-card-desc",
|
|
{t(l, "developer.agents_api_ref_desc")}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|