feat(ui): all-time weekly contribution graph + date range timespan support
Add AllTimeGraph component showing one circle per week across the full history (earliest event to today). Uses the /sources endpoint to find the earliest date, then fetches daily counts and aggregates to weekly. Clicking a week navigates to /activity/YYYY-MM-DD..YYYY-MM-DD. Update parseTimespan to handle both date-only (YYYY-MM-DD) and full ISO datetime strings in range expressions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,16 +12,27 @@ import { TimelineEntry } from '../components/TimelineEntry';
|
||||
const RANGE_MIN = new Date('2010-01-01T00:00:00Z').getTime();
|
||||
const RANGE_MAX = Date.now();
|
||||
|
||||
function parseDate(s: string): number {
|
||||
// Accept YYYY-MM-DD or full ISO datetime
|
||||
const t = new Date(s.includes('T') ? s : s + 'T00:00:00Z').getTime();
|
||||
return isNaN(t) ? NaN : t;
|
||||
}
|
||||
|
||||
function endOfDay(s: string): number {
|
||||
const t = new Date(s.includes('T') ? s : s + 'T23:59:59Z').getTime();
|
||||
return isNaN(t) ? NaN : t;
|
||||
}
|
||||
|
||||
function parseTimespan(timespan?: string): [number, number] | null {
|
||||
if (!timespan) return null;
|
||||
if (timespan.includes('..')) {
|
||||
const [a, b] = timespan.split('..');
|
||||
const from = new Date(a + 'T00:00:00Z').getTime();
|
||||
const to = new Date(b + 'T23:59:59Z').getTime();
|
||||
const from = parseDate(a);
|
||||
const to = endOfDay(b);
|
||||
if (!isNaN(from) && !isNaN(to)) return [from, to];
|
||||
} else {
|
||||
const from = new Date(timespan + 'T00:00:00Z').getTime();
|
||||
const to = new Date(timespan + 'T23:59:59Z').getTime();
|
||||
const from = parseDate(timespan);
|
||||
const to = endOfDay(timespan);
|
||||
if (!isNaN(from)) return [from, to];
|
||||
}
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user