feat(ui): project drill-down route with repo-filtered event timeline
Add repo filter param to /v1/events (SQL COALESCE across payload shapes per source). New /project/:source/* route renders a filtered activity timeline for a single repo. Dashboard cards link to the drill-down page. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -82,6 +82,8 @@ struct EventsQueryParams {
|
||||
to: Option<DateTime<Utc>>,
|
||||
/// Comma-separated list, e.g. `source=github,gitea`.
|
||||
source: Option<String>,
|
||||
/// Filter to a specific repo, e.g. `repo=grenade/moments`.
|
||||
repo: Option<String>,
|
||||
limit: Option<u32>,
|
||||
}
|
||||
|
||||
@@ -101,6 +103,7 @@ async fn list_events(
|
||||
from: params.from,
|
||||
to: params.to,
|
||||
sources,
|
||||
repo: params.repo,
|
||||
// Public timeline only — private events stay in the DB but are never
|
||||
// surfaced. A future authenticated path can flip this.
|
||||
include_private: false,
|
||||
|
||||
@@ -54,6 +54,12 @@ impl EventReader for PgStore {
|
||||
AND ($2::timestamptz IS NULL OR occurred_at < $2)
|
||||
AND ($3::text[] IS NULL OR source = ANY($3))
|
||||
AND ($4::bool OR public = true)
|
||||
AND ($6::text IS NULL OR COALESCE(
|
||||
payload->'repo'->>'name',
|
||||
payload->'repository'->>'full_name',
|
||||
payload->>'_repo',
|
||||
payload->>'product'
|
||||
) = $6)
|
||||
ORDER BY occurred_at DESC
|
||||
LIMIT $5
|
||||
"#,
|
||||
@@ -63,6 +69,7 @@ impl EventReader for PgStore {
|
||||
.bind(sources.as_deref())
|
||||
.bind(query.include_private)
|
||||
.bind(query.limit as i64)
|
||||
.bind(query.repo.as_deref())
|
||||
.fetch_all(&self.pool)
|
||||
.await
|
||||
.map_err(map_err)?;
|
||||
|
||||
@@ -67,6 +67,8 @@ pub struct EventQuery {
|
||||
pub from: Option<DateTime<Utc>>,
|
||||
pub to: Option<DateTime<Utc>>,
|
||||
pub sources: Option<Vec<Source>>,
|
||||
/// Filter to events matching a specific repo (matched against payload).
|
||||
pub repo: Option<String>,
|
||||
/// When false (default), only `public = true` rows are returned. The API
|
||||
/// pins this to false today; a future authenticated path can flip it.
|
||||
pub include_private: bool,
|
||||
|
||||
Reference in New Issue
Block a user