20260728_2 修复rpki-explorer体验问题7项(#134):证书资源可展开、CMS对象新增EE Parsed Tab、Overview增加repo数KPI/修复Object types标签/Top repositories按objects排序(后端sort参数)/reject reasons按前缀聚类可下钻、Run选择器30s轮询

This commit is contained in:
2026-07-28 13:21:58 +08:00
parent 0d6bbec9f3
commit f7f80fe684
20 changed files with 676 additions and 70 deletions

View File

@@ -11,7 +11,7 @@ use rpki::query::report_stream::{ObjectFilter, ObjectScope};
use rpki::query::vrp::VrpLookup;
use rpki::query_db::{
ChainEdgeRecord, ExportJobRecord, ObjectInstanceRecord, ObjectUriIndexRecord, QueryDb,
QueryDbError, ValidationExplainRecord,
QueryDbError, RepoSortOrder, ValidationExplainRecord,
};
use serde::Serialize;
use serde_json::{Value, json};
@@ -646,10 +646,11 @@ fn route_request(
}
["runs", raw_run_id, "repos"] => {
let run_id = resolve_run(db, raw_run_id)?;
page_response(
db.list_repos(&run_id, limit(&query), cursor(&query))?,
Some(run_id),
)
let page = match repo_sort_from_query(&query)? {
Some(order) => db.list_repos_sorted(&run_id, limit(&query), cursor(&query), order)?,
None => db.list_repos(&run_id, limit(&query), cursor(&query))?,
};
page_response(page, Some(run_id))
}
["runs", raw_run_id, "repos", repo_id] => {
let run_id = resolve_run(db, raw_run_id)?;
@@ -936,10 +937,11 @@ fn route_request(
}
["runs", raw_run_id, "stats", "repos"] => {
let run_id = resolve_run(db, raw_run_id)?;
page_response(
db.list_repos(&run_id, limit(&query), cursor(&query))?,
Some(run_id),
)
let page = match repo_sort_from_query(&query)? {
Some(order) => db.list_repos_sorted(&run_id, limit(&query), cursor(&query), order)?,
None => db.list_repos(&run_id, limit(&query), cursor(&query))?,
};
page_response(page, Some(run_id))
}
["runs", raw_run_id, "stats", "publication-points"] => {
let run_id = resolve_run(db, raw_run_id)?;
@@ -2155,6 +2157,18 @@ fn exports_limit(query: &BTreeMap<String, String>) -> usize {
.clamp(1, 200)
}
fn repo_sort_from_query(query: &BTreeMap<String, String>) -> Result<Option<RepoSortOrder>, ApiError> {
match query.get("sort").map(|value| value.as_str()) {
None => Ok(None),
Some("objects") => match query.get("order").map(|value| value.as_str()) {
None | Some("desc") => Ok(Some(RepoSortOrder::ObjectsDesc)),
Some("asc") => Ok(Some(RepoSortOrder::ObjectsAsc)),
Some(other) => Err(ApiError::new(400, format!("invalid repos order: {other}"))),
},
Some(other) => Err(ApiError::new(400, format!("invalid repos sort: {other}"))),
}
}
fn object_filter_from_query(query: &BTreeMap<String, String>) -> Result<ObjectFilter, ApiError> {
let mut filter = ObjectFilter::default();
if let Some(value) = query.get("type") {