@burdenoff/microfe-vibecontrols 2026.623.1 → 2026.623.3

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.
Files changed (295) hide show
  1. package/dist/components/actions/ActionCard.js +2 -2
  2. package/dist/components/actions/ActionCard.js.map +1 -1
  3. package/dist/components/actions/ActionTypeBadge.js +1 -1
  4. package/dist/components/actions/ActionTypeBadge.js.map +1 -1
  5. package/dist/components/actions/ExecutionHistory.js +1 -1
  6. package/dist/components/actions/ExecutionHistory.js.map +1 -1
  7. package/dist/components/agent-manager/AgentManagerAdminBar.js +1 -1
  8. package/dist/components/agent-manager/AgentManagerAdminBar.js.map +1 -1
  9. package/dist/components/agent-manager/AgentManagerChatPane.js +2 -2
  10. package/dist/components/agent-manager/AgentManagerChatPane.js.map +1 -1
  11. package/dist/components/agent-manager/AgentManagerInputArea.js +4 -4
  12. package/dist/components/agent-manager/AgentManagerInputArea.js.map +1 -1
  13. package/dist/components/agent-manager/AgentManagerLayout.js +1 -1
  14. package/dist/components/agent-manager/AgentManagerLayout.js.map +1 -1
  15. package/dist/components/agent-manager/AgentManagerMessageItem.js +1 -1
  16. package/dist/components/agent-manager/AgentManagerMessageItem.js.map +1 -1
  17. package/dist/components/agent-manager/AgentManagerSidebar.js +5 -5
  18. package/dist/components/agent-manager/AgentManagerSidebar.js.map +1 -1
  19. package/dist/components/agent-manager/AgentManagerTab.js +1 -1
  20. package/dist/components/agent-manager/AgentManagerTab.js.map +1 -1
  21. package/dist/components/agent-manager/AgentManagerTabBar.js +1 -1
  22. package/dist/components/agent-manager/AgentManagerTabBar.js.map +1 -1
  23. package/dist/components/agent-manager/BridleConfigPanel.js +24 -24
  24. package/dist/components/agent-manager/BridleConfigPanel.js.map +1 -1
  25. package/dist/components/agent-manager/PluginInstallModal.js +1 -1
  26. package/dist/components/agent-manager/PluginInstallModal.js.map +1 -1
  27. package/dist/components/agent-manager/ProfilesPanel.js +5 -5
  28. package/dist/components/agent-manager/ProfilesPanel.js.map +1 -1
  29. package/dist/components/agent-manager/controls/AutonomySelector.js +1 -1
  30. package/dist/components/agent-manager/controls/AutonomySelector.js.map +1 -1
  31. package/dist/components/agent-manager/controls/SdkSelector.js +1 -1
  32. package/dist/components/agent-manager/controls/SdkSelector.js.map +1 -1
  33. package/dist/components/agent-manager/controls/VoiceToggle.js +1 -1
  34. package/dist/components/agent-manager/controls/VoiceToggle.js.map +1 -1
  35. package/dist/components/agent-manager/detail/SessionConfigPanel.js +6 -6
  36. package/dist/components/agent-manager/detail/SessionConfigPanel.js.map +1 -1
  37. package/dist/components/agent-manager/detail/SessionLogsPanel.js +5 -5
  38. package/dist/components/agent-manager/detail/SessionLogsPanel.js.map +1 -1
  39. package/dist/components/agent-manager/detail/SessionToolsPanel.js +1 -1
  40. package/dist/components/agent-manager/detail/SessionToolsPanel.js.map +1 -1
  41. package/dist/components/agent-manager/dialogs/NewSessionDialog.js +2 -2
  42. package/dist/components/agent-manager/dialogs/NewSessionDialog.js.map +1 -1
  43. package/dist/components/agent-manager/dialogs/RenameSessionDialog.js +1 -1
  44. package/dist/components/agent-manager/dialogs/RenameSessionDialog.js.map +1 -1
  45. package/dist/components/agents/AgentCard.js +14 -11
  46. package/dist/components/agents/AgentCard.js.map +1 -1
  47. package/dist/components/ai/AIContextsTab.js +1 -1
  48. package/dist/components/ai/AIContextsTab.js.map +1 -1
  49. package/dist/components/ai/AIOverviewTab.js +4 -4
  50. package/dist/components/ai/AIOverviewTab.js.map +1 -1
  51. package/dist/components/ai/AIPlanPanel.js +4 -4
  52. package/dist/components/ai/AIPlanPanel.js.map +1 -1
  53. package/dist/components/ai/AIPlaygroundTab.js +1 -1
  54. package/dist/components/ai/AIPlaygroundTab.js.map +1 -1
  55. package/dist/components/ai/AIPromptsTab.js +2 -2
  56. package/dist/components/ai/AIPromptsTab.js.map +1 -1
  57. package/dist/components/ai/AIProviderCredentialsCard.js +4 -4
  58. package/dist/components/ai/AIProviderCredentialsCard.js.map +1 -1
  59. package/dist/components/ai/AIQueueTab.js +4 -4
  60. package/dist/components/ai/AIQueueTab.js.map +1 -1
  61. package/dist/components/ai/AISessionsTab.js +4 -4
  62. package/dist/components/ai/AISessionsTab.js.map +1 -1
  63. package/dist/components/ai/AITasksTab.js +1 -1
  64. package/dist/components/ai/AITasksTab.js.map +1 -1
  65. package/dist/components/ai/ClaudeCredentialsCard.js +3 -3
  66. package/dist/components/ai/ClaudeCredentialsCard.js.map +1 -1
  67. package/dist/components/ai/PluginHarnessPicker.js +3 -3
  68. package/dist/components/ai/PluginHarnessPicker.js.map +1 -1
  69. package/dist/components/analytics/AnalyticsBreakdownChart.js +8 -8
  70. package/dist/components/analytics/AnalyticsBreakdownChart.js.map +1 -1
  71. package/dist/components/analytics/AnalyticsTimeSeriesChart.js +5 -5
  72. package/dist/components/analytics/AnalyticsTimeSeriesChart.js.map +1 -1
  73. package/dist/components/audit/AuditDeleteDialog.js +2 -2
  74. package/dist/components/audit/AuditDeleteDialog.js.map +1 -1
  75. package/dist/components/audit/AuditExportButton.js +5 -5
  76. package/dist/components/audit/AuditExportButton.js.map +1 -1
  77. package/dist/components/audit/AuditLogDetail.js +9 -9
  78. package/dist/components/audit/AuditLogDetail.js.map +1 -1
  79. package/dist/components/audit/AuditLogFilters.js +1 -1
  80. package/dist/components/audit/AuditLogFilters.js.map +1 -1
  81. package/dist/components/audit/AuditLogStats.js +1 -1
  82. package/dist/components/audit/AuditLogStats.js.map +1 -1
  83. package/dist/components/audit/AuditLogTable.js +28 -28
  84. package/dist/components/audit/AuditLogTable.js.map +1 -1
  85. package/dist/components/catalog/CatalogCard.js +3 -3
  86. package/dist/components/catalog/CatalogCard.js.map +1 -1
  87. package/dist/components/catalog/CatalogForm.js +1 -1
  88. package/dist/components/catalog/CatalogForm.js.map +1 -1
  89. package/dist/components/common/ActionAgentTargetNotice.js +6 -6
  90. package/dist/components/common/ActionAgentTargetNotice.js.map +1 -1
  91. package/dist/components/common/CommandEditor.js +1 -1
  92. package/dist/components/common/CommandEditor.js.map +1 -1
  93. package/dist/components/docs/DocsPageTree.js +1 -1
  94. package/dist/components/docs/DocsPageTree.js.map +1 -1
  95. package/dist/components/docs/DocsPreviewPanel.js +1 -1
  96. package/dist/components/docs/DocsPreviewPanel.js.map +1 -1
  97. package/dist/components/docs/DocsRevisionHistory.js +4 -4
  98. package/dist/components/docs/DocsRevisionHistory.js.map +1 -1
  99. package/dist/components/docs/DocsSettingsPanel.js +7 -7
  100. package/dist/components/docs/DocsSettingsPanel.js.map +1 -1
  101. package/dist/components/docs/DocsTabPanel.js +1 -1
  102. package/dist/components/docs/DocsTabPanel.js.map +1 -1
  103. package/dist/components/graph/ConnectionPermissionsDialog.js +2 -2
  104. package/dist/components/graph/ConnectionPermissionsDialog.js.map +1 -1
  105. package/dist/components/graph/MeshDeployWizard.js +3 -3
  106. package/dist/components/graph/MeshDeployWizard.js.map +1 -1
  107. package/dist/components/graph/MeshRequestPanel.js +2 -2
  108. package/dist/components/graph/MeshRequestPanel.js.map +1 -1
  109. package/dist/components/idp-components/ComponentCard.js +5 -5
  110. package/dist/components/idp-components/ComponentCard.js.map +1 -1
  111. package/dist/components/idp-components/ComponentForm.js +1 -1
  112. package/dist/components/idp-components/ComponentForm.js.map +1 -1
  113. package/dist/components/idp-components/DependencyGraphTab.js +7 -7
  114. package/dist/components/idp-components/DependencyGraphTab.js.map +1 -1
  115. package/dist/components/logs/LogViewer.js +14 -14
  116. package/dist/components/logs/LogViewer.js.map +1 -1
  117. package/dist/components/notes/NoteCard.js +1 -1
  118. package/dist/components/notes/NoteCard.js.map +1 -1
  119. package/dist/components/notes/NoteEditor.js +2 -2
  120. package/dist/components/notes/NoteEditor.js.map +1 -1
  121. package/dist/components/notes/NoteList.js +1 -1
  122. package/dist/components/notes/NoteList.js.map +1 -1
  123. package/dist/components/notes/NotesTabPanel.js +1 -1
  124. package/dist/components/notes/NotesTabPanel.js.map +1 -1
  125. package/dist/components/scorecard/ScorecardEmptyState.js +1 -1
  126. package/dist/components/scorecard/ScorecardEmptyState.js.map +1 -1
  127. package/dist/components/scorecard/ScorecardPanel.js +3 -3
  128. package/dist/components/scorecard/ScorecardPanel.js.map +1 -1
  129. package/dist/components/security/SecurityScanList.js +11 -11
  130. package/dist/components/security/SecurityScanList.js.map +1 -1
  131. package/dist/components/sessions/SessionCard.js +26 -19
  132. package/dist/components/sessions/SessionCard.js.map +1 -1
  133. package/dist/components/sessions/SessionStatusBadge.js +7 -7
  134. package/dist/components/sessions/SessionStatusBadge.js.map +1 -1
  135. package/dist/components/shared/AgentSelector.js +4 -4
  136. package/dist/components/shared/AgentSelector.js.map +1 -1
  137. package/dist/components/shared/AgentSetupBanner.js +4 -4
  138. package/dist/components/shared/AgentSetupBanner.js.map +1 -1
  139. package/dist/components/shared/Card.js +4 -4
  140. package/dist/components/shared/Card.js.map +1 -1
  141. package/dist/components/shared/ErrorState.js +15 -9
  142. package/dist/components/shared/ErrorState.js.map +1 -1
  143. package/dist/components/shared/FilterDropdown.js +2 -2
  144. package/dist/components/shared/FilterDropdown.js.map +1 -1
  145. package/dist/components/shared/PageSkeleton.js +6 -6
  146. package/dist/components/shared/PageSkeleton.js.map +1 -1
  147. package/dist/components/shared/SearchInput.js +1 -1
  148. package/dist/components/shared/SearchInput.js.map +1 -1
  149. package/dist/components/shared/StatCard.js +7 -7
  150. package/dist/components/shared/StatCard.js.map +1 -1
  151. package/dist/components/templates/PublishTemplateForm.js +2 -2
  152. package/dist/components/templates/PublishTemplateForm.js.map +1 -1
  153. package/dist/components/templates/TemplateCard.js +5 -5
  154. package/dist/components/templates/TemplateCard.js.map +1 -1
  155. package/dist/components/templates/TemplateWizard.js +2 -2
  156. package/dist/components/templates/TemplateWizard.js.map +1 -1
  157. package/dist/components/tunnels/DomainVerificationBadge.js +4 -4
  158. package/dist/components/tunnels/DomainVerificationBadge.js.map +1 -1
  159. package/dist/components/tunnels/ProviderBadge.js +1 -1
  160. package/dist/components/tunnels/ProviderBadge.js.map +1 -1
  161. package/dist/components/tunnels/TunnelCard.js +16 -16
  162. package/dist/components/tunnels/TunnelCard.js.map +1 -1
  163. package/dist/components/tunnels/TunnelCreateWizard.js +1 -1
  164. package/dist/components/tunnels/TunnelCreateWizard.js.map +1 -1
  165. package/dist/components/tunnels/TunnelPublicAccessPanel.js +1 -1
  166. package/dist/components/tunnels/TunnelPublicAccessPanel.js.map +1 -1
  167. package/dist/components/tunnels/TunnelStatusBadge.js +4 -4
  168. package/dist/components/tunnels/TunnelStatusBadge.js.map +1 -1
  169. package/dist/components/vibecalendar/LogsDrawer.js +2 -2
  170. package/dist/components/vibecalendar/LogsDrawer.js.map +1 -1
  171. package/dist/components/vibecalendar/ScheduleTaskModal.js +5 -5
  172. package/dist/components/vibecalendar/ScheduleTaskModal.js.map +1 -1
  173. package/dist/components/vibecalendar/VibeCalAgendaView.js +2 -2
  174. package/dist/components/vibecalendar/VibeCalAgendaView.js.map +1 -1
  175. package/dist/components/vibecalendar/VibeCalDayView.js +3 -3
  176. package/dist/components/vibecalendar/VibeCalDayView.js.map +1 -1
  177. package/dist/components/vibecalendar/VibeCalMonthView.js +1 -1
  178. package/dist/components/vibecalendar/VibeCalMonthView.js.map +1 -1
  179. package/dist/components/vibecalendar/VibeCalWeekView.js +4 -4
  180. package/dist/components/vibecalendar/VibeCalWeekView.js.map +1 -1
  181. package/dist/components/vibecalendar/VibeCalendarHeader.js +4 -4
  182. package/dist/components/vibecalendar/VibeCalendarHeader.js.map +1 -1
  183. package/dist/components/vibecalendar/VibeTaskBlock.js +2 -2
  184. package/dist/components/vibecalendar/VibeTaskBlock.js.map +1 -1
  185. package/dist/components/vibecalendar/types.js +7 -7
  186. package/dist/components/vibecalendar/types.js.map +1 -1
  187. package/dist/components/vibedeck/VibeDeckButtonForm.js +9 -9
  188. package/dist/components/vibedeck/VibeDeckButtonForm.js.map +1 -1
  189. package/dist/components/vibedeck/VibeDeckButtonTile.js +6 -6
  190. package/dist/components/vibedeck/VibeDeckButtonTile.js.map +1 -1
  191. package/dist/components/vibedeck/VibeDeckExecutionLog.js +10 -10
  192. package/dist/components/vibedeck/VibeDeckExecutionLog.js.map +1 -1
  193. package/dist/components/vibedeck/VibeDeckForm.js +8 -8
  194. package/dist/components/vibedeck/VibeDeckForm.js.map +1 -1
  195. package/dist/components/vibedeck/VibeDeckGrid.js +2 -2
  196. package/dist/components/vibedeck/VibeDeckGrid.js.map +1 -1
  197. package/dist/components/vibedeck/VibeDeckPublicLinkPanel.js +2 -2
  198. package/dist/components/vibedeck/VibeDeckPublicLinkPanel.js.map +1 -1
  199. package/dist/components/vibedeck/VibeDeckSwitcher.js +8 -8
  200. package/dist/components/vibedeck/VibeDeckSwitcher.js.map +1 -1
  201. package/dist/components/vibes/VibeCard.js +22 -18
  202. package/dist/components/vibes/VibeCard.js.map +1 -1
  203. package/dist/components/vibes/VibeList.js +16 -12
  204. package/dist/components/vibes/VibeList.js.map +1 -1
  205. package/dist/pages/ActionsPage.js +4 -3
  206. package/dist/pages/ActionsPage.js.map +1 -1
  207. package/dist/pages/AgentDetailsPage.js +9 -9
  208. package/dist/pages/AgentDetailsPage.js.map +1 -1
  209. package/dist/pages/AgentsLandingPage.js +4 -4
  210. package/dist/pages/AgentsLandingPage.js.map +1 -1
  211. package/dist/pages/AgentsPage.js +14 -14
  212. package/dist/pages/AgentsPage.js.map +1 -1
  213. package/dist/pages/AnalyticsPage.js +8 -8
  214. package/dist/pages/AnalyticsPage.js.map +1 -1
  215. package/dist/pages/CatalogDetailPage.js +11 -11
  216. package/dist/pages/CatalogDetailPage.js.map +1 -1
  217. package/dist/pages/CatalogPage.js +12 -9
  218. package/dist/pages/CatalogPage.js.map +1 -1
  219. package/dist/pages/ComponentDetailPage.js +7 -7
  220. package/dist/pages/ComponentDetailPage.js.map +1 -1
  221. package/dist/pages/ComponentsPage.js +12 -9
  222. package/dist/pages/ComponentsPage.js.map +1 -1
  223. package/dist/pages/EnvTopologyPage.js +2 -2
  224. package/dist/pages/EnvTopologyPage.js.map +1 -1
  225. package/dist/pages/GettingStartedPage.js +12 -12
  226. package/dist/pages/GettingStartedPage.js.map +1 -1
  227. package/dist/pages/HealthPage.js +12 -12
  228. package/dist/pages/HealthPage.js.map +1 -1
  229. package/dist/pages/LogsPage.js +4 -4
  230. package/dist/pages/LogsPage.js.map +1 -1
  231. package/dist/pages/NoteDetailsPage.js +5 -5
  232. package/dist/pages/NoteDetailsPage.js.map +1 -1
  233. package/dist/pages/OverviewPage.js +76 -43
  234. package/dist/pages/OverviewPage.js.map +1 -1
  235. package/dist/pages/PluginsCatalogPage.js +7 -4
  236. package/dist/pages/PluginsCatalogPage.js.map +1 -1
  237. package/dist/pages/ScheduledJobDetailPage.js +7 -7
  238. package/dist/pages/ScheduledJobDetailPage.js.map +1 -1
  239. package/dist/pages/SessionDetailsPage.js +21 -21
  240. package/dist/pages/SessionDetailsPage.js.map +1 -1
  241. package/dist/pages/SessionsPage.js +20 -20
  242. package/dist/pages/SessionsPage.js.map +1 -1
  243. package/dist/pages/SettingsPage.js +64 -52
  244. package/dist/pages/SettingsPage.js.map +1 -1
  245. package/dist/pages/SharedSessionPage.js +21 -21
  246. package/dist/pages/SharedSessionPage.js.map +1 -1
  247. package/dist/pages/SharedVibeDeckPage.js +5 -5
  248. package/dist/pages/SharedVibeDeckPage.js.map +1 -1
  249. package/dist/pages/TargetDetailsPage.js +56 -65
  250. package/dist/pages/TargetDetailsPage.js.map +1 -1
  251. package/dist/pages/TargetsPage.js +4 -4
  252. package/dist/pages/TargetsPage.js.map +1 -1
  253. package/dist/pages/TemplateDetailPage.js +10 -10
  254. package/dist/pages/TemplateDetailPage.js.map +1 -1
  255. package/dist/pages/TemplatesPage.js +6 -5
  256. package/dist/pages/TemplatesPage.js.map +1 -1
  257. package/dist/pages/VibeAuditPage.js +3 -3
  258. package/dist/pages/VibeAuditPage.js.map +1 -1
  259. package/dist/pages/VibeCalendarPage.js +3 -3
  260. package/dist/pages/VibeCalendarPage.js.map +1 -1
  261. package/dist/pages/VibeDeckPage.js +3 -3
  262. package/dist/pages/VibeDeckPage.js.map +1 -1
  263. package/dist/pages/VibeDetailsPage.js +15 -15
  264. package/dist/pages/VibeDetailsPage.js.map +1 -1
  265. package/dist/pages/VibeTaskDetailPage.js +5 -5
  266. package/dist/pages/VibeTaskDetailPage.js.map +1 -1
  267. package/dist/pages/VibesPage.js +18 -18
  268. package/dist/pages/VibesPage.js.map +1 -1
  269. package/dist/pages/WebhooksPage.js +11 -11
  270. package/dist/pages/WebhooksPage.js.map +1 -1
  271. package/dist/pages/ai/AIBookmarksPage.js +1 -1
  272. package/dist/pages/ai/AIBookmarksPage.js.map +1 -1
  273. package/dist/pages/ai/AISessionDetailPage.js +6 -6
  274. package/dist/pages/ai/AISessionDetailPage.js.map +1 -1
  275. package/dist/pages/tunnels/AuditTab.js +1 -1
  276. package/dist/pages/tunnels/AuditTab.js.map +1 -1
  277. package/dist/pages/tunnels/DomainsTab.js +1 -1
  278. package/dist/pages/tunnels/DomainsTab.js.map +1 -1
  279. package/dist/pages/tunnels/ProvidersTab.js +1 -1
  280. package/dist/pages/tunnels/ProvidersTab.js.map +1 -1
  281. package/dist/pages/tunnels/SessionsTab.js +1 -1
  282. package/dist/pages/tunnels/SessionsTab.js.map +1 -1
  283. package/dist/pages/tunnels/TunnelDetailsPage.js +3 -3
  284. package/dist/pages/tunnels/TunnelDetailsPage.js.map +1 -1
  285. package/dist/pages/tunnels/UsageTab.js +1 -1
  286. package/dist/pages/tunnels/UsageTab.js.map +1 -1
  287. package/dist/pages/tunnels/tabs/TunnelDomainsTab.js +16 -16
  288. package/dist/pages/tunnels/tabs/TunnelDomainsTab.js.map +1 -1
  289. package/dist/pages/tunnels/tabs/TunnelOverviewTab.js +1 -1
  290. package/dist/pages/tunnels/tabs/TunnelOverviewTab.js.map +1 -1
  291. package/dist/pages/tunnels/tabs/TunnelSessionsTab.js +52 -49
  292. package/dist/pages/tunnels/tabs/TunnelSessionsTab.js.map +1 -1
  293. package/dist/pages/tunnels/tabs/TunnelSettingsTab.js +9 -9
  294. package/dist/pages/tunnels/tabs/TunnelSettingsTab.js.map +1 -1
  295. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AnalyticsBreakdownChart.js","names":[],"sources":["../../../src/components/analytics/AnalyticsBreakdownChart.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { ResponsiveContainer, PieChart, Pie, Cell, Tooltip, Legend } from 'recharts';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface BreakdownBucket {\n key: string;\n count: number;\n}\n\ninterface AnalyticsBreakdownChartProps {\n title: string;\n data: BreakdownBucket[] | null | undefined;\n height?: number;\n}\n\nconst PIE_COLORS = [\n 'var(--color-text-link)',\n 'var(--color-status-success-text)',\n 'var(--color-accent-purple)',\n 'var(--color-status-warning-text)',\n 'var(--color-status-error-text)',\n 'var(--color-accent-teal)',\n 'var(--color-text-tertiary)',\n 'var(--color-border-strong)',\n];\n\nexport function AnalyticsBreakdownChart({\n title,\n data,\n height = 250,\n}: AnalyticsBreakdownChartProps) {\n const chartData = useMemo(() => {\n if (!data || data.length === 0) return [];\n return data.map((d) => ({\n name: d.key,\n value: d.count,\n }));\n }, [data]);\n\n const tr = useTr();\n\n if (chartData.length === 0) {\n return (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <h3 className=\"text-sm font-medium text-text-primary mb-3\">{title}</h3>\n <div className=\"flex items-center justify-center h-[150px] text-text-secondary text-sm\">\n {tr('vibecontrols.analytics.noData', 'No data')}\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <h3 className=\"text-sm font-medium text-text-primary mb-3\">{title}</h3>\n <ResponsiveContainer width=\"100%\" height={height}>\n <PieChart>\n <Pie\n data={chartData}\n cx=\"50%\"\n cy=\"50%\"\n innerRadius={55}\n outerRadius={80}\n paddingAngle={2}\n dataKey=\"value\"\n >\n {chartData.map((_, i) => (\n <Cell key={i} fill={PIE_COLORS[i % PIE_COLORS.length]} />\n ))}\n </Pie>\n <Tooltip\n contentStyle={{\n background: 'var(--color-bg-surface)',\n border: '1px solid var(--color-border-default)',\n borderRadius: '6px',\n fontSize: '12px',\n }}\n />\n <Legend\n wrapperStyle={{ fontSize: '11px' }}\n layout=\"vertical\"\n align=\"right\"\n verticalAlign=\"middle\"\n />\n </PieChart>\n </ResponsiveContainer>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;AAeA,IAAM,IAAa;CACjB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,SAAgB,EAAwB,EACtC,UACA,SACA,YAAS,OACsB;CAC/B,IAAM,IAAY,QACZ,CAAC,KAAQ,EAAK,WAAW,IAAU,EAAE,GAClC,EAAK,KAAK,OAAO;EACtB,MAAM,EAAE;EACR,OAAO,EAAE;EACV,EAAE,EACF,CAAC,EAAK,CAAC,EAEJ,IAAK,GAAO;AAalB,QAXI,EAAU,WAAW,IAErB,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,MAAD;GAAI,WAAU;aAA8C;GAAW,CAAA,EACvE,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAG,iCAAiC,UAAU;GAC3C,CAAA,CACF;MAKR,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,MAAD;GAAI,WAAU;aAA8C;GAAW,CAAA,EACvE,kBAAC,GAAD;GAAqB,OAAM;GAAe;aACxC,kBAAC,GAAD,EAAA,UAAA;IACE,kBAAC,GAAD;KACE,MAAM;KACN,IAAG;KACH,IAAG;KACH,aAAa;KACb,aAAa;KACb,cAAc;KACd,SAAQ;eAEP,EAAU,KAAK,GAAG,MACjB,kBAAC,GAAD,EAAc,MAAM,EAAW,IAAI,EAAW,SAAW,EAA9C,EAA8C,CACzD;KACE,CAAA;IACN,kBAAC,GAAD,EACE,cAAc;KACZ,YAAY;KACZ,QAAQ;KACR,cAAc;KACd,UAAU;KACX,EACD,CAAA;IACF,kBAAC,GAAD;KACE,cAAc,EAAE,UAAU,QAAQ;KAClC,QAAO;KACP,OAAM;KACN,eAAc;KACd,CAAA;IACO,EAAA,CAAA;GACS,CAAA,CAClB"}
1
+ {"version":3,"file":"AnalyticsBreakdownChart.js","names":[],"sources":["../../../src/components/analytics/AnalyticsBreakdownChart.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { ResponsiveContainer, PieChart, Pie, Cell, Tooltip, Legend } from 'recharts';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface BreakdownBucket {\n key: string;\n count: number;\n}\n\ninterface AnalyticsBreakdownChartProps {\n title: string;\n data: BreakdownBucket[] | null | undefined;\n height?: number;\n}\n\nconst PIE_COLORS = [\n 'var(--color-chart-1)',\n 'var(--color-chart-2)',\n 'var(--color-chart-3)',\n 'var(--color-chart-4)',\n 'var(--color-chart-5)',\n 'var(--color-chart-6)',\n 'var(--color-chart-7)',\n 'var(--color-chart-8)',\n];\n\nexport function AnalyticsBreakdownChart({\n title,\n data,\n height = 250,\n}: AnalyticsBreakdownChartProps) {\n const chartData = useMemo(() => {\n if (!data || data.length === 0) return [];\n return data.map((d) => ({\n name: d.key,\n value: d.count,\n }));\n }, [data]);\n\n const tr = useTr();\n\n if (chartData.length === 0) {\n return (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <h3 className=\"text-sm font-medium text-text-primary mb-3\">{title}</h3>\n <div className=\"flex items-center justify-center h-[150px] text-text-secondary text-sm\">\n {tr('vibecontrols.analytics.noData', 'No data')}\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <h3 className=\"text-sm font-medium text-text-primary mb-3\">{title}</h3>\n <ResponsiveContainer width=\"100%\" height={height}>\n <PieChart>\n <Pie\n data={chartData}\n cx=\"50%\"\n cy=\"50%\"\n innerRadius={55}\n outerRadius={80}\n paddingAngle={2}\n dataKey=\"value\"\n >\n {chartData.map((_, i) => (\n <Cell key={i} fill={PIE_COLORS[i % PIE_COLORS.length]} />\n ))}\n </Pie>\n <Tooltip\n contentStyle={{\n background: 'var(--color-bg-surface)',\n border: '1px solid var(--color-border-default)',\n borderRadius: '6px',\n fontSize: '12px',\n }}\n />\n <Legend\n wrapperStyle={{ fontSize: '11px' }}\n layout=\"vertical\"\n align=\"right\"\n verticalAlign=\"middle\"\n />\n </PieChart>\n </ResponsiveContainer>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;AAeA,IAAM,IAAa;CACjB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,SAAgB,EAAwB,EACtC,UACA,SACA,YAAS,OACsB;CAC/B,IAAM,IAAY,QACZ,CAAC,KAAQ,EAAK,WAAW,IAAU,EAAE,GAClC,EAAK,KAAK,OAAO;EACtB,MAAM,EAAE;EACR,OAAO,EAAE;EACV,EAAE,EACF,CAAC,EAAK,CAAC,EAEJ,IAAK,GAAO;AAalB,QAXI,EAAU,WAAW,IAErB,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,MAAD;GAAI,WAAU;aAA8C;GAAW,CAAA,EACvE,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAG,iCAAiC,UAAU;GAC3C,CAAA,CACF;MAKR,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,MAAD;GAAI,WAAU;aAA8C;GAAW,CAAA,EACvE,kBAAC,GAAD;GAAqB,OAAM;GAAe;aACxC,kBAAC,GAAD,EAAA,UAAA;IACE,kBAAC,GAAD;KACE,MAAM;KACN,IAAG;KACH,IAAG;KACH,aAAa;KACb,aAAa;KACb,cAAc;KACd,SAAQ;eAEP,EAAU,KAAK,GAAG,MACjB,kBAAC,GAAD,EAAc,MAAM,EAAW,IAAI,EAAW,SAAW,EAA9C,EAA8C,CACzD;KACE,CAAA;IACN,kBAAC,GAAD,EACE,cAAc;KACZ,YAAY;KACZ,QAAQ;KACR,cAAc;KACd,UAAU;KACX,EACD,CAAA;IACF,kBAAC,GAAD;KACE,cAAc,EAAE,UAAU,QAAQ;KAClC,QAAO;KACP,OAAM;KACN,eAAc;KACd,CAAA;IACO,EAAA,CAAA;GACS,CAAA,CAClB"}
@@ -11,11 +11,11 @@ import { useMemo as l } from "react";
11
11
  import { jsx as u, jsxs as d } from "react/jsx-runtime";
12
12
  //#region src/components/analytics/AnalyticsTimeSeriesChart.tsx
13
13
  var f = [
14
- "var(--color-text-link)",
15
- "var(--color-status-success-text)",
16
- "var(--color-accent-purple)",
17
- "var(--color-status-warning-text)",
18
- "var(--color-status-error-text)"
14
+ "var(--color-chart-1)",
15
+ "var(--color-chart-2)",
16
+ "var(--color-chart-3)",
17
+ "var(--color-chart-4)",
18
+ "var(--color-chart-5)"
19
19
  ];
20
20
  function p({ datasets: p, title: m, height: h = 300 }) {
21
21
  let g = l(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"AnalyticsTimeSeriesChart.js","names":[],"sources":["../../../src/components/analytics/AnalyticsTimeSeriesChart.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { useTr } from '../../shared/hooks/useTr';\nimport {\n ResponsiveContainer,\n AreaChart,\n Area,\n XAxis,\n YAxis,\n Tooltip,\n Legend,\n CartesianGrid,\n} from 'recharts';\n\ninterface TimeSeriesDataset {\n label: string;\n data: Array<{ timestamp: string; value: number }> | null | undefined;\n color: string;\n}\n\ninterface AnalyticsTimeSeriesChartProps {\n datasets: TimeSeriesDataset[];\n title?: string;\n height?: number;\n}\n\nconst COLORS = [\n 'var(--color-text-link)',\n 'var(--color-status-success-text)',\n 'var(--color-accent-purple)',\n 'var(--color-status-warning-text)',\n 'var(--color-status-error-text)',\n];\n\nexport function AnalyticsTimeSeriesChart({\n datasets,\n title,\n height = 300,\n}: AnalyticsTimeSeriesChartProps) {\n const chartData = useMemo(() => {\n // Merge all datasets into a single array keyed by timestamp\n const map = new Map<string, Record<string, number>>();\n\n for (const ds of datasets) {\n if (!ds.data) continue;\n for (const point of ds.data) {\n const ts = new Date(point.timestamp).toISOString();\n if (!map.has(ts)) map.set(ts, {});\n map.get(ts)![ds.label] = point.value;\n }\n }\n\n return Array.from(map.entries())\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([ts, values]) => ({\n timestamp: ts,\n ...values,\n }));\n }, [datasets]);\n\n const formatDate = (ts: string) => {\n const d = new Date(ts);\n return `${d.getMonth() + 1}/${d.getDate()}`;\n };\n\n const formatTooltipDate = (ts: string) => {\n return new Date(ts).toLocaleString(undefined, {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n };\n\n const tr = useTr();\n\n if (chartData.length === 0) {\n return (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n {title && <h3 className=\"text-sm font-medium text-text-primary mb-3\">{title}</h3>}\n <div className=\"flex items-center justify-center h-[200px] text-text-secondary text-sm\">\n {tr(\n 'vibecontrols.analytics.noDataForRange',\n 'No data available for the selected time range'\n )}\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n {title && <h3 className=\"text-sm font-medium text-text-primary mb-3\">{title}</h3>}\n <ResponsiveContainer width=\"100%\" height={height}>\n <AreaChart data={chartData} margin={{ top: 5, right: 10, left: 0, bottom: 5 }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke=\"var(--color-border-default)\" opacity={0.3} />\n <XAxis\n dataKey=\"timestamp\"\n tickFormatter={formatDate}\n tick={{ fill: 'var(--color-text-secondary)', fontSize: 11 }}\n axisLine={{ stroke: 'var(--color-border-default)' }}\n />\n <YAxis\n tick={{ fill: 'var(--color-text-secondary)', fontSize: 11 }}\n axisLine={{ stroke: 'var(--color-border-default)' }}\n allowDecimals={false}\n />\n <Tooltip\n labelFormatter={formatTooltipDate}\n contentStyle={{\n background: 'var(--color-bg-surface)',\n border: '1px solid var(--color-border-default)',\n borderRadius: '6px',\n fontSize: '12px',\n }}\n />\n <Legend wrapperStyle={{ fontSize: '12px' }} />\n {datasets.map((ds, i) => (\n <Area\n key={ds.label}\n type=\"monotone\"\n dataKey={ds.label}\n stroke={ds.color || COLORS[i % COLORS.length]}\n fill={ds.color || COLORS[i % COLORS.length]}\n fillOpacity={0.1}\n strokeWidth={2}\n dot={false}\n />\n ))}\n </AreaChart>\n </ResponsiveContainer>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAyBA,IAAM,IAAS;CACb;CACA;CACA;CACA;CACA;CACD;AAED,SAAgB,EAAyB,EACvC,aACA,UACA,YAAS,OACuB;CAChC,IAAM,IAAY,QAAc;EAE9B,IAAM,oBAAM,IAAI,KAAqC;AAErD,OAAK,IAAM,KAAM,EACV,OAAG,KACR,MAAK,IAAM,KAAS,EAAG,MAAM;GAC3B,IAAM,IAAK,IAAI,KAAK,EAAM,UAAU,CAAC,aAAa;AAElD,GADK,EAAI,IAAI,EAAG,IAAE,EAAI,IAAI,GAAI,EAAE,CAAC,EACjC,EAAI,IAAI,EAAG,CAAE,EAAG,SAAS,EAAM;;AAInC,SAAO,MAAM,KAAK,EAAI,SAAS,CAAC,CAC7B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC,CACtC,KAAK,CAAC,GAAI,QAAa;GACtB,WAAW;GACX,GAAG;GACJ,EAAE;IACJ,CAAC,EAAS,CAAC,EAER,KAAc,MAAe;EACjC,IAAM,IAAI,IAAI,KAAK,EAAG;AACtB,SAAO,GAAG,EAAE,UAAU,GAAG,EAAE,GAAG,EAAE,SAAS;IAGrC,KAAqB,MAClB,IAAI,KAAK,EAAG,CAAC,eAAe,KAAA,GAAW;EAC5C,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;EACT,CAAC,EAGE,IAAK,GAAO;AAgBlB,QAdI,EAAU,WAAW,IAErB,kBAAC,OAAD;EAAK,WAAU;YAAf,CACG,KAAS,kBAAC,MAAD;GAAI,WAAU;aAA8C;GAAW,CAAA,EACjF,kBAAC,OAAD;GAAK,WAAU;aACZ,EACC,yCACA,gDACD;GACG,CAAA,CACF;MAKR,kBAAC,OAAD;EAAK,WAAU;YAAf,CACG,KAAS,kBAAC,MAAD;GAAI,WAAU;aAA8C;GAAW,CAAA,EACjF,kBAAC,GAAD;GAAqB,OAAM;GAAe;aACxC,kBAAC,GAAD;IAAW,MAAM;IAAW,QAAQ;KAAE,KAAK;KAAG,OAAO;KAAI,MAAM;KAAG,QAAQ;KAAG;cAA7E;KACE,kBAAC,GAAD;MAAe,iBAAgB;MAAM,QAAO;MAA8B,SAAS;MAAO,CAAA;KAC1F,kBAAC,GAAD;MACE,SAAQ;MACR,eAAe;MACf,MAAM;OAAE,MAAM;OAA+B,UAAU;OAAI;MAC3D,UAAU,EAAE,QAAQ,+BAA+B;MACnD,CAAA;KACF,kBAAC,GAAD;MACE,MAAM;OAAE,MAAM;OAA+B,UAAU;OAAI;MAC3D,UAAU,EAAE,QAAQ,+BAA+B;MACnD,eAAe;MACf,CAAA;KACF,kBAAC,GAAD;MACE,gBAAgB;MAChB,cAAc;OACZ,YAAY;OACZ,QAAQ;OACR,cAAc;OACd,UAAU;OACX;MACD,CAAA;KACF,kBAAC,GAAD,EAAQ,cAAc,EAAE,UAAU,QAAQ,EAAI,CAAA;KAC7C,EAAS,KAAK,GAAI,MACjB,kBAAC,GAAD;MAEE,MAAK;MACL,SAAS,EAAG;MACZ,QAAQ,EAAG,SAAS,EAAO,IAAI,EAAO;MACtC,MAAM,EAAG,SAAS,EAAO,IAAI,EAAO;MACpC,aAAa;MACb,aAAa;MACb,KAAK;MACL,EARK,EAAG,MAQR,CACF;KACQ;;GACQ,CAAA,CAClB"}
1
+ {"version":3,"file":"AnalyticsTimeSeriesChart.js","names":[],"sources":["../../../src/components/analytics/AnalyticsTimeSeriesChart.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { useTr } from '../../shared/hooks/useTr';\nimport {\n ResponsiveContainer,\n AreaChart,\n Area,\n XAxis,\n YAxis,\n Tooltip,\n Legend,\n CartesianGrid,\n} from 'recharts';\n\ninterface TimeSeriesDataset {\n label: string;\n data: Array<{ timestamp: string; value: number }> | null | undefined;\n color: string;\n}\n\ninterface AnalyticsTimeSeriesChartProps {\n datasets: TimeSeriesDataset[];\n title?: string;\n height?: number;\n}\n\nconst COLORS = [\n 'var(--color-chart-1)',\n 'var(--color-chart-2)',\n 'var(--color-chart-3)',\n 'var(--color-chart-4)',\n 'var(--color-chart-5)',\n];\n\nexport function AnalyticsTimeSeriesChart({\n datasets,\n title,\n height = 300,\n}: AnalyticsTimeSeriesChartProps) {\n const chartData = useMemo(() => {\n // Merge all datasets into a single array keyed by timestamp\n const map = new Map<string, Record<string, number>>();\n\n for (const ds of datasets) {\n if (!ds.data) continue;\n for (const point of ds.data) {\n const ts = new Date(point.timestamp).toISOString();\n if (!map.has(ts)) map.set(ts, {});\n map.get(ts)![ds.label] = point.value;\n }\n }\n\n return Array.from(map.entries())\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([ts, values]) => ({\n timestamp: ts,\n ...values,\n }));\n }, [datasets]);\n\n const formatDate = (ts: string) => {\n const d = new Date(ts);\n return `${d.getMonth() + 1}/${d.getDate()}`;\n };\n\n const formatTooltipDate = (ts: string) => {\n return new Date(ts).toLocaleString(undefined, {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n };\n\n const tr = useTr();\n\n if (chartData.length === 0) {\n return (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n {title && <h3 className=\"text-sm font-medium text-text-primary mb-3\">{title}</h3>}\n <div className=\"flex items-center justify-center h-[200px] text-text-secondary text-sm\">\n {tr(\n 'vibecontrols.analytics.noDataForRange',\n 'No data available for the selected time range'\n )}\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n {title && <h3 className=\"text-sm font-medium text-text-primary mb-3\">{title}</h3>}\n <ResponsiveContainer width=\"100%\" height={height}>\n <AreaChart data={chartData} margin={{ top: 5, right: 10, left: 0, bottom: 5 }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke=\"var(--color-border-default)\" opacity={0.3} />\n <XAxis\n dataKey=\"timestamp\"\n tickFormatter={formatDate}\n tick={{ fill: 'var(--color-text-secondary)', fontSize: 11 }}\n axisLine={{ stroke: 'var(--color-border-default)' }}\n />\n <YAxis\n tick={{ fill: 'var(--color-text-secondary)', fontSize: 11 }}\n axisLine={{ stroke: 'var(--color-border-default)' }}\n allowDecimals={false}\n />\n <Tooltip\n labelFormatter={formatTooltipDate}\n contentStyle={{\n background: 'var(--color-bg-surface)',\n border: '1px solid var(--color-border-default)',\n borderRadius: '6px',\n fontSize: '12px',\n }}\n />\n <Legend wrapperStyle={{ fontSize: '12px' }} />\n {datasets.map((ds, i) => (\n <Area\n key={ds.label}\n type=\"monotone\"\n dataKey={ds.label}\n stroke={ds.color || COLORS[i % COLORS.length]}\n fill={ds.color || COLORS[i % COLORS.length]}\n fillOpacity={0.1}\n strokeWidth={2}\n dot={false}\n />\n ))}\n </AreaChart>\n </ResponsiveContainer>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAyBA,IAAM,IAAS;CACb;CACA;CACA;CACA;CACA;CACD;AAED,SAAgB,EAAyB,EACvC,aACA,UACA,YAAS,OACuB;CAChC,IAAM,IAAY,QAAc;EAE9B,IAAM,oBAAM,IAAI,KAAqC;AAErD,OAAK,IAAM,KAAM,EACV,OAAG,KACR,MAAK,IAAM,KAAS,EAAG,MAAM;GAC3B,IAAM,IAAK,IAAI,KAAK,EAAM,UAAU,CAAC,aAAa;AAElD,GADK,EAAI,IAAI,EAAG,IAAE,EAAI,IAAI,GAAI,EAAE,CAAC,EACjC,EAAI,IAAI,EAAG,CAAE,EAAG,SAAS,EAAM;;AAInC,SAAO,MAAM,KAAK,EAAI,SAAS,CAAC,CAC7B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC,CACtC,KAAK,CAAC,GAAI,QAAa;GACtB,WAAW;GACX,GAAG;GACJ,EAAE;IACJ,CAAC,EAAS,CAAC,EAER,KAAc,MAAe;EACjC,IAAM,IAAI,IAAI,KAAK,EAAG;AACtB,SAAO,GAAG,EAAE,UAAU,GAAG,EAAE,GAAG,EAAE,SAAS;IAGrC,KAAqB,MAClB,IAAI,KAAK,EAAG,CAAC,eAAe,KAAA,GAAW;EAC5C,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;EACT,CAAC,EAGE,IAAK,GAAO;AAgBlB,QAdI,EAAU,WAAW,IAErB,kBAAC,OAAD;EAAK,WAAU;YAAf,CACG,KAAS,kBAAC,MAAD;GAAI,WAAU;aAA8C;GAAW,CAAA,EACjF,kBAAC,OAAD;GAAK,WAAU;aACZ,EACC,yCACA,gDACD;GACG,CAAA,CACF;MAKR,kBAAC,OAAD;EAAK,WAAU;YAAf,CACG,KAAS,kBAAC,MAAD;GAAI,WAAU;aAA8C;GAAW,CAAA,EACjF,kBAAC,GAAD;GAAqB,OAAM;GAAe;aACxC,kBAAC,GAAD;IAAW,MAAM;IAAW,QAAQ;KAAE,KAAK;KAAG,OAAO;KAAI,MAAM;KAAG,QAAQ;KAAG;cAA7E;KACE,kBAAC,GAAD;MAAe,iBAAgB;MAAM,QAAO;MAA8B,SAAS;MAAO,CAAA;KAC1F,kBAAC,GAAD;MACE,SAAQ;MACR,eAAe;MACf,MAAM;OAAE,MAAM;OAA+B,UAAU;OAAI;MAC3D,UAAU,EAAE,QAAQ,+BAA+B;MACnD,CAAA;KACF,kBAAC,GAAD;MACE,MAAM;OAAE,MAAM;OAA+B,UAAU;OAAI;MAC3D,UAAU,EAAE,QAAQ,+BAA+B;MACnD,eAAe;MACf,CAAA;KACF,kBAAC,GAAD;MACE,gBAAgB;MAChB,cAAc;OACZ,YAAY;OACZ,QAAQ;OACR,cAAc;OACd,UAAU;OACX;MACD,CAAA;KACF,kBAAC,GAAD,EAAQ,cAAc,EAAE,UAAU,QAAQ,EAAI,CAAA;KAC7C,EAAS,KAAK,GAAI,MACjB,kBAAC,GAAD;MAEE,MAAK;MACL,SAAS,EAAG;MACZ,QAAQ,EAAG,SAAS,EAAO,IAAI,EAAO;MACtC,MAAM,EAAG,SAAS,EAAO,IAAI,EAAO;MACpC,aAAa;MACb,aAAa;MACb,KAAK;MACL,EARK,EAAG,MAQR,CACF;KACQ;;GACQ,CAAA,CAClB"}
@@ -53,7 +53,7 @@ function a({ isOpen: a, onClose: o, onConfirm: s, loading: c, title: l = "Delete
53
53
  onClick: () => {
54
54
  m(""), o();
55
55
  },
56
- className: "px-4 py-2 text-sm rounded-lg border border-border-primary hover:bg-bg-secondary",
56
+ className: "px-4 py-2 text-sm rounded-lg border border-border-default hover:bg-bg-surface",
57
57
  disabled: c,
58
58
  children: f("vibecontrols.audit.cancel", "Cancel")
59
59
  }), /* @__PURE__ */ r("button", {
@@ -62,7 +62,7 @@ function a({ isOpen: a, onClose: o, onConfirm: s, loading: c, title: l = "Delete
62
62
  p.trim() && (s(p.trim()), m(""));
63
63
  },
64
64
  disabled: !p.trim() || c,
65
- className: "rounded-lg bg-status-error-bg px-4 py-2 text-sm text-status-error-text transition-colors hover:bg-status-error-bg/80 disabled:opacity-50",
65
+ className: "rounded-button bg-action-danger-bg px-4 py-2 text-sm text-action-danger-text transition-colors hover:bg-action-danger-bg-hover disabled:opacity-50",
66
66
  children: c ? f("vibecontrols.audit.deleting", "Deleting...") : d
67
67
  })]
68
68
  })
@@ -1 +1 @@
1
- {"version":3,"file":"AuditDeleteDialog.js","names":[],"sources":["../../../src/components/audit/AuditDeleteDialog.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { AlertTriangle } from 'lucide-react';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface AuditDeleteDialogProps {\n isOpen: boolean;\n onClose: () => void;\n onConfirm: (reason: string) => void;\n loading: boolean;\n title?: string;\n description?: string;\n confirmLabel?: string;\n}\n\nexport function AuditDeleteDialog({\n isOpen,\n onClose,\n onConfirm,\n loading,\n title = 'Delete Audit Log',\n description = 'This action will be recorded in the audit trail.',\n confirmLabel = 'Delete',\n}: AuditDeleteDialogProps) {\n const tr = useTr();\n const [reason, setReason] = useState('');\n\n const handleConfirm = () => {\n if (reason.trim()) {\n onConfirm(reason.trim());\n setReason('');\n }\n };\n\n const handleClose = () => {\n setReason('');\n onClose();\n };\n\n if (!isOpen) return null;\n\n return (\n <div className=\"fixed inset-0 bg-bg-overlay z-50 flex items-center justify-center p-4\">\n <div className=\"bg-bg-surface rounded-lg shadow-xl max-w-md w-full p-6\">\n <div className=\"mb-4 flex items-center gap-3\">\n <div className=\"rounded-full bg-status-error-bg-subtle p-2\">\n <AlertTriangle size={20} className=\"text-status-error-text\" />\n </div>\n <div>\n <h3 className=\"text-lg font-semibold\">{title}</h3>\n <p className=\"text-sm text-text-secondary\">{description}</p>\n </div>\n </div>\n\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1\">\n {tr('vibecontrols.audit.reasonLabel', 'Reason for deletion')}{' '}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <textarea\n aria-label=\"control\"\n value={reason}\n onChange={(e) => setReason(e.target.value)}\n placeholder={tr(\n 'vibecontrols.audit.reasonPlaceholder',\n 'Enter the reason for deleting this audit log entry...'\n )}\n className=\"h-24 w-full resize-none rounded-lg border border-border-default bg-bg-sunken px-3 py-2 text-sm focus:border-action-primary-bg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/30\"\n />\n </div>\n\n <div className=\"flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={handleClose}\n className=\"px-4 py-2 text-sm rounded-lg border border-border-primary hover:bg-bg-secondary\"\n disabled={loading}\n >\n {tr('vibecontrols.audit.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n onClick={handleConfirm}\n disabled={!reason.trim() || loading}\n className=\"rounded-lg bg-status-error-bg px-4 py-2 text-sm text-status-error-text transition-colors hover:bg-status-error-bg/80 disabled:opacity-50\"\n >\n {loading ? tr('vibecontrols.audit.deleting', 'Deleting...') : confirmLabel}\n </button>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAcA,SAAgB,EAAkB,EAChC,WACA,YACA,cACA,YACA,WAAQ,oBACR,iBAAc,oDACd,kBAAe,YACU;CACzB,IAAM,IAAK,GAAO,EACZ,CAAC,GAAQ,KAAa,EAAS,GAAG;AAgBxC,QAFK,IAGH,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD;OAAe,MAAM;OAAI,WAAU;OAA2B,CAAA;MAC1D,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;gBAAyB;MAAW,CAAA,EAClD,kBAAC,KAAD;MAAG,WAAU;gBAA+B;MAAgB,CAAA,CACxD,EAAA,CAAA,CACF;;IAEN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,SAAD;MAAO,WAAU;gBAAjB;OACG,EAAG,kCAAkC,sBAAsB;OAAE;OAC9D,kBAAC,QAAD;QAAM,WAAU;kBAAyB;QAAQ,CAAA;OAC3C;SACR,kBAAC,YAAD;MACE,cAAW;MACX,OAAO;MACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;MAC1C,aAAa,EACX,wCACA,wDACD;MACD,WAAU;MACV,CAAA,CACE;;IAEN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,MAAK;MACL,eAxCgB;AAExB,OADA,EAAU,GAAG,EACb,GAAS;;MAuCD,WAAU;MACV,UAAU;gBAET,EAAG,6BAA6B,SAAS;MACnC,CAAA,EACT,kBAAC,UAAD;MACE,MAAK;MACL,eAvDkB;AAC1B,OAAI,EAAO,MAAM,KACf,EAAU,EAAO,MAAM,CAAC,EACxB,EAAU,GAAG;;MAqDP,UAAU,CAAC,EAAO,MAAM,IAAI;MAC5B,WAAU;gBAET,IAAU,EAAG,+BAA+B,cAAc,GAAG;MACvD,CAAA,CACL;;IACF;;EACF,CAAA,GAnDY"}
1
+ {"version":3,"file":"AuditDeleteDialog.js","names":[],"sources":["../../../src/components/audit/AuditDeleteDialog.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { AlertTriangle } from 'lucide-react';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface AuditDeleteDialogProps {\n isOpen: boolean;\n onClose: () => void;\n onConfirm: (reason: string) => void;\n loading: boolean;\n title?: string;\n description?: string;\n confirmLabel?: string;\n}\n\nexport function AuditDeleteDialog({\n isOpen,\n onClose,\n onConfirm,\n loading,\n title = 'Delete Audit Log',\n description = 'This action will be recorded in the audit trail.',\n confirmLabel = 'Delete',\n}: AuditDeleteDialogProps) {\n const tr = useTr();\n const [reason, setReason] = useState('');\n\n const handleConfirm = () => {\n if (reason.trim()) {\n onConfirm(reason.trim());\n setReason('');\n }\n };\n\n const handleClose = () => {\n setReason('');\n onClose();\n };\n\n if (!isOpen) return null;\n\n return (\n <div className=\"fixed inset-0 bg-bg-overlay z-50 flex items-center justify-center p-4\">\n <div className=\"bg-bg-surface rounded-lg shadow-xl max-w-md w-full p-6\">\n <div className=\"mb-4 flex items-center gap-3\">\n <div className=\"rounded-full bg-status-error-bg-subtle p-2\">\n <AlertTriangle size={20} className=\"text-status-error-text\" />\n </div>\n <div>\n <h3 className=\"text-lg font-semibold\">{title}</h3>\n <p className=\"text-sm text-text-secondary\">{description}</p>\n </div>\n </div>\n\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1\">\n {tr('vibecontrols.audit.reasonLabel', 'Reason for deletion')}{' '}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <textarea\n aria-label=\"control\"\n value={reason}\n onChange={(e) => setReason(e.target.value)}\n placeholder={tr(\n 'vibecontrols.audit.reasonPlaceholder',\n 'Enter the reason for deleting this audit log entry...'\n )}\n className=\"h-24 w-full resize-none rounded-lg border border-border-default bg-bg-sunken px-3 py-2 text-sm focus:border-action-primary-bg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/30\"\n />\n </div>\n\n <div className=\"flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={handleClose}\n className=\"px-4 py-2 text-sm rounded-lg border border-border-default hover:bg-bg-surface\"\n disabled={loading}\n >\n {tr('vibecontrols.audit.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n onClick={handleConfirm}\n disabled={!reason.trim() || loading}\n className=\"rounded-button bg-action-danger-bg px-4 py-2 text-sm text-action-danger-text transition-colors hover:bg-action-danger-bg-hover disabled:opacity-50\"\n >\n {loading ? tr('vibecontrols.audit.deleting', 'Deleting...') : confirmLabel}\n </button>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAcA,SAAgB,EAAkB,EAChC,WACA,YACA,cACA,YACA,WAAQ,oBACR,iBAAc,oDACd,kBAAe,YACU;CACzB,IAAM,IAAK,GAAO,EACZ,CAAC,GAAQ,KAAa,EAAS,GAAG;AAgBxC,QAFK,IAGH,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD;OAAe,MAAM;OAAI,WAAU;OAA2B,CAAA;MAC1D,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;gBAAyB;MAAW,CAAA,EAClD,kBAAC,KAAD;MAAG,WAAU;gBAA+B;MAAgB,CAAA,CACxD,EAAA,CAAA,CACF;;IAEN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,SAAD;MAAO,WAAU;gBAAjB;OACG,EAAG,kCAAkC,sBAAsB;OAAE;OAC9D,kBAAC,QAAD;QAAM,WAAU;kBAAyB;QAAQ,CAAA;OAC3C;SACR,kBAAC,YAAD;MACE,cAAW;MACX,OAAO;MACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;MAC1C,aAAa,EACX,wCACA,wDACD;MACD,WAAU;MACV,CAAA,CACE;;IAEN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,MAAK;MACL,eAxCgB;AAExB,OADA,EAAU,GAAG,EACb,GAAS;;MAuCD,WAAU;MACV,UAAU;gBAET,EAAG,6BAA6B,SAAS;MACnC,CAAA,EACT,kBAAC,UAAD;MACE,MAAK;MACL,eAvDkB;AAC1B,OAAI,EAAO,MAAM,KACf,EAAU,EAAO,MAAM,CAAC,EACxB,EAAU,GAAG;;MAqDP,UAAU,CAAC,EAAO,MAAM,IAAI;MAC5B,WAAU;gBAET,IAAU,EAAG,+BAA+B,cAAc,GAAG;MACvD,CAAA,CACL;;IACF;;EACF,CAAA,GAnDY"}
@@ -44,7 +44,7 @@ function d({ filter: d }) {
44
44
  "aria-expanded": m,
45
45
  onClick: () => h((e) => !e),
46
46
  disabled: y,
47
- className: "inline-flex items-center gap-2 rounded-lg border border-border-primary px-3 py-2 text-sm transition-colors hover:bg-bg-secondary disabled:opacity-50",
47
+ className: "inline-flex items-center gap-2 rounded-lg border border-border-default px-3 py-2 text-sm transition-colors hover:bg-bg-surface disabled:opacity-50",
48
48
  children: [/* @__PURE__ */ c(o, { size: 14 }), y ? b("audit.exporting", "Exporting…") : b("audit.export", "Export")]
49
49
  }),
50
50
  m ? /* @__PURE__ */ l("div", {
@@ -56,14 +56,14 @@ function d({ filter: d }) {
56
56
  type: "button",
57
57
  role: "menuitem",
58
58
  onClick: () => x(t.Csv),
59
- className: "flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-secondary",
59
+ className: "flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-surface",
60
60
  children: [/* @__PURE__ */ c(o, { size: 12 }), b("audit.exportCsv", "Download CSV")]
61
61
  }),
62
62
  /* @__PURE__ */ l("button", {
63
63
  type: "button",
64
64
  role: "menuitem",
65
65
  onClick: () => x(t.Json),
66
- className: "flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-secondary",
66
+ className: "flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-surface",
67
67
  children: [/* @__PURE__ */ c(o, { size: 12 }), b("audit.exportJson", "Download JSON")]
68
68
  }),
69
69
  /* @__PURE__ */ c("div", { className: "my-1 border-t border-border-subtle" }),
@@ -73,7 +73,7 @@ function d({ filter: d }) {
73
73
  onClick: () => {
74
74
  h(!1), _(t.Csv);
75
75
  },
76
- className: "flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-secondary",
76
+ className: "flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-surface",
77
77
  children: [/* @__PURE__ */ c(s, { size: 12 }), b("audit.saveCsvToFiles", "Save CSV to Files…")]
78
78
  }),
79
79
  /* @__PURE__ */ l("button", {
@@ -82,7 +82,7 @@ function d({ filter: d }) {
82
82
  onClick: () => {
83
83
  h(!1), _(t.Json);
84
84
  },
85
- className: "flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-secondary",
85
+ className: "flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-surface",
86
86
  children: [/* @__PURE__ */ c(s, { size: 12 }), b("audit.saveJsonToFiles", "Save JSON to Files…")]
87
87
  })
88
88
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"AuditExportButton.js","names":[],"sources":["../../../src/components/audit/AuditExportButton.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport { Download, FolderInput } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { SaveToFilesDialog } from '@burdenoff/fe-libs/storage';\nimport { useExportVibeAuditLogsMutation } from '@/generated/wspace-operations';\nimport { VibeAuditExportFormat, type VibeAuditLogFilterInput } from '@/generated/wspace-types';\n\ninterface AuditExportButtonProps {\n filter?: VibeAuditLogFilterInput;\n}\n\nexport function AuditExportButton({ filter }: AuditExportButtonProps) {\n const { t } = useI18n();\n const menuRef = useRef<HTMLDivElement | null>(null);\n const [showMenu, setShowMenu] = useState(false);\n const [saveFormat, setSaveFormat] = useState<VibeAuditExportFormat | null>(null);\n const [exportMutation, { loading }] = useExportVibeAuditLogsMutation();\n\n const tr = (key: string, fallback: string) => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n useEffect(() => {\n if (!showMenu) return undefined;\n\n const handlePointerDown = (event: MouseEvent) => {\n if (!menuRef.current?.contains(event.target as Node)) {\n setShowMenu(false);\n }\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setShowMenu(false);\n }\n };\n\n window.addEventListener('mousedown', handlePointerDown);\n window.addEventListener('keydown', handleKeyDown);\n return () => {\n window.removeEventListener('mousedown', handlePointerDown);\n window.removeEventListener('keydown', handleKeyDown);\n };\n }, [showMenu]);\n\n const handleExport = async (format: VibeAuditExportFormat) => {\n setShowMenu(false);\n try {\n const result = await exportMutation({\n variables: {\n input: { filter: filter || {}, format },\n },\n });\n\n const exportData = result.data?.exportVibeAuditLogs;\n if (!exportData) return;\n\n const blob = new Blob([exportData.data], {\n type: format === 'CSV' ? 'text/csv' : 'application/json',\n });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = `vibe-audit-${new Date().toISOString().slice(0, 10)}.${format.toLowerCase()}`;\n document.body.appendChild(anchor);\n anchor.click();\n document.body.removeChild(anchor);\n URL.revokeObjectURL(url);\n } catch {\n // Apollo error handling surfaces failures globally.\n }\n };\n\n return (\n <div ref={menuRef} className=\"relative\">\n <button\n type=\"button\"\n aria-haspopup=\"menu\"\n aria-expanded={showMenu}\n onClick={() => setShowMenu((current) => !current)}\n disabled={loading}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-primary px-3 py-2 text-sm transition-colors hover:bg-bg-secondary disabled:opacity-50\"\n >\n <Download size={14} />\n {loading ? tr('audit.exporting', 'Exporting…') : tr('audit.export', 'Export')}\n </button>\n\n {showMenu ? (\n <div\n role=\"menu\"\n aria-label={tr('audit.exportOptions', 'Export options')}\n className=\"absolute right-0 top-full z-10 mt-1 min-w-[200px] rounded-lg border border-border-default bg-bg-surface py-1 shadow-lg\"\n >\n <button\n type=\"button\"\n role=\"menuitem\"\n onClick={() => handleExport(VibeAuditExportFormat.Csv)}\n className=\"flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-secondary\"\n >\n <Download size={12} />\n {tr('audit.exportCsv', 'Download CSV')}\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n onClick={() => handleExport(VibeAuditExportFormat.Json)}\n className=\"flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-secondary\"\n >\n <Download size={12} />\n {tr('audit.exportJson', 'Download JSON')}\n </button>\n <div className=\"my-1 border-t border-border-subtle\" />\n <button\n type=\"button\"\n role=\"menuitem\"\n onClick={() => {\n setShowMenu(false);\n setSaveFormat(VibeAuditExportFormat.Csv);\n }}\n className=\"flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-secondary\"\n >\n <FolderInput size={12} />\n {tr('audit.saveCsvToFiles', 'Save CSV to Files…')}\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n onClick={() => {\n setShowMenu(false);\n setSaveFormat(VibeAuditExportFormat.Json);\n }}\n className=\"flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-secondary\"\n >\n <FolderInput size={12} />\n {tr('audit.saveJsonToFiles', 'Save JSON to Files…')}\n </button>\n </div>\n ) : null}\n\n {saveFormat && (\n <SaveToFilesDialog\n open\n onOpenChange={(open: boolean) => {\n if (!open) setSaveFormat(null);\n }}\n defaultFolderPath=\"/Vibecontrols/Audit Logs\"\n filename={`vibe-audit-${new Date().toISOString().slice(0, 10)}.${saveFormat.toLowerCase()}`}\n source={{\n kind: 'blob',\n filename: `vibe-audit-${new Date().toISOString().slice(0, 10)}.${saveFormat.toLowerCase()}`,\n mimeType: saveFormat === VibeAuditExportFormat.Csv ? 'text/csv' : 'application/json',\n getBlob: async () => {\n const result = await exportMutation({\n variables: { input: { filter: filter || {}, format: saveFormat } },\n });\n const data = result.data?.exportVibeAuditLogs?.data;\n if (!data) return null;\n return {\n blob: new Blob([data], {\n type: saveFormat === VibeAuditExportFormat.Csv ? 'text/csv' : 'application/json',\n }),\n };\n },\n }}\n />\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AuditExportButton.js","names":[],"sources":["../../../src/components/audit/AuditExportButton.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport { Download, FolderInput } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { SaveToFilesDialog } from '@burdenoff/fe-libs/storage';\nimport { useExportVibeAuditLogsMutation } from '@/generated/wspace-operations';\nimport { VibeAuditExportFormat, type VibeAuditLogFilterInput } from '@/generated/wspace-types';\n\ninterface AuditExportButtonProps {\n filter?: VibeAuditLogFilterInput;\n}\n\nexport function AuditExportButton({ filter }: AuditExportButtonProps) {\n const { t } = useI18n();\n const menuRef = useRef<HTMLDivElement | null>(null);\n const [showMenu, setShowMenu] = useState(false);\n const [saveFormat, setSaveFormat] = useState<VibeAuditExportFormat | null>(null);\n const [exportMutation, { loading }] = useExportVibeAuditLogsMutation();\n\n const tr = (key: string, fallback: string) => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n useEffect(() => {\n if (!showMenu) return undefined;\n\n const handlePointerDown = (event: MouseEvent) => {\n if (!menuRef.current?.contains(event.target as Node)) {\n setShowMenu(false);\n }\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setShowMenu(false);\n }\n };\n\n window.addEventListener('mousedown', handlePointerDown);\n window.addEventListener('keydown', handleKeyDown);\n return () => {\n window.removeEventListener('mousedown', handlePointerDown);\n window.removeEventListener('keydown', handleKeyDown);\n };\n }, [showMenu]);\n\n const handleExport = async (format: VibeAuditExportFormat) => {\n setShowMenu(false);\n try {\n const result = await exportMutation({\n variables: {\n input: { filter: filter || {}, format },\n },\n });\n\n const exportData = result.data?.exportVibeAuditLogs;\n if (!exportData) return;\n\n const blob = new Blob([exportData.data], {\n type: format === 'CSV' ? 'text/csv' : 'application/json',\n });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = `vibe-audit-${new Date().toISOString().slice(0, 10)}.${format.toLowerCase()}`;\n document.body.appendChild(anchor);\n anchor.click();\n document.body.removeChild(anchor);\n URL.revokeObjectURL(url);\n } catch {\n // Apollo error handling surfaces failures globally.\n }\n };\n\n return (\n <div ref={menuRef} className=\"relative\">\n <button\n type=\"button\"\n aria-haspopup=\"menu\"\n aria-expanded={showMenu}\n onClick={() => setShowMenu((current) => !current)}\n disabled={loading}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-default px-3 py-2 text-sm transition-colors hover:bg-bg-surface disabled:opacity-50\"\n >\n <Download size={14} />\n {loading ? tr('audit.exporting', 'Exporting…') : tr('audit.export', 'Export')}\n </button>\n\n {showMenu ? (\n <div\n role=\"menu\"\n aria-label={tr('audit.exportOptions', 'Export options')}\n className=\"absolute right-0 top-full z-10 mt-1 min-w-[200px] rounded-lg border border-border-default bg-bg-surface py-1 shadow-lg\"\n >\n <button\n type=\"button\"\n role=\"menuitem\"\n onClick={() => handleExport(VibeAuditExportFormat.Csv)}\n className=\"flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-surface\"\n >\n <Download size={12} />\n {tr('audit.exportCsv', 'Download CSV')}\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n onClick={() => handleExport(VibeAuditExportFormat.Json)}\n className=\"flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-surface\"\n >\n <Download size={12} />\n {tr('audit.exportJson', 'Download JSON')}\n </button>\n <div className=\"my-1 border-t border-border-subtle\" />\n <button\n type=\"button\"\n role=\"menuitem\"\n onClick={() => {\n setShowMenu(false);\n setSaveFormat(VibeAuditExportFormat.Csv);\n }}\n className=\"flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-surface\"\n >\n <FolderInput size={12} />\n {tr('audit.saveCsvToFiles', 'Save CSV to Files…')}\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n onClick={() => {\n setShowMenu(false);\n setSaveFormat(VibeAuditExportFormat.Json);\n }}\n className=\"flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors hover:bg-bg-surface\"\n >\n <FolderInput size={12} />\n {tr('audit.saveJsonToFiles', 'Save JSON to Files…')}\n </button>\n </div>\n ) : null}\n\n {saveFormat && (\n <SaveToFilesDialog\n open\n onOpenChange={(open: boolean) => {\n if (!open) setSaveFormat(null);\n }}\n defaultFolderPath=\"/Vibecontrols/Audit Logs\"\n filename={`vibe-audit-${new Date().toISOString().slice(0, 10)}.${saveFormat.toLowerCase()}`}\n source={{\n kind: 'blob',\n filename: `vibe-audit-${new Date().toISOString().slice(0, 10)}.${saveFormat.toLowerCase()}`,\n mimeType: saveFormat === VibeAuditExportFormat.Csv ? 'text/csv' : 'application/json',\n getBlob: async () => {\n const result = await exportMutation({\n variables: { input: { filter: filter || {}, format: saveFormat } },\n });\n const data = result.data?.exportVibeAuditLogs?.data;\n if (!data) return null;\n return {\n blob: new Blob([data], {\n type: saveFormat === VibeAuditExportFormat.Csv ? 'text/csv' : 'application/json',\n }),\n };\n },\n }}\n />\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -8,11 +8,11 @@ import { jsx as u, jsxs as d } from "react/jsx-runtime";
8
8
  function f({ data: e, label: t }) {
9
9
  let [r, i] = n(!1);
10
10
  return e ? /* @__PURE__ */ d("div", {
11
- className: "border border-border-primary rounded-lg overflow-hidden",
11
+ className: "border border-border-default rounded-lg overflow-hidden",
12
12
  children: [/* @__PURE__ */ d("button", {
13
13
  type: "button",
14
14
  onClick: () => i(!r),
15
- className: "w-full flex items-center gap-2 px-3 py-2 text-sm font-medium bg-bg-secondary/50 hover:bg-bg-secondary",
15
+ className: "w-full flex items-center gap-2 px-3 py-2 text-sm font-medium bg-bg-sunken hover:bg-bg-surface",
16
16
  children: [u(r ? a : o, { size: 14 }), t]
17
17
  }), r && /* @__PURE__ */ u("pre", {
18
18
  className: "px-3 py-2 text-xs overflow-auto max-h-64 bg-bg-sunken",
@@ -23,17 +23,17 @@ function f({ data: e, label: t }) {
23
23
  function p({ command: e, output: t, exitCode: r }) {
24
24
  let [a, o] = n(!1);
25
25
  return !e && !t ? null : /* @__PURE__ */ d("div", {
26
- className: "border border-border-primary rounded-lg overflow-hidden",
26
+ className: "border border-border-default rounded-lg overflow-hidden",
27
27
  children: [
28
28
  /* @__PURE__ */ d("div", {
29
- className: "flex items-center justify-between px-3 py-2 bg-bg-secondary/50",
29
+ className: "flex items-center justify-between px-3 py-2 bg-bg-sunken",
30
30
  children: [/* @__PURE__ */ d("span", {
31
31
  className: "flex items-center gap-2 text-sm font-medium",
32
32
  children: [
33
33
  /* @__PURE__ */ u(c, { size: 14 }),
34
34
  "Command Execution",
35
35
  r != null && /* @__PURE__ */ d("span", {
36
- className: `px-1.5 py-0.5 rounded text-xs ${r === 0 ? "bg-status-success-bg text-status-success-text" : "bg-status-error-bg text-status-error-text"}`,
36
+ className: `px-1.5 py-0.5 rounded text-xs ${r === 0 ? "bg-status-success-bg-subtle text-status-success-text" : "bg-status-error-bg-subtle text-status-error-text"}`,
37
37
  children: ["exit ", r]
38
38
  })
39
39
  ]
@@ -42,7 +42,7 @@ function p({ command: e, output: t, exitCode: r }) {
42
42
  onClick: () => {
43
43
  e && (navigator.clipboard.writeText(e), o(!0), setTimeout(() => o(!1), 2e3));
44
44
  },
45
- className: "p-1 rounded hover:bg-bg-secondary text-text-secondary",
45
+ className: "p-1 rounded hover:bg-bg-surface text-text-secondary",
46
46
  title: "Copy command",
47
47
  children: u(a ? i : s, { size: 14 })
48
48
  })]
@@ -70,11 +70,11 @@ function m({ changeset: e }) {
70
70
  if (!e || typeof e != "object") return null;
71
71
  let i = Object.entries(e);
72
72
  return i.length === 0 ? null : /* @__PURE__ */ d("div", {
73
- className: "border border-border-primary rounded-lg overflow-hidden",
73
+ className: "border border-border-default rounded-lg overflow-hidden",
74
74
  children: [/* @__PURE__ */ d("button", {
75
75
  type: "button",
76
76
  onClick: () => r(!t),
77
- className: "w-full flex items-center gap-2 px-3 py-2 text-sm font-medium bg-bg-secondary/50 hover:bg-bg-secondary",
77
+ className: "w-full flex items-center gap-2 px-3 py-2 text-sm font-medium bg-bg-sunken hover:bg-bg-surface",
78
78
  children: [
79
79
  u(t ? a : o, { size: 14 }),
80
80
  "Changes (",
@@ -160,7 +160,7 @@ function h({ log: n, onClose: i, footer: a }) {
160
160
  type: "button",
161
161
  "aria-label": s("audit.closeDetail", "Close audit log detail"),
162
162
  onClick: i,
163
- className: "flex size-10 items-center justify-center rounded hover:bg-bg-secondary",
163
+ className: "flex size-10 items-center justify-center rounded hover:bg-bg-surface",
164
164
  children: /* @__PURE__ */ u(l, { size: 16 })
165
165
  })]
166
166
  }), /* @__PURE__ */ d("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"AuditLogDetail.js","names":[],"sources":["../../../src/components/audit/AuditLogDetail.tsx"],"sourcesContent":["import { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useEffect, useState, type ReactNode } from 'react';\nimport { X, ChevronDown, ChevronRight, Copy, Check, Terminal } from 'lucide-react';\nimport type { VibeAuditLogDetailFragment } from '@/generated/wspace-operations';\nimport { StatusBadge } from '@/components/shared';\n\ninterface AuditLogDetailProps {\n log: VibeAuditLogDetailFragment;\n onClose: () => void;\n /** Optional action node rendered at the bottom of the panel (e.g. drill-down). */\n footer?: ReactNode;\n}\n\nfunction JsonViewer({ data, label }: { data: unknown; label: string }) {\n const [expanded, setExpanded] = useState(false);\n if (!data) return null;\n\n return (\n <div className=\"border border-border-primary rounded-lg overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setExpanded(!expanded)}\n className=\"w-full flex items-center gap-2 px-3 py-2 text-sm font-medium bg-bg-secondary/50 hover:bg-bg-secondary\"\n >\n {expanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n {label}\n </button>\n {expanded && (\n <pre className=\"px-3 py-2 text-xs overflow-auto max-h-64 bg-bg-sunken\">\n {JSON.stringify(data, null, 2)}\n </pre>\n )}\n </div>\n );\n}\n\nfunction CommandBlock({\n command,\n output,\n exitCode,\n}: {\n command?: string | null;\n output?: string | null;\n exitCode?: number | null;\n}) {\n const [copied, setCopied] = useState(false);\n if (!command && !output) return null;\n\n const handleCopy = () => {\n if (command) {\n navigator.clipboard.writeText(command);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }\n };\n\n return (\n <div className=\"border border-border-primary rounded-lg overflow-hidden\">\n <div className=\"flex items-center justify-between px-3 py-2 bg-bg-secondary/50\">\n <span className=\"flex items-center gap-2 text-sm font-medium\">\n <Terminal size={14} />\n Command Execution\n {exitCode !== null && exitCode !== undefined && (\n <span\n className={`px-1.5 py-0.5 rounded text-xs ${exitCode === 0 ? 'bg-status-success-bg text-status-success-text' : 'bg-status-error-bg text-status-error-text'}`}\n >\n exit {exitCode}\n </span>\n )}\n </span>\n {command && (\n <button\n type=\"button\"\n onClick={handleCopy}\n className=\"p-1 rounded hover:bg-bg-secondary text-text-secondary\"\n title=\"Copy command\"\n >\n {copied ? <Check size={14} /> : <Copy size={14} />}\n </button>\n )}\n </div>\n {command && (\n <div className=\"px-3 py-2 bg-bg-sunken text-text-secondary font-mono text-xs\">\n <span className=\"text-status-success-text\">$</span> {command}\n </div>\n )}\n {output && (\n <pre className=\"px-3 py-2 text-xs bg-bg-sunken text-text-tertiary font-mono overflow-auto max-h-48\">\n {output}\n </pre>\n )}\n </div>\n );\n}\n\nfunction ChangesetViewer({ changeset }: { changeset: Record<string, unknown> | null | undefined }) {\n const [expanded, setExpanded] = useState(false);\n if (!changeset || typeof changeset !== 'object') return null;\n\n const changes = Object.entries(changeset as Record<string, { from: unknown; to: unknown }>);\n if (changes.length === 0) return null;\n\n return (\n <div className=\"border border-border-primary rounded-lg overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setExpanded(!expanded)}\n className=\"w-full flex items-center gap-2 px-3 py-2 text-sm font-medium bg-bg-secondary/50 hover:bg-bg-secondary\"\n >\n {expanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n Changes ({changes.length} field{changes.length !== 1 ? 's' : ''})\n </button>\n {expanded && (\n <div className=\"px-3 py-2 space-y-2\">\n {changes.map(([field, change]) => (\n <div key={field} className=\"text-xs\">\n <span className=\"font-medium text-text-primary\">{field}</span>\n <div className=\"ml-4 mt-1 space-y-0.5\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-status-error-text font-mono\">-</span>\n <span className=\"text-status-error-text\">\n {JSON.stringify((change as { from: unknown }).from)}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-status-success-text font-mono\">+</span>\n <span className=\"text-status-success-text\">\n {JSON.stringify((change as { to: unknown }).to)}\n </span>\n </div>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nexport function AuditLogDetail({ log, onClose, footer }: AuditLogDetailProps) {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n onClose();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [onClose]);\n\n return (\n <div className=\"fixed inset-0 z-[1000] flex justify-end bg-bg-overlay/40\">\n <button\n type=\"button\"\n aria-label={tr('audit.closeDetailOverlay', 'Close audit log detail')}\n className=\"absolute inset-0 cursor-default\"\n onClick={onClose}\n />\n <aside className=\"relative flex h-full w-full max-w-[480px] flex-col border-l border-border-default bg-bg-surface shadow-xl\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-border-default\">\n <div>\n <h3 className=\"text-sm font-semibold\">{log.action.replace(/_/g, ' ')}</h3>\n <p className=\"text-xs text-text-secondary\">\n {log.resourceType.replace(/_/g, ' ')}\n {log.resourceName ? ` · ${log.resourceName}` : ''}\n </p>\n <details className=\"mt-1\">\n <summary className=\"cursor-pointer text-[10px] uppercase tracking-wider text-text-secondary hover:text-text-primary\">\n Event ID\n </summary>\n <span className=\"mt-1 block break-all font-mono text-[11px] text-text-secondary\">\n {log.id}\n </span>\n </details>\n </div>\n <button\n type=\"button\"\n aria-label={tr('audit.closeDetail', 'Close audit log detail')}\n onClick={onClose}\n className=\"flex size-10 items-center justify-center rounded hover:bg-bg-secondary\"\n >\n <X size={16} />\n </button>\n </div>\n\n {/* Content */}\n <div className=\"flex-1 overflow-y-auto p-4 space-y-4\">\n {/* Summary */}\n <div className=\"grid grid-cols-2 gap-3 text-sm\">\n <div>\n <span className=\"text-text-secondary text-xs\">Action</span>\n <div className=\"font-medium\">{log.action}</div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Status</span>\n <div>\n <StatusBadge status={log.status} size=\"sm\" />\n </div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Resource Type</span>\n <div className=\"font-medium\">{log.resourceType.replace(/_/g, ' ')}</div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Resource ID</span>\n <div className=\"font-mono text-xs truncate\">{log.resourceId || '-'}</div>\n </div>\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Resource Name</span>\n <div>{log.resourceName || '-'}</div>\n </div>\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Description</span>\n <div className=\"text-text-secondary\">{log.description || '-'}</div>\n </div>\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Actor</span>\n <div className=\"flex items-center gap-2\">\n <span className=\"capitalize\">\n {(log.actorType || 'unknown').toLowerCase().replace(/_/g, ' ')}\n </span>\n <details className=\"text-xs text-text-secondary\">\n <summary className=\"cursor-pointer hover:text-text-primary\">ID</summary>\n <span className=\"ml-2 break-all font-mono text-[11px]\">{log.actorId}</span>\n </details>\n </div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Timestamp</span>\n <div className=\"text-xs\">{new Date(log.createdAt).toLocaleString()}</div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">IP Address</span>\n <div className=\"font-mono text-xs\">{log.ipAddress || '-'}</div>\n </div>\n {log.expiresAt && (\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Expires At</span>\n <div className=\"text-xs text-status-warning-text\">\n {new Date(log.expiresAt).toLocaleString()}\n </div>\n </div>\n )}\n {log.errorMessage && (\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Error</span>\n <div className=\"text-status-error-text text-xs\">{log.errorMessage}</div>\n </div>\n )}\n {log.deleteReason && (\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Delete Reason</span>\n <div className=\"text-xs\">{log.deleteReason}</div>\n </div>\n )}\n </div>\n\n {/* Command execution */}\n <CommandBlock command={log.command} output={log.output} exitCode={log.exitCode} />\n\n {/* Changeset */}\n <ChangesetViewer changeset={log.changeset as Record<string, unknown> | null} />\n\n {/* State snapshots */}\n <JsonViewer data={log.previousState} label=\"Previous State\" />\n <JsonViewer data={log.newState} label=\"New State\" />\n <JsonViewer data={log.metadata} label=\"Metadata\" />\n\n {footer ? <div className=\"pt-2\">{footer}</div> : null}\n </div>\n </aside>\n </div>\n );\n}\n"],"mappings":";;;;;;;AAaA,SAAS,EAAW,EAAE,SAAM,YAA2C;CACrE,IAAM,CAAC,GAAU,KAAe,EAAS,GAAM;AAG/C,QAFK,IAGH,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,UAAD;GACE,MAAK;GACL,eAAe,EAAY,CAAC,EAAS;GACrC,WAAU;aAHZ,CAKc,EAAX,IAAY,IAA4B,GAA7B,EAAa,MAAM,IAAM,CAA6B,EACjE,EACM;MACR,KACC,kBAAC,OAAD;GAAK,WAAU;aACZ,KAAK,UAAU,GAAM,MAAM,EAAE;GAC1B,CAAA,CAEJ;MAjBU;;AAqBpB,SAAS,EAAa,EACpB,YACA,WACA,eAKC;CACD,IAAM,CAAC,GAAQ,KAAa,EAAS,GAAM;AAW3C,QAVI,CAAC,KAAW,CAAC,IAAe,OAW9B,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,QAAD;KAAM,WAAU;eAAhB;MACE,kBAAC,GAAD,EAAU,MAAM,IAAM,CAAA;;MAErB,KAAa,QACZ,kBAAC,QAAD;OACE,WAAW,iCAAiC,MAAa,IAAI,kDAAkD;iBADjH,CAEC,SACO,EACD;;MAEJ;QACN,KACC,kBAAC,UAAD;KACE,MAAK;KACL,eAzBe;AACvB,MAAI,MACF,UAAU,UAAU,UAAU,EAAQ,EACtC,EAAU,GAAK,EACf,iBAAiB,EAAU,GAAM,EAAE,IAAK;;KAsBlC,WAAU;KACV,OAAM;eAEI,EAAT,IAAU,IAAsB,GAAvB,EAAO,MAAM,IAAM,CAAqB;KAC3C,CAAA,CAEP;;GACL,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,QAAD;MAAM,WAAU;gBAA2B;MAAQ,CAAA;;KAAE;KACjD;;GAEP,KACC,kBAAC,OAAD;IAAK,WAAU;cACZ;IACG,CAAA;GAEJ;;;AAIV,SAAS,EAAgB,EAAE,gBAAwE;CACjG,IAAM,CAAC,GAAU,KAAe,EAAS,GAAM;AAC/C,KAAI,CAAC,KAAa,OAAO,KAAc,SAAU,QAAO;CAExD,IAAM,IAAU,OAAO,QAAQ,EAA4D;AAG3F,QAFI,EAAQ,WAAW,IAAU,OAG/B,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,UAAD;GACE,MAAK;GACL,eAAe,EAAY,CAAC,EAAS;GACrC,WAAU;aAHZ;IAKc,EAAX,IAAY,IAA4B,GAA7B,EAAa,MAAM,IAAM,CAA6B;IAAC;IACzD,EAAQ;IAAO;IAAO,EAAQ,WAAW,IAAU,KAAN;IAAS;IACzD;MACR,KACC,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAQ,KAAK,CAAC,GAAO,OACpB,kBAAC,OAAD;IAAiB,WAAU;cAA3B,CACE,kBAAC,QAAD;KAAM,WAAU;eAAiC;KAAa,CAAA,EAC9D,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAmC;OAAQ,CAAA,EAC3D,kBAAC,QAAD;OAAM,WAAU;iBACb,KAAK,UAAW,EAA6B,KAAK;OAC9C,CAAA,CACH;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAqC;OAAQ,CAAA,EAC7D,kBAAC,QAAD;OAAM,WAAU;iBACb,KAAK,UAAW,EAA2B,GAAG;OAC1C,CAAA,CACH;QACF;OACF;MAhBI,EAgBJ,CACN;GACE,CAAA,CAEJ;;;AAIV,SAAgB,EAAe,EAAE,QAAK,YAAS,aAA+B;CAC5E,IAAM,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAAqB;EAC5C,IAAM,IAAI,EAAE,EAAI;AAChB,SAAO,MAAM,IAAM,IAAW;;AAchC,QAXA,QAAgB;EACd,IAAM,KAAiB,MAAyB;AAC9C,GAAI,EAAM,QAAQ,YAChB,GAAS;;AAKb,SADA,OAAO,iBAAiB,WAAW,EAAc,QACpC,OAAO,oBAAoB,WAAW,EAAc;IAChE,CAAC,EAAQ,CAAC,EAGX,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,UAAD;GACE,MAAK;GACL,cAAY,EAAG,4BAA4B,yBAAyB;GACpE,WAAU;GACV,SAAS;GACT,CAAA,EACF,kBAAC,SAAD;GAAO,WAAU;aAAjB,CAEE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA;KACE,kBAAC,MAAD;MAAI,WAAU;gBAAyB,EAAI,OAAO,QAAQ,MAAM,IAAI;MAAM,CAAA;KAC1E,kBAAC,KAAD;MAAG,WAAU;gBAAb,CACG,EAAI,aAAa,QAAQ,MAAM,IAAI,EACnC,EAAI,eAAe,MAAM,EAAI,iBAAiB,GAC7C;;KACJ,kBAAC,WAAD;MAAS,WAAU;gBAAnB,CACE,kBAAC,WAAD;OAAS,WAAU;iBAAkG;OAE3G,CAAA,EACV,kBAAC,QAAD;OAAM,WAAU;iBACb,EAAI;OACA,CAAA,CACC;;KACN,EAAA,CAAA,EACN,kBAAC,UAAD;KACE,MAAK;KACL,cAAY,EAAG,qBAAqB,yBAAyB;KAC7D,SAAS;KACT,WAAU;eAEV,kBAAC,GAAD,EAAG,MAAM,IAAM,CAAA;KACR,CAAA,CACL;OAGN,kBAAC,OAAD;IAAK,WAAU;cAAf;KAEE,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAa,CAAA,EAC3D,kBAAC,OAAD;QAAK,WAAU;kBAAe,EAAI;QAAa,CAAA,CAC3C,EAAA,CAAA;OACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAa,CAAA,EAC3D,kBAAC,OAAD,EAAA,UACE,kBAAC,GAAD;QAAa,QAAQ,EAAI;QAAQ,MAAK;QAAO,CAAA,EACzC,CAAA,CACF,EAAA,CAAA;OACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAoB,CAAA,EAClE,kBAAC,OAAD;QAAK,WAAU;kBAAe,EAAI,aAAa,QAAQ,MAAM,IAAI;QAAO,CAAA,CACpE,EAAA,CAAA;OACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAkB,CAAA,EAChE,kBAAC,OAAD;QAAK,WAAU;kBAA8B,EAAI,cAAc;QAAU,CAAA,CACrE,EAAA,CAAA;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAoB,CAAA,EAClE,kBAAC,OAAD,EAAA,UAAM,EAAI,gBAAgB,KAAU,CAAA,CAChC;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAkB,CAAA,EAChE,kBAAC,OAAD;SAAK,WAAU;mBAAuB,EAAI,eAAe;SAAU,CAAA,CAC/D;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAY,CAAA,EAC1D,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,QAAD;UAAM,WAAU;qBACZ,EAAI,aAAa,WAAW,aAAa,CAAC,QAAQ,MAAM,IAAI;UACzD,CAAA,EACP,kBAAC,WAAD;UAAS,WAAU;oBAAnB,CACE,kBAAC,WAAD;WAAS,WAAU;qBAAyC;WAAY,CAAA,EACxE,kBAAC,QAAD;WAAM,WAAU;qBAAwC,EAAI;WAAe,CAAA,CACnE;YACN;WACF;;OACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAgB,CAAA,EAC9D,kBAAC,OAAD;QAAK,WAAU;kBAAW,IAAI,KAAK,EAAI,UAAU,CAAC,gBAAgB;QAAO,CAAA,CACrE,EAAA,CAAA;OACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAiB,CAAA,EAC/D,kBAAC,OAAD;QAAK,WAAU;kBAAqB,EAAI,aAAa;QAAU,CAAA,CAC3D,EAAA,CAAA;OACL,EAAI,aACH,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAiB,CAAA,EAC/D,kBAAC,OAAD;SAAK,WAAU;mBACZ,IAAI,KAAK,EAAI,UAAU,CAAC,gBAAgB;SACrC,CAAA,CACF;;OAEP,EAAI,gBACH,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAY,CAAA,EAC1D,kBAAC,OAAD;SAAK,WAAU;mBAAkC,EAAI;SAAmB,CAAA,CACpE;;OAEP,EAAI,gBACH,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAoB,CAAA,EAClE,kBAAC,OAAD;SAAK,WAAU;mBAAW,EAAI;SAAmB,CAAA,CAC7C;;OAEJ;;KAGN,kBAAC,GAAD;MAAc,SAAS,EAAI;MAAS,QAAQ,EAAI;MAAQ,UAAU,EAAI;MAAY,CAAA;KAGlF,kBAAC,GAAD,EAAiB,WAAW,EAAI,WAA+C,CAAA;KAG/E,kBAAC,GAAD;MAAY,MAAM,EAAI;MAAe,OAAM;MAAmB,CAAA;KAC9D,kBAAC,GAAD;MAAY,MAAM,EAAI;MAAU,OAAM;MAAc,CAAA;KACpD,kBAAC,GAAD;MAAY,MAAM,EAAI;MAAU,OAAM;MAAa,CAAA;KAElD,IAAS,kBAAC,OAAD;MAAK,WAAU;gBAAQ;MAAa,CAAA,GAAG;KAC7C;MACA;KACJ"}
1
+ {"version":3,"file":"AuditLogDetail.js","names":[],"sources":["../../../src/components/audit/AuditLogDetail.tsx"],"sourcesContent":["import { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useEffect, useState, type ReactNode } from 'react';\nimport { X, ChevronDown, ChevronRight, Copy, Check, Terminal } from 'lucide-react';\nimport type { VibeAuditLogDetailFragment } from '@/generated/wspace-operations';\nimport { StatusBadge } from '@/components/shared';\n\ninterface AuditLogDetailProps {\n log: VibeAuditLogDetailFragment;\n onClose: () => void;\n /** Optional action node rendered at the bottom of the panel (e.g. drill-down). */\n footer?: ReactNode;\n}\n\nfunction JsonViewer({ data, label }: { data: unknown; label: string }) {\n const [expanded, setExpanded] = useState(false);\n if (!data) return null;\n\n return (\n <div className=\"border border-border-default rounded-lg overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setExpanded(!expanded)}\n className=\"w-full flex items-center gap-2 px-3 py-2 text-sm font-medium bg-bg-sunken hover:bg-bg-surface\"\n >\n {expanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n {label}\n </button>\n {expanded && (\n <pre className=\"px-3 py-2 text-xs overflow-auto max-h-64 bg-bg-sunken\">\n {JSON.stringify(data, null, 2)}\n </pre>\n )}\n </div>\n );\n}\n\nfunction CommandBlock({\n command,\n output,\n exitCode,\n}: {\n command?: string | null;\n output?: string | null;\n exitCode?: number | null;\n}) {\n const [copied, setCopied] = useState(false);\n if (!command && !output) return null;\n\n const handleCopy = () => {\n if (command) {\n navigator.clipboard.writeText(command);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }\n };\n\n return (\n <div className=\"border border-border-default rounded-lg overflow-hidden\">\n <div className=\"flex items-center justify-between px-3 py-2 bg-bg-sunken\">\n <span className=\"flex items-center gap-2 text-sm font-medium\">\n <Terminal size={14} />\n Command Execution\n {exitCode !== null && exitCode !== undefined && (\n <span\n className={`px-1.5 py-0.5 rounded text-xs ${exitCode === 0 ? 'bg-status-success-bg-subtle text-status-success-text' : 'bg-status-error-bg-subtle text-status-error-text'}`}\n >\n exit {exitCode}\n </span>\n )}\n </span>\n {command && (\n <button\n type=\"button\"\n onClick={handleCopy}\n className=\"p-1 rounded hover:bg-bg-surface text-text-secondary\"\n title=\"Copy command\"\n >\n {copied ? <Check size={14} /> : <Copy size={14} />}\n </button>\n )}\n </div>\n {command && (\n <div className=\"px-3 py-2 bg-bg-sunken text-text-secondary font-mono text-xs\">\n <span className=\"text-status-success-text\">$</span> {command}\n </div>\n )}\n {output && (\n <pre className=\"px-3 py-2 text-xs bg-bg-sunken text-text-tertiary font-mono overflow-auto max-h-48\">\n {output}\n </pre>\n )}\n </div>\n );\n}\n\nfunction ChangesetViewer({ changeset }: { changeset: Record<string, unknown> | null | undefined }) {\n const [expanded, setExpanded] = useState(false);\n if (!changeset || typeof changeset !== 'object') return null;\n\n const changes = Object.entries(changeset as Record<string, { from: unknown; to: unknown }>);\n if (changes.length === 0) return null;\n\n return (\n <div className=\"border border-border-default rounded-lg overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setExpanded(!expanded)}\n className=\"w-full flex items-center gap-2 px-3 py-2 text-sm font-medium bg-bg-sunken hover:bg-bg-surface\"\n >\n {expanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n Changes ({changes.length} field{changes.length !== 1 ? 's' : ''})\n </button>\n {expanded && (\n <div className=\"px-3 py-2 space-y-2\">\n {changes.map(([field, change]) => (\n <div key={field} className=\"text-xs\">\n <span className=\"font-medium text-text-primary\">{field}</span>\n <div className=\"ml-4 mt-1 space-y-0.5\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-status-error-text font-mono\">-</span>\n <span className=\"text-status-error-text\">\n {JSON.stringify((change as { from: unknown }).from)}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-status-success-text font-mono\">+</span>\n <span className=\"text-status-success-text\">\n {JSON.stringify((change as { to: unknown }).to)}\n </span>\n </div>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nexport function AuditLogDetail({ log, onClose, footer }: AuditLogDetailProps) {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n onClose();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [onClose]);\n\n return (\n <div className=\"fixed inset-0 z-[1000] flex justify-end bg-bg-overlay/40\">\n <button\n type=\"button\"\n aria-label={tr('audit.closeDetailOverlay', 'Close audit log detail')}\n className=\"absolute inset-0 cursor-default\"\n onClick={onClose}\n />\n <aside className=\"relative flex h-full w-full max-w-[480px] flex-col border-l border-border-default bg-bg-surface shadow-xl\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-border-default\">\n <div>\n <h3 className=\"text-sm font-semibold\">{log.action.replace(/_/g, ' ')}</h3>\n <p className=\"text-xs text-text-secondary\">\n {log.resourceType.replace(/_/g, ' ')}\n {log.resourceName ? ` · ${log.resourceName}` : ''}\n </p>\n <details className=\"mt-1\">\n <summary className=\"cursor-pointer text-[10px] uppercase tracking-wider text-text-secondary hover:text-text-primary\">\n Event ID\n </summary>\n <span className=\"mt-1 block break-all font-mono text-[11px] text-text-secondary\">\n {log.id}\n </span>\n </details>\n </div>\n <button\n type=\"button\"\n aria-label={tr('audit.closeDetail', 'Close audit log detail')}\n onClick={onClose}\n className=\"flex size-10 items-center justify-center rounded hover:bg-bg-surface\"\n >\n <X size={16} />\n </button>\n </div>\n\n {/* Content */}\n <div className=\"flex-1 overflow-y-auto p-4 space-y-4\">\n {/* Summary */}\n <div className=\"grid grid-cols-2 gap-3 text-sm\">\n <div>\n <span className=\"text-text-secondary text-xs\">Action</span>\n <div className=\"font-medium\">{log.action}</div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Status</span>\n <div>\n <StatusBadge status={log.status} size=\"sm\" />\n </div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Resource Type</span>\n <div className=\"font-medium\">{log.resourceType.replace(/_/g, ' ')}</div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Resource ID</span>\n <div className=\"font-mono text-xs truncate\">{log.resourceId || '-'}</div>\n </div>\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Resource Name</span>\n <div>{log.resourceName || '-'}</div>\n </div>\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Description</span>\n <div className=\"text-text-secondary\">{log.description || '-'}</div>\n </div>\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Actor</span>\n <div className=\"flex items-center gap-2\">\n <span className=\"capitalize\">\n {(log.actorType || 'unknown').toLowerCase().replace(/_/g, ' ')}\n </span>\n <details className=\"text-xs text-text-secondary\">\n <summary className=\"cursor-pointer hover:text-text-primary\">ID</summary>\n <span className=\"ml-2 break-all font-mono text-[11px]\">{log.actorId}</span>\n </details>\n </div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Timestamp</span>\n <div className=\"text-xs\">{new Date(log.createdAt).toLocaleString()}</div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">IP Address</span>\n <div className=\"font-mono text-xs\">{log.ipAddress || '-'}</div>\n </div>\n {log.expiresAt && (\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Expires At</span>\n <div className=\"text-xs text-status-warning-text\">\n {new Date(log.expiresAt).toLocaleString()}\n </div>\n </div>\n )}\n {log.errorMessage && (\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Error</span>\n <div className=\"text-status-error-text text-xs\">{log.errorMessage}</div>\n </div>\n )}\n {log.deleteReason && (\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Delete Reason</span>\n <div className=\"text-xs\">{log.deleteReason}</div>\n </div>\n )}\n </div>\n\n {/* Command execution */}\n <CommandBlock command={log.command} output={log.output} exitCode={log.exitCode} />\n\n {/* Changeset */}\n <ChangesetViewer changeset={log.changeset as Record<string, unknown> | null} />\n\n {/* State snapshots */}\n <JsonViewer data={log.previousState} label=\"Previous State\" />\n <JsonViewer data={log.newState} label=\"New State\" />\n <JsonViewer data={log.metadata} label=\"Metadata\" />\n\n {footer ? <div className=\"pt-2\">{footer}</div> : null}\n </div>\n </aside>\n </div>\n );\n}\n"],"mappings":";;;;;;;AAaA,SAAS,EAAW,EAAE,SAAM,YAA2C;CACrE,IAAM,CAAC,GAAU,KAAe,EAAS,GAAM;AAG/C,QAFK,IAGH,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,UAAD;GACE,MAAK;GACL,eAAe,EAAY,CAAC,EAAS;GACrC,WAAU;aAHZ,CAKc,EAAX,IAAY,IAA4B,GAA7B,EAAa,MAAM,IAAM,CAA6B,EACjE,EACM;MACR,KACC,kBAAC,OAAD;GAAK,WAAU;aACZ,KAAK,UAAU,GAAM,MAAM,EAAE;GAC1B,CAAA,CAEJ;MAjBU;;AAqBpB,SAAS,EAAa,EACpB,YACA,WACA,eAKC;CACD,IAAM,CAAC,GAAQ,KAAa,EAAS,GAAM;AAW3C,QAVI,CAAC,KAAW,CAAC,IAAe,OAW9B,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,QAAD;KAAM,WAAU;eAAhB;MACE,kBAAC,GAAD,EAAU,MAAM,IAAM,CAAA;;MAErB,KAAa,QACZ,kBAAC,QAAD;OACE,WAAW,iCAAiC,MAAa,IAAI,yDAAyD;iBADxH,CAEC,SACO,EACD;;MAEJ;QACN,KACC,kBAAC,UAAD;KACE,MAAK;KACL,eAzBe;AACvB,MAAI,MACF,UAAU,UAAU,UAAU,EAAQ,EACtC,EAAU,GAAK,EACf,iBAAiB,EAAU,GAAM,EAAE,IAAK;;KAsBlC,WAAU;KACV,OAAM;eAEI,EAAT,IAAU,IAAsB,GAAvB,EAAO,MAAM,IAAM,CAAqB;KAC3C,CAAA,CAEP;;GACL,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,QAAD;MAAM,WAAU;gBAA2B;MAAQ,CAAA;;KAAE;KACjD;;GAEP,KACC,kBAAC,OAAD;IAAK,WAAU;cACZ;IACG,CAAA;GAEJ;;;AAIV,SAAS,EAAgB,EAAE,gBAAwE;CACjG,IAAM,CAAC,GAAU,KAAe,EAAS,GAAM;AAC/C,KAAI,CAAC,KAAa,OAAO,KAAc,SAAU,QAAO;CAExD,IAAM,IAAU,OAAO,QAAQ,EAA4D;AAG3F,QAFI,EAAQ,WAAW,IAAU,OAG/B,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,UAAD;GACE,MAAK;GACL,eAAe,EAAY,CAAC,EAAS;GACrC,WAAU;aAHZ;IAKc,EAAX,IAAY,IAA4B,GAA7B,EAAa,MAAM,IAAM,CAA6B;IAAC;IACzD,EAAQ;IAAO;IAAO,EAAQ,WAAW,IAAU,KAAN;IAAS;IACzD;MACR,KACC,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAQ,KAAK,CAAC,GAAO,OACpB,kBAAC,OAAD;IAAiB,WAAU;cAA3B,CACE,kBAAC,QAAD;KAAM,WAAU;eAAiC;KAAa,CAAA,EAC9D,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAmC;OAAQ,CAAA,EAC3D,kBAAC,QAAD;OAAM,WAAU;iBACb,KAAK,UAAW,EAA6B,KAAK;OAC9C,CAAA,CACH;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAqC;OAAQ,CAAA,EAC7D,kBAAC,QAAD;OAAM,WAAU;iBACb,KAAK,UAAW,EAA2B,GAAG;OAC1C,CAAA,CACH;QACF;OACF;MAhBI,EAgBJ,CACN;GACE,CAAA,CAEJ;;;AAIV,SAAgB,EAAe,EAAE,QAAK,YAAS,aAA+B;CAC5E,IAAM,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAAqB;EAC5C,IAAM,IAAI,EAAE,EAAI;AAChB,SAAO,MAAM,IAAM,IAAW;;AAchC,QAXA,QAAgB;EACd,IAAM,KAAiB,MAAyB;AAC9C,GAAI,EAAM,QAAQ,YAChB,GAAS;;AAKb,SADA,OAAO,iBAAiB,WAAW,EAAc,QACpC,OAAO,oBAAoB,WAAW,EAAc;IAChE,CAAC,EAAQ,CAAC,EAGX,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,UAAD;GACE,MAAK;GACL,cAAY,EAAG,4BAA4B,yBAAyB;GACpE,WAAU;GACV,SAAS;GACT,CAAA,EACF,kBAAC,SAAD;GAAO,WAAU;aAAjB,CAEE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA;KACE,kBAAC,MAAD;MAAI,WAAU;gBAAyB,EAAI,OAAO,QAAQ,MAAM,IAAI;MAAM,CAAA;KAC1E,kBAAC,KAAD;MAAG,WAAU;gBAAb,CACG,EAAI,aAAa,QAAQ,MAAM,IAAI,EACnC,EAAI,eAAe,MAAM,EAAI,iBAAiB,GAC7C;;KACJ,kBAAC,WAAD;MAAS,WAAU;gBAAnB,CACE,kBAAC,WAAD;OAAS,WAAU;iBAAkG;OAE3G,CAAA,EACV,kBAAC,QAAD;OAAM,WAAU;iBACb,EAAI;OACA,CAAA,CACC;;KACN,EAAA,CAAA,EACN,kBAAC,UAAD;KACE,MAAK;KACL,cAAY,EAAG,qBAAqB,yBAAyB;KAC7D,SAAS;KACT,WAAU;eAEV,kBAAC,GAAD,EAAG,MAAM,IAAM,CAAA;KACR,CAAA,CACL;OAGN,kBAAC,OAAD;IAAK,WAAU;cAAf;KAEE,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAa,CAAA,EAC3D,kBAAC,OAAD;QAAK,WAAU;kBAAe,EAAI;QAAa,CAAA,CAC3C,EAAA,CAAA;OACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAa,CAAA,EAC3D,kBAAC,OAAD,EAAA,UACE,kBAAC,GAAD;QAAa,QAAQ,EAAI;QAAQ,MAAK;QAAO,CAAA,EACzC,CAAA,CACF,EAAA,CAAA;OACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAoB,CAAA,EAClE,kBAAC,OAAD;QAAK,WAAU;kBAAe,EAAI,aAAa,QAAQ,MAAM,IAAI;QAAO,CAAA,CACpE,EAAA,CAAA;OACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAkB,CAAA,EAChE,kBAAC,OAAD;QAAK,WAAU;kBAA8B,EAAI,cAAc;QAAU,CAAA,CACrE,EAAA,CAAA;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAoB,CAAA,EAClE,kBAAC,OAAD,EAAA,UAAM,EAAI,gBAAgB,KAAU,CAAA,CAChC;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAkB,CAAA,EAChE,kBAAC,OAAD;SAAK,WAAU;mBAAuB,EAAI,eAAe;SAAU,CAAA,CAC/D;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAY,CAAA,EAC1D,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,QAAD;UAAM,WAAU;qBACZ,EAAI,aAAa,WAAW,aAAa,CAAC,QAAQ,MAAM,IAAI;UACzD,CAAA,EACP,kBAAC,WAAD;UAAS,WAAU;oBAAnB,CACE,kBAAC,WAAD;WAAS,WAAU;qBAAyC;WAAY,CAAA,EACxE,kBAAC,QAAD;WAAM,WAAU;qBAAwC,EAAI;WAAe,CAAA,CACnE;YACN;WACF;;OACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAgB,CAAA,EAC9D,kBAAC,OAAD;QAAK,WAAU;kBAAW,IAAI,KAAK,EAAI,UAAU,CAAC,gBAAgB;QAAO,CAAA,CACrE,EAAA,CAAA;OACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAiB,CAAA,EAC/D,kBAAC,OAAD;QAAK,WAAU;kBAAqB,EAAI,aAAa;QAAU,CAAA,CAC3D,EAAA,CAAA;OACL,EAAI,aACH,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAiB,CAAA,EAC/D,kBAAC,OAAD;SAAK,WAAU;mBACZ,IAAI,KAAK,EAAI,UAAU,CAAC,gBAAgB;SACrC,CAAA,CACF;;OAEP,EAAI,gBACH,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAY,CAAA,EAC1D,kBAAC,OAAD;SAAK,WAAU;mBAAkC,EAAI;SAAmB,CAAA,CACpE;;OAEP,EAAI,gBACH,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAoB,CAAA,EAClE,kBAAC,OAAD;SAAK,WAAU;mBAAW,EAAI;SAAmB,CAAA,CAC7C;;OAEJ;;KAGN,kBAAC,GAAD;MAAc,SAAS,EAAI;MAAS,QAAQ,EAAI;MAAQ,UAAU,EAAI;MAAY,CAAA;KAGlF,kBAAC,GAAD,EAAiB,WAAW,EAAI,WAA+C,CAAA;KAG/E,kBAAC,GAAD;MAAY,MAAM,EAAI;MAAe,OAAM;MAAmB,CAAA;KAC9D,kBAAC,GAAD;MAAY,MAAM,EAAI;MAAU,OAAM;MAAc,CAAA;KACpD,kBAAC,GAAD;MAAY,MAAM,EAAI;MAAU,OAAM;MAAa,CAAA;KAElD,IAAS,kBAAC,OAAD;MAAK,WAAU;gBAAQ;MAAa,CAAA,GAAG;KAC7C;MACA;KACJ"}
@@ -198,7 +198,7 @@ function a({ searchQuery: a, onSearchChange: o, actionFilter: s, onActionChange:
198
198
  type: "checkbox",
199
199
  checked: p,
200
200
  onChange: (e) => m(e.target.checked),
201
- className: "rounded border-border-primary"
201
+ className: "rounded border-border-default"
202
202
  }), S("audit.commandsOnly", "Commands only")]
203
203
  })
204
204
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"AuditLogFilters.js","names":[],"sources":["../../../src/components/audit/AuditLogFilters.tsx"],"sourcesContent":["import { SearchInput, FilterDropdown } from '@/components/shared';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\ninterface AgentOption {\n id: string;\n name: string;\n}\n\ninterface VibeOption {\n id: string;\n name: string;\n}\n\ninterface AuditLogFiltersProps {\n searchQuery: string;\n onSearchChange: (query: string) => void;\n actionFilter: string | null;\n onActionChange: (value: string) => void;\n resourceTypeFilter: string | null;\n onResourceTypeChange: (value: string) => void;\n statusFilter: string | null;\n onStatusChange: (value: string) => void;\n hasCommandFilter: boolean;\n onHasCommandChange: (value: boolean) => void;\n agentFilter?: string | null;\n onAgentChange?: (value: string) => void;\n agents?: AgentOption[];\n vibeFilter?: string | null;\n onVibeChange?: (value: string) => void;\n vibes?: VibeOption[];\n}\n\nexport function AuditLogFilters({\n searchQuery,\n onSearchChange,\n actionFilter,\n onActionChange,\n resourceTypeFilter,\n onResourceTypeChange,\n statusFilter,\n onStatusChange,\n hasCommandFilter,\n onHasCommandChange,\n agentFilter,\n onAgentChange,\n agents,\n vibeFilter,\n onVibeChange,\n vibes,\n}: AuditLogFiltersProps) {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n const actionOptions = [\n { value: 'all', label: tr('audit.allActions', 'All Actions') },\n { value: 'CREATE', label: tr('audit.actionCreate', 'Create') },\n { value: 'UPDATE', label: tr('audit.actionUpdate', 'Update') },\n { value: 'DELETE', label: tr('audit.actionDelete', 'Delete') },\n { value: 'EXECUTE', label: tr('audit.actionExecute', 'Execute') },\n { value: 'EXPORT', label: tr('audit.actionExport', 'Export') },\n { value: 'SHARE', label: tr('audit.actionShare', 'Share') },\n { value: 'REVOKE', label: tr('audit.actionRevoke', 'Revoke') },\n { value: 'ARCHIVE', label: tr('audit.actionArchive', 'Archive') },\n { value: 'RESTORE', label: tr('audit.actionRestore', 'Restore') },\n ];\n\n const resourceTypeOptions = [\n { value: 'all', label: tr('audit.allResources', 'All Resources') },\n { value: 'AGENT', label: tr('audit.resourceAgent', 'Agent') },\n { value: 'VIBE', label: tr('audit.resourceVibe', 'Vibe') },\n { value: 'SESSION', label: tr('audit.resourceSession', 'Session') },\n { value: 'VIBE_DECK', label: tr('audit.resourceVibeDeck', 'Vibe Deck') },\n { value: 'VIBE_DECK_BUTTON', label: tr('audit.resourceDeckButton', 'Deck Button') },\n { value: 'NOTE', label: tr('audit.resourceNote', 'Note') },\n { value: 'CONFIGURATION', label: tr('audit.resourceConfiguration', 'Configuration') },\n { value: 'WEBHOOK', label: tr('audit.resourceWebhook', 'Webhook') },\n { value: 'SESSION_SHARE', label: tr('audit.resourceSessionShare', 'Session Share') },\n { value: 'AI_TOOL_EVENT', label: tr('audit.resourceAiToolEvent', 'AI Tool Event') },\n { value: 'AUDIT_LOG', label: tr('audit.resourceAuditLog', 'Audit Log') },\n { value: 'CALENDAR_TASK', label: tr('audit.resourceCalendarTask', 'Calendar Task') },\n { value: 'TARGET', label: tr('audit.resourceTarget', 'Target') },\n { value: 'AGENT_CONNECTION', label: tr('audit.resourceAgentConnection', 'Agent Connection') },\n { value: 'UI_SESSION', label: tr('audit.resourceUiSession', 'UI Session') },\n { value: 'SESSION_SHARE_LINK', label: tr('audit.resourceShareLink', 'Share Link') },\n ];\n\n const statusOptions = [\n { value: 'all', label: tr('audit.allStatuses', 'All Statuses') },\n { value: 'SUCCESS', label: tr('audit.statusSuccess', 'Success') },\n { value: 'FAILURE', label: tr('audit.statusFailure', 'Failure') },\n { value: 'DENIED', label: tr('audit.statusDenied', 'Denied') },\n { value: 'ERROR', label: tr('audit.statusError', 'Error') },\n ];\n\n const agentOptions = [\n { value: 'all', label: tr('audit.allAgents', 'All Agents') },\n ...(agents ?? []).map((a) => ({ value: a.id, label: a.name })),\n ];\n\n const vibeOptions = [\n { value: 'all', label: tr('audit.allVibes', 'All Vibes') },\n ...(vibes ?? []).map((v) => ({ value: v.id, label: v.name })),\n ];\n\n return (\n <div className=\"mb-4 flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center\">\n <SearchInput\n value={searchQuery}\n onChange={onSearchChange}\n placeholder={tr('audit.searchPlaceholder', 'Search audit logs...')}\n className=\"w-full sm:w-64\"\n />\n <FilterDropdown\n label={tr('audit.action', 'Action')}\n options={actionOptions}\n value={actionFilter}\n onChange={onActionChange}\n />\n <FilterDropdown\n label={tr('audit.resource', 'Resource')}\n options={resourceTypeOptions}\n value={resourceTypeFilter}\n onChange={onResourceTypeChange}\n />\n <FilterDropdown\n label={tr('audit.status', 'Status')}\n options={statusOptions}\n value={statusFilter}\n onChange={onStatusChange}\n />\n {onAgentChange && (\n <FilterDropdown\n label={tr('audit.agent', 'Agent')}\n options={agentOptions}\n value={agentFilter ?? 'all'}\n onChange={onAgentChange}\n />\n )}\n {onVibeChange && (\n <FilterDropdown\n label={tr('audit.vibe', 'Vibe')}\n options={vibeOptions}\n value={vibeFilter ?? 'all'}\n onChange={onVibeChange}\n />\n )}\n <label className=\"flex items-center gap-2 text-sm text-text-secondary cursor-pointer\">\n <input\n aria-label=\"control\"\n type=\"checkbox\"\n checked={hasCommandFilter}\n onChange={(e) => onHasCommandChange(e.target.checked)}\n className=\"rounded border-border-primary\"\n />\n {tr('audit.commandsOnly', 'Commands only')}\n </label>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AuditLogFilters.js","names":[],"sources":["../../../src/components/audit/AuditLogFilters.tsx"],"sourcesContent":["import { SearchInput, FilterDropdown } from '@/components/shared';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\ninterface AgentOption {\n id: string;\n name: string;\n}\n\ninterface VibeOption {\n id: string;\n name: string;\n}\n\ninterface AuditLogFiltersProps {\n searchQuery: string;\n onSearchChange: (query: string) => void;\n actionFilter: string | null;\n onActionChange: (value: string) => void;\n resourceTypeFilter: string | null;\n onResourceTypeChange: (value: string) => void;\n statusFilter: string | null;\n onStatusChange: (value: string) => void;\n hasCommandFilter: boolean;\n onHasCommandChange: (value: boolean) => void;\n agentFilter?: string | null;\n onAgentChange?: (value: string) => void;\n agents?: AgentOption[];\n vibeFilter?: string | null;\n onVibeChange?: (value: string) => void;\n vibes?: VibeOption[];\n}\n\nexport function AuditLogFilters({\n searchQuery,\n onSearchChange,\n actionFilter,\n onActionChange,\n resourceTypeFilter,\n onResourceTypeChange,\n statusFilter,\n onStatusChange,\n hasCommandFilter,\n onHasCommandChange,\n agentFilter,\n onAgentChange,\n agents,\n vibeFilter,\n onVibeChange,\n vibes,\n}: AuditLogFiltersProps) {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n const actionOptions = [\n { value: 'all', label: tr('audit.allActions', 'All Actions') },\n { value: 'CREATE', label: tr('audit.actionCreate', 'Create') },\n { value: 'UPDATE', label: tr('audit.actionUpdate', 'Update') },\n { value: 'DELETE', label: tr('audit.actionDelete', 'Delete') },\n { value: 'EXECUTE', label: tr('audit.actionExecute', 'Execute') },\n { value: 'EXPORT', label: tr('audit.actionExport', 'Export') },\n { value: 'SHARE', label: tr('audit.actionShare', 'Share') },\n { value: 'REVOKE', label: tr('audit.actionRevoke', 'Revoke') },\n { value: 'ARCHIVE', label: tr('audit.actionArchive', 'Archive') },\n { value: 'RESTORE', label: tr('audit.actionRestore', 'Restore') },\n ];\n\n const resourceTypeOptions = [\n { value: 'all', label: tr('audit.allResources', 'All Resources') },\n { value: 'AGENT', label: tr('audit.resourceAgent', 'Agent') },\n { value: 'VIBE', label: tr('audit.resourceVibe', 'Vibe') },\n { value: 'SESSION', label: tr('audit.resourceSession', 'Session') },\n { value: 'VIBE_DECK', label: tr('audit.resourceVibeDeck', 'Vibe Deck') },\n { value: 'VIBE_DECK_BUTTON', label: tr('audit.resourceDeckButton', 'Deck Button') },\n { value: 'NOTE', label: tr('audit.resourceNote', 'Note') },\n { value: 'CONFIGURATION', label: tr('audit.resourceConfiguration', 'Configuration') },\n { value: 'WEBHOOK', label: tr('audit.resourceWebhook', 'Webhook') },\n { value: 'SESSION_SHARE', label: tr('audit.resourceSessionShare', 'Session Share') },\n { value: 'AI_TOOL_EVENT', label: tr('audit.resourceAiToolEvent', 'AI Tool Event') },\n { value: 'AUDIT_LOG', label: tr('audit.resourceAuditLog', 'Audit Log') },\n { value: 'CALENDAR_TASK', label: tr('audit.resourceCalendarTask', 'Calendar Task') },\n { value: 'TARGET', label: tr('audit.resourceTarget', 'Target') },\n { value: 'AGENT_CONNECTION', label: tr('audit.resourceAgentConnection', 'Agent Connection') },\n { value: 'UI_SESSION', label: tr('audit.resourceUiSession', 'UI Session') },\n { value: 'SESSION_SHARE_LINK', label: tr('audit.resourceShareLink', 'Share Link') },\n ];\n\n const statusOptions = [\n { value: 'all', label: tr('audit.allStatuses', 'All Statuses') },\n { value: 'SUCCESS', label: tr('audit.statusSuccess', 'Success') },\n { value: 'FAILURE', label: tr('audit.statusFailure', 'Failure') },\n { value: 'DENIED', label: tr('audit.statusDenied', 'Denied') },\n { value: 'ERROR', label: tr('audit.statusError', 'Error') },\n ];\n\n const agentOptions = [\n { value: 'all', label: tr('audit.allAgents', 'All Agents') },\n ...(agents ?? []).map((a) => ({ value: a.id, label: a.name })),\n ];\n\n const vibeOptions = [\n { value: 'all', label: tr('audit.allVibes', 'All Vibes') },\n ...(vibes ?? []).map((v) => ({ value: v.id, label: v.name })),\n ];\n\n return (\n <div className=\"mb-4 flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center\">\n <SearchInput\n value={searchQuery}\n onChange={onSearchChange}\n placeholder={tr('audit.searchPlaceholder', 'Search audit logs...')}\n className=\"w-full sm:w-64\"\n />\n <FilterDropdown\n label={tr('audit.action', 'Action')}\n options={actionOptions}\n value={actionFilter}\n onChange={onActionChange}\n />\n <FilterDropdown\n label={tr('audit.resource', 'Resource')}\n options={resourceTypeOptions}\n value={resourceTypeFilter}\n onChange={onResourceTypeChange}\n />\n <FilterDropdown\n label={tr('audit.status', 'Status')}\n options={statusOptions}\n value={statusFilter}\n onChange={onStatusChange}\n />\n {onAgentChange && (\n <FilterDropdown\n label={tr('audit.agent', 'Agent')}\n options={agentOptions}\n value={agentFilter ?? 'all'}\n onChange={onAgentChange}\n />\n )}\n {onVibeChange && (\n <FilterDropdown\n label={tr('audit.vibe', 'Vibe')}\n options={vibeOptions}\n value={vibeFilter ?? 'all'}\n onChange={onVibeChange}\n />\n )}\n <label className=\"flex items-center gap-2 text-sm text-text-secondary cursor-pointer\">\n <input\n aria-label=\"control\"\n type=\"checkbox\"\n checked={hasCommandFilter}\n onChange={(e) => onHasCommandChange(e.target.checked)}\n className=\"rounded border-border-default\"\n />\n {tr('audit.commandsOnly', 'Commands only')}\n </label>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -16,7 +16,7 @@ function o({ stats: o, loading: s }) {
16
16
  ,
17
17
  ,
18
18
  ,
19
- ]].map((e, t) => /* @__PURE__ */ i("div", { className: "h-20 rounded-lg bg-bg-secondary/50 animate-pulse" }, t))
19
+ ]].map((e, t) => /* @__PURE__ */ i("div", { className: "h-20 rounded-lg bg-bg-sunken animate-pulse" }, t))
20
20
  });
21
21
  let u = o.logsByStatus.find((e) => e.status === "SUCCESS")?.count ?? 0, d = o.logsByStatus.find((e) => e.status === "ERROR")?.count ?? 0, f = o.logsByStatus.find((e) => e.status === "FAILURE")?.count ?? 0;
22
22
  return /* @__PURE__ */ a("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"AuditLogStats.js","names":[],"sources":["../../../src/components/audit/AuditLogStats.tsx"],"sourcesContent":["import { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Shield, Clock } from 'lucide-react';\nimport { StatCard } from '@/components/shared';\nimport type { GetVibeAuditLogStatsQuery } from '@/generated/wspace-operations';\n\ninterface AuditLogStatsProps {\n stats: GetVibeAuditLogStatsQuery['vibeAuditLogStats'] | undefined;\n loading: boolean;\n}\n\nexport function AuditLogStats({ stats, loading }: AuditLogStatsProps) {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n if (loading || !stats) {\n return (\n <div className=\"mb-6 grid grid-cols-2 gap-4 md:grid-cols-4\">\n {[...Array(4)].map((_, i) => (\n <div key={i} className=\"h-20 rounded-lg bg-bg-secondary/50 animate-pulse\" />\n ))}\n </div>\n );\n }\n\n const successCount = stats.logsByStatus.find((s) => s.status === 'SUCCESS')?.count ?? 0;\n const errorCount = stats.logsByStatus.find((s) => s.status === 'ERROR')?.count ?? 0;\n const failureCount = stats.logsByStatus.find((s) => s.status === 'FAILURE')?.count ?? 0;\n\n return (\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4 mb-6\">\n <StatCard\n title={tr('audit.stats.totalLogs', 'Total Logs')}\n value={stats.totalLogs.toLocaleString()}\n icon={<Shield size={16} />}\n />\n <StatCard\n title={tr('audit.stats.successful', 'Successful')}\n value={successCount.toLocaleString()}\n icon={<Shield size={16} className=\"text-status-success-text\" />}\n />\n <StatCard\n title={tr('audit.stats.errorsFailures', 'Errors / Failures')}\n value={`${errorCount + failureCount}`}\n icon={<Shield size={16} className=\"text-status-error-text\" />}\n />\n <StatCard\n title={tr('audit.stats.retention', 'Retention')}\n value={\n stats.retentionPolicy.retentionDays === -1\n ? tr('audit.stats.unlimited', 'Unlimited')\n : `${stats.retentionPolicy.retentionDays} ${tr('audit.stats.days', 'days')}`\n }\n icon={<Clock size={16} />}\n />\n </div>\n );\n}\n"],"mappings":";;;;;;AAUA,SAAgB,EAAc,EAAE,UAAO,cAA+B;CACpE,IAAM,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAAqB;EAC5C,IAAM,IAAI,EAAE,EAAI;AAChB,SAAO,MAAM,IAAM,IAAW;;AAEhC,KAAI,KAAW,CAAC,EACd,QACE,kBAAC,OAAD;EAAK,WAAU;YACZ,CAAC,GAAG;;;;;GAAQ,CAAC,CAAC,KAAK,GAAG,MACrB,kBAAC,OAAD,EAAa,WAAU,oDAAqD,EAAlE,EAAkE,CAC5E;EACE,CAAA;CAIV,IAAM,IAAe,EAAM,aAAa,MAAM,MAAM,EAAE,WAAW,UAAU,EAAE,SAAS,GAChF,IAAa,EAAM,aAAa,MAAM,MAAM,EAAE,WAAW,QAAQ,EAAE,SAAS,GAC5E,IAAe,EAAM,aAAa,MAAM,MAAM,EAAE,WAAW,UAAU,EAAE,SAAS;AAEtF,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,GAAD;IACE,OAAO,EAAG,yBAAyB,aAAa;IAChD,OAAO,EAAM,UAAU,gBAAgB;IACvC,MAAM,kBAAC,GAAD,EAAQ,MAAM,IAAM,CAAA;IAC1B,CAAA;GACF,kBAAC,GAAD;IACE,OAAO,EAAG,0BAA0B,aAAa;IACjD,OAAO,EAAa,gBAAgB;IACpC,MAAM,kBAAC,GAAD;KAAQ,MAAM;KAAI,WAAU;KAA6B,CAAA;IAC/D,CAAA;GACF,kBAAC,GAAD;IACE,OAAO,EAAG,8BAA8B,oBAAoB;IAC5D,OAAO,GAAG,IAAa;IACvB,MAAM,kBAAC,GAAD;KAAQ,MAAM;KAAI,WAAU;KAA2B,CAAA;IAC7D,CAAA;GACF,kBAAC,GAAD;IACE,OAAO,EAAG,yBAAyB,YAAY;IAC/C,OACE,EAAM,gBAAgB,kBAAkB,KACpC,EAAG,yBAAyB,YAAY,GACxC,GAAG,EAAM,gBAAgB,cAAc,GAAG,EAAG,oBAAoB,OAAO;IAE9E,MAAM,kBAAC,GAAD,EAAO,MAAM,IAAM,CAAA;IACzB,CAAA;GACE"}
1
+ {"version":3,"file":"AuditLogStats.js","names":[],"sources":["../../../src/components/audit/AuditLogStats.tsx"],"sourcesContent":["import { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Shield, Clock } from 'lucide-react';\nimport { StatCard } from '@/components/shared';\nimport type { GetVibeAuditLogStatsQuery } from '@/generated/wspace-operations';\n\ninterface AuditLogStatsProps {\n stats: GetVibeAuditLogStatsQuery['vibeAuditLogStats'] | undefined;\n loading: boolean;\n}\n\nexport function AuditLogStats({ stats, loading }: AuditLogStatsProps) {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n if (loading || !stats) {\n return (\n <div className=\"mb-6 grid grid-cols-2 gap-4 md:grid-cols-4\">\n {[...Array(4)].map((_, i) => (\n <div key={i} className=\"h-20 rounded-lg bg-bg-sunken animate-pulse\" />\n ))}\n </div>\n );\n }\n\n const successCount = stats.logsByStatus.find((s) => s.status === 'SUCCESS')?.count ?? 0;\n const errorCount = stats.logsByStatus.find((s) => s.status === 'ERROR')?.count ?? 0;\n const failureCount = stats.logsByStatus.find((s) => s.status === 'FAILURE')?.count ?? 0;\n\n return (\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4 mb-6\">\n <StatCard\n title={tr('audit.stats.totalLogs', 'Total Logs')}\n value={stats.totalLogs.toLocaleString()}\n icon={<Shield size={16} />}\n />\n <StatCard\n title={tr('audit.stats.successful', 'Successful')}\n value={successCount.toLocaleString()}\n icon={<Shield size={16} className=\"text-status-success-text\" />}\n />\n <StatCard\n title={tr('audit.stats.errorsFailures', 'Errors / Failures')}\n value={`${errorCount + failureCount}`}\n icon={<Shield size={16} className=\"text-status-error-text\" />}\n />\n <StatCard\n title={tr('audit.stats.retention', 'Retention')}\n value={\n stats.retentionPolicy.retentionDays === -1\n ? tr('audit.stats.unlimited', 'Unlimited')\n : `${stats.retentionPolicy.retentionDays} ${tr('audit.stats.days', 'days')}`\n }\n icon={<Clock size={16} />}\n />\n </div>\n );\n}\n"],"mappings":";;;;;;AAUA,SAAgB,EAAc,EAAE,UAAO,cAA+B;CACpE,IAAM,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAAqB;EAC5C,IAAM,IAAI,EAAE,EAAI;AAChB,SAAO,MAAM,IAAM,IAAW;;AAEhC,KAAI,KAAW,CAAC,EACd,QACE,kBAAC,OAAD;EAAK,WAAU;YACZ,CAAC,GAAG;;;;;GAAQ,CAAC,CAAC,KAAK,GAAG,MACrB,kBAAC,OAAD,EAAa,WAAU,8CAA+C,EAA5D,EAA4D,CACtE;EACE,CAAA;CAIV,IAAM,IAAe,EAAM,aAAa,MAAM,MAAM,EAAE,WAAW,UAAU,EAAE,SAAS,GAChF,IAAa,EAAM,aAAa,MAAM,MAAM,EAAE,WAAW,QAAQ,EAAE,SAAS,GAC5E,IAAe,EAAM,aAAa,MAAM,MAAM,EAAE,WAAW,UAAU,EAAE,SAAS;AAEtF,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,GAAD;IACE,OAAO,EAAG,yBAAyB,aAAa;IAChD,OAAO,EAAM,UAAU,gBAAgB;IACvC,MAAM,kBAAC,GAAD,EAAQ,MAAM,IAAM,CAAA;IAC1B,CAAA;GACF,kBAAC,GAAD;IACE,OAAO,EAAG,0BAA0B,aAAa;IACjD,OAAO,EAAa,gBAAgB;IACpC,MAAM,kBAAC,GAAD;KAAQ,MAAM;KAAI,WAAU;KAA6B,CAAA;IAC/D,CAAA;GACF,kBAAC,GAAD;IACE,OAAO,EAAG,8BAA8B,oBAAoB;IAC5D,OAAO,GAAG,IAAa;IACvB,MAAM,kBAAC,GAAD;KAAQ,MAAM;KAAI,WAAU;KAA2B,CAAA;IAC7D,CAAA;GACF,kBAAC,GAAD;IACE,OAAO,EAAG,yBAAyB,YAAY;IAC/C,OACE,EAAM,gBAAgB,kBAAkB,KACpC,EAAG,yBAAyB,YAAY,GACxC,GAAG,EAAM,gBAAgB,cAAc,GAAG,EAAG,oBAAoB,OAAO;IAE9E,MAAM,kBAAC,GAAD,EAAO,MAAM,IAAM,CAAA;IACzB,CAAA;GACE"}