feat(ui): add /dash route, shared nav, project dashboard with /v1/projects API
Restructure routes: / and /dash show a project overview dashboard, /activity hosts the existing timeline, /cv remains. Shared Layout component provides consistent nav header and footer across all routes. New /v1/projects endpoint aggregates per-repo activity stats (commits, issues, PRs, date range) from existing event data via SQL. Dashboard ranks projects by weighted recency + volume score and renders a card grid. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@ use chrono::{DateTime, Utc};
|
||||
use clap::Parser;
|
||||
use moments_core::{EventReader, reshape};
|
||||
use moments_data::PgStore;
|
||||
use moments_entities::{EventQuery, Source, SourceSummary, TimelineItem};
|
||||
use moments_entities::{EventQuery, ProjectSummary, Source, SourceSummary, TimelineItem};
|
||||
use serde::Deserialize;
|
||||
use tower_http::{cors::CorsLayer, trace::TraceLayer};
|
||||
use tracing::info;
|
||||
@@ -50,6 +50,7 @@ async fn main() -> anyhow::Result<()> {
|
||||
.route("/v1/healthz", get(healthz))
|
||||
.route("/v1/events", get(list_events))
|
||||
.route("/v1/sources", get(list_sources))
|
||||
.route("/v1/projects", get(list_projects))
|
||||
.with_state(state)
|
||||
.layer(TraceLayer::new_for_http())
|
||||
.layer(CorsLayer::permissive());
|
||||
@@ -122,6 +123,13 @@ async fn list_sources(
|
||||
Ok(Json(summaries))
|
||||
}
|
||||
|
||||
async fn list_projects(
|
||||
State(state): State<AppState>,
|
||||
) -> Result<Json<Vec<ProjectSummary>>, ApiError> {
|
||||
let projects = state.store.list_projects().await.map_err(internal)?;
|
||||
Ok(Json(projects))
|
||||
}
|
||||
|
||||
fn parse_sources(raw: &str) -> Result<Vec<Source>, ApiError> {
|
||||
raw.split(',')
|
||||
.map(str::trim)
|
||||
|
||||
Reference in New Issue
Block a user