@burdenoff/microfe-vibecontrols 2026.623.1 → 2026.623.2
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/dist/components/actions/ActionCard.js +2 -2
- package/dist/components/actions/ActionCard.js.map +1 -1
- package/dist/components/actions/ExecutionHistory.js +1 -1
- package/dist/components/actions/ExecutionHistory.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerAdminBar.js +1 -1
- package/dist/components/agent-manager/AgentManagerAdminBar.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerChatPane.js +2 -2
- package/dist/components/agent-manager/AgentManagerChatPane.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerInputArea.js +4 -4
- package/dist/components/agent-manager/AgentManagerInputArea.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerLayout.js +1 -1
- package/dist/components/agent-manager/AgentManagerLayout.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerMessageItem.js +1 -1
- package/dist/components/agent-manager/AgentManagerMessageItem.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerSidebar.js +5 -5
- package/dist/components/agent-manager/AgentManagerSidebar.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerTab.js +1 -1
- package/dist/components/agent-manager/AgentManagerTab.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerTabBar.js +1 -1
- package/dist/components/agent-manager/AgentManagerTabBar.js.map +1 -1
- package/dist/components/agent-manager/BridleConfigPanel.js +23 -23
- package/dist/components/agent-manager/BridleConfigPanel.js.map +1 -1
- package/dist/components/agent-manager/PluginInstallModal.js +1 -1
- package/dist/components/agent-manager/PluginInstallModal.js.map +1 -1
- package/dist/components/agent-manager/ProfilesPanel.js +5 -5
- package/dist/components/agent-manager/ProfilesPanel.js.map +1 -1
- package/dist/components/agent-manager/controls/AutonomySelector.js +1 -1
- package/dist/components/agent-manager/controls/AutonomySelector.js.map +1 -1
- package/dist/components/agent-manager/controls/SdkSelector.js +1 -1
- package/dist/components/agent-manager/controls/SdkSelector.js.map +1 -1
- package/dist/components/agent-manager/controls/VoiceToggle.js +1 -1
- package/dist/components/agent-manager/controls/VoiceToggle.js.map +1 -1
- package/dist/components/agent-manager/detail/SessionConfigPanel.js +6 -6
- package/dist/components/agent-manager/detail/SessionConfigPanel.js.map +1 -1
- package/dist/components/agent-manager/detail/SessionLogsPanel.js +5 -5
- package/dist/components/agent-manager/detail/SessionLogsPanel.js.map +1 -1
- package/dist/components/agent-manager/detail/SessionToolsPanel.js +1 -1
- package/dist/components/agent-manager/detail/SessionToolsPanel.js.map +1 -1
- package/dist/components/agent-manager/dialogs/NewSessionDialog.js +2 -2
- package/dist/components/agent-manager/dialogs/NewSessionDialog.js.map +1 -1
- package/dist/components/agent-manager/dialogs/RenameSessionDialog.js +1 -1
- package/dist/components/agent-manager/dialogs/RenameSessionDialog.js.map +1 -1
- package/dist/components/agents/AgentCard.js +14 -11
- package/dist/components/agents/AgentCard.js.map +1 -1
- package/dist/components/ai/AIContextsTab.js +1 -1
- package/dist/components/ai/AIContextsTab.js.map +1 -1
- package/dist/components/ai/AIOverviewTab.js +4 -4
- package/dist/components/ai/AIOverviewTab.js.map +1 -1
- package/dist/components/ai/AIPlanPanel.js +4 -4
- package/dist/components/ai/AIPlanPanel.js.map +1 -1
- package/dist/components/ai/AIPlaygroundTab.js +1 -1
- package/dist/components/ai/AIPlaygroundTab.js.map +1 -1
- package/dist/components/ai/AIPromptsTab.js +2 -2
- package/dist/components/ai/AIPromptsTab.js.map +1 -1
- package/dist/components/ai/AIProviderCredentialsCard.js +4 -4
- package/dist/components/ai/AIProviderCredentialsCard.js.map +1 -1
- package/dist/components/ai/AIQueueTab.js +4 -4
- package/dist/components/ai/AIQueueTab.js.map +1 -1
- package/dist/components/ai/AISessionsTab.js +4 -4
- package/dist/components/ai/AISessionsTab.js.map +1 -1
- package/dist/components/ai/AITasksTab.js +1 -1
- package/dist/components/ai/AITasksTab.js.map +1 -1
- package/dist/components/ai/ClaudeCredentialsCard.js +3 -3
- package/dist/components/ai/ClaudeCredentialsCard.js.map +1 -1
- package/dist/components/ai/PluginHarnessPicker.js +3 -3
- package/dist/components/ai/PluginHarnessPicker.js.map +1 -1
- package/dist/components/analytics/AnalyticsBreakdownChart.js +8 -8
- package/dist/components/analytics/AnalyticsBreakdownChart.js.map +1 -1
- package/dist/components/analytics/AnalyticsTimeSeriesChart.js +5 -5
- package/dist/components/analytics/AnalyticsTimeSeriesChart.js.map +1 -1
- package/dist/components/audit/AuditDeleteDialog.js +2 -2
- package/dist/components/audit/AuditDeleteDialog.js.map +1 -1
- package/dist/components/audit/AuditExportButton.js +5 -5
- package/dist/components/audit/AuditExportButton.js.map +1 -1
- package/dist/components/audit/AuditLogDetail.js +9 -9
- package/dist/components/audit/AuditLogDetail.js.map +1 -1
- package/dist/components/audit/AuditLogFilters.js +1 -1
- package/dist/components/audit/AuditLogFilters.js.map +1 -1
- package/dist/components/audit/AuditLogStats.js +1 -1
- package/dist/components/audit/AuditLogStats.js.map +1 -1
- package/dist/components/audit/AuditLogTable.js +28 -28
- package/dist/components/audit/AuditLogTable.js.map +1 -1
- package/dist/components/catalog/CatalogCard.js +3 -3
- package/dist/components/catalog/CatalogCard.js.map +1 -1
- package/dist/components/catalog/CatalogForm.js +1 -1
- package/dist/components/catalog/CatalogForm.js.map +1 -1
- package/dist/components/common/ActionAgentTargetNotice.js +6 -6
- package/dist/components/common/ActionAgentTargetNotice.js.map +1 -1
- package/dist/components/common/CommandEditor.js +1 -1
- package/dist/components/common/CommandEditor.js.map +1 -1
- package/dist/components/docs/DocsPageTree.js +1 -1
- package/dist/components/docs/DocsPageTree.js.map +1 -1
- package/dist/components/docs/DocsPreviewPanel.js +1 -1
- package/dist/components/docs/DocsPreviewPanel.js.map +1 -1
- package/dist/components/docs/DocsRevisionHistory.js +4 -4
- package/dist/components/docs/DocsRevisionHistory.js.map +1 -1
- package/dist/components/docs/DocsSettingsPanel.js +7 -7
- package/dist/components/docs/DocsSettingsPanel.js.map +1 -1
- package/dist/components/docs/DocsTabPanel.js +1 -1
- package/dist/components/docs/DocsTabPanel.js.map +1 -1
- package/dist/components/graph/ConnectionPermissionsDialog.js +2 -2
- package/dist/components/graph/ConnectionPermissionsDialog.js.map +1 -1
- package/dist/components/graph/MeshDeployWizard.js +3 -3
- package/dist/components/graph/MeshDeployWizard.js.map +1 -1
- package/dist/components/graph/MeshRequestPanel.js +2 -2
- package/dist/components/graph/MeshRequestPanel.js.map +1 -1
- package/dist/components/idp-components/ComponentCard.js +5 -5
- package/dist/components/idp-components/ComponentCard.js.map +1 -1
- package/dist/components/idp-components/ComponentForm.js +1 -1
- package/dist/components/idp-components/ComponentForm.js.map +1 -1
- package/dist/components/idp-components/DependencyGraphTab.js +7 -7
- package/dist/components/idp-components/DependencyGraphTab.js.map +1 -1
- package/dist/components/logs/LogViewer.js +14 -14
- package/dist/components/logs/LogViewer.js.map +1 -1
- package/dist/components/notes/NoteCard.js +1 -1
- package/dist/components/notes/NoteCard.js.map +1 -1
- package/dist/components/notes/NoteEditor.js +2 -2
- package/dist/components/notes/NoteEditor.js.map +1 -1
- package/dist/components/notes/NoteList.js +1 -1
- package/dist/components/notes/NoteList.js.map +1 -1
- package/dist/components/notes/NotesTabPanel.js +1 -1
- package/dist/components/notes/NotesTabPanel.js.map +1 -1
- package/dist/components/scorecard/ScorecardEmptyState.js +1 -1
- package/dist/components/scorecard/ScorecardEmptyState.js.map +1 -1
- package/dist/components/scorecard/ScorecardPanel.js +3 -3
- package/dist/components/scorecard/ScorecardPanel.js.map +1 -1
- package/dist/components/security/SecurityScanList.js +11 -11
- package/dist/components/security/SecurityScanList.js.map +1 -1
- package/dist/components/sessions/SessionCard.js +26 -19
- package/dist/components/sessions/SessionCard.js.map +1 -1
- package/dist/components/sessions/SessionStatusBadge.js +7 -7
- package/dist/components/sessions/SessionStatusBadge.js.map +1 -1
- package/dist/components/shared/AgentSelector.js +4 -4
- package/dist/components/shared/AgentSelector.js.map +1 -1
- package/dist/components/shared/AgentSetupBanner.js +3 -3
- package/dist/components/shared/AgentSetupBanner.js.map +1 -1
- package/dist/components/shared/Card.js +4 -4
- package/dist/components/shared/Card.js.map +1 -1
- package/dist/components/shared/ErrorState.js +15 -9
- package/dist/components/shared/ErrorState.js.map +1 -1
- package/dist/components/shared/FilterDropdown.js +2 -2
- package/dist/components/shared/FilterDropdown.js.map +1 -1
- package/dist/components/shared/PageSkeleton.js +6 -6
- package/dist/components/shared/PageSkeleton.js.map +1 -1
- package/dist/components/shared/SearchInput.js +1 -1
- package/dist/components/shared/SearchInput.js.map +1 -1
- package/dist/components/shared/StatCard.js +7 -7
- package/dist/components/shared/StatCard.js.map +1 -1
- package/dist/components/templates/PublishTemplateForm.js +2 -2
- package/dist/components/templates/PublishTemplateForm.js.map +1 -1
- package/dist/components/templates/TemplateCard.js +5 -5
- package/dist/components/templates/TemplateCard.js.map +1 -1
- package/dist/components/templates/TemplateWizard.js +2 -2
- package/dist/components/templates/TemplateWizard.js.map +1 -1
- package/dist/components/tunnels/DomainVerificationBadge.js +4 -4
- package/dist/components/tunnels/DomainVerificationBadge.js.map +1 -1
- package/dist/components/tunnels/ProviderBadge.js +1 -1
- package/dist/components/tunnels/ProviderBadge.js.map +1 -1
- package/dist/components/tunnels/TunnelCard.js +16 -16
- package/dist/components/tunnels/TunnelCard.js.map +1 -1
- package/dist/components/tunnels/TunnelCreateWizard.js +1 -1
- package/dist/components/tunnels/TunnelCreateWizard.js.map +1 -1
- package/dist/components/tunnels/TunnelPublicAccessPanel.js +1 -1
- package/dist/components/tunnels/TunnelPublicAccessPanel.js.map +1 -1
- package/dist/components/tunnels/TunnelStatusBadge.js +4 -4
- package/dist/components/tunnels/TunnelStatusBadge.js.map +1 -1
- package/dist/components/vibecalendar/LogsDrawer.js +2 -2
- package/dist/components/vibecalendar/LogsDrawer.js.map +1 -1
- package/dist/components/vibecalendar/ScheduleTaskModal.js +5 -5
- package/dist/components/vibecalendar/ScheduleTaskModal.js.map +1 -1
- package/dist/components/vibecalendar/VibeCalAgendaView.js +2 -2
- package/dist/components/vibecalendar/VibeCalAgendaView.js.map +1 -1
- package/dist/components/vibecalendar/VibeCalDayView.js +3 -3
- package/dist/components/vibecalendar/VibeCalDayView.js.map +1 -1
- package/dist/components/vibecalendar/VibeCalMonthView.js +1 -1
- package/dist/components/vibecalendar/VibeCalMonthView.js.map +1 -1
- package/dist/components/vibecalendar/VibeCalWeekView.js +4 -4
- package/dist/components/vibecalendar/VibeCalWeekView.js.map +1 -1
- package/dist/components/vibecalendar/VibeCalendarHeader.js +4 -4
- package/dist/components/vibecalendar/VibeCalendarHeader.js.map +1 -1
- package/dist/components/vibecalendar/VibeTaskBlock.js +2 -2
- package/dist/components/vibecalendar/VibeTaskBlock.js.map +1 -1
- package/dist/components/vibecalendar/types.js +6 -6
- package/dist/components/vibecalendar/types.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckButtonForm.js +9 -9
- package/dist/components/vibedeck/VibeDeckButtonForm.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckButtonTile.js +6 -6
- package/dist/components/vibedeck/VibeDeckButtonTile.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckExecutionLog.js +10 -10
- package/dist/components/vibedeck/VibeDeckExecutionLog.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckForm.js +8 -8
- package/dist/components/vibedeck/VibeDeckForm.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckGrid.js +2 -2
- package/dist/components/vibedeck/VibeDeckGrid.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckPublicLinkPanel.js +2 -2
- package/dist/components/vibedeck/VibeDeckPublicLinkPanel.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckSwitcher.js +8 -8
- package/dist/components/vibedeck/VibeDeckSwitcher.js.map +1 -1
- package/dist/components/vibes/VibeCard.js +22 -18
- package/dist/components/vibes/VibeCard.js.map +1 -1
- package/dist/components/vibes/VibeList.js +16 -12
- package/dist/components/vibes/VibeList.js.map +1 -1
- package/dist/pages/ActionsPage.js +4 -3
- package/dist/pages/ActionsPage.js.map +1 -1
- package/dist/pages/AgentDetailsPage.js +9 -9
- package/dist/pages/AgentDetailsPage.js.map +1 -1
- package/dist/pages/AgentsLandingPage.js +4 -4
- package/dist/pages/AgentsLandingPage.js.map +1 -1
- package/dist/pages/AgentsPage.js +14 -14
- package/dist/pages/AgentsPage.js.map +1 -1
- package/dist/pages/AnalyticsPage.js +8 -8
- package/dist/pages/AnalyticsPage.js.map +1 -1
- package/dist/pages/CatalogDetailPage.js +11 -11
- package/dist/pages/CatalogDetailPage.js.map +1 -1
- package/dist/pages/CatalogPage.js +12 -9
- package/dist/pages/CatalogPage.js.map +1 -1
- package/dist/pages/ComponentDetailPage.js +7 -7
- package/dist/pages/ComponentDetailPage.js.map +1 -1
- package/dist/pages/ComponentsPage.js +12 -9
- package/dist/pages/ComponentsPage.js.map +1 -1
- package/dist/pages/EnvTopologyPage.js +2 -2
- package/dist/pages/EnvTopologyPage.js.map +1 -1
- package/dist/pages/GettingStartedPage.js +12 -12
- package/dist/pages/GettingStartedPage.js.map +1 -1
- package/dist/pages/HealthPage.js +12 -12
- package/dist/pages/HealthPage.js.map +1 -1
- package/dist/pages/LogsPage.js +4 -4
- package/dist/pages/LogsPage.js.map +1 -1
- package/dist/pages/NoteDetailsPage.js +5 -5
- package/dist/pages/NoteDetailsPage.js.map +1 -1
- package/dist/pages/OverviewPage.js +74 -41
- package/dist/pages/OverviewPage.js.map +1 -1
- package/dist/pages/PluginsCatalogPage.js +6 -3
- package/dist/pages/PluginsCatalogPage.js.map +1 -1
- package/dist/pages/ScheduledJobDetailPage.js +7 -7
- package/dist/pages/ScheduledJobDetailPage.js.map +1 -1
- package/dist/pages/SessionDetailsPage.js +21 -21
- package/dist/pages/SessionDetailsPage.js.map +1 -1
- package/dist/pages/SessionsPage.js +20 -20
- package/dist/pages/SessionsPage.js.map +1 -1
- package/dist/pages/SettingsPage.js +64 -52
- package/dist/pages/SettingsPage.js.map +1 -1
- package/dist/pages/SharedSessionPage.js +21 -21
- package/dist/pages/SharedSessionPage.js.map +1 -1
- package/dist/pages/SharedVibeDeckPage.js +5 -5
- package/dist/pages/SharedVibeDeckPage.js.map +1 -1
- package/dist/pages/TargetDetailsPage.js +56 -65
- package/dist/pages/TargetDetailsPage.js.map +1 -1
- package/dist/pages/TargetsPage.js +4 -4
- package/dist/pages/TargetsPage.js.map +1 -1
- package/dist/pages/TemplateDetailPage.js +10 -10
- package/dist/pages/TemplateDetailPage.js.map +1 -1
- package/dist/pages/TemplatesPage.js +6 -5
- package/dist/pages/TemplatesPage.js.map +1 -1
- package/dist/pages/VibeAuditPage.js +3 -3
- package/dist/pages/VibeAuditPage.js.map +1 -1
- package/dist/pages/VibeCalendarPage.js +3 -3
- package/dist/pages/VibeCalendarPage.js.map +1 -1
- package/dist/pages/VibeDeckPage.js +3 -3
- package/dist/pages/VibeDeckPage.js.map +1 -1
- package/dist/pages/VibeDetailsPage.js +15 -15
- package/dist/pages/VibeDetailsPage.js.map +1 -1
- package/dist/pages/VibeTaskDetailPage.js +5 -5
- package/dist/pages/VibeTaskDetailPage.js.map +1 -1
- package/dist/pages/VibesPage.js +18 -18
- package/dist/pages/VibesPage.js.map +1 -1
- package/dist/pages/WebhooksPage.js +11 -11
- package/dist/pages/WebhooksPage.js.map +1 -1
- package/dist/pages/ai/AIBookmarksPage.js +1 -1
- package/dist/pages/ai/AIBookmarksPage.js.map +1 -1
- package/dist/pages/ai/AISessionDetailPage.js +6 -6
- package/dist/pages/ai/AISessionDetailPage.js.map +1 -1
- package/dist/pages/tunnels/AuditTab.js +1 -1
- package/dist/pages/tunnels/AuditTab.js.map +1 -1
- package/dist/pages/tunnels/DomainsTab.js +1 -1
- package/dist/pages/tunnels/DomainsTab.js.map +1 -1
- package/dist/pages/tunnels/ProvidersTab.js +1 -1
- package/dist/pages/tunnels/ProvidersTab.js.map +1 -1
- package/dist/pages/tunnels/SessionsTab.js +1 -1
- package/dist/pages/tunnels/SessionsTab.js.map +1 -1
- package/dist/pages/tunnels/TunnelDetailsPage.js +3 -3
- package/dist/pages/tunnels/TunnelDetailsPage.js.map +1 -1
- package/dist/pages/tunnels/UsageTab.js +1 -1
- package/dist/pages/tunnels/UsageTab.js.map +1 -1
- package/dist/pages/tunnels/tabs/TunnelDomainsTab.js +16 -16
- package/dist/pages/tunnels/tabs/TunnelDomainsTab.js.map +1 -1
- package/dist/pages/tunnels/tabs/TunnelOverviewTab.js +1 -1
- package/dist/pages/tunnels/tabs/TunnelOverviewTab.js.map +1 -1
- package/dist/pages/tunnels/tabs/TunnelSessionsTab.js +52 -49
- package/dist/pages/tunnels/tabs/TunnelSessionsTab.js.map +1 -1
- package/dist/pages/tunnels/tabs/TunnelSettingsTab.js +9 -9
- package/dist/pages/tunnels/tabs/TunnelSettingsTab.js.map +1 -1
- package/package.json +1 -1
|
@@ -79,7 +79,7 @@ function j() {
|
|
|
79
79
|
children: /* @__PURE__ */ T("div", {
|
|
80
80
|
className: "text-center space-y-2",
|
|
81
81
|
children: [/* @__PURE__ */ w("h2", {
|
|
82
|
-
className: "text-lg font-semibold text-
|
|
82
|
+
className: "text-lg font-semibold text-text-primary",
|
|
83
83
|
children: "Access Denied"
|
|
84
84
|
}), /* @__PURE__ */ w("p", {
|
|
85
85
|
className: "text-sm text-text-secondary",
|
|
@@ -88,7 +88,7 @@ function j() {
|
|
|
88
88
|
})
|
|
89
89
|
});
|
|
90
90
|
if (!a) return /* @__PURE__ */ T(E, {
|
|
91
|
-
className: "min-h-screen space-y-6 bg-bg-
|
|
91
|
+
className: "min-h-screen space-y-6 bg-bg-canvas px-6 lg:px-8 py-6",
|
|
92
92
|
children: [/* @__PURE__ */ w(r, { title: W("nav.analytics", "Analytics") }), /* @__PURE__ */ w("div", {
|
|
93
93
|
className: "text-sm text-text-secondary",
|
|
94
94
|
children: "Waiting for workspace context…"
|
|
@@ -97,9 +97,9 @@ function j() {
|
|
|
97
97
|
if (X && !Q) {
|
|
98
98
|
let e = X.message ?? "", t = e.includes("upstream connect error") || e.includes("Connection refused") || e.includes("disconnect/reset before headers") || e.includes("Unexpected response");
|
|
99
99
|
return /* @__PURE__ */ T(E, {
|
|
100
|
-
className: "min-h-screen space-y-6 bg-bg-
|
|
100
|
+
className: "min-h-screen space-y-6 bg-bg-canvas px-6 lg:px-8 py-6",
|
|
101
101
|
children: [/* @__PURE__ */ w(r, { title: W("nav.analytics", "Analytics") }), /* @__PURE__ */ T("div", {
|
|
102
|
-
className: "space-y-3 rounded-
|
|
102
|
+
className: "space-y-3 rounded-card border border-status-warning-border bg-status-warning-bg-subtle p-4 text-sm text-text-primary",
|
|
103
103
|
children: [t ? /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w("p", {
|
|
104
104
|
className: "font-medium",
|
|
105
105
|
children: W("analyticsPage.transientUnavailable", "Analytics is temporarily unavailable")
|
|
@@ -109,14 +109,14 @@ function j() {
|
|
|
109
109
|
})] }) : /* @__PURE__ */ T("p", { children: ["Failed to load analytics: ", X.message] }), /* @__PURE__ */ w("button", {
|
|
110
110
|
type: "button",
|
|
111
111
|
onClick: $,
|
|
112
|
-
className: "rounded-
|
|
112
|
+
className: "rounded-button border border-status-warning-border bg-status-warning-bg-subtle px-3 py-1.5 text-xs font-medium text-status-warning-text transition-colors hover:bg-bg-sunken",
|
|
113
113
|
children: W("analyticsPage.retry", "Retry")
|
|
114
114
|
})]
|
|
115
115
|
})]
|
|
116
116
|
});
|
|
117
117
|
}
|
|
118
118
|
return /* @__PURE__ */ T(E, {
|
|
119
|
-
className: "min-h-screen space-y-
|
|
119
|
+
className: "min-h-screen space-y-6 bg-bg-canvas px-6 lg:px-8 py-6 vc-printable",
|
|
120
120
|
children: [
|
|
121
121
|
/* @__PURE__ */ w(r, { title: W("nav.analytics", "Analytics") }),
|
|
122
122
|
/* @__PURE__ */ w("div", {
|
|
@@ -539,12 +539,12 @@ function j() {
|
|
|
539
539
|
}
|
|
540
540
|
function M({ label: e, value: t, variant: n }) {
|
|
541
541
|
return /* @__PURE__ */ T("div", {
|
|
542
|
-
className: `${n === "success" ? "bg-status-success-bg
|
|
542
|
+
className: `${n === "success" ? "bg-status-success-bg-subtle border-status-success-border" : n === "warning" ? "bg-status-warning-bg-subtle border-status-warning-border" : n === "error" ? "bg-status-error-bg-subtle border-status-error-border" : "bg-bg-surface border-border-subtle"} rounded-card border p-4 shadow-elevation-1`,
|
|
543
543
|
children: [/* @__PURE__ */ w("p", {
|
|
544
544
|
className: "text-xs text-text-secondary",
|
|
545
545
|
children: e
|
|
546
546
|
}), /* @__PURE__ */ w("p", {
|
|
547
|
-
className: "mt-1 text-xl font-
|
|
547
|
+
className: "mt-1 text-xl font-semibold text-text-primary tabular-nums",
|
|
548
548
|
children: typeof t == "number" ? t.toLocaleString() : t
|
|
549
549
|
})]
|
|
550
550
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnalyticsPage.js","names":[],"sources":["../../src/pages/AnalyticsPage.tsx"],"sourcesContent":["import { lazy, Suspense, useCallback, useMemo, useState } from 'react';\nimport { Download, Printer } from 'lucide-react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { MotionPage } from '@burdenoff/fe-libs/shared/motion';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { PageHeader } from '@/components/shared';\nimport { SkeletonLine } from '@/components/shared/PageSkeleton';\nimport {\n AnalyticsBreakdownTable,\n AnalyticsEntityTabs,\n AnalyticsFilterBar,\n AnalyticsKpiGrid,\n SandboxAnalyticsSection,\n getAnalyticsTabConfig,\n getDateRange,\n} from '@/components/analytics';\n\n// Recharts is ~150KB+ gzipped and only mounts on the Analytics page once\n// the user lands on it. Lazy-load both chart components so the recharts\n// bundle is excluded from the initial page-load chunk.\nconst AnalyticsTimeSeriesChart = lazy(() =>\n import('@/components/analytics/AnalyticsTimeSeriesChart').then((m) => ({\n default: m.AnalyticsTimeSeriesChart,\n }))\n);\nconst AnalyticsBreakdownChart = lazy(() =>\n import('@/components/analytics/AnalyticsBreakdownChart').then((m) => ({\n default: m.AnalyticsBreakdownChart,\n }))\n);\n\nconst ChartFallback = () => (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <SkeletonLine height=\"h-40\" />\n </div>\n);\nimport type { EntityTab, Granularity, TimeRange } from '@/components/analytics';\nimport { useVibecontrolsAnalyticsQuery } from '@/generated/wspace-operations';\nimport { useVibeControls, useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useQueryBackedTab } from '@/hooks/useQueryBackedTab';\n\nconst ANALYTICS_TABS: readonly EntityTab[] = [\n 'overview',\n 'agents',\n 'sessions',\n 'sandbox',\n 'vibes',\n 'actions',\n 'vibedecks',\n 'aievents',\n 'audit',\n 'docs',\n];\n\nconst ANALYTICS_SERIES_COLORS = {\n primary: 'var(--color-text-link)',\n success: 'var(--color-status-success-text)',\n accent: 'var(--color-accent-purple)',\n warning: 'var(--color-status-warning-text)',\n} as const;\n\nexport function AnalyticsPage() {\n const { workspaceId } = useVibeControls();\n const { t } = useI18n();\n const navigate = useVibeNavigate();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const [timeRange, setTimeRange] = useState<TimeRange>('LAST_7D');\n const [granularity, setGranularity] = useState<Granularity>('DAY');\n const [activeTab, setActiveTab] = useQueryBackedTab<EntityTab>(ANALYTICS_TABS, 'overview');\n\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n\n const { startDate, endDate } = useMemo(() => getDateRange(timeRange), [timeRange]);\n const activeTabConfig = useMemo(() => getAnalyticsTabConfig(activeTab), [activeTab]);\n\n const { data, loading, error, refetch } = useVibecontrolsAnalyticsQuery({\n variables: {\n input: {\n startDate: startDate.toISOString(),\n endDate: endDate.toISOString(),\n granularity,\n entityTypes: activeTabConfig.entityTypes,\n },\n },\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n notifyOnNetworkStatusChange: true,\n skip: !workspaceId,\n });\n\n const analytics = data?.vibecontrolsAnalytics;\n\n const handleRefresh = useCallback(() => {\n void refetch();\n }, [refetch]);\n\n const handlePrint = useCallback(() => {\n if (typeof window !== 'undefined') window.print();\n }, []);\n\n const handleExportCsv = useCallback(() => {\n if (!analytics) return;\n const rows = buildCsvRowsForTab(activeTab, analytics);\n if (rows.length === 0) return;\n const csv = rowsToCsv(rows);\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n const stamp = new Date().toISOString().slice(0, 10);\n a.download = `vibecontrols-analytics-${activeTab}-${stamp}.csv`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n }, [analytics, activeTab]);\n\n const handleCardClick = useCallback(\n (href: string) => {\n navigate(href);\n },\n [navigate]\n );\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">Loading permissions…</p>\n </div>\n );\n if (!hasPermission(VIBE_PERMISSIONS.ANALYTICS_READ))\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-foreground\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary\">\n You don't have permission to access this page.\n </p>\n </div>\n </div>\n );\n\n if (!workspaceId) {\n return (\n <MotionPage className=\"min-h-screen space-y-6 bg-bg-surface p-4 sm:p-6\">\n <PageHeader title={tr('nav.analytics', 'Analytics')} />\n <div className=\"text-sm text-text-secondary\">Waiting for workspace context…</div>\n </MotionPage>\n );\n }\n\n if (error && !analytics) {\n // The wspace-vibecontrols-svc analytics resolver already safe-degrades\n // to an empty payload on its own; when this error path actually fires\n // the failure is upstream (ACA proxy returning \"upstream connect\n // error\" / \"Connection refused\" while the svc is restarting, or a\n // transient gateway hiccup). Show a transient-failure copy instead of\n // the raw Envoy-style message so users don't try to debug a string\n // that's meaningless to them.\n const raw = error.message ?? '';\n const looksTransient =\n raw.includes('upstream connect error') ||\n raw.includes('Connection refused') ||\n raw.includes('disconnect/reset before headers') ||\n raw.includes('Unexpected response');\n return (\n <MotionPage className=\"min-h-screen space-y-6 bg-bg-surface p-4 sm:p-6\">\n <PageHeader title={tr('nav.analytics', 'Analytics')} />\n <div className=\"space-y-3 rounded-lg border border-status-warning-border bg-status-warning-bg/10 p-4 text-sm text-text-primary\">\n {looksTransient ? (\n <>\n <p className=\"font-medium\">\n {tr('analyticsPage.transientUnavailable', 'Analytics is temporarily unavailable')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'analyticsPage.transientHint',\n 'This is usually brief — please wait a moment and retry. Other VibeControls features are unaffected.'\n )}\n </p>\n </>\n ) : (\n <p>Failed to load analytics: {error.message}</p>\n )}\n <button\n type=\"button\"\n onClick={handleRefresh}\n className=\"rounded-md bg-status-warning-bg/20 px-3 py-1.5 text-xs font-medium transition-colors hover:bg-status-warning-bg/30\"\n >\n {tr('analyticsPage.retry', 'Retry')}\n </button>\n </div>\n </MotionPage>\n );\n }\n\n return (\n <MotionPage className=\"min-h-screen space-y-4 bg-bg-surface p-4 sm:p-6 vc-printable\">\n <PageHeader title={tr('nav.analytics', 'Analytics')} />\n\n {/* AnalyticsFilterBar / AnalyticsEntityTabs are custom components that\n don't forward rest props onto a DOM node, so the tour anchors are\n attached to wrapper <div>s (same pattern as VibeDeckSwitcher etc.)\n to keep `[data-tour=\"...\"]` selectors reachable in the DOM. */}\n <div data-tour=\"analytics-filter-bar\">\n <AnalyticsFilterBar\n timeRange={timeRange}\n granularity={granularity}\n onTimeRangeChange={setTimeRange}\n onGranularityChange={setGranularity}\n onRefresh={handleRefresh}\n loading={loading}\n executionTimeMs={analytics?.executionTimeMs}\n cached={analytics?.cached}\n />\n </div>\n\n <div data-tour=\"analytics-entity-tabs\">\n <AnalyticsEntityTabs activeTab={activeTab} onTabChange={setActiveTab} />\n </div>\n\n {/* F11: Per-tab export + print toolbar. Hidden in print output via the\n `vc-print-hide` class. */}\n <div\n data-tour=\"analytics-export-print-actions\"\n className=\"flex flex-wrap items-center justify-end gap-2 vc-print-hide\"\n >\n <button\n type=\"button\"\n onClick={handleExportCsv}\n disabled={loading || !analytics}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-default px-3 py-1.5 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n title={tr('analytics.exportCsvTitle', 'Export current tab as CSV')}\n >\n <Download size={14} />\n {tr('analytics.exportCsv', 'Export CSV')}\n </button>\n <button\n type=\"button\"\n onClick={handlePrint}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-default px-3 py-1.5 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n title={tr('analytics.printTitle', 'Print this report')}\n >\n <Printer size={14} />\n {tr('analytics.print', 'Print')}\n </button>\n {/* TODO(boff-analytics-png): wire PNG export once html-to-image\n or recharts svg-to-image helper is added to deps. */}\n </div>\n\n <Suspense fallback={<ChartFallback />}>\n <section\n id={`analytics-panel-${activeTab}`}\n role=\"tabpanel\"\n aria-labelledby={`analytics-tab-${activeTab}`}\n className=\"space-y-4\"\n >\n {activeTab === 'overview' ? (\n <div className=\"space-y-4\">\n <AnalyticsKpiGrid data={analytics} loading={loading} onCardClick={handleCardClick} />\n\n <AnalyticsTimeSeriesChart\n title=\"Activity Over Time\"\n datasets={[\n {\n label: 'Sessions',\n data: analytics?.sessions?.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.primary,\n },\n {\n label: 'Executions',\n data: analytics?.actions?.executionsOverTime,\n color: ANALYTICS_SERIES_COLORS.success,\n },\n {\n label: 'AI Events',\n data: analytics?.aiEvents?.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.accent,\n },\n {\n label: 'Audit Logs',\n data: analytics?.audit?.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.warning,\n },\n ]}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"Sessions by Status\"\n data={analytics?.sessions?.byStatus}\n />\n <AnalyticsBreakdownChart\n title=\"Vibes by Status\"\n data={analytics?.vibes?.byStatus}\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'agents' && analytics?.agents ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total\" value={analytics.agents.total} />\n <KpiCard label=\"Active\" value={analytics.agents.active} variant=\"success\" />\n <KpiCard label=\"Inactive\" value={analytics.agents.inactive} variant=\"warning\" />\n <KpiCard\n label=\"Stale Heartbeat\"\n value={analytics.agents.staleHeartbeatCount}\n variant=\"error\"\n />\n </div>\n\n <AnalyticsTimeSeriesChart\n title=\"Agents Created Over Time\"\n datasets={[\n {\n label: 'Agents',\n data: analytics.agents.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.primary,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownTable\n title=\"By Platform\"\n data={analytics.agents.byPlatform}\n keyLabel=\"Platform\"\n />\n <AnalyticsBreakdownTable\n title=\"By Architecture\"\n data={analytics.agents.byArchitecture}\n keyLabel=\"Architecture\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'sessions' && analytics?.sessions ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total\" value={analytics.sessions.total} />\n <KpiCard label=\"Running\" value={analytics.sessions.active} variant=\"success\" />\n <KpiCard label=\"Collaborators\" value={analytics.sessions.totalCollaborators} />\n <KpiCard\n label=\"Shares\"\n value={analytics.sessions.totalShares + analytics.sessions.totalShareLinks}\n />\n </div>\n\n {analytics.sessions.avgDurationMs != null ? (\n <div className=\"text-sm text-text-secondary\">\n Average duration:{' '}\n <span className=\"font-medium text-text-primary\">\n {formatDuration(analytics.sessions.avgDurationMs)}\n </span>\n </div>\n ) : null}\n\n <AnalyticsTimeSeriesChart\n title=\"Sessions Created Over Time\"\n datasets={[\n {\n label: 'Sessions',\n data: analytics.sessions.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.primary,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"Sessions by Type\"\n data={analytics.sessions.byType}\n />\n <AnalyticsBreakdownTable\n title=\"Sessions by Status\"\n data={analytics.sessions.byStatus}\n keyLabel=\"Status\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'sandbox' ? <SandboxAnalyticsSection /> : null}\n\n {activeTab === 'vibes' && analytics?.vibes ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total\" value={analytics.vibes.total} />\n <KpiCard label=\"With Agent\" value={analytics.vibes.withAgent} variant=\"success\" />\n <KpiCard label=\"Without Agent\" value={analytics.vibes.withoutAgent} />\n </div>\n\n <AnalyticsTimeSeriesChart\n title=\"Vibes Created Over Time\"\n datasets={[\n {\n label: 'Vibes',\n data: analytics.vibes.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.accent,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart title=\"Vibes by Type\" data={analytics.vibes.byType} />\n <AnalyticsBreakdownChart title=\"Vibes by Status\" data={analytics.vibes.byStatus} />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'actions' && analytics?.actions ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total Actions\" value={analytics.actions.total} />\n <KpiCard label=\"Executions\" value={analytics.actions.totalExecutions} />\n <KpiCard\n label=\"Success Rate\"\n value={\n analytics.actions.successRate != null\n ? `${analytics.actions.successRate.toFixed(1)}%`\n : 'N/A'\n }\n variant={\n analytics.actions.successRate != null && analytics.actions.successRate >= 90\n ? 'success'\n : 'warning'\n }\n />\n <KpiCard\n label=\"Avg Duration\"\n value={\n analytics.actions.avgDurationMs != null\n ? formatDuration(analytics.actions.avgDurationMs)\n : 'N/A'\n }\n />\n </div>\n\n <AnalyticsTimeSeriesChart\n title=\"Executions Over Time\"\n datasets={[\n {\n label: 'Executions',\n data: analytics.actions.executionsOverTime,\n color: ANALYTICS_SERIES_COLORS.success,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"By Action Type\"\n data={analytics.actions.byActionType}\n />\n <AnalyticsBreakdownChart\n title=\"Execution Status\"\n data={analytics.actions.executionsByStatus}\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownTable\n title=\"By Trigger Type\"\n data={analytics.actions.byTriggerType}\n keyLabel=\"Trigger\"\n />\n <AnalyticsBreakdownTable\n title=\"By Source Type\"\n data={analytics.actions.bySourceType}\n keyLabel=\"Source\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'vibedecks' && analytics?.vibeDecks ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3\">\n <KpiCard label=\"Decks\" value={analytics.vibeDecks.totalDecks} />\n <KpiCard label=\"Buttons\" value={analytics.vibeDecks.totalButtons} />\n </div>\n\n <AnalyticsBreakdownChart\n title=\"Buttons by Action Type\"\n data={analytics.vibeDecks.buttonsByActionType}\n />\n </div>\n ) : null}\n\n {activeTab === 'aievents' && analytics?.aiEvents ? (\n <div className=\"space-y-4\">\n <KpiCard label=\"Total AI Events\" value={analytics.aiEvents.total} />\n\n <AnalyticsTimeSeriesChart\n title=\"AI Events Over Time\"\n datasets={[\n {\n label: 'Events',\n data: analytics.aiEvents.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.accent,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart title=\"By Source\" data={analytics.aiEvents.bySource} />\n <AnalyticsBreakdownTable\n title=\"By Event Type\"\n data={analytics.aiEvents.byEventType}\n keyLabel=\"Event Type\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'audit' && analytics?.audit ? (\n <div className=\"space-y-4\">\n <KpiCard label=\"Total Audit Logs\" value={analytics.audit.total} />\n\n <AnalyticsTimeSeriesChart\n title=\"Audit Events Over Time\"\n datasets={[\n {\n label: 'Events',\n data: analytics.audit.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.warning,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart title=\"By Action\" data={analytics.audit.byAction} />\n <AnalyticsBreakdownChart title=\"By Status\" data={analytics.audit.byStatus} />\n </div>\n\n <AnalyticsBreakdownTable\n title=\"By Resource Type\"\n data={analytics.audit.byResourceType}\n keyLabel=\"Resource\"\n />\n </div>\n ) : null}\n\n {activeTab === 'docs' && analytics?.docs ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Sites\" value={analytics.docs.totalSites} />\n <KpiCard label=\"Pages\" value={analytics.docs.totalPages} />\n <KpiCard label=\"Revisions\" value={analytics.docs.totalRevisions} />\n <KpiCard\n label=\"Build Success\"\n value={\n analytics.docs.buildSuccessRate != null\n ? `${analytics.docs.buildSuccessRate.toFixed(1)}%`\n : 'N/A'\n }\n variant={\n analytics.docs.buildSuccessRate != null && analytics.docs.buildSuccessRate >= 90\n ? 'success'\n : 'warning'\n }\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"Pages by Status\"\n data={analytics.docs.pagesByStatus}\n />\n <AnalyticsBreakdownChart\n title=\"Revisions by Status\"\n data={analytics.docs.revisionsByStatus}\n />\n </div>\n </div>\n ) : null}\n </section>\n </Suspense>\n </MotionPage>\n );\n}\n\nfunction KpiCard({\n label,\n value,\n variant,\n}: {\n label: string;\n value: number | string;\n variant?: 'success' | 'warning' | 'error';\n}) {\n const surfaceClass =\n variant === 'success'\n ? 'bg-status-success-bg/10'\n : variant === 'warning'\n ? 'bg-status-warning-bg/10'\n : variant === 'error'\n ? 'bg-status-error-bg/10'\n : 'bg-bg-surface';\n\n return (\n <div className={`${surfaceClass} rounded-lg border border-border-default p-3`}>\n <p className=\"text-xs text-text-secondary\">{label}</p>\n <p className=\"mt-1 text-xl font-bold text-text-primary\">\n {typeof value === 'number' ? value.toLocaleString() : value}\n </p>\n </div>\n );\n}\n\nfunction formatDuration(milliseconds: number): string {\n if (milliseconds < 1000) {\n return `${Math.round(milliseconds)}ms`;\n }\n\n if (milliseconds < 60000) {\n return `${(milliseconds / 1000).toFixed(1)}s`;\n }\n\n const minutes = Math.floor(milliseconds / 60000);\n const seconds = Math.round((milliseconds % 60000) / 1000);\n return `${minutes}m ${seconds}s`;\n}\n\n// ── F11: CSV serialization for the active analytics tab ──────────────────\n\ntype CsvRow = (string | number)[];\n\nfunction rowsToCsv(rows: CsvRow[]): string {\n return rows\n .map((row) =>\n row\n .map((cell) => {\n const s = cell == null ? '' : String(cell);\n // Escape per RFC4180 — wrap in quotes when the cell contains a\n // separator, quote, or newline; double any internal quotes.\n if (/[\",\\n\\r]/.test(s)) return `\"${s.replace(/\"/g, '\"\"')}\"`;\n return s;\n })\n .join(',')\n )\n .join('\\r\\n');\n}\n\n/**\n * Build the CSV row matrix for an analytics tab. Each tab serialises its\n * primary table data; chart-only tabs fall back to a sparse summary.\n * The first row is always headers.\n */\ntype AnalyticsBreakdownEntry = {\n key?: string | null;\n label?: string | null;\n count?: number | null;\n};\n\ninterface AnalyticsTabSlice {\n total?: number | null;\n active?: number | null;\n inactive?: number | null;\n staleHeartbeatCount?: number | null;\n withAgent?: number | null;\n withoutAgent?: number | null;\n totalExecutions?: number | null;\n successRate?: number | null;\n avgDurationMs?: number | null;\n totalDecks?: number | null;\n totalButtons?: number | null;\n totalSites?: number | null;\n totalPages?: number | null;\n totalRevisions?: number | null;\n buildSuccessRate?: number | null;\n byPlatform?: ReadonlyArray<AnalyticsBreakdownEntry>;\n byType?: ReadonlyArray<AnalyticsBreakdownEntry>;\n}\n\ninterface AnalyticsSnapshot {\n sessions?: AnalyticsTabSlice;\n agents?: AnalyticsTabSlice;\n vibes?: AnalyticsTabSlice;\n actions?: AnalyticsTabSlice;\n aiEvents?: AnalyticsTabSlice;\n audit?: AnalyticsTabSlice;\n docs?: AnalyticsTabSlice;\n vibeDecks?: AnalyticsTabSlice;\n}\n\nfunction buildCsvRowsForTab(tab: EntityTab, analytics: AnalyticsSnapshot): CsvRow[] {\n const rows: CsvRow[] = [];\n if (tab === 'overview') {\n rows.push(['metric', 'value']);\n if (analytics.sessions) rows.push(['sessions.total', analytics.sessions.total ?? 0]);\n if (analytics.agents) rows.push(['agents.total', analytics.agents.total ?? 0]);\n if (analytics.vibes) rows.push(['vibes.total', analytics.vibes.total ?? 0]);\n if (analytics.actions) rows.push(['actions.total', analytics.actions.total ?? 0]);\n return rows;\n }\n if (tab === 'agents' && analytics.agents) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.agents.total ?? 0]);\n rows.push(['active', analytics.agents.active ?? 0]);\n rows.push(['inactive', analytics.agents.inactive ?? 0]);\n rows.push(['staleHeartbeat', analytics.agents.staleHeartbeatCount ?? 0]);\n if (Array.isArray(analytics.agents.byPlatform)) {\n rows.push([], ['platform', 'count']);\n for (const e of analytics.agents.byPlatform)\n rows.push([e.key ?? e.label ?? '', e.count ?? 0]);\n }\n return rows;\n }\n if (tab === 'sessions' && analytics.sessions) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.sessions.total ?? 0]);\n rows.push(['running', analytics.sessions.active ?? 0]);\n rows.push(['avgDurationMs', analytics.sessions.avgDurationMs ?? '']);\n if (Array.isArray(analytics.sessions.byType)) {\n rows.push([], ['type', 'count']);\n for (const e of analytics.sessions.byType) rows.push([e.key ?? e.label ?? '', e.count ?? 0]);\n }\n return rows;\n }\n if (tab === 'actions' && analytics.actions) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.actions.total ?? 0]);\n rows.push(['totalExecutions', analytics.actions.totalExecutions ?? 0]);\n rows.push(['successRate', analytics.actions.successRate ?? '']);\n rows.push(['avgDurationMs', analytics.actions.avgDurationMs ?? '']);\n return rows;\n }\n if (tab === 'vibes' && analytics.vibes) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.vibes.total ?? 0]);\n rows.push(['withAgent', analytics.vibes.withAgent ?? 0]);\n rows.push(['withoutAgent', analytics.vibes.withoutAgent ?? 0]);\n return rows;\n }\n if (tab === 'vibedecks' && analytics.vibeDecks) {\n rows.push(['metric', 'value']);\n rows.push(['decks', analytics.vibeDecks.totalDecks ?? 0]);\n rows.push(['buttons', analytics.vibeDecks.totalButtons ?? 0]);\n return rows;\n }\n if (tab === 'aievents' && analytics.aiEvents) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.aiEvents.total ?? 0]);\n return rows;\n }\n if (tab === 'audit' && analytics.audit) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.audit.total ?? 0]);\n return rows;\n }\n if (tab === 'docs' && analytics.docs) {\n rows.push(['metric', 'value']);\n rows.push(['sites', analytics.docs.totalSites ?? 0]);\n rows.push(['pages', analytics.docs.totalPages ?? 0]);\n rows.push(['revisions', analytics.docs.totalRevisions ?? 0]);\n rows.push(['buildSuccessRate', analytics.docs.buildSuccessRate ?? '']);\n return rows;\n }\n // sandbox + others fall back to a sparse summary\n rows.push(['metric', 'value']);\n rows.push(['note', `No CSV serialiser for ${tab} tab yet`]);\n return rows;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AnalyticsPage.js","names":[],"sources":["../../src/pages/AnalyticsPage.tsx"],"sourcesContent":["import { lazy, Suspense, useCallback, useMemo, useState } from 'react';\nimport { Download, Printer } from 'lucide-react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { MotionPage } from '@burdenoff/fe-libs/shared/motion';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { PageHeader } from '@/components/shared';\nimport { SkeletonLine } from '@/components/shared/PageSkeleton';\nimport {\n AnalyticsBreakdownTable,\n AnalyticsEntityTabs,\n AnalyticsFilterBar,\n AnalyticsKpiGrid,\n SandboxAnalyticsSection,\n getAnalyticsTabConfig,\n getDateRange,\n} from '@/components/analytics';\n\n// Recharts is ~150KB+ gzipped and only mounts on the Analytics page once\n// the user lands on it. Lazy-load both chart components so the recharts\n// bundle is excluded from the initial page-load chunk.\nconst AnalyticsTimeSeriesChart = lazy(() =>\n import('@/components/analytics/AnalyticsTimeSeriesChart').then((m) => ({\n default: m.AnalyticsTimeSeriesChart,\n }))\n);\nconst AnalyticsBreakdownChart = lazy(() =>\n import('@/components/analytics/AnalyticsBreakdownChart').then((m) => ({\n default: m.AnalyticsBreakdownChart,\n }))\n);\n\nconst ChartFallback = () => (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <SkeletonLine height=\"h-40\" />\n </div>\n);\nimport type { EntityTab, Granularity, TimeRange } from '@/components/analytics';\nimport { useVibecontrolsAnalyticsQuery } from '@/generated/wspace-operations';\nimport { useVibeControls, useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useQueryBackedTab } from '@/hooks/useQueryBackedTab';\n\nconst ANALYTICS_TABS: readonly EntityTab[] = [\n 'overview',\n 'agents',\n 'sessions',\n 'sandbox',\n 'vibes',\n 'actions',\n 'vibedecks',\n 'aievents',\n 'audit',\n 'docs',\n];\n\nconst ANALYTICS_SERIES_COLORS = {\n primary: 'var(--color-text-link)',\n success: 'var(--color-status-success-text)',\n accent: 'var(--color-accent-purple)',\n warning: 'var(--color-status-warning-text)',\n} as const;\n\nexport function AnalyticsPage() {\n const { workspaceId } = useVibeControls();\n const { t } = useI18n();\n const navigate = useVibeNavigate();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const [timeRange, setTimeRange] = useState<TimeRange>('LAST_7D');\n const [granularity, setGranularity] = useState<Granularity>('DAY');\n const [activeTab, setActiveTab] = useQueryBackedTab<EntityTab>(ANALYTICS_TABS, 'overview');\n\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n\n const { startDate, endDate } = useMemo(() => getDateRange(timeRange), [timeRange]);\n const activeTabConfig = useMemo(() => getAnalyticsTabConfig(activeTab), [activeTab]);\n\n const { data, loading, error, refetch } = useVibecontrolsAnalyticsQuery({\n variables: {\n input: {\n startDate: startDate.toISOString(),\n endDate: endDate.toISOString(),\n granularity,\n entityTypes: activeTabConfig.entityTypes,\n },\n },\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n notifyOnNetworkStatusChange: true,\n skip: !workspaceId,\n });\n\n const analytics = data?.vibecontrolsAnalytics;\n\n const handleRefresh = useCallback(() => {\n void refetch();\n }, [refetch]);\n\n const handlePrint = useCallback(() => {\n if (typeof window !== 'undefined') window.print();\n }, []);\n\n const handleExportCsv = useCallback(() => {\n if (!analytics) return;\n const rows = buildCsvRowsForTab(activeTab, analytics);\n if (rows.length === 0) return;\n const csv = rowsToCsv(rows);\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n const stamp = new Date().toISOString().slice(0, 10);\n a.download = `vibecontrols-analytics-${activeTab}-${stamp}.csv`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n }, [analytics, activeTab]);\n\n const handleCardClick = useCallback(\n (href: string) => {\n navigate(href);\n },\n [navigate]\n );\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">Loading permissions…</p>\n </div>\n );\n if (!hasPermission(VIBE_PERMISSIONS.ANALYTICS_READ))\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary\">\n You don't have permission to access this page.\n </p>\n </div>\n </div>\n );\n\n if (!workspaceId) {\n return (\n <MotionPage className=\"min-h-screen space-y-6 bg-bg-canvas px-6 lg:px-8 py-6\">\n <PageHeader title={tr('nav.analytics', 'Analytics')} />\n <div className=\"text-sm text-text-secondary\">Waiting for workspace context…</div>\n </MotionPage>\n );\n }\n\n if (error && !analytics) {\n // The wspace-vibecontrols-svc analytics resolver already safe-degrades\n // to an empty payload on its own; when this error path actually fires\n // the failure is upstream (ACA proxy returning \"upstream connect\n // error\" / \"Connection refused\" while the svc is restarting, or a\n // transient gateway hiccup). Show a transient-failure copy instead of\n // the raw Envoy-style message so users don't try to debug a string\n // that's meaningless to them.\n const raw = error.message ?? '';\n const looksTransient =\n raw.includes('upstream connect error') ||\n raw.includes('Connection refused') ||\n raw.includes('disconnect/reset before headers') ||\n raw.includes('Unexpected response');\n return (\n <MotionPage className=\"min-h-screen space-y-6 bg-bg-canvas px-6 lg:px-8 py-6\">\n <PageHeader title={tr('nav.analytics', 'Analytics')} />\n <div className=\"space-y-3 rounded-card border border-status-warning-border bg-status-warning-bg-subtle p-4 text-sm text-text-primary\">\n {looksTransient ? (\n <>\n <p className=\"font-medium\">\n {tr('analyticsPage.transientUnavailable', 'Analytics is temporarily unavailable')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'analyticsPage.transientHint',\n 'This is usually brief — please wait a moment and retry. Other VibeControls features are unaffected.'\n )}\n </p>\n </>\n ) : (\n <p>Failed to load analytics: {error.message}</p>\n )}\n <button\n type=\"button\"\n onClick={handleRefresh}\n className=\"rounded-button border border-status-warning-border bg-status-warning-bg-subtle px-3 py-1.5 text-xs font-medium text-status-warning-text transition-colors hover:bg-bg-sunken\"\n >\n {tr('analyticsPage.retry', 'Retry')}\n </button>\n </div>\n </MotionPage>\n );\n }\n\n return (\n <MotionPage className=\"min-h-screen space-y-6 bg-bg-canvas px-6 lg:px-8 py-6 vc-printable\">\n <PageHeader title={tr('nav.analytics', 'Analytics')} />\n\n {/* AnalyticsFilterBar / AnalyticsEntityTabs are custom components that\n don't forward rest props onto a DOM node, so the tour anchors are\n attached to wrapper <div>s (same pattern as VibeDeckSwitcher etc.)\n to keep `[data-tour=\"...\"]` selectors reachable in the DOM. */}\n <div data-tour=\"analytics-filter-bar\">\n <AnalyticsFilterBar\n timeRange={timeRange}\n granularity={granularity}\n onTimeRangeChange={setTimeRange}\n onGranularityChange={setGranularity}\n onRefresh={handleRefresh}\n loading={loading}\n executionTimeMs={analytics?.executionTimeMs}\n cached={analytics?.cached}\n />\n </div>\n\n <div data-tour=\"analytics-entity-tabs\">\n <AnalyticsEntityTabs activeTab={activeTab} onTabChange={setActiveTab} />\n </div>\n\n {/* F11: Per-tab export + print toolbar. Hidden in print output via the\n `vc-print-hide` class. */}\n <div\n data-tour=\"analytics-export-print-actions\"\n className=\"flex flex-wrap items-center justify-end gap-2 vc-print-hide\"\n >\n <button\n type=\"button\"\n onClick={handleExportCsv}\n disabled={loading || !analytics}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-default px-3 py-1.5 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n title={tr('analytics.exportCsvTitle', 'Export current tab as CSV')}\n >\n <Download size={14} />\n {tr('analytics.exportCsv', 'Export CSV')}\n </button>\n <button\n type=\"button\"\n onClick={handlePrint}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-default px-3 py-1.5 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n title={tr('analytics.printTitle', 'Print this report')}\n >\n <Printer size={14} />\n {tr('analytics.print', 'Print')}\n </button>\n {/* TODO(boff-analytics-png): wire PNG export once html-to-image\n or recharts svg-to-image helper is added to deps. */}\n </div>\n\n <Suspense fallback={<ChartFallback />}>\n <section\n id={`analytics-panel-${activeTab}`}\n role=\"tabpanel\"\n aria-labelledby={`analytics-tab-${activeTab}`}\n className=\"space-y-4\"\n >\n {activeTab === 'overview' ? (\n <div className=\"space-y-4\">\n <AnalyticsKpiGrid data={analytics} loading={loading} onCardClick={handleCardClick} />\n\n <AnalyticsTimeSeriesChart\n title=\"Activity Over Time\"\n datasets={[\n {\n label: 'Sessions',\n data: analytics?.sessions?.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.primary,\n },\n {\n label: 'Executions',\n data: analytics?.actions?.executionsOverTime,\n color: ANALYTICS_SERIES_COLORS.success,\n },\n {\n label: 'AI Events',\n data: analytics?.aiEvents?.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.accent,\n },\n {\n label: 'Audit Logs',\n data: analytics?.audit?.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.warning,\n },\n ]}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"Sessions by Status\"\n data={analytics?.sessions?.byStatus}\n />\n <AnalyticsBreakdownChart\n title=\"Vibes by Status\"\n data={analytics?.vibes?.byStatus}\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'agents' && analytics?.agents ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total\" value={analytics.agents.total} />\n <KpiCard label=\"Active\" value={analytics.agents.active} variant=\"success\" />\n <KpiCard label=\"Inactive\" value={analytics.agents.inactive} variant=\"warning\" />\n <KpiCard\n label=\"Stale Heartbeat\"\n value={analytics.agents.staleHeartbeatCount}\n variant=\"error\"\n />\n </div>\n\n <AnalyticsTimeSeriesChart\n title=\"Agents Created Over Time\"\n datasets={[\n {\n label: 'Agents',\n data: analytics.agents.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.primary,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownTable\n title=\"By Platform\"\n data={analytics.agents.byPlatform}\n keyLabel=\"Platform\"\n />\n <AnalyticsBreakdownTable\n title=\"By Architecture\"\n data={analytics.agents.byArchitecture}\n keyLabel=\"Architecture\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'sessions' && analytics?.sessions ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total\" value={analytics.sessions.total} />\n <KpiCard label=\"Running\" value={analytics.sessions.active} variant=\"success\" />\n <KpiCard label=\"Collaborators\" value={analytics.sessions.totalCollaborators} />\n <KpiCard\n label=\"Shares\"\n value={analytics.sessions.totalShares + analytics.sessions.totalShareLinks}\n />\n </div>\n\n {analytics.sessions.avgDurationMs != null ? (\n <div className=\"text-sm text-text-secondary\">\n Average duration:{' '}\n <span className=\"font-medium text-text-primary\">\n {formatDuration(analytics.sessions.avgDurationMs)}\n </span>\n </div>\n ) : null}\n\n <AnalyticsTimeSeriesChart\n title=\"Sessions Created Over Time\"\n datasets={[\n {\n label: 'Sessions',\n data: analytics.sessions.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.primary,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"Sessions by Type\"\n data={analytics.sessions.byType}\n />\n <AnalyticsBreakdownTable\n title=\"Sessions by Status\"\n data={analytics.sessions.byStatus}\n keyLabel=\"Status\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'sandbox' ? <SandboxAnalyticsSection /> : null}\n\n {activeTab === 'vibes' && analytics?.vibes ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total\" value={analytics.vibes.total} />\n <KpiCard label=\"With Agent\" value={analytics.vibes.withAgent} variant=\"success\" />\n <KpiCard label=\"Without Agent\" value={analytics.vibes.withoutAgent} />\n </div>\n\n <AnalyticsTimeSeriesChart\n title=\"Vibes Created Over Time\"\n datasets={[\n {\n label: 'Vibes',\n data: analytics.vibes.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.accent,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart title=\"Vibes by Type\" data={analytics.vibes.byType} />\n <AnalyticsBreakdownChart title=\"Vibes by Status\" data={analytics.vibes.byStatus} />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'actions' && analytics?.actions ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total Actions\" value={analytics.actions.total} />\n <KpiCard label=\"Executions\" value={analytics.actions.totalExecutions} />\n <KpiCard\n label=\"Success Rate\"\n value={\n analytics.actions.successRate != null\n ? `${analytics.actions.successRate.toFixed(1)}%`\n : 'N/A'\n }\n variant={\n analytics.actions.successRate != null && analytics.actions.successRate >= 90\n ? 'success'\n : 'warning'\n }\n />\n <KpiCard\n label=\"Avg Duration\"\n value={\n analytics.actions.avgDurationMs != null\n ? formatDuration(analytics.actions.avgDurationMs)\n : 'N/A'\n }\n />\n </div>\n\n <AnalyticsTimeSeriesChart\n title=\"Executions Over Time\"\n datasets={[\n {\n label: 'Executions',\n data: analytics.actions.executionsOverTime,\n color: ANALYTICS_SERIES_COLORS.success,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"By Action Type\"\n data={analytics.actions.byActionType}\n />\n <AnalyticsBreakdownChart\n title=\"Execution Status\"\n data={analytics.actions.executionsByStatus}\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownTable\n title=\"By Trigger Type\"\n data={analytics.actions.byTriggerType}\n keyLabel=\"Trigger\"\n />\n <AnalyticsBreakdownTable\n title=\"By Source Type\"\n data={analytics.actions.bySourceType}\n keyLabel=\"Source\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'vibedecks' && analytics?.vibeDecks ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3\">\n <KpiCard label=\"Decks\" value={analytics.vibeDecks.totalDecks} />\n <KpiCard label=\"Buttons\" value={analytics.vibeDecks.totalButtons} />\n </div>\n\n <AnalyticsBreakdownChart\n title=\"Buttons by Action Type\"\n data={analytics.vibeDecks.buttonsByActionType}\n />\n </div>\n ) : null}\n\n {activeTab === 'aievents' && analytics?.aiEvents ? (\n <div className=\"space-y-4\">\n <KpiCard label=\"Total AI Events\" value={analytics.aiEvents.total} />\n\n <AnalyticsTimeSeriesChart\n title=\"AI Events Over Time\"\n datasets={[\n {\n label: 'Events',\n data: analytics.aiEvents.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.accent,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart title=\"By Source\" data={analytics.aiEvents.bySource} />\n <AnalyticsBreakdownTable\n title=\"By Event Type\"\n data={analytics.aiEvents.byEventType}\n keyLabel=\"Event Type\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'audit' && analytics?.audit ? (\n <div className=\"space-y-4\">\n <KpiCard label=\"Total Audit Logs\" value={analytics.audit.total} />\n\n <AnalyticsTimeSeriesChart\n title=\"Audit Events Over Time\"\n datasets={[\n {\n label: 'Events',\n data: analytics.audit.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.warning,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart title=\"By Action\" data={analytics.audit.byAction} />\n <AnalyticsBreakdownChart title=\"By Status\" data={analytics.audit.byStatus} />\n </div>\n\n <AnalyticsBreakdownTable\n title=\"By Resource Type\"\n data={analytics.audit.byResourceType}\n keyLabel=\"Resource\"\n />\n </div>\n ) : null}\n\n {activeTab === 'docs' && analytics?.docs ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Sites\" value={analytics.docs.totalSites} />\n <KpiCard label=\"Pages\" value={analytics.docs.totalPages} />\n <KpiCard label=\"Revisions\" value={analytics.docs.totalRevisions} />\n <KpiCard\n label=\"Build Success\"\n value={\n analytics.docs.buildSuccessRate != null\n ? `${analytics.docs.buildSuccessRate.toFixed(1)}%`\n : 'N/A'\n }\n variant={\n analytics.docs.buildSuccessRate != null && analytics.docs.buildSuccessRate >= 90\n ? 'success'\n : 'warning'\n }\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"Pages by Status\"\n data={analytics.docs.pagesByStatus}\n />\n <AnalyticsBreakdownChart\n title=\"Revisions by Status\"\n data={analytics.docs.revisionsByStatus}\n />\n </div>\n </div>\n ) : null}\n </section>\n </Suspense>\n </MotionPage>\n );\n}\n\nfunction KpiCard({\n label,\n value,\n variant,\n}: {\n label: string;\n value: number | string;\n variant?: 'success' | 'warning' | 'error';\n}) {\n const surfaceClass =\n variant === 'success'\n ? 'bg-status-success-bg-subtle border-status-success-border'\n : variant === 'warning'\n ? 'bg-status-warning-bg-subtle border-status-warning-border'\n : variant === 'error'\n ? 'bg-status-error-bg-subtle border-status-error-border'\n : 'bg-bg-surface border-border-subtle';\n\n return (\n <div className={`${surfaceClass} rounded-card border p-4 shadow-elevation-1`}>\n <p className=\"text-xs text-text-secondary\">{label}</p>\n <p className=\"mt-1 text-xl font-semibold text-text-primary tabular-nums\">\n {typeof value === 'number' ? value.toLocaleString() : value}\n </p>\n </div>\n );\n}\n\nfunction formatDuration(milliseconds: number): string {\n if (milliseconds < 1000) {\n return `${Math.round(milliseconds)}ms`;\n }\n\n if (milliseconds < 60000) {\n return `${(milliseconds / 1000).toFixed(1)}s`;\n }\n\n const minutes = Math.floor(milliseconds / 60000);\n const seconds = Math.round((milliseconds % 60000) / 1000);\n return `${minutes}m ${seconds}s`;\n}\n\n// ── F11: CSV serialization for the active analytics tab ──────────────────\n\ntype CsvRow = (string | number)[];\n\nfunction rowsToCsv(rows: CsvRow[]): string {\n return rows\n .map((row) =>\n row\n .map((cell) => {\n const s = cell == null ? '' : String(cell);\n // Escape per RFC4180 — wrap in quotes when the cell contains a\n // separator, quote, or newline; double any internal quotes.\n if (/[\",\\n\\r]/.test(s)) return `\"${s.replace(/\"/g, '\"\"')}\"`;\n return s;\n })\n .join(',')\n )\n .join('\\r\\n');\n}\n\n/**\n * Build the CSV row matrix for an analytics tab. Each tab serialises its\n * primary table data; chart-only tabs fall back to a sparse summary.\n * The first row is always headers.\n */\ntype AnalyticsBreakdownEntry = {\n key?: string | null;\n label?: string | null;\n count?: number | null;\n};\n\ninterface AnalyticsTabSlice {\n total?: number | null;\n active?: number | null;\n inactive?: number | null;\n staleHeartbeatCount?: number | null;\n withAgent?: number | null;\n withoutAgent?: number | null;\n totalExecutions?: number | null;\n successRate?: number | null;\n avgDurationMs?: number | null;\n totalDecks?: number | null;\n totalButtons?: number | null;\n totalSites?: number | null;\n totalPages?: number | null;\n totalRevisions?: number | null;\n buildSuccessRate?: number | null;\n byPlatform?: ReadonlyArray<AnalyticsBreakdownEntry>;\n byType?: ReadonlyArray<AnalyticsBreakdownEntry>;\n}\n\ninterface AnalyticsSnapshot {\n sessions?: AnalyticsTabSlice;\n agents?: AnalyticsTabSlice;\n vibes?: AnalyticsTabSlice;\n actions?: AnalyticsTabSlice;\n aiEvents?: AnalyticsTabSlice;\n audit?: AnalyticsTabSlice;\n docs?: AnalyticsTabSlice;\n vibeDecks?: AnalyticsTabSlice;\n}\n\nfunction buildCsvRowsForTab(tab: EntityTab, analytics: AnalyticsSnapshot): CsvRow[] {\n const rows: CsvRow[] = [];\n if (tab === 'overview') {\n rows.push(['metric', 'value']);\n if (analytics.sessions) rows.push(['sessions.total', analytics.sessions.total ?? 0]);\n if (analytics.agents) rows.push(['agents.total', analytics.agents.total ?? 0]);\n if (analytics.vibes) rows.push(['vibes.total', analytics.vibes.total ?? 0]);\n if (analytics.actions) rows.push(['actions.total', analytics.actions.total ?? 0]);\n return rows;\n }\n if (tab === 'agents' && analytics.agents) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.agents.total ?? 0]);\n rows.push(['active', analytics.agents.active ?? 0]);\n rows.push(['inactive', analytics.agents.inactive ?? 0]);\n rows.push(['staleHeartbeat', analytics.agents.staleHeartbeatCount ?? 0]);\n if (Array.isArray(analytics.agents.byPlatform)) {\n rows.push([], ['platform', 'count']);\n for (const e of analytics.agents.byPlatform)\n rows.push([e.key ?? e.label ?? '', e.count ?? 0]);\n }\n return rows;\n }\n if (tab === 'sessions' && analytics.sessions) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.sessions.total ?? 0]);\n rows.push(['running', analytics.sessions.active ?? 0]);\n rows.push(['avgDurationMs', analytics.sessions.avgDurationMs ?? '']);\n if (Array.isArray(analytics.sessions.byType)) {\n rows.push([], ['type', 'count']);\n for (const e of analytics.sessions.byType) rows.push([e.key ?? e.label ?? '', e.count ?? 0]);\n }\n return rows;\n }\n if (tab === 'actions' && analytics.actions) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.actions.total ?? 0]);\n rows.push(['totalExecutions', analytics.actions.totalExecutions ?? 0]);\n rows.push(['successRate', analytics.actions.successRate ?? '']);\n rows.push(['avgDurationMs', analytics.actions.avgDurationMs ?? '']);\n return rows;\n }\n if (tab === 'vibes' && analytics.vibes) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.vibes.total ?? 0]);\n rows.push(['withAgent', analytics.vibes.withAgent ?? 0]);\n rows.push(['withoutAgent', analytics.vibes.withoutAgent ?? 0]);\n return rows;\n }\n if (tab === 'vibedecks' && analytics.vibeDecks) {\n rows.push(['metric', 'value']);\n rows.push(['decks', analytics.vibeDecks.totalDecks ?? 0]);\n rows.push(['buttons', analytics.vibeDecks.totalButtons ?? 0]);\n return rows;\n }\n if (tab === 'aievents' && analytics.aiEvents) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.aiEvents.total ?? 0]);\n return rows;\n }\n if (tab === 'audit' && analytics.audit) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.audit.total ?? 0]);\n return rows;\n }\n if (tab === 'docs' && analytics.docs) {\n rows.push(['metric', 'value']);\n rows.push(['sites', analytics.docs.totalSites ?? 0]);\n rows.push(['pages', analytics.docs.totalPages ?? 0]);\n rows.push(['revisions', analytics.docs.totalRevisions ?? 0]);\n rows.push(['buildSuccessRate', analytics.docs.buildSuccessRate ?? '']);\n return rows;\n }\n // sandbox + others fall back to a sparse summary\n rows.push(['metric', 'value']);\n rows.push(['note', `No CSV serialiser for ${tab} tab yet`]);\n return rows;\n}\n"],"mappings":"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"}
|
|
@@ -77,7 +77,7 @@ function W() {
|
|
|
77
77
|
children: /* @__PURE__ */ j("div", {
|
|
78
78
|
className: "text-center space-y-2",
|
|
79
79
|
children: [/* @__PURE__ */ A("h2", {
|
|
80
|
-
className: "text-lg font-semibold text-
|
|
80
|
+
className: "text-lg font-semibold text-text-primary",
|
|
81
81
|
children: "Access Denied"
|
|
82
82
|
}), /* @__PURE__ */ A("p", {
|
|
83
83
|
className: "text-sm text-text-secondary",
|
|
@@ -143,7 +143,7 @@ function W() {
|
|
|
143
143
|
}
|
|
144
144
|
];
|
|
145
145
|
return Y && !Z ? /* @__PURE__ */ j(P, {
|
|
146
|
-
className: "space-y-6
|
|
146
|
+
className: "space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen",
|
|
147
147
|
children: [/* @__PURE__ */ j("button", {
|
|
148
148
|
type: "button",
|
|
149
149
|
onClick: $,
|
|
@@ -151,7 +151,7 @@ function W() {
|
|
|
151
151
|
children: [/* @__PURE__ */ A(S, { className: "size-4" }), I("catalog.backToCatalogs", "Back to Catalogs")]
|
|
152
152
|
}), /* @__PURE__ */ A(te, { variant: "detail" })]
|
|
153
153
|
}) : X && !Z ? /* @__PURE__ */ j(P, {
|
|
154
|
-
className: "space-y-6
|
|
154
|
+
className: "space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen",
|
|
155
155
|
children: [/* @__PURE__ */ j("button", {
|
|
156
156
|
type: "button",
|
|
157
157
|
onClick: $,
|
|
@@ -163,7 +163,7 @@ function W() {
|
|
|
163
163
|
onRetry: () => Ce()
|
|
164
164
|
})]
|
|
165
165
|
}) : Z ? /* @__PURE__ */ j(P, {
|
|
166
|
-
className: "space-y-6
|
|
166
|
+
className: "space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen",
|
|
167
167
|
children: [
|
|
168
168
|
q && /* @__PURE__ */ A("div", {
|
|
169
169
|
className: "fixed top-4 left-4 right-4 sm:left-auto z-50 bg-status-success-bg text-status-success-text px-4 py-3 rounded-md shadow-lg",
|
|
@@ -194,7 +194,7 @@ function W() {
|
|
|
194
194
|
type: "button",
|
|
195
195
|
onClick: () => Ce(),
|
|
196
196
|
disabled: Y,
|
|
197
|
-
className: "flex items-center justify-center p-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-
|
|
197
|
+
className: "flex items-center justify-center p-2 bg-bg-sunken text-text-primary rounded-md hover:bg-action-secondary-bg-hover transition-colors disabled:opacity-50",
|
|
198
198
|
title: I("common.refresh", "Refresh"),
|
|
199
199
|
children: /* @__PURE__ */ A(ue, { className: `size-4 ${Y ? "animate-spin" : ""}` })
|
|
200
200
|
}),
|
|
@@ -256,7 +256,7 @@ function W() {
|
|
|
256
256
|
/* @__PURE__ */ A(t, { className: "size-4" }),
|
|
257
257
|
e.label,
|
|
258
258
|
e.badge && /* @__PURE__ */ A("span", {
|
|
259
|
-
className: `hidden rounded-full px-1.5 py-0.5 text-[10px] sm:inline-flex sm:text-xs ${n ? "bg-
|
|
259
|
+
className: `hidden rounded-full px-1.5 py-0.5 text-[10px] sm:inline-flex sm:text-xs ${n ? "bg-[var(--color-accent-soft)] text-action-primary-bg" : "bg-bg-sunken text-text-muted"}`,
|
|
260
260
|
children: e.badge
|
|
261
261
|
})
|
|
262
262
|
]
|
|
@@ -525,7 +525,7 @@ function W() {
|
|
|
525
525
|
})
|
|
526
526
|
]
|
|
527
527
|
}) : /* @__PURE__ */ j(P, {
|
|
528
|
-
className: "space-y-6
|
|
528
|
+
className: "space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen",
|
|
529
529
|
children: [/* @__PURE__ */ j("button", {
|
|
530
530
|
type: "button",
|
|
531
531
|
onClick: $,
|
|
@@ -600,7 +600,7 @@ function q(e, t) {
|
|
|
600
600
|
/* @__PURE__ */ j("div", {
|
|
601
601
|
style: {
|
|
602
602
|
fontSize: 10,
|
|
603
|
-
color: o > 0 ? "
|
|
603
|
+
color: o > 0 ? "var(--color-action-primary-text)" : "var(--color-text-muted)",
|
|
604
604
|
marginTop: 2
|
|
605
605
|
},
|
|
606
606
|
children: [e.type, e.version ? ` v${e.version}` : ""]
|
|
@@ -609,7 +609,7 @@ function q(e, t) {
|
|
|
609
609
|
style: {
|
|
610
610
|
fontSize: 10,
|
|
611
611
|
marginTop: 3,
|
|
612
|
-
color: "
|
|
612
|
+
color: "var(--color-action-primary-text)"
|
|
613
613
|
},
|
|
614
614
|
children: [
|
|
615
615
|
o,
|
|
@@ -621,13 +621,13 @@ function q(e, t) {
|
|
|
621
621
|
}) },
|
|
622
622
|
style: {
|
|
623
623
|
background: o > 0 ? "var(--color-action-primary-bg)" : "var(--color-bg-sunken)",
|
|
624
|
-
color: o > 0 ? "
|
|
624
|
+
color: o > 0 ? "var(--color-action-primary-text)" : "var(--color-text-primary)",
|
|
625
625
|
border: `1px solid ${o > 0 ? "transparent" : "var(--color-border-default)"}`,
|
|
626
626
|
borderRadius: 10,
|
|
627
627
|
padding: "10px 14px",
|
|
628
628
|
width: 180,
|
|
629
629
|
fontSize: 12,
|
|
630
|
-
boxShadow: o > 0 ? "
|
|
630
|
+
boxShadow: o > 0 ? "var(--shadow-elevation-2)" : "none",
|
|
631
631
|
textAlign: "center",
|
|
632
632
|
cursor: "pointer"
|
|
633
633
|
}
|