diff --git a/crates/webui/src/components/component_detail.rs b/crates/webui/src/components/component_detail.rs index 88899da..e90a0d4 100644 --- a/crates/webui/src/components/component_detail.rs +++ b/crates/webui/src/components/component_detail.rs @@ -184,11 +184,16 @@ fn component_file_sources(files: &[ComponentFileRef]) -> Vec { return None; } let file = &file_ref.file; + let content = if role == ComponentFileRole::WasmComponent { + SourceContent::Binary + } else { + SourceContent::FetchFile { + digest: file.digest.clone(), + } + }; Some(SourceView { file_name: file.path.clone(), - content: SourceContent::FetchFile { - digest: file.digest.clone(), - }, + content, metadata: Some(SourceMetadata { role: component_file_role_label(role), entrypoint: role == ComponentFileRole::JsEntrypoint, @@ -269,6 +274,7 @@ pub fn component_detail( let wit_state = use_state(|| None); let wit_loaded = use_state(|| false); let selected_tab = use_state(|| ComponentDetailTab::Exports); + let show_extensions = use_state(|| false); let deployment_config = use_state(|| None::, String>>); // Fetch raw WIT only when its tab is selected. @@ -390,7 +396,18 @@ pub fn component_detail( } }); - let exports = map_interfaces_to_fn_details(component.exported_fns(), InterfaceFilter::All); + let has_extensions = component + .exported_fns() + .iter() + .any(|fn_detail| fn_detail.ffqn.ifc_fqn.is_extension()); + let exports = map_interfaces_to_fn_details( + component.exported_fns(), + if *show_extensions { + InterfaceFilter::All + } else { + InterfaceFilter::WithoutExtensions + }, + ); let render_exported_ifc_with_fns = |ifc_fqn: &IfcFqnName, fn_details: &[FunctionMetadataLite]| { let exported_fn_details = fn_details @@ -433,15 +450,32 @@ pub fn component_detail( .iter() .map(|(ifc_fqn, fn_details)| render_exported_ifc_with_fns(ifc_fqn, fn_details)) .collect::>(); - let exported_functions = if exported_ifcs_fns.is_empty() { - html! { + let on_show_extensions_change = { + let show_extensions = show_extensions.clone(); + Callback::from(move |e: Event| { + let input: web_sys::HtmlInputElement = e.target_unchecked_into(); + show_extensions.set(input.checked()); + }) + }; + let exported_functions = html! { <> + if has_extensions { + + } + if exported_ifcs_fns.is_empty() {

{"This component does not export any functions."}

+ } else { + { for exported_ifcs_fns } } - } else { - html! { <>{ for exported_ifcs_fns } } - }; + }; let dependencies = || { let connections = component_connections(component, deployment_components); diff --git a/crates/webui/src/components/deployment_config_view.rs b/crates/webui/src/components/deployment_config_view.rs index e0e6df0..165a61f 100644 --- a/crates/webui/src/components/deployment_config_view.rs +++ b/crates/webui/src/components/deployment_config_view.rs @@ -78,6 +78,8 @@ pub enum SourceContent { Fetch { file: String, }, + /// A binary file such as a WASM component, listed but not displayable. + Binary, } const SOURCE_MARKER: &str = "(source rendered below)"; @@ -224,7 +226,10 @@ pub fn build_sections_from_manifest(manifest: &Value, files: &[FileRefSer]) -> V let Some(tables) = manifest.get(toml_key).and_then(Value::as_array) else { continue; }; - let has_backtrace = matches!(*toml_key, "workflow_wasm" | "webhook_endpoint_wasm"); + let has_backtrace = matches!( + *toml_key, + "activity_wasm" | "workflow_wasm" | "webhook_endpoint_wasm" + ); let has_script = matches!( *toml_key, "workflow_js" | "activity_js" | "activity_exec" | "webhook_endpoint_js" @@ -432,7 +437,9 @@ pub fn collapsible_source( .as_ref() .and_then(|result| result.as_ref().as_ref().ok()) .cloned(), - SourceContent::Oci { .. } | SourceContent::ExternalPath { .. } => None, + SourceContent::Oci { .. } + | SourceContent::ExternalPath { .. } + | SourceContent::Binary => None, }?; let language = PathBuf::from(&source.file_name) .extension() @@ -444,11 +451,20 @@ pub fn collapsible_source( }, ); + if source.content == SourceContent::Binary { + return html! { +
+
{ source_summary_contents(source) }
+
+ }; + } + let body = if !*opened { html! {} } else { let source_available = match &source.content { SourceContent::Inline(_) => true, + SourceContent::Binary => unreachable!("binary sources return early"), SourceContent::Oci { image } => { return html! {
@@ -518,16 +534,22 @@ fn source_summary(source: &SourceView) -> Html { .is_some_and(|metadata| metadata.entrypoint); html! { - { &source.file_name } - if let Some(metadata) = &source.metadata { - - } + { source_summary_contents(source) } } } +fn source_summary_contents(source: &SourceView) -> Html { + html! { <> + { &source.file_name } + if let Some(metadata) = &source.metadata { + + } + } +} + #[derive(Properties, PartialEq)] pub struct DeploymentConfigViewProps { pub sections: Vec, diff --git a/crates/webui/src/components/deployment_diff_page.rs b/crates/webui/src/components/deployment_diff_page.rs index f72ce11..e7d6faa 100644 --- a/crates/webui/src/components/deployment_diff_page.rs +++ b/crates/webui/src/components/deployment_diff_page.rs @@ -430,6 +430,7 @@ async fn resolve_source(source: SourceView, component_id: Option) - SourceContent::ExternalPath { path } => ResolvedSource::Note(format!( "Source is read at runtime from the external path `{path}`." )), + SourceContent::Binary => ResolvedSource::Note("Binary file, not shown.".to_string()), SourceContent::FetchFile { digest } => rest::deployments::file(&digest) .await .map(ResolvedSource::Text) diff --git a/crates/webui/styles/pages/_definitions.scss b/crates/webui/styles/pages/_definitions.scss index 490ea52..718a018 100644 --- a/crates/webui/styles/pages/_definitions.scss +++ b/crates/webui/styles/pages/_definitions.scss @@ -96,7 +96,8 @@ border-radius: $border-radius-lg; background: $color-bg-primary; - > summary { + > summary, + > .source-summary { display: flex; align-items: center; gap: $spacing-sm; @@ -130,6 +131,18 @@ } } + > .source-summary { + cursor: default; + + &::before { + visibility: hidden; + } + + &:hover { + background: $color-bg-secondary; + } + } + &[open] { > summary { border-bottom: 1px solid $color-border-primary; diff --git a/crates/webui/styles/pages/_deployment.scss b/crates/webui/styles/pages/_deployment.scss index 5d65df5..c7fde3b 100644 --- a/crates/webui/styles/pages/_deployment.scss +++ b/crates/webui/styles/pages/_deployment.scss @@ -303,6 +303,13 @@ .component-detail-tabs { margin-top: $spacing-sm; } .component-detail-tab-content { min-height: 0; } + + .component-show-extensions { + display: inline-flex; + align-items: center; + gap: $spacing-xs; + margin: $spacing-sm 0; + } } .deployment-component-search {