@agent-native/core 0.120.2 → 0.120.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +3 -3
- package/corpus/core/CHANGELOG.md +28 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/cli/context-xray-local.ts +1 -1
- package/corpus/core/src/cli/index.ts +63 -18
- package/corpus/core/src/cli/skills.ts +5 -0
- package/corpus/core/src/cli/telemetry.ts +118 -1
- package/corpus/core/src/client/AgentPanel.tsx +10 -0
- package/corpus/core/src/client/CommandMenu.tsx +13 -1
- package/corpus/core/src/client/agent-page/AgentTabsPage.tsx +39 -4
- package/corpus/core/src/client/analytics.ts +13 -0
- package/corpus/core/src/client/error-capture.ts +6 -1
- package/corpus/core/src/client/extensions/ExtensionsListPage.tsx +12 -5
- package/corpus/core/src/client/extensions/agent-native-extension-runtime.ts +1 -1
- package/corpus/core/src/client/navigation/index.ts +2 -0
- package/corpus/core/src/client/org/OrgSwitcher.tsx +14 -32
- package/corpus/core/src/client/settings/ExtensionsSettingsContent.tsx +1 -1
- package/corpus/core/src/extensions/theme.ts +1 -1
- package/corpus/core/src/localization/default-messages.ts +2 -0
- package/corpus/core/src/server/core-routes-plugin.ts +10 -1
- package/corpus/core/src/server/framework-request-handler.ts +17 -26
- package/corpus/core/src/styles/agent-native.css +13 -0
- package/corpus/core/src/templates/chat/app/components/layout/Layout.tsx +3 -0
- package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +78 -45
- package/corpus/core/src/templates/chat/app/global.css +1 -1
- package/corpus/core/src/templates/default/app/global.css +1 -1
- package/corpus/core/src/tracking/error-capture.ts +151 -0
- package/corpus/core/src/tracking/index.ts +5 -0
- package/corpus/templates/analytics/app/components/dashboard/CumulativeNetChart.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/DashboardHistoryPanel.tsx +1 -4
- package/corpus/templates/analytics/app/components/dashboard/DashboardPanelSkeleton.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/DataTable.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/DateRangePicker.tsx +2 -2
- package/corpus/templates/analytics/app/components/dashboard/MetricCard.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/RecentActivity.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/RevenueChart.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/RevenueComparisonChart.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +41 -9
- package/corpus/templates/analytics/app/components/dashboard/StatsCard.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/TimeSeriesChart.tsx +1 -1
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +2 -0
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +28 -14
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +152 -124
- package/corpus/templates/analytics/app/global.css +5 -5
- package/corpus/templates/analytics/app/lib/dashboard-report-capture.ts +42 -0
- package/corpus/templates/analytics/app/pages/adhoc/_shared/KpiChart.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/ChartTypePicker.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/DateRangePicker.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/EventRow.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/SqlPreview.tsx +2 -2
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +3 -3
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/EmailReportDialog.tsx +2 -2
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +162 -51
- package/corpus/templates/analytics/app/root.tsx +28 -0
- package/corpus/templates/analytics/changelog/2026-07-24-analytics-charts-now-explain-slow-loads-and-offer-a-direct-r.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-24-daily-dashboard-emails-now-load-signed-reports-more-reliably.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-24-manage-agent-is-clearly-marked-as-a-link-to-its-dedicated-pa.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +1 -1
- package/corpus/templates/analytics/server/db/schema.ts +5 -0
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +21 -0
- package/corpus/templates/analytics/server/lib/canonical-first-party-dashboard-repair.ts +11 -0
- package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +54 -0
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +235 -26
- package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +4 -1
- package/corpus/templates/analytics/server/plugins/db.ts +9 -0
- package/corpus/templates/analytics/shared/dashboard-report-timeouts.ts +1 -1
- package/corpus/templates/assets/app/components/asset/AssetPreviewDialog.tsx +376 -0
- package/corpus/templates/assets/app/components/create/RecentDraftsSection.tsx +14 -4
- package/corpus/templates/assets/app/components/layout/Layout.tsx +5 -0
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +118 -74
- package/corpus/templates/assets/app/global.css +1 -1
- package/corpus/templates/assets/app/i18n-data.ts +10 -0
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +99 -10
- package/corpus/templates/assets/app/routes/library.tsx +21 -198
- package/corpus/templates/assets/changelog/2026-07-21-unified-asset-preview-click-any-asset-to-open-one-preview-wi.md +6 -0
- package/corpus/templates/assets/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/assets/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/brain/app/components/layout/Layout.tsx +3 -0
- package/corpus/templates/brain/app/components/layout/Sidebar.tsx +76 -43
- package/corpus/templates/brain/app/global.css +1 -1
- package/corpus/templates/brain/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/brain/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +67 -52
- package/corpus/templates/calendar/app/global.css +1 -1
- package/corpus/templates/calendar/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/chat/app/components/layout/Layout.tsx +3 -0
- package/corpus/templates/chat/app/components/layout/Sidebar.tsx +78 -45
- package/corpus/templates/chat/app/global.css +1 -1
- package/corpus/templates/chat/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/chat/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/clips/app/components/library/library-layout.tsx +65 -31
- package/corpus/templates/clips/app/components/library/organization-switcher.tsx +2 -2
- package/corpus/templates/clips/app/components/player/video-player.tsx +16 -1
- package/corpus/templates/clips/app/global.css +1 -1
- package/corpus/templates/clips/app/hooks/use-view-tracking.ts +55 -12
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +6 -5
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +7 -7
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -5
- package/corpus/templates/clips/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/clips/server/plugins/db.ts +113 -68
- package/corpus/templates/content/actions/update-document.ts +145 -91
- package/corpus/templates/content/app/components/editor/CommentComposer.tsx +4 -1
- package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +366 -164
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +51 -28
- package/corpus/templates/content/app/components/editor/database/sidebar.tsx +19 -8
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +66 -42
- package/corpus/templates/content/app/global.css +1 -1
- package/corpus/templates/content/app/i18n-data.ts +15 -0
- package/corpus/templates/content/changelog/2026-07-23-shared-pages-now-keep-durable-content-visible-and-comment-th.md +6 -0
- package/corpus/templates/content/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/content/changelog/2026-07-24-comment-drafts-now-stay-open-when-saving-fails-and-long-live.md +6 -0
- package/corpus/templates/content/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/design/actions/update-file.ts +85 -18
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +65 -30
- package/corpus/templates/design/app/entry.client.tsx +14 -1
- package/corpus/templates/design/app/global.css +1 -1
- package/corpus/templates/design/app/lib/design-save-outbox.ts +39 -0
- package/corpus/templates/design/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/design/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/dispatch/app/global.css +1 -1
- package/corpus/templates/dispatch/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/forms/app/components/layout/Layout.tsx +3 -0
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +72 -37
- package/corpus/templates/forms/app/global.css +1 -1
- package/corpus/templates/forms/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-24-forms-sidebar-actions-now-keep-search-language-feedback-and-.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/macros/app/components/DailyProgress.tsx +5 -5
- package/corpus/templates/macros/app/components/ExerciseCard.tsx +2 -2
- package/corpus/templates/macros/app/components/MealCard.tsx +2 -2
- package/corpus/templates/macros/app/components/WeightCard.tsx +2 -2
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +56 -29
- package/corpus/templates/macros/app/components/ui/button.tsx +1 -2
- package/corpus/templates/macros/app/components/ui/card.tsx +1 -1
- package/corpus/templates/macros/app/global.css +1 -1
- package/corpus/templates/macros/app/routes/_index.tsx +1 -1
- package/corpus/templates/macros/app/routes/analytics.tsx +4 -7
- package/corpus/templates/macros/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/macros/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +125 -37
- package/corpus/templates/mail/app/global.css +1 -1
- package/corpus/templates/mail/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/mail/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/plan/app/components/layout/Layout.tsx +3 -0
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +90 -60
- package/corpus/templates/plan/app/global.css +1 -1
- package/corpus/templates/plan/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +69 -32
- package/corpus/templates/slides/app/global.css +1 -1
- package/corpus/templates/slides/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/tasks/app/global.css +1 -1
- package/corpus/templates/tasks/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/toolkit/CHANGELOG.md +14 -0
- package/corpus/toolkit/README.md +8 -1
- package/corpus/toolkit/agent-native.eject.json +1 -1
- package/corpus/toolkit/package.json +1 -1
- package/corpus/toolkit/src/app-shell/index.ts +1 -0
- package/corpus/toolkit/src/app-shell/sidebar-footer-actions.tsx +48 -0
- package/corpus/toolkit/src/chat-history.css +52 -1
- package/corpus/toolkit/src/design-system/default-adapter.tsx +1 -1
- package/corpus/toolkit/src/editor/useCollabReconcile.ts +83 -15
- package/corpus/toolkit/src/ui/button.tsx +1 -2
- package/corpus/toolkit/src/ui/card.tsx +1 -1
- package/corpus/toolkit/src/ui/table.tsx +4 -11
- package/dist/cli/context-xray-local.js +1 -1
- package/dist/cli/context-xray-local.js.map +1 -1
- package/dist/cli/index.js +56 -17
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +5 -0
- package/dist/cli/skills.js.map +1 -1
- package/dist/cli/telemetry.d.ts +7 -0
- package/dist/cli/telemetry.d.ts.map +1 -1
- package/dist/cli/telemetry.js +91 -1
- package/dist/cli/telemetry.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +7 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +2 -2
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/CommandMenu.d.ts +2 -0
- package/dist/client/CommandMenu.d.ts.map +1 -1
- package/dist/client/CommandMenu.js +12 -1
- package/dist/client/CommandMenu.js.map +1 -1
- package/dist/client/agent-page/AgentTabsPage.d.ts +4 -0
- package/dist/client/agent-page/AgentTabsPage.d.ts.map +1 -1
- package/dist/client/agent-page/AgentTabsPage.js +8 -4
- package/dist/client/agent-page/AgentTabsPage.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +7 -0
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/error-capture.d.ts.map +1 -1
- package/dist/client/error-capture.js +8 -1
- package/dist/client/error-capture.js.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.js +2 -2
- package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
- package/dist/client/extensions/agent-native-extension-runtime.js +1 -1
- package/dist/client/extensions/agent-native-extension-runtime.js.map +1 -1
- package/dist/client/navigation/index.d.ts +1 -1
- package/dist/client/navigation/index.d.ts.map +1 -1
- package/dist/client/navigation/index.js +1 -1
- package/dist/client/navigation/index.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +9 -13
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/settings/ExtensionsSettingsContent.js +1 -1
- package/dist/client/settings/ExtensionsSettingsContent.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/extensions/theme.js +1 -1
- package/dist/extensions/theme.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/localization/default-messages.d.ts +2 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +2 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/provider-api/actions/provider-api.d.ts +2 -2
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +8 -1
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +17 -27
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/styles/agent-native.css +13 -0
- package/dist/templates/chat/app/components/layout/Layout.tsx +3 -0
- package/dist/templates/chat/app/components/layout/Sidebar.tsx +78 -45
- package/dist/templates/chat/app/global.css +1 -1
- package/dist/templates/chat/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/dist/templates/chat/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/dist/templates/default/app/global.css +1 -1
- package/dist/tracking/error-capture.d.ts +14 -0
- package/dist/tracking/error-capture.d.ts.map +1 -0
- package/dist/tracking/error-capture.js +113 -0
- package/dist/tracking/error-capture.js.map +1 -0
- package/dist/tracking/index.d.ts +1 -0
- package/dist/tracking/index.d.ts.map +1 -1
- package/dist/tracking/index.js +1 -0
- package/dist/tracking/index.js.map +1 -1
- package/package.json +2 -2
- package/src/cli/context-xray-local.ts +1 -1
- package/src/cli/index.ts +63 -18
- package/src/cli/skills.ts +5 -0
- package/src/cli/telemetry.ts +118 -1
- package/src/client/AgentPanel.tsx +10 -0
- package/src/client/CommandMenu.tsx +13 -1
- package/src/client/agent-page/AgentTabsPage.tsx +39 -4
- package/src/client/analytics.ts +13 -0
- package/src/client/error-capture.ts +6 -1
- package/src/client/extensions/ExtensionsListPage.tsx +12 -5
- package/src/client/extensions/agent-native-extension-runtime.ts +1 -1
- package/src/client/navigation/index.ts +2 -0
- package/src/client/org/OrgSwitcher.tsx +14 -32
- package/src/client/settings/ExtensionsSettingsContent.tsx +1 -1
- package/src/extensions/theme.ts +1 -1
- package/src/localization/default-messages.ts +2 -0
- package/src/server/core-routes-plugin.ts +10 -1
- package/src/server/framework-request-handler.ts +17 -26
- package/src/styles/agent-native.css +13 -0
- package/src/templates/chat/app/components/layout/Layout.tsx +3 -0
- package/src/templates/chat/app/components/layout/Sidebar.tsx +78 -45
- package/src/templates/chat/app/global.css +1 -1
- package/src/templates/chat/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/src/templates/chat/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/src/templates/default/app/global.css +1 -1
- package/src/tracking/error-capture.ts +151 -0
- package/src/tracking/index.ts +5 -0
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
--accent-foreground: 0 0% 98%;
|
|
36
36
|
|
|
37
37
|
/* Destructive - bright enough for text on dark surfaces */
|
|
38
|
-
--destructive: 0
|
|
38
|
+
--destructive: 0 91% 71%;
|
|
39
39
|
--destructive-foreground: 0 0% 98%;
|
|
40
40
|
|
|
41
41
|
/* Borders - Subtle and thin */
|
|
@@ -139,13 +139,13 @@
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
.dashboard-panel-skeleton {
|
|
142
|
-
background-color: hsl(var(--muted-foreground) / 0.
|
|
142
|
+
background-color: hsl(var(--muted-foreground) / 0.18);
|
|
143
143
|
background-image: linear-gradient(
|
|
144
144
|
105deg,
|
|
145
145
|
transparent 24%,
|
|
146
|
-
hsl(var(--foreground) / 0.
|
|
147
|
-
hsl(var(--foreground) / 0.
|
|
148
|
-
hsl(var(--foreground) / 0.
|
|
146
|
+
hsl(var(--foreground) / 0.04) 42%,
|
|
147
|
+
hsl(var(--foreground) / 0.1) 50%,
|
|
148
|
+
hsl(var(--foreground) / 0.04) 58%,
|
|
149
149
|
transparent 76%
|
|
150
150
|
);
|
|
151
151
|
background-size: 220% 100%;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { EMBED_TOKEN_QUERY_PARAM } from "@agent-native/core/shared";
|
|
2
|
+
|
|
3
|
+
export const DASHBOARD_REPORT_BOOTSTRAP_TIMEOUT_MS = 12_000;
|
|
4
|
+
export const DASHBOARD_REPORT_BOOTSTRAP_RETRY_DELAY_MS = 500;
|
|
5
|
+
export const DASHBOARD_REPORT_CAPTURE_ERROR_LIMIT = 240;
|
|
6
|
+
|
|
7
|
+
export type DashboardReportCapturePhase =
|
|
8
|
+
| "loading"
|
|
9
|
+
| "error"
|
|
10
|
+
| "missing"
|
|
11
|
+
| "ready";
|
|
12
|
+
|
|
13
|
+
export function isDashboardReportScreenshot(search: string): boolean {
|
|
14
|
+
return new URLSearchParams(search).get("reportScreenshot") === "1";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The server verifies this scoped token on every action. This only prevents
|
|
19
|
+
* the client session gate from redirecting an otherwise authorized capture.
|
|
20
|
+
*/
|
|
21
|
+
export function hasDashboardReportEmbedToken(
|
|
22
|
+
search: string,
|
|
23
|
+
storedEmbedToken?: string | null,
|
|
24
|
+
): boolean {
|
|
25
|
+
if (!isDashboardReportScreenshot(search)) return false;
|
|
26
|
+
return Boolean(
|
|
27
|
+
new URLSearchParams(search).get(EMBED_TOKEN_QUERY_PARAM)?.trim() ||
|
|
28
|
+
storedEmbedToken?.trim(),
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function dashboardReportCaptureError(error: unknown): string {
|
|
33
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
34
|
+
return message
|
|
35
|
+
.replace(
|
|
36
|
+
new RegExp(`(${EMBED_TOKEN_QUERY_PARAM}=)[^&\\s]+`, "g"),
|
|
37
|
+
"$1[REDACTED]",
|
|
38
|
+
)
|
|
39
|
+
.replace(/\s+/g, " ")
|
|
40
|
+
.trim()
|
|
41
|
+
.slice(0, DASHBOARD_REPORT_CAPTURE_ERROR_LIMIT);
|
|
42
|
+
}
|
|
@@ -33,7 +33,7 @@ export function ChartTypePicker({ value, onChange }: ChartTypePickerProps) {
|
|
|
33
33
|
onValueChange={(v) => {
|
|
34
34
|
if (v) onChange(v as ChartType);
|
|
35
35
|
}}
|
|
36
|
-
className="
|
|
36
|
+
className="rounded-md bg-card p-0.5"
|
|
37
37
|
>
|
|
38
38
|
{CHART_TYPES.map((ct) => (
|
|
39
39
|
<ToggleGroupItem
|
|
@@ -17,7 +17,7 @@ interface DateRangePickerProps {
|
|
|
17
17
|
|
|
18
18
|
export function DateRangePicker({ value, onChange }: DateRangePickerProps) {
|
|
19
19
|
return (
|
|
20
|
-
<div className="flex items-center
|
|
20
|
+
<div className="flex items-center gap-0.5 rounded-md bg-card p-0.5">
|
|
21
21
|
{OPTIONS.map((opt) => (
|
|
22
22
|
<Button
|
|
23
23
|
key={opt.value}
|
|
@@ -15,7 +15,7 @@ interface EventRowProps {
|
|
|
15
15
|
|
|
16
16
|
export function EventRow({ event, onChange, onRemove }: EventRowProps) {
|
|
17
17
|
return (
|
|
18
|
-
<div className="
|
|
18
|
+
<div className="space-y-2 rounded-lg bg-card p-3">
|
|
19
19
|
<div className="flex items-center gap-2">
|
|
20
20
|
<IconGripVertical className="h-4 w-4 text-muted-foreground shrink-0 cursor-grab" />
|
|
21
21
|
<div className="flex-1 min-w-0">
|
|
@@ -23,7 +23,7 @@ export function SqlPreview({ sql }: SqlPreviewProps) {
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
return (
|
|
26
|
-
<div className="
|
|
26
|
+
<div className="rounded-lg bg-card">
|
|
27
27
|
<button
|
|
28
28
|
className="flex items-center gap-2 w-full px-3 py-2 text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
29
29
|
type="button"
|
|
@@ -51,7 +51,7 @@ export function SqlPreview({ sql }: SqlPreviewProps) {
|
|
|
51
51
|
)}
|
|
52
52
|
>
|
|
53
53
|
<div className="min-h-0 overflow-hidden">
|
|
54
|
-
<div className="relative
|
|
54
|
+
<div className="relative">
|
|
55
55
|
<SqlHighlight
|
|
56
56
|
sql={sql}
|
|
57
57
|
preClassName="p-3 overflow-auto max-h-[300px] bg-muted/50 rounded-b-lg"
|
|
@@ -256,7 +256,7 @@ export function DashboardFilterBar({
|
|
|
256
256
|
<Collapsible
|
|
257
257
|
open={filtersOpen}
|
|
258
258
|
onOpenChange={setFiltersOpen}
|
|
259
|
-
className="group rounded-lg
|
|
259
|
+
className="group rounded-lg bg-card px-3 py-2"
|
|
260
260
|
>
|
|
261
261
|
<div className="flex flex-wrap items-end justify-between gap-3">
|
|
262
262
|
<CollapsibleContent className="min-w-0 flex-1">
|
|
@@ -426,8 +426,8 @@ function FilterControl({
|
|
|
426
426
|
value={current}
|
|
427
427
|
onValueChange={(v) => setValue({ [filter.id]: v })}
|
|
428
428
|
>
|
|
429
|
-
<SelectTrigger className="h-8 w-[140px] text-xs">
|
|
430
|
-
<SelectValue className="flex-1 text-left" />
|
|
429
|
+
<SelectTrigger className="h-8 w-[140px] justify-start gap-2 text-xs">
|
|
430
|
+
<SelectValue className="min-w-0 flex-1 text-left" />
|
|
431
431
|
</SelectTrigger>
|
|
432
432
|
<SelectContent>
|
|
433
433
|
{filter.options?.map((opt) => (
|
|
@@ -294,7 +294,7 @@ export function EmailReportDialog({
|
|
|
294
294
|
<button
|
|
295
295
|
key={sub.id}
|
|
296
296
|
type="button"
|
|
297
|
-
className="flex w-full items-center justify-between gap-3 rounded-md
|
|
297
|
+
className="flex w-full items-center justify-between gap-3 rounded-md bg-card px-3 py-2 text-left transition-colors hover:bg-muted/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
298
298
|
onClick={() => loadSubscription(sub)}
|
|
299
299
|
>
|
|
300
300
|
<span className="min-w-0">
|
|
@@ -383,7 +383,7 @@ export function EmailReportDialog({
|
|
|
383
383
|
/>
|
|
384
384
|
</div>
|
|
385
385
|
|
|
386
|
-
<div className="flex items-center justify-between gap-3 rounded-md
|
|
386
|
+
<div className="flex items-center justify-between gap-3 rounded-md bg-card px-3 py-2 sm:col-span-2">
|
|
387
387
|
<div className="min-w-0">
|
|
388
388
|
<Label>{t("sqlDashboard.reportEnabled")}</Label>
|
|
389
389
|
<p className="text-xs text-muted-foreground">
|
|
@@ -506,7 +506,7 @@ function PanelEditorContent({
|
|
|
506
506
|
</div>
|
|
507
507
|
|
|
508
508
|
{isExtensionPanel ? (
|
|
509
|
-
<div className="grid gap-4 rounded-lg
|
|
509
|
+
<div className="grid gap-4 rounded-lg bg-card p-4">
|
|
510
510
|
<div className="grid gap-1.5">
|
|
511
511
|
<Label htmlFor="panel-extension-mode">
|
|
512
512
|
{t("panelEditor.extensionDisplay")}
|
|
@@ -371,7 +371,7 @@ export function SqlChartCard({
|
|
|
371
371
|
data-dashboard-report-panel-id={panel.id}
|
|
372
372
|
data-dashboard-report-panel-title={panel.title}
|
|
373
373
|
className={cn(
|
|
374
|
-
"dashboard-extension-card group relative h-full rounded-lg
|
|
374
|
+
"dashboard-extension-card group relative h-full rounded-lg transition-colors",
|
|
375
375
|
selectedForChat && "border-foreground/35 ring-1 ring-foreground/10",
|
|
376
376
|
)}
|
|
377
377
|
>
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
callAction,
|
|
12
12
|
useChangeVersions,
|
|
13
13
|
useActionMutation,
|
|
14
|
+
type AuthSession,
|
|
14
15
|
} from "@agent-native/core/client/hooks";
|
|
15
16
|
import { useT } from "@agent-native/core/client/i18n";
|
|
16
17
|
import { ShareButton } from "@agent-native/core/client/sharing";
|
|
@@ -104,6 +105,12 @@ import {
|
|
|
104
105
|
} from "@/hooks/use-dashboard-chat-context";
|
|
105
106
|
import { useDashboardViews } from "@/hooks/use-dashboard-views";
|
|
106
107
|
import { useUserPref } from "@/hooks/use-user-pref";
|
|
108
|
+
import {
|
|
109
|
+
DASHBOARD_REPORT_BOOTSTRAP_RETRY_DELAY_MS,
|
|
110
|
+
DASHBOARD_REPORT_BOOTSTRAP_TIMEOUT_MS,
|
|
111
|
+
dashboardReportCaptureError,
|
|
112
|
+
type DashboardReportCapturePhase,
|
|
113
|
+
} from "@/lib/dashboard-report-capture";
|
|
107
114
|
import { incrementItemView } from "@/lib/item-popularity";
|
|
108
115
|
import {
|
|
109
116
|
sqlDashboardPrefetchKey,
|
|
@@ -423,14 +430,31 @@ function parseDashboardCatalogMetadata(
|
|
|
423
430
|
};
|
|
424
431
|
}
|
|
425
432
|
|
|
426
|
-
async function fetchDashboard(
|
|
433
|
+
async function fetchDashboard(
|
|
434
|
+
id: string,
|
|
435
|
+
options?: { reportScreenshot?: boolean },
|
|
436
|
+
): Promise<FetchedDashboard | null> {
|
|
427
437
|
try {
|
|
428
438
|
const data: any = await callAction(
|
|
429
439
|
"get-sql-dashboard",
|
|
430
440
|
{ id, includeConfig: true },
|
|
431
|
-
{
|
|
441
|
+
{
|
|
442
|
+
method: "GET",
|
|
443
|
+
...(options?.reportScreenshot
|
|
444
|
+
? { timeoutMs: DASHBOARD_REPORT_BOOTSTRAP_TIMEOUT_MS }
|
|
445
|
+
: {}),
|
|
446
|
+
},
|
|
432
447
|
);
|
|
433
|
-
if (!data
|
|
448
|
+
if (!data) return null;
|
|
449
|
+
if (data.error) {
|
|
450
|
+
throw new Error(
|
|
451
|
+
typeof data.message === "string" && data.message
|
|
452
|
+
? data.message
|
|
453
|
+
: typeof data.error === "string"
|
|
454
|
+
? data.error
|
|
455
|
+
: "Dashboard bootstrap failed",
|
|
456
|
+
);
|
|
457
|
+
}
|
|
434
458
|
return {
|
|
435
459
|
id,
|
|
436
460
|
config: {
|
|
@@ -463,11 +487,44 @@ async function fetchDashboard(id: string): Promise<FetchedDashboard | null> {
|
|
|
463
487
|
canManage:
|
|
464
488
|
typeof data.canManage === "boolean" ? data.canManage : undefined,
|
|
465
489
|
};
|
|
466
|
-
} catch {
|
|
490
|
+
} catch (error) {
|
|
491
|
+
if (options?.reportScreenshot) throw error;
|
|
467
492
|
return null;
|
|
468
493
|
}
|
|
469
494
|
}
|
|
470
495
|
|
|
496
|
+
function DashboardReportCaptureSurface({
|
|
497
|
+
phase,
|
|
498
|
+
panelIds,
|
|
499
|
+
error,
|
|
500
|
+
className,
|
|
501
|
+
children,
|
|
502
|
+
}: {
|
|
503
|
+
phase: DashboardReportCapturePhase;
|
|
504
|
+
panelIds?: string[];
|
|
505
|
+
error?: unknown;
|
|
506
|
+
className?: string;
|
|
507
|
+
children: React.ReactNode;
|
|
508
|
+
}) {
|
|
509
|
+
const captureError = error ? dashboardReportCaptureError(error) : undefined;
|
|
510
|
+
|
|
511
|
+
return (
|
|
512
|
+
<div
|
|
513
|
+
className={className}
|
|
514
|
+
data-dashboard-report-capture
|
|
515
|
+
data-dashboard-report-ready={phase === "ready" ? "true" : "false"}
|
|
516
|
+
data-dashboard-report-phase={phase}
|
|
517
|
+
data-dashboard-report-fetch-state={phase}
|
|
518
|
+
data-dashboard-report-error={captureError || undefined}
|
|
519
|
+
data-dashboard-report-panel-ids={
|
|
520
|
+
panelIds ? JSON.stringify(panelIds) : undefined
|
|
521
|
+
}
|
|
522
|
+
>
|
|
523
|
+
{children}
|
|
524
|
+
</div>
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
|
|
471
528
|
/**
|
|
472
529
|
* Save dashboard config via the update-dashboard action. Throws on error so
|
|
473
530
|
* callers (e.g. the panel editor dialog) can surface BigQuery validation
|
|
@@ -484,13 +541,34 @@ async function saveDashboard(
|
|
|
484
541
|
}
|
|
485
542
|
|
|
486
543
|
export default function SqlDashboardPage() {
|
|
544
|
+
const [searchParams] = useSearchParams();
|
|
545
|
+
|
|
546
|
+
if (searchParams.get("reportScreenshot") === "1") {
|
|
547
|
+
return <SqlDashboardPageContent reportScreenshot session={null} />;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
return <InteractiveSqlDashboardPage />;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
function InteractiveSqlDashboardPage() {
|
|
554
|
+
const { session } = useSession();
|
|
555
|
+
|
|
556
|
+
return <SqlDashboardPageContent reportScreenshot={false} session={session} />;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
function SqlDashboardPageContent({
|
|
560
|
+
reportScreenshot,
|
|
561
|
+
session,
|
|
562
|
+
}: {
|
|
563
|
+
reportScreenshot: boolean;
|
|
564
|
+
session: AuthSession | null;
|
|
565
|
+
}) {
|
|
487
566
|
const t = useT();
|
|
488
567
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
489
568
|
const { id: routeId } = useParams<{ id: string }>();
|
|
490
569
|
const queryClient = useQueryClient();
|
|
491
570
|
const navigate = useNavigate();
|
|
492
571
|
const dashboardId = searchParams.get("id") || routeId;
|
|
493
|
-
const reportScreenshot = searchParams.get("reportScreenshot") === "1";
|
|
494
572
|
const reportSettingsRequested = searchParams.get("reportSettings") === "1";
|
|
495
573
|
const reportPanelWindow = reportScreenshot
|
|
496
574
|
? parseReportPanelWindow(
|
|
@@ -573,8 +651,12 @@ export default function SqlDashboardPage() {
|
|
|
573
651
|
enabled: !!dashboardId,
|
|
574
652
|
queryFn: async () => {
|
|
575
653
|
if (!dashboardId) return null;
|
|
576
|
-
return fetchDashboard(dashboardId);
|
|
654
|
+
return fetchDashboard(dashboardId, { reportScreenshot });
|
|
577
655
|
},
|
|
656
|
+
retry: reportScreenshot ? 1 : false,
|
|
657
|
+
retryDelay: reportScreenshot
|
|
658
|
+
? DASHBOARD_REPORT_BOOTSTRAP_RETRY_DELAY_MS
|
|
659
|
+
: undefined,
|
|
578
660
|
staleTime: 30_000,
|
|
579
661
|
placeholderData: (prev) => prev,
|
|
580
662
|
initialData: () => {
|
|
@@ -602,7 +684,6 @@ export default function SqlDashboardPage() {
|
|
|
602
684
|
const [editingPanel, setEditingPanel] = useState<SqlPanel | null>(null);
|
|
603
685
|
|
|
604
686
|
// ── Collaborative editing ──────────────────────────────────────────
|
|
605
|
-
const { session } = useSession();
|
|
606
687
|
const currentUser: CollabUser | undefined =
|
|
607
688
|
!reportScreenshot && session?.email
|
|
608
689
|
? {
|
|
@@ -1516,41 +1597,6 @@ export default function SqlDashboardPage() {
|
|
|
1516
1597
|
<TooltipContent>{t("sqlDashboard.details")}</TooltipContent>
|
|
1517
1598
|
</Tooltip>
|
|
1518
1599
|
<DropdownMenuContent align="end" className="w-72">
|
|
1519
|
-
<DropdownMenuLabel className="font-normal">
|
|
1520
|
-
<DashboardMetadata
|
|
1521
|
-
createdAt={dashboardCreatedAt}
|
|
1522
|
-
createdBy={dashboardOwner}
|
|
1523
|
-
updatedAt={dashboardUpdatedAt}
|
|
1524
|
-
updatedBy={dashboardUpdatedBy}
|
|
1525
|
-
/>
|
|
1526
|
-
<div className="mt-2 flex flex-col gap-1.5 text-xs text-muted-foreground">
|
|
1527
|
-
{dashboardVisibility ? (
|
|
1528
|
-
<span className="flex items-center gap-1.5">
|
|
1529
|
-
{dashboardVisibility === "public" ? (
|
|
1530
|
-
<IconWorld className="h-3 w-3" />
|
|
1531
|
-
) : dashboardVisibility === "org" ? (
|
|
1532
|
-
<IconUsersGroup className="h-3 w-3" />
|
|
1533
|
-
) : (
|
|
1534
|
-
<IconLock className="h-3 w-3" />
|
|
1535
|
-
)}
|
|
1536
|
-
{dashboardVisibility === "public"
|
|
1537
|
-
? t("sqlDashboard.public")
|
|
1538
|
-
: dashboardVisibility === "org"
|
|
1539
|
-
? t("sqlDashboard.sharedWithOrg")
|
|
1540
|
-
: t("sqlDashboard.private")}
|
|
1541
|
-
</span>
|
|
1542
|
-
) : null}
|
|
1543
|
-
{hiddenAt && (
|
|
1544
|
-
<span className="flex items-center gap-1.5 font-medium text-amber-600 dark:text-amber-400">
|
|
1545
|
-
<IconEyeOff className="h-3 w-3" />
|
|
1546
|
-
{t("sqlDashboard.hidden")}
|
|
1547
|
-
</span>
|
|
1548
|
-
)}
|
|
1549
|
-
</div>
|
|
1550
|
-
</DropdownMenuLabel>
|
|
1551
|
-
{(canEdit && !archivedAt) || canManage ? (
|
|
1552
|
-
<DropdownMenuSeparator />
|
|
1553
|
-
) : null}
|
|
1554
1600
|
{dashboardId && canEdit && !archivedAt ? (
|
|
1555
1601
|
<DropdownMenuItem
|
|
1556
1602
|
onSelect={(event) => {
|
|
@@ -1616,6 +1662,41 @@ export default function SqlDashboardPage() {
|
|
|
1616
1662
|
{t("sqlDashboard.deletePermanently")}
|
|
1617
1663
|
</DropdownMenuItem>
|
|
1618
1664
|
) : null}
|
|
1665
|
+
{dashboardId || (canEdit && !archivedAt) || canManage ? (
|
|
1666
|
+
<DropdownMenuSeparator />
|
|
1667
|
+
) : null}
|
|
1668
|
+
<DropdownMenuLabel className="font-normal">
|
|
1669
|
+
<DashboardMetadata
|
|
1670
|
+
createdAt={dashboardCreatedAt}
|
|
1671
|
+
createdBy={dashboardOwner}
|
|
1672
|
+
updatedAt={dashboardUpdatedAt}
|
|
1673
|
+
updatedBy={dashboardUpdatedBy}
|
|
1674
|
+
/>
|
|
1675
|
+
<div className="mt-2 flex flex-col gap-1.5 text-xs text-muted-foreground">
|
|
1676
|
+
{dashboardVisibility ? (
|
|
1677
|
+
<span className="flex items-center gap-1.5">
|
|
1678
|
+
{dashboardVisibility === "public" ? (
|
|
1679
|
+
<IconWorld className="h-3 w-3" />
|
|
1680
|
+
) : dashboardVisibility === "org" ? (
|
|
1681
|
+
<IconUsersGroup className="h-3 w-3" />
|
|
1682
|
+
) : (
|
|
1683
|
+
<IconLock className="h-3 w-3" />
|
|
1684
|
+
)}
|
|
1685
|
+
{dashboardVisibility === "public"
|
|
1686
|
+
? t("sqlDashboard.public")
|
|
1687
|
+
: dashboardVisibility === "org"
|
|
1688
|
+
? t("sqlDashboard.sharedWithOrg")
|
|
1689
|
+
: t("sqlDashboard.private")}
|
|
1690
|
+
</span>
|
|
1691
|
+
) : null}
|
|
1692
|
+
{hiddenAt && (
|
|
1693
|
+
<span className="flex items-center gap-1.5 font-medium text-amber-600 dark:text-amber-400">
|
|
1694
|
+
<IconEyeOff className="h-3 w-3" />
|
|
1695
|
+
{t("sqlDashboard.hidden")}
|
|
1696
|
+
</span>
|
|
1697
|
+
)}
|
|
1698
|
+
</div>
|
|
1699
|
+
</DropdownMenuLabel>
|
|
1619
1700
|
</DropdownMenuContent>
|
|
1620
1701
|
</DropdownMenu>
|
|
1621
1702
|
{dashboardId ? (
|
|
@@ -1687,6 +1768,15 @@ export default function SqlDashboardPage() {
|
|
|
1687
1768
|
);
|
|
1688
1769
|
|
|
1689
1770
|
if (!dashboardId) {
|
|
1771
|
+
if (reportScreenshot) {
|
|
1772
|
+
return (
|
|
1773
|
+
<DashboardReportCaptureSurface phase="missing">
|
|
1774
|
+
<div className="flex h-64 items-center justify-center text-muted-foreground">
|
|
1775
|
+
{t("sqlDashboard.noDashboardSelected")}
|
|
1776
|
+
</div>
|
|
1777
|
+
</DashboardReportCaptureSurface>
|
|
1778
|
+
);
|
|
1779
|
+
}
|
|
1690
1780
|
return (
|
|
1691
1781
|
<div className="flex items-center justify-center h-64 text-muted-foreground">
|
|
1692
1782
|
{t("sqlDashboard.noDashboardSelected")}
|
|
@@ -1694,21 +1784,42 @@ export default function SqlDashboardPage() {
|
|
|
1694
1784
|
);
|
|
1695
1785
|
}
|
|
1696
1786
|
|
|
1787
|
+
if (reportScreenshot && dashboardQuery.isError) {
|
|
1788
|
+
return (
|
|
1789
|
+
<DashboardReportCaptureSurface phase="error" error={dashboardQuery.error}>
|
|
1790
|
+
<DashboardSkeleton />
|
|
1791
|
+
</DashboardReportCaptureSurface>
|
|
1792
|
+
);
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1697
1795
|
if (!loaded) {
|
|
1796
|
+
if (reportScreenshot) {
|
|
1797
|
+
return (
|
|
1798
|
+
<DashboardReportCaptureSurface phase="loading">
|
|
1799
|
+
<DashboardSkeleton />
|
|
1800
|
+
</DashboardReportCaptureSurface>
|
|
1801
|
+
);
|
|
1802
|
+
}
|
|
1698
1803
|
return <DashboardSkeleton />;
|
|
1699
1804
|
}
|
|
1700
1805
|
|
|
1701
|
-
if (!dashboard)
|
|
1806
|
+
if (!dashboard) {
|
|
1807
|
+
if (reportScreenshot) {
|
|
1808
|
+
return (
|
|
1809
|
+
<DashboardReportCaptureSurface phase="missing">
|
|
1810
|
+
<BlankDashboard />
|
|
1811
|
+
</DashboardReportCaptureSurface>
|
|
1812
|
+
);
|
|
1813
|
+
}
|
|
1814
|
+
return <BlankDashboard />;
|
|
1815
|
+
}
|
|
1702
1816
|
|
|
1703
1817
|
return (
|
|
1704
|
-
<
|
|
1818
|
+
<DashboardReportCaptureSurface
|
|
1705
1819
|
className="space-y-4"
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
reportScreenshot
|
|
1710
|
-
? JSON.stringify(listReportablePanelIds(visiblePanels))
|
|
1711
|
-
: undefined
|
|
1820
|
+
phase="ready"
|
|
1821
|
+
panelIds={
|
|
1822
|
+
reportScreenshot ? listReportablePanelIds(visiblePanels) : undefined
|
|
1712
1823
|
}
|
|
1713
1824
|
>
|
|
1714
1825
|
{hiddenAt ? (
|
|
@@ -2031,6 +2142,6 @@ export default function SqlDashboardPage() {
|
|
|
2031
2142
|
existingPanelTitles={dashboard.panels.map((p) => p.title)}
|
|
2032
2143
|
/>
|
|
2033
2144
|
) : null}
|
|
2034
|
-
</
|
|
2145
|
+
</DashboardReportCaptureSurface>
|
|
2035
2146
|
);
|
|
2036
2147
|
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
createAgentNativeQueryClient,
|
|
7
7
|
useDbSync,
|
|
8
8
|
} from "@agent-native/core/client/hooks";
|
|
9
|
+
import { getEmbedAuthToken } from "@agent-native/core/client/host";
|
|
9
10
|
import { getLocaleInitScript } from "@agent-native/core/client/i18n";
|
|
10
11
|
import { getThemeInitScript } from "@agent-native/core/client/ui";
|
|
11
12
|
import { useQueryClient } from "@tanstack/react-query";
|
|
@@ -31,6 +32,10 @@ import { TAB_ID } from "@/lib/tab-id";
|
|
|
31
32
|
import { CommandPalette } from "./components/layout/CommandPalette";
|
|
32
33
|
import { Layout as AppLayout } from "./components/layout/Layout";
|
|
33
34
|
import { i18nCatalog } from "./i18n";
|
|
35
|
+
import {
|
|
36
|
+
hasDashboardReportEmbedToken,
|
|
37
|
+
isDashboardReportScreenshot,
|
|
38
|
+
} from "./lib/dashboard-report-capture";
|
|
34
39
|
|
|
35
40
|
import stylesheet from "./global.css?url";
|
|
36
41
|
configureTracking({
|
|
@@ -146,6 +151,11 @@ export default function Root() {
|
|
|
146
151
|
// server/plugins/auth.ts.
|
|
147
152
|
const isPublicStatusPath =
|
|
148
153
|
location.pathname === "/status" || location.pathname.startsWith("/status/");
|
|
154
|
+
const isDashboardReportCapture = isDashboardReportScreenshot(location.search);
|
|
155
|
+
const hasReportEmbedToken = hasDashboardReportEmbedToken(
|
|
156
|
+
location.search,
|
|
157
|
+
getEmbedAuthToken(),
|
|
158
|
+
);
|
|
149
159
|
|
|
150
160
|
if (isPublicStatusPath) {
|
|
151
161
|
return (
|
|
@@ -163,6 +173,24 @@ export default function Root() {
|
|
|
163
173
|
);
|
|
164
174
|
}
|
|
165
175
|
|
|
176
|
+
if (isDashboardReportCapture && hasReportEmbedToken) {
|
|
177
|
+
return (
|
|
178
|
+
<AppToolkitProvider>
|
|
179
|
+
<AppProviders
|
|
180
|
+
queryClient={queryClient}
|
|
181
|
+
sessionBypass
|
|
182
|
+
defaultTheme="dark"
|
|
183
|
+
toaster={null}
|
|
184
|
+
i18n={{ catalog: i18nCatalog }}
|
|
185
|
+
>
|
|
186
|
+
<AppLayout>
|
|
187
|
+
<Outlet />
|
|
188
|
+
</AppLayout>
|
|
189
|
+
</AppProviders>
|
|
190
|
+
</AppToolkitProvider>
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
166
194
|
return (
|
|
167
195
|
// defaultTheme="dark": analytics defaults to dark mode if no stored preference.
|
|
168
196
|
// toaster={null}: suppress AppProviders' built-in sonner; analytics renders
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"chartType": "area",
|
|
76
76
|
"source": "first-party",
|
|
77
77
|
"width": 2,
|
|
78
|
-
"sql": "WITH
|
|
78
|
+
"sql": "WITH digits AS (SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9), offsets AS (SELECT ones.n + tens.n * 10 + hundreds.n * 100 AS n FROM digits ones CROSS JOIN digits tens CROSS JOIN digits hundreds WHERE hundreds.n < 8), signup_events AS (SELECT event_date AS date, COALESCE(NULLIF(template, ''), NULLIF(properties::jsonb ->> 'templateId', ''), NULLIF(properties::jsonb ->> 'agent_native_template', ''), NULLIF(properties::jsonb ->> 'agentNativeTemplate', ''), NULLIF(app, ''), NULLIF(properties::jsonb ->> 'agent_native_app', ''), NULLIF(properties::jsonb ->> 'agentNativeApp', ''), 'unknown') AS template FROM analytics_events WHERE event_name = 'signup' AND (event_date <= to_char(CURRENT_DATE, 'YYYY-MM-DD') AND ('{{timeRange}}' IN ('', 'all') OR ('{{timeRange}}' = '7d' AND event_date >= to_char(CURRENT_DATE - INTERVAL '7 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '30d' AND event_date >= to_char(CURRENT_DATE - INTERVAL '30 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '90d' AND event_date >= to_char(CURRENT_DATE - INTERVAL '90 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '180d' AND event_date >= to_char(CURRENT_DATE - INTERVAL '180 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '365d' AND event_date >= to_char(CURRENT_DATE - INTERVAL '365 days', 'YYYY-MM-DD')))) AND ('{{emailFilter}}' IN ('', 'all') OR ('{{emailFilter}}' = 'exclude_builder' AND lower(coalesce(user_id, '')) NOT LIKE '%@builder.io') OR ('{{emailFilter}}' = 'only_builder' AND lower(coalesce(user_id, '')) LIKE '%@builder.io'))), bounds AS (SELECT MIN(date::date) AS start_date, MAX(date::date) AS end_date FROM signup_events), dates AS (SELECT to_char(bounds.start_date + offsets.n, 'YYYY-MM-DD') AS date FROM bounds CROSS JOIN offsets WHERE bounds.start_date IS NOT NULL AND bounds.start_date + offsets.n <= bounds.end_date), templates AS (SELECT DISTINCT template FROM signup_events), daily AS (SELECT date, template, COUNT(*) AS count FROM signup_events GROUP BY date, template) SELECT dates.date, templates.template, COALESCE(daily.count, 0) AS count FROM dates CROSS JOIN templates LEFT JOIN daily ON daily.date = dates.date AND daily.template = templates.template ORDER BY dates.date, templates.template",
|
|
79
79
|
"config": {
|
|
80
80
|
"xKey": "date",
|
|
81
81
|
"yKey": "count",
|
|
@@ -113,6 +113,11 @@ export const dashboardReportSubscriptions = table(
|
|
|
113
113
|
enum: ["success", "error", "running"],
|
|
114
114
|
}),
|
|
115
115
|
lastError: text("last_error"),
|
|
116
|
+
lastCaptureAt: text("last_capture_at"),
|
|
117
|
+
lastCaptureMode: text("last_capture_mode", {
|
|
118
|
+
enum: ["full", "partial", "none"],
|
|
119
|
+
}),
|
|
120
|
+
lastCaptureError: text("last_capture_error"),
|
|
116
121
|
createdAt: text("created_at").notNull().default(now()),
|
|
117
122
|
updatedAt: text("updated_at").notNull().default(now()),
|
|
118
123
|
ownerEmail: text("owner_email").notNull().default("local@localhost"),
|