fix(dashboard,server): restore code change ledger UI and enrich model schema parity and pagination
This commit is contained in:
1 parent
3b146f91c2
commit
73c3d41c87
9 files changed
+297
-19
No files matched your search
@@ -235,6 +235,26 @@ pub fn create_router(app_state: Arc<AppState>) -> Router {
|
||||
}
|
||||
}),
|
||||
)
|
||||
.route(
|
||||
"/api/ledger",
|
||||
get({
|
||||
let state_clone = app_state.handler.state.clone();
|
||||
move |axum::extract::Query(params): axum::extract::Query<
|
||||
std::collections::HashMap<String, String>,
|
||||
>| async move {
|
||||
let limit = params
|
||||
.get("limit")
|
||||
.and_then(|l| l.parse::<usize>().ok())
|
||||
.unwrap_or(100);
|
||||
|
||||
let json = state_clone.code.ledger.read_with(|items| {
|
||||
let recent: Vec<_> = items.iter().rev().take(limit).collect();
|
||||
serde_json::to_string(&recent).unwrap_or_else(|_| "[]".to_string())
|
||||
});
|
||||
([(axum::http::header::CONTENT_TYPE, "application/json")], json)
|
||||
}
|
||||
}),
|
||||
)
|
||||
.route(
|
||||
"/api/tech_debts",
|
||||
get({
|
||||
@@ -265,6 +285,26 @@ pub fn create_router(app_state: Arc<AppState>) -> Router {
|
||||
}
|
||||
}),
|
||||
)
|
||||
.route(
|
||||
"/api/session_summaries",
|
||||
get({
|
||||
let state_clone = app_state.handler.state.clone();
|
||||
move |axum::extract::Query(params): axum::extract::Query<
|
||||
std::collections::HashMap<String, String>,
|
||||
>| async move {
|
||||
let limit = params
|
||||
.get("limit")
|
||||
.and_then(|l| l.parse::<usize>().ok())
|
||||
.unwrap_or(100);
|
||||
|
||||
let json = state_clone.telemetry.session_summaries.read_with(|items| {
|
||||
let recent: Vec<_> = items.iter().rev().take(limit).collect();
|
||||
serde_json::to_string(&recent).unwrap_or_else(|_| "[]".to_string())
|
||||
});
|
||||
([(axum::http::header::CONTENT_TYPE, "application/json")], json)
|
||||
}
|
||||
}),
|
||||
)
|
||||
.route(
|
||||
"/api/milestones",
|
||||
get({
|
||||
@@ -789,4 +829,83 @@ mod tests {
|
||||
assert!(js_str.contains("/api/activity/stream"));
|
||||
assert!(js_str.contains("parseActivityPayload"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_ledger_endpoint() {
|
||||
let (app, app_state, _dir) = setup_app().await;
|
||||
|
||||
app_state.handler.state.code.ledger.modify(|l| {
|
||||
l.push(crate::models::CodeChange {
|
||||
timestamp: 1728000000,
|
||||
file_path: "src/main.rs".to_string(),
|
||||
description: "Test commit 1".to_string(),
|
||||
git_commit: Some("abc1234".to_string()),
|
||||
..Default::default()
|
||||
});
|
||||
l.push(crate::models::CodeChange {
|
||||
timestamp: 1728000100,
|
||||
file_path: "src/lib.rs".to_string(),
|
||||
description: "Test commit 2".to_string(),
|
||||
git_commit: Some("def5678".to_string()),
|
||||
..Default::default()
|
||||
});
|
||||
});
|
||||
|
||||
let request = Request::builder()
|
||||
.uri("/api/ledger?limit=1")
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
|
||||
let response = app.oneshot(request).await.unwrap();
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
let body_bytes = axum::body::to_bytes(response.into_body(), usize::MAX)
|
||||
.await
|
||||
.unwrap();
|
||||
let changes: Vec<crate::models::CodeChange> = serde_json::from_slice(&body_bytes).unwrap();
|
||||
assert_eq!(changes.len(), 1);
|
||||
assert_eq!(changes[0].description, "Test commit 2");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_session_summaries_endpoint() {
|
||||
let (app, app_state, _dir) = setup_app().await;
|
||||
|
||||
app_state
|
||||
.handler
|
||||
.state
|
||||
.telemetry
|
||||
.session_summaries
|
||||
.modify(|summaries| {
|
||||
summaries.push(crate::models::SessionSummary {
|
||||
session_id: Some("session-1".to_string()),
|
||||
summary: "Session 1 summary".to_string(),
|
||||
namespace: "test".to_string(),
|
||||
timestamp: 100,
|
||||
..Default::default()
|
||||
});
|
||||
summaries.push(crate::models::SessionSummary {
|
||||
session_id: Some("session-2".to_string()),
|
||||
summary: "Session 2 summary".to_string(),
|
||||
namespace: "test".to_string(),
|
||||
timestamp: 200,
|
||||
..Default::default()
|
||||
});
|
||||
});
|
||||
|
||||
let request = Request::builder()
|
||||
.uri("/api/session_summaries?limit=1")
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
|
||||
let response = app.oneshot(request).await.unwrap();
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
let body_bytes = axum::body::to_bytes(response.into_body(), usize::MAX)
|
||||
.await
|
||||
.unwrap();
|
||||
let summaries: Vec<crate::models::SessionSummary> = serde_json::from_slice(&body_bytes).unwrap();
|
||||
assert_eq!(summaries.len(), 1);
|
||||
assert_eq!(summaries[0].summary, "Session 2 summary");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user