diff --git a/crates/moments-api/src/main.rs b/crates/moments-api/src/main.rs index 65e1ee2..023f09d 100644 --- a/crates/moments-api/src/main.rs +++ b/crates/moments-api/src/main.rs @@ -180,7 +180,10 @@ async fn og_contributions( .await .map_err(internal)?; - let png = render_contributions_png(&counts, earliest, today).map_err(|e| ApiError { + let projects = state.store.list_projects().await.map_err(internal)?; + let repo_count = projects.len(); + + let png = render_contributions_png(&counts, earliest, today, repo_count).map_err(|e| ApiError { status: StatusCode::INTERNAL_SERVER_ERROR, message: e, })?; @@ -199,6 +202,7 @@ fn render_contributions_png( counts: &[DailyCount], from: NaiveDate, to: NaiveDate, + repo_count: usize, ) -> Result, String> { use std::collections::HashMap; @@ -280,8 +284,13 @@ fn render_contributions_png( let mut svg = format!( r#""#, ); + let repo_text = if repo_count > 0 { + format!(" in {repo_count} repositories") + } else { + String::new() + }; svg.push_str(&format!( - r##"{total} contributions since {from}"##, + r##"{total} contributions since {from}{repo_text}"##, x = year_label_w, )); diff --git a/ui/src/components/ContributionGraph.tsx b/ui/src/components/ContributionGraph.tsx index fea7ec0..f5e30b2 100644 --- a/ui/src/components/ContributionGraph.tsx +++ b/ui/src/components/ContributionGraph.tsx @@ -2,7 +2,7 @@ import { useMemo } from 'react'; import { useQuery } from '@tanstack/react-query'; import { useNavigate } from 'react-router-dom'; -import { fetchDailyCounts, fetchSources } from '../api/client'; +import { fetchDailyCounts, fetchProjects, fetchSources } from '../api/client'; const CELL_SIZE = 12; const GAP = 3; @@ -37,6 +37,23 @@ export function ContributionGraph() { staleTime: 5 * 60_000, }); + const projectsQ = useQuery({ + queryKey: ['projects'], + queryFn: fetchProjects, + staleTime: 60_000, + }); + + const repoCount = useMemo(() => { + if (!projectsQ.data) return 0; + const fromMs = from.getTime(); + const toMs = to.getTime(); + return projectsQ.data.filter((p) => { + const first = p.first_activity ? new Date(p.first_activity).getTime() : Infinity; + const last = p.last_activity ? new Date(p.last_activity).getTime() : 0; + return last >= fromMs && first <= toMs; + }).length; + }, [projectsQ.data]); + const navigate = useNavigate(); const { weeks, monthMarkers, thresholds, totalCount } = useMemo(() => { @@ -89,6 +106,7 @@ export function ContributionGraph() {

{totalCount} contributions in the last year + {repoCount > 0 && ` in ${repoCount} repositories`}

@@ -155,6 +173,13 @@ export function AllTimeGraph() { return dates.length > 0 ? new Date(Math.min(...dates.map((d) => d.getTime()))) : null; }, [sourcesQ.data]); + const projectsQ = useQuery({ + queryKey: ['projects'], + queryFn: fetchProjects, + staleTime: 60_000, + }); + const repoCount = projectsQ.data?.length ?? 0; + const to = new Date(); const from = earliest ?? new Date(to.getFullYear() - 5, 0, 1); const fromStr = fmt(from); @@ -227,6 +252,7 @@ export function AllTimeGraph() {

{totalCount} contributions since {fmt(from)} + {repoCount > 0 && ` in ${repoCount} repositories`}