Skip to content

Commit 8812115

Browse files
ofershapcursoragent
andcommitted
feat: add time range and group filtering to insights page
- Add time range picker (7d/14d/30d) and group dropdown to insights - Commands, MCP, Model Rankings, Plan Exhaustion filter by selected group - Reorder sections: filtered content first, team-wide below a divider - Update analytics API to accept group param, resolve to email filter - Show member count badge on active filter in members table Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 44cbeaa commit 8812115

5 files changed

Lines changed: 352 additions & 110 deletions

File tree

src/app/api/analytics/route.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,36 @@ import {
1111
getAnalyticsClientVersionsSummary,
1212
getUsersByClientVersion,
1313
getPlanExhaustionStats,
14+
getModelEfficiency,
15+
getGroupsWithMembers,
1416
} from "@/lib/db";
1517

1618
export const dynamic = "force-dynamic";
1719

20+
function resolveGroupEmails(group: string): string[] | undefined {
21+
if (!group || group === "all") return undefined;
22+
const groups = getGroupsWithMembers();
23+
24+
if (group.startsWith("parent:")) {
25+
const prefix = group.replace("parent:", "");
26+
const emails = new Set<string>();
27+
for (const g of groups) {
28+
if (g.name === prefix || g.name.startsWith(prefix + " > ")) {
29+
for (const e of g.emails) emails.add(e);
30+
}
31+
}
32+
return emails.size > 0 ? [...emails] : undefined;
33+
}
34+
35+
const found = groups.find((g) => g.id === group);
36+
return found?.emails.length ? found.emails : undefined;
37+
}
38+
1839
export function GET(request: Request) {
1940
const { searchParams } = new URL(request.url);
2041
const days = parseInt(searchParams.get("days") ?? "30", 10);
42+
const group = searchParams.get("group") ?? "all";
43+
const emails = resolveGroupEmails(group);
2144

2245
try {
2346
return NextResponse.json({
@@ -26,12 +49,13 @@ export function GET(request: Request) {
2649
modelTrend: getAnalyticsModelUsageTrend(days),
2750
agentEdits: getAnalyticsAgentEditsTrend(days),
2851
tabs: getAnalyticsTabsTrend(days),
29-
mcp: getAnalyticsMCPSummary(days),
30-
commands: getAnalyticsCommandsSummary(days),
52+
mcp: getAnalyticsMCPSummary(days, emails),
53+
commands: getAnalyticsCommandsSummary(days, emails),
3154
fileExtensions: getAnalyticsFileExtensionsSummary(days),
3255
clientVersions: getAnalyticsClientVersionsSummary(),
3356
versionUsers: getUsersByClientVersion(),
34-
planExhaustion: getPlanExhaustionStats(),
57+
planExhaustion: getPlanExhaustionStats(emails),
58+
modelEfficiency: getModelEfficiency(emails),
3559
});
3660
} catch {
3761
return NextResponse.json({ error: "No analytics data yet" }, { status: 404 });

0 commit comments

Comments
 (0)