feat: added langflow, langfuse and langgraph integrations (#17)
Some checks failed
Some checks failed
Co-authored-by: Sharang Parnerkar <parnerkarsharang@gmail.com> Reviewed-on: #17
This commit was merged in pull request #17.
This commit is contained in:
@@ -5,7 +5,7 @@ use dioxus_free_icons::Icon;
|
||||
use crate::components::sidebar::Sidebar;
|
||||
use crate::i18n::{t, tw, Locale};
|
||||
use crate::infrastructure::auth_check::check_auth;
|
||||
use crate::models::AuthInfo;
|
||||
use crate::models::{AuthInfo, ServiceUrlsContext};
|
||||
use crate::Route;
|
||||
|
||||
/// Application shell layout that wraps all authenticated pages.
|
||||
@@ -29,6 +29,16 @@ pub fn AppShell() -> Element {
|
||||
|
||||
match auth_snapshot {
|
||||
Some(Ok(info)) if info.authenticated => {
|
||||
// Provide developer tool URLs as context so child pages
|
||||
// can read them without prop-drilling through layouts.
|
||||
use_context_provider(|| {
|
||||
Signal::new(ServiceUrlsContext {
|
||||
langgraph_url: info.langgraph_url.clone(),
|
||||
langflow_url: info.langflow_url.clone(),
|
||||
langfuse_url: info.langfuse_url.clone(),
|
||||
})
|
||||
});
|
||||
|
||||
let menu_open = *mobile_menu_open.read();
|
||||
let sidebar_cls = if menu_open {
|
||||
"sidebar sidebar--open"
|
||||
|
||||
@@ -9,6 +9,7 @@ mod page_header;
|
||||
mod pricing_card;
|
||||
pub mod sidebar;
|
||||
pub mod sub_nav;
|
||||
mod tool_embed;
|
||||
|
||||
pub use app_shell::*;
|
||||
pub use article_detail::*;
|
||||
@@ -20,3 +21,4 @@ pub use news_card::*;
|
||||
pub use page_header::*;
|
||||
pub use pricing_card::*;
|
||||
pub use sub_nav::*;
|
||||
pub use tool_embed::*;
|
||||
|
||||
81
src/components/tool_embed.rs
Normal file
81
src/components/tool_embed.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
use crate::i18n::{t, Locale};
|
||||
|
||||
/// Properties for the [`ToolEmbed`] component.
|
||||
///
|
||||
/// # Fields
|
||||
///
|
||||
/// * `url` - Service URL; when empty, a "Not Configured" placeholder is shown
|
||||
/// * `title` - Display title for the tool (e.g. "Agent Builder")
|
||||
/// * `description` - Description text shown in the placeholder card
|
||||
/// * `icon` - Single-character icon for the placeholder card
|
||||
/// * `launch_label` - Label for the disabled button in the placeholder
|
||||
#[derive(Props, Clone, PartialEq)]
|
||||
pub struct ToolEmbedProps {
|
||||
/// Service URL. Empty string means "not configured".
|
||||
pub url: String,
|
||||
/// Display title shown in the toolbar / placeholder heading.
|
||||
pub title: String,
|
||||
/// Description shown in the "not configured" placeholder.
|
||||
pub description: String,
|
||||
/// Single-character icon for the placeholder card.
|
||||
pub icon: &'static str,
|
||||
/// Label for the disabled launch button in placeholder mode.
|
||||
pub launch_label: String,
|
||||
}
|
||||
|
||||
/// Hybrid iframe / placeholder component for developer tool pages.
|
||||
///
|
||||
/// When `url` is non-empty, renders a toolbar (title + pop-out button)
|
||||
/// above a full-height iframe embedding the service. When `url` is
|
||||
/// empty, renders the existing placeholder card with a "Not Configured"
|
||||
/// badge instead of "Coming Soon".
|
||||
#[component]
|
||||
pub fn ToolEmbed(props: ToolEmbedProps) -> Element {
|
||||
let locale = use_context::<Signal<Locale>>();
|
||||
let l = *locale.read();
|
||||
|
||||
if props.url.is_empty() {
|
||||
// Not configured -- show placeholder card
|
||||
rsx! {
|
||||
section { class: "placeholder-page",
|
||||
div { class: "placeholder-card",
|
||||
div { class: "placeholder-icon", "{props.icon}" }
|
||||
h2 { "{props.title}" }
|
||||
p { class: "placeholder-desc", "{props.description}" }
|
||||
button {
|
||||
class: "btn-primary",
|
||||
disabled: true,
|
||||
"{props.launch_label}"
|
||||
}
|
||||
span { class: "placeholder-badge",
|
||||
"{t(l, \"developer.not_configured\")}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// URL is set -- render toolbar + iframe
|
||||
let pop_out_url = props.url.clone();
|
||||
rsx! {
|
||||
div { class: "tool-embed",
|
||||
div { class: "tool-embed-toolbar",
|
||||
span { class: "tool-embed-title", "{props.title}" }
|
||||
a {
|
||||
class: "tool-embed-popout-btn",
|
||||
href: "{pop_out_url}",
|
||||
target: "_blank",
|
||||
rel: "noopener noreferrer",
|
||||
"{t(l, \"developer.open_new_tab\")}"
|
||||
}
|
||||
}
|
||||
iframe {
|
||||
class: "tool-embed-iframe",
|
||||
src: "{props.url}",
|
||||
title: "{props.title}",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user