- Run cargo fmt on all crates - Fix regex patterns using unsupported lookahead in patterns.rs - Replace unwrap() calls with compile_regex() helper - Fix never type fallback in GitHub tracker - Fix redundant field name in findings page - Allow enum_variant_names for Dioxus Route enum - Fix &mut Vec -> &mut [T] clippy lint in sbom.rs - Mark unused-but-intended APIs with #[allow(dead_code)] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
84 lines
3.5 KiB
Rust
84 lines
3.5 KiB
Rust
use dioxus::prelude::*;
|
|
|
|
use crate::components::page_header::PageHeader;
|
|
use crate::components::pagination::Pagination;
|
|
|
|
#[component]
|
|
pub fn SbomPage() -> Element {
|
|
let mut page = use_signal(|| 1u64);
|
|
|
|
let sbom = use_resource(move || {
|
|
let p = page();
|
|
async move { crate::infrastructure::sbom::fetch_sbom(p).await.ok() }
|
|
});
|
|
|
|
rsx! {
|
|
PageHeader {
|
|
title: "SBOM",
|
|
description: "Software Bill of Materials - dependency inventory across all repositories",
|
|
}
|
|
|
|
match &*sbom.read() {
|
|
Some(Some(resp)) => {
|
|
let total_pages = resp.total.unwrap_or(0).div_ceil(50).max(1);
|
|
rsx! {
|
|
div { class: "card",
|
|
div { class: "table-wrapper",
|
|
table {
|
|
thead {
|
|
tr {
|
|
th { "Package" }
|
|
th { "Version" }
|
|
th { "Manager" }
|
|
th { "License" }
|
|
th { "Vulnerabilities" }
|
|
}
|
|
}
|
|
tbody {
|
|
for entry in &resp.data {
|
|
tr {
|
|
td {
|
|
style: "font-weight: 500;",
|
|
"{entry.name}"
|
|
}
|
|
td {
|
|
style: "font-family: monospace; font-size: 13px;",
|
|
"{entry.version}"
|
|
}
|
|
td { "{entry.package_manager}" }
|
|
td { "{entry.license.as_deref().unwrap_or(\"-\")}" }
|
|
td {
|
|
if entry.known_vulnerabilities.is_empty() {
|
|
span {
|
|
style: "color: var(--success);",
|
|
"None"
|
|
}
|
|
} else {
|
|
span { class: "badge badge-high",
|
|
"{entry.known_vulnerabilities.len()} vuln(s)"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Pagination {
|
|
current_page: page(),
|
|
total_pages: total_pages,
|
|
on_page_change: move |p| page.set(p),
|
|
}
|
|
}
|
|
}
|
|
},
|
|
Some(None) => rsx! {
|
|
div { class: "card", p { "Failed to load SBOM." } }
|
|
},
|
|
None => rsx! {
|
|
div { class: "loading", "Loading SBOM..." }
|
|
},
|
|
}
|
|
}
|
|
}
|