@skyhook-io/radar-app 0.1.1

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 (251) hide show
  1. package/README.md +67 -0
  2. package/package.json +80 -0
  3. package/src/App.tsx +1538 -0
  4. package/src/RadarApp.tsx +145 -0
  5. package/src/api/apiResources.ts +28 -0
  6. package/src/api/client.ts +2583 -0
  7. package/src/api/config.ts +116 -0
  8. package/src/api/traffic.ts +139 -0
  9. package/src/components/ConnectionErrorView.tsx +272 -0
  10. package/src/components/ContextSwitcher.tsx +481 -0
  11. package/src/components/DebugOverlay.tsx +94 -0
  12. package/src/components/UserMenu.tsx +87 -0
  13. package/src/components/audit/AuditSettingsDialog.tsx +162 -0
  14. package/src/components/audit/AuditView.tsx +123 -0
  15. package/src/components/cost/CostTrendChart.tsx +388 -0
  16. package/src/components/cost/CostView.tsx +545 -0
  17. package/src/components/dock/BottomDock.tsx +96 -0
  18. package/src/components/dock/DockContext.tsx +11 -0
  19. package/src/components/dock/LocalTerminalTab.tsx +22 -0
  20. package/src/components/dock/LogsTab.tsx +26 -0
  21. package/src/components/dock/NodeTerminalTab.tsx +50 -0
  22. package/src/components/dock/TerminalTab.tsx +42 -0
  23. package/src/components/dock/TrafficFlowListTab.tsx +18 -0
  24. package/src/components/dock/WorkloadLogsTab.tsx +23 -0
  25. package/src/components/dock/index.ts +2 -0
  26. package/src/components/gitops/GitOpsActions.tsx +1 -0
  27. package/src/components/gitops/GitOpsStatusBadge.tsx +1 -0
  28. package/src/components/gitops/ManagedResourcesList.tsx +1 -0
  29. package/src/components/gitops/SyncCountdown.tsx +1 -0
  30. package/src/components/gitops/index.ts +4 -0
  31. package/src/components/helm/ChartBrowser.tsx +580 -0
  32. package/src/components/helm/HelmReleaseDrawer.tsx +774 -0
  33. package/src/components/helm/HelmView.tsx +475 -0
  34. package/src/components/helm/InstallWizard.tsx +1060 -0
  35. package/src/components/helm/ManifestDiffViewer.tsx +91 -0
  36. package/src/components/helm/ManifestViewer.tsx +61 -0
  37. package/src/components/helm/OwnedResources.tsx +465 -0
  38. package/src/components/helm/RevisionHistory.tsx +167 -0
  39. package/src/components/helm/ValuesDiffPreview.tsx +190 -0
  40. package/src/components/helm/ValuesViewer.tsx +365 -0
  41. package/src/components/helm/helm-utils.ts +37 -0
  42. package/src/components/home/ActivitySummary.tsx +262 -0
  43. package/src/components/home/CertificateHealthCard.tsx +105 -0
  44. package/src/components/home/ClusterHealthCard.tsx +483 -0
  45. package/src/components/home/CostCard.tsx +112 -0
  46. package/src/components/home/HealthRing.tsx +1 -0
  47. package/src/components/home/HelmSummary.tsx +129 -0
  48. package/src/components/home/HomeView.tsx +224 -0
  49. package/src/components/home/MCPSetupDialog.tsx +417 -0
  50. package/src/components/home/NetworkPolicyCoverageCard.tsx +109 -0
  51. package/src/components/home/TopologyPreview.tsx +219 -0
  52. package/src/components/home/TrafficSummary.tsx +154 -0
  53. package/src/components/logs/JsonLogLine.tsx +1 -0
  54. package/src/components/logs/LogCore.tsx +2 -0
  55. package/src/components/logs/LogsViewer.tsx +44 -0
  56. package/src/components/logs/WorkloadLogsViewer.tsx +40 -0
  57. package/src/components/logs/useLogBuffer.ts +2 -0
  58. package/src/components/logs/useLogSearch.ts +1 -0
  59. package/src/components/portforward/PortForwardButton.tsx +375 -0
  60. package/src/components/portforward/PortForwardManager.tsx +871 -0
  61. package/src/components/resource/PrometheusCharts.tsx +687 -0
  62. package/src/components/resource-drawer/ResourceDrawer.tsx +214 -0
  63. package/src/components/resources/ImageFilesystemModal.tsx +745 -0
  64. package/src/components/resources/PodFilesystemModal.tsx +407 -0
  65. package/src/components/resources/ResourceDetailDrawer.tsx +43 -0
  66. package/src/components/resources/ResourcesView.tsx +190 -0
  67. package/src/components/resources/drawer-components.tsx +1 -0
  68. package/src/components/resources/file-browser-utils.ts +35 -0
  69. package/src/components/resources/renderers/AlertRenderer.tsx +1 -0
  70. package/src/components/resources/renderers/ArgoApplicationRenderer.tsx +17 -0
  71. package/src/components/resources/renderers/CNPGBackupRenderer.tsx +1 -0
  72. package/src/components/resources/renderers/CNPGClusterRenderer.tsx +1 -0
  73. package/src/components/resources/renderers/CNPGPoolerRenderer.tsx +1 -0
  74. package/src/components/resources/renderers/CNPGScheduledBackupRenderer.tsx +1 -0
  75. package/src/components/resources/renderers/CertificateRenderer.tsx +1 -0
  76. package/src/components/resources/renderers/CertificateRequestRenderer.tsx +1 -0
  77. package/src/components/resources/renderers/ChallengeRenderer.tsx +1 -0
  78. package/src/components/resources/renderers/ClusterComplianceReportRenderer.tsx +1 -0
  79. package/src/components/resources/renderers/ClusterExternalSecretRenderer.tsx +1 -0
  80. package/src/components/resources/renderers/ClusterIssuerRenderer.tsx +1 -0
  81. package/src/components/resources/renderers/ConfigAuditReportRenderer.tsx +1 -0
  82. package/src/components/resources/renderers/ConfigMapRenderer.tsx +1 -0
  83. package/src/components/resources/renderers/CronJobRenderer.tsx +1 -0
  84. package/src/components/resources/renderers/EventRenderer.tsx +1 -0
  85. package/src/components/resources/renderers/ExposedSecretReportRenderer.tsx +1 -0
  86. package/src/components/resources/renderers/ExternalSecretRenderer.tsx +1 -0
  87. package/src/components/resources/renderers/FluxHelmReleaseRenderer.tsx +1 -0
  88. package/src/components/resources/renderers/GRPCRouteRenderer.tsx +1 -0
  89. package/src/components/resources/renderers/GatewayClassRenderer.tsx +1 -0
  90. package/src/components/resources/renderers/GatewayRenderer.tsx +1 -0
  91. package/src/components/resources/renderers/GenericRenderer.tsx +1 -0
  92. package/src/components/resources/renderers/GitRepositoryRenderer.tsx +1 -0
  93. package/src/components/resources/renderers/HPARenderer.tsx +1 -0
  94. package/src/components/resources/renderers/HTTPRouteRenderer.tsx +1 -0
  95. package/src/components/resources/renderers/HelmRepositoryRenderer.tsx +1 -0
  96. package/src/components/resources/renderers/IngressClassRenderer.tsx +1 -0
  97. package/src/components/resources/renderers/IngressRenderer.tsx +1 -0
  98. package/src/components/resources/renderers/IstioAuthorizationPolicyRenderer.tsx +1 -0
  99. package/src/components/resources/renderers/IstioDestinationRuleRenderer.tsx +1 -0
  100. package/src/components/resources/renderers/IstioGatewayRenderer.tsx +1 -0
  101. package/src/components/resources/renderers/IstioPeerAuthenticationRenderer.tsx +1 -0
  102. package/src/components/resources/renderers/IstioServiceEntryRenderer.tsx +1 -0
  103. package/src/components/resources/renderers/IstioVirtualServiceRenderer.tsx +1 -0
  104. package/src/components/resources/renderers/JobRenderer.tsx +1 -0
  105. package/src/components/resources/renderers/KarpenterEC2NodeClassRenderer.tsx +1 -0
  106. package/src/components/resources/renderers/KarpenterNodeClaimRenderer.tsx +1 -0
  107. package/src/components/resources/renderers/KarpenterNodePoolRenderer.tsx +1 -0
  108. package/src/components/resources/renderers/KedaScaledJobRenderer.tsx +1 -0
  109. package/src/components/resources/renderers/KedaScaledObjectRenderer.tsx +1 -0
  110. package/src/components/resources/renderers/KedaTriggerAuthRenderer.tsx +1 -0
  111. package/src/components/resources/renderers/KnativeConfigurationRenderer.tsx +1 -0
  112. package/src/components/resources/renderers/KnativeEventingRenderer.tsx +1 -0
  113. package/src/components/resources/renderers/KnativeFlowRenderer.tsx +1 -0
  114. package/src/components/resources/renderers/KnativeNetworkingRenderer.tsx +1 -0
  115. package/src/components/resources/renderers/KnativeRevisionRenderer.tsx +1 -0
  116. package/src/components/resources/renderers/KnativeRouteRenderer.tsx +1 -0
  117. package/src/components/resources/renderers/KnativeServiceRenderer.tsx +1 -0
  118. package/src/components/resources/renderers/KnativeSourceRenderer.tsx +1 -0
  119. package/src/components/resources/renderers/KustomizationRenderer.tsx +1 -0
  120. package/src/components/resources/renderers/KyvernoPolicyReportRenderer.tsx +1 -0
  121. package/src/components/resources/renderers/LeaseRenderer.tsx +1 -0
  122. package/src/components/resources/renderers/NetworkPolicyRenderer.tsx +1 -0
  123. package/src/components/resources/renderers/NodeRenderer.tsx +44 -0
  124. package/src/components/resources/renderers/OCIRepositoryRenderer.tsx +1 -0
  125. package/src/components/resources/renderers/OrderRenderer.tsx +1 -0
  126. package/src/components/resources/renderers/PVCRenderer.tsx +1 -0
  127. package/src/components/resources/renderers/PersistentVolumeRenderer.tsx +1 -0
  128. package/src/components/resources/renderers/PodDisruptionBudgetRenderer.tsx +1 -0
  129. package/src/components/resources/renderers/PodMonitorRenderer.tsx +1 -0
  130. package/src/components/resources/renderers/PodRenderer.tsx +94 -0
  131. package/src/components/resources/renderers/PriorityClassRenderer.tsx +1 -0
  132. package/src/components/resources/renderers/PrometheusRuleRenderer.tsx +1 -0
  133. package/src/components/resources/renderers/ReplicaSetRenderer.tsx +1 -0
  134. package/src/components/resources/renderers/RoleBindingRenderer.tsx +1 -0
  135. package/src/components/resources/renderers/RoleRenderer.tsx +1 -0
  136. package/src/components/resources/renderers/RolloutRenderer.tsx +1 -0
  137. package/src/components/resources/renderers/RuntimeClassRenderer.tsx +1 -0
  138. package/src/components/resources/renderers/SbomReportRenderer.tsx +1 -0
  139. package/src/components/resources/renderers/SealedSecretRenderer.tsx +1 -0
  140. package/src/components/resources/renderers/SecretRenderer.tsx +1 -0
  141. package/src/components/resources/renderers/SecretStoreRenderer.tsx +1 -0
  142. package/src/components/resources/renderers/ServiceAccountRenderer.tsx +1 -0
  143. package/src/components/resources/renderers/ServiceMonitorRenderer.tsx +1 -0
  144. package/src/components/resources/renderers/ServiceRenderer.tsx +26 -0
  145. package/src/components/resources/renderers/SimpleRouteRenderer.tsx +1 -0
  146. package/src/components/resources/renderers/StorageClassRenderer.tsx +1 -0
  147. package/src/components/resources/renderers/TraefikIngressRouteRenderer.tsx +1 -0
  148. package/src/components/resources/renderers/VPARenderer.tsx +1 -0
  149. package/src/components/resources/renderers/VeleroBSLRenderer.tsx +1 -0
  150. package/src/components/resources/renderers/VeleroBackupRenderer.tsx +1 -0
  151. package/src/components/resources/renderers/VeleroRestoreRenderer.tsx +1 -0
  152. package/src/components/resources/renderers/VeleroScheduleRenderer.tsx +1 -0
  153. package/src/components/resources/renderers/VeleroVSLRenderer.tsx +1 -0
  154. package/src/components/resources/renderers/VulnerabilityReportRenderer.tsx +1 -0
  155. package/src/components/resources/renderers/WebhookConfigRenderer.tsx +1 -0
  156. package/src/components/resources/renderers/WorkflowRenderer.tsx +1 -0
  157. package/src/components/resources/renderers/WorkflowTemplateRenderer.tsx +1 -0
  158. package/src/components/resources/renderers/WorkloadRenderer.tsx +52 -0
  159. package/src/components/resources/renderers/argo-cells.tsx +1 -0
  160. package/src/components/resources/renderers/certmanager-cells.tsx +1 -0
  161. package/src/components/resources/renderers/cnpg-cells.tsx +1 -0
  162. package/src/components/resources/renderers/eso-cells.tsx +1 -0
  163. package/src/components/resources/renderers/flux-cells.tsx +1 -0
  164. package/src/components/resources/renderers/index.ts +91 -0
  165. package/src/components/resources/renderers/istio-cells.tsx +1 -0
  166. package/src/components/resources/renderers/karpenter-cells.tsx +1 -0
  167. package/src/components/resources/renderers/keda-cells.tsx +1 -0
  168. package/src/components/resources/renderers/knative-cells.tsx +1 -0
  169. package/src/components/resources/renderers/kyverno-cells.tsx +1 -0
  170. package/src/components/resources/renderers/prometheus-cells.tsx +1 -0
  171. package/src/components/resources/renderers/traefik-cells.tsx +1 -0
  172. package/src/components/resources/renderers/trivy-cells.tsx +1 -0
  173. package/src/components/resources/renderers/trivy-shared.tsx +1 -0
  174. package/src/components/resources/renderers/velero-cells.tsx +1 -0
  175. package/src/components/resources/resource-utils-argo.ts +2 -0
  176. package/src/components/resources/resource-utils-certmanager.ts +2 -0
  177. package/src/components/resources/resource-utils-cnpg.ts +2 -0
  178. package/src/components/resources/resource-utils-eso.ts +2 -0
  179. package/src/components/resources/resource-utils-flux.ts +2 -0
  180. package/src/components/resources/resource-utils-istio.ts +2 -0
  181. package/src/components/resources/resource-utils-karpenter.ts +2 -0
  182. package/src/components/resources/resource-utils-keda.ts +2 -0
  183. package/src/components/resources/resource-utils-knative.ts +2 -0
  184. package/src/components/resources/resource-utils-kyverno.ts +2 -0
  185. package/src/components/resources/resource-utils-prometheus.ts +2 -0
  186. package/src/components/resources/resource-utils-traefik.ts +1 -0
  187. package/src/components/resources/resource-utils-trivy.ts +2 -0
  188. package/src/components/resources/resource-utils-velero.ts +2 -0
  189. package/src/components/resources/resource-utils.ts +5 -0
  190. package/src/components/settings/SettingsDialog.tsx +537 -0
  191. package/src/components/shared/CreateResourceDialog.tsx +17 -0
  192. package/src/components/shared/EditableYamlView.tsx +24 -0
  193. package/src/components/shared/LargeClusterNamespacePicker.tsx +70 -0
  194. package/src/components/shared/ResourceRendererDispatch.tsx +31 -0
  195. package/src/components/timeline/DiffViewer.tsx +1 -0
  196. package/src/components/timeline/TimelineList.tsx +69 -0
  197. package/src/components/timeline/TimelineSwimlanes.tsx +1308 -0
  198. package/src/components/timeline/TimelineView.tsx +157 -0
  199. package/src/components/timeline/shared.tsx +1 -0
  200. package/src/components/traffic/TrafficFilterSidebar.tsx +571 -0
  201. package/src/components/traffic/TrafficFlowList.tsx +415 -0
  202. package/src/components/traffic/TrafficFlowListContext.tsx +68 -0
  203. package/src/components/traffic/TrafficGraph.tsx +1546 -0
  204. package/src/components/traffic/TrafficView.tsx +1213 -0
  205. package/src/components/traffic/TrafficWizard.tsx +386 -0
  206. package/src/components/traffic/index.ts +3 -0
  207. package/src/components/ui/CodeViewer.tsx +8 -0
  208. package/src/components/ui/CommandPalette.tsx +460 -0
  209. package/src/components/ui/ConfirmDialog.tsx +1 -0
  210. package/src/components/ui/DiagnosticsOverlay.tsx +619 -0
  211. package/src/components/ui/ErrorBoundary.tsx +46 -0
  212. package/src/components/ui/ForceDeleteConfirmDialog.tsx +1 -0
  213. package/src/components/ui/Markdown.tsx +108 -0
  214. package/src/components/ui/MetricsChart.tsx +1 -0
  215. package/src/components/ui/NamespaceSelector.tsx +436 -0
  216. package/src/components/ui/ResourceBar.tsx +1 -0
  217. package/src/components/ui/ShortcutHelpOverlay.tsx +301 -0
  218. package/src/components/ui/Toast.tsx +1 -0
  219. package/src/components/ui/Tooltip.tsx +1 -0
  220. package/src/components/ui/UpdateNotification.tsx +299 -0
  221. package/src/components/ui/YamlEditor.tsx +1 -0
  222. package/src/components/workload/WorkloadView.tsx +532 -0
  223. package/src/context/ConnectionContext.tsx +173 -0
  224. package/src/context/ContextSwitchContext.tsx +56 -0
  225. package/src/context/NavCustomization.tsx +62 -0
  226. package/src/context/ThemeContext.tsx +97 -0
  227. package/src/contexts/CapabilitiesContext.tsx +130 -0
  228. package/src/hooks/useAnimatedUnmount.ts +1 -0
  229. package/src/hooks/useDesktopDownload.ts +41 -0
  230. package/src/hooks/useEventSource.ts +262 -0
  231. package/src/hooks/useFavorites.ts +69 -0
  232. package/src/hooks/useKeyboardShortcuts.tsx +7 -0
  233. package/src/hooks/useRefreshAnimation.ts +1 -0
  234. package/src/index.css +243 -0
  235. package/src/index.ts +17 -0
  236. package/src/main.tsx +158 -0
  237. package/src/types/gitops.ts +2 -0
  238. package/src/types.ts +3 -0
  239. package/src/utils/animation.ts +2 -0
  240. package/src/utils/badge-colors.ts +2 -0
  241. package/src/utils/context-name.ts +2 -0
  242. package/src/utils/desktop-download.ts +66 -0
  243. package/src/utils/desktop-open-folder.ts +21 -0
  244. package/src/utils/format.ts +2 -0
  245. package/src/utils/log-format.ts +12 -0
  246. package/src/utils/navigation.ts +23 -0
  247. package/src/utils/resource-hierarchy.ts +2 -0
  248. package/src/utils/resource-icons.ts +2 -0
  249. package/src/utils/skeleton-yaml.ts +2 -0
  250. package/src/utils/traffic-colors.ts +54 -0
  251. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,386 @@
1
+ import { useState, useEffect } from 'react'
2
+ import type { TrafficSourcesResponse, TrafficWizardState } from '../../types'
3
+ import { Loader2, CheckCircle2, XCircle, AlertTriangle, Copy, ExternalLink, ArrowRight, ArrowLeft, Package } from 'lucide-react'
4
+ import { InstallWizard } from '../helm/InstallWizard'
5
+
6
+ interface TrafficWizardProps {
7
+ state: TrafficWizardState
8
+ setState: (state: TrafficWizardState) => void
9
+ sourcesData?: TrafficSourcesResponse
10
+ sourcesLoading: boolean
11
+ onRefetch: () => void
12
+ }
13
+
14
+ export function TrafficWizard({
15
+ state,
16
+ setState,
17
+ sourcesData,
18
+ sourcesLoading,
19
+ onRefetch,
20
+ }: TrafficWizardProps) {
21
+ const [step, setStep] = useState<'choice' | 'install'>('choice')
22
+ const [copied, setCopied] = useState(false)
23
+ const [lastChecked, setLastChecked] = useState<Date | null>(null)
24
+ const [showHelmInstall, setShowHelmInstall] = useState(false)
25
+
26
+ const cluster = sourcesData?.cluster
27
+ const recommendation = sourcesData?.recommended
28
+ const helmChart = recommendation?.helmChart
29
+
30
+ // Auto-check when in 'checking' state
31
+ useEffect(() => {
32
+ if (state !== 'checking') return
33
+
34
+ // Initial check
35
+ onRefetch()
36
+ setLastChecked(new Date())
37
+
38
+ const interval = setInterval(() => {
39
+ onRefetch()
40
+ setLastChecked(new Date())
41
+ }, 30000) // Check every 30 seconds
42
+
43
+ return () => clearInterval(interval)
44
+ }, [state, onRefetch])
45
+
46
+ // Format relative time
47
+ const formatLastChecked = (date: Date | null): string => {
48
+ if (!date) return 'never'
49
+ const seconds = Math.floor((Date.now() - date.getTime()) / 1000)
50
+ if (seconds < 5) return 'just now'
51
+ if (seconds < 60) return `${seconds}s ago`
52
+ const minutes = Math.floor(seconds / 60)
53
+ return `${minutes}m ${seconds % 60}s ago`
54
+ }
55
+
56
+ // Update display every second when checking
57
+ const [, setTick] = useState(0)
58
+ useEffect(() => {
59
+ if (state !== 'checking') return
60
+ const interval = setInterval(() => setTick(t => t + 1), 1000)
61
+ return () => clearInterval(interval)
62
+ }, [state])
63
+
64
+ // Copy command to clipboard
65
+ const copyCommand = (command: string) => {
66
+ navigator.clipboard.writeText(command)
67
+ setCopied(true)
68
+ setTimeout(() => setCopied(false), 2000)
69
+ }
70
+
71
+ // Render Helm InstallWizard as overlay if shown
72
+ const helmInstallOverlay = showHelmInstall && helmChart ? (
73
+ <InstallWizard
74
+ repo={helmChart.repo}
75
+ chartName={helmChart.chartName}
76
+ version={helmChart.version || 'latest'}
77
+ source="artifacthub"
78
+ repoUrl={helmChart.repoUrl} // Pass direct repo URL for non-ArtifactHub charts
79
+ defaultValues={helmChart.defaultValues}
80
+ onClose={() => setShowHelmInstall(false)}
81
+ onSuccess={() => {
82
+ setShowHelmInstall(false)
83
+ setState('checking')
84
+ setLastChecked(null)
85
+ }}
86
+ />
87
+ ) : null
88
+
89
+ // Detecting state
90
+ if (state === 'detecting' || sourcesLoading) {
91
+ return (
92
+ <div className="flex items-center justify-center h-full w-full">
93
+ <div className="text-center space-y-4">
94
+ <Loader2 className="h-8 w-8 animate-spin text-blue-400 mx-auto" />
95
+ <p className="text-theme-text-secondary">Detecting traffic sources...</p>
96
+ </div>
97
+ </div>
98
+ )
99
+ }
100
+
101
+ // Checking state (polling for newly enabled source)
102
+ if (state === 'checking') {
103
+ return (
104
+ <>
105
+ <div className="flex items-center justify-center h-full w-full">
106
+ <div className="max-w-md w-full p-6 space-y-6">
107
+ <div className="text-center space-y-2">
108
+ <Loader2 className="h-8 w-8 animate-spin text-blue-400 mx-auto" />
109
+ <h2 className="text-lg font-medium text-theme-text-primary">Waiting for traffic source...</h2>
110
+ <p className="text-sm text-theme-text-secondary">
111
+ Checking for availability
112
+ </p>
113
+ </div>
114
+
115
+ <div className="bg-theme-elevated/50 rounded-lg p-4 text-sm">
116
+ <p className="text-theme-text-tertiary">
117
+ Last checked: {formatLastChecked(lastChecked)}
118
+ </p>
119
+ <p className="text-theme-text-tertiary">
120
+ Polls every 30 seconds automatically
121
+ </p>
122
+ </div>
123
+
124
+ <div className="flex gap-2 justify-center">
125
+ <button
126
+ onClick={() => {
127
+ setStep('choice')
128
+ setState('wizard')
129
+ }}
130
+ className="flex items-center gap-1 px-3 py-2 text-sm rounded border border-theme-border text-theme-text-primary hover:bg-theme-hover transition-colors"
131
+ >
132
+ <ArrowLeft className="h-4 w-4" />
133
+ Back
134
+ </button>
135
+ <button
136
+ onClick={() => {
137
+ onRefetch()
138
+ setLastChecked(new Date())
139
+ }}
140
+ className="px-3 py-2 text-sm rounded border border-theme-border text-theme-text-primary hover:bg-theme-hover transition-colors"
141
+ >
142
+ Check Now
143
+ </button>
144
+ </div>
145
+ </div>
146
+ </div>
147
+ {helmInstallOverlay}
148
+ </>
149
+ )
150
+ }
151
+
152
+ // Step 1: Choice screen
153
+ if (step === 'choice') {
154
+ return (
155
+ <>
156
+ <div className="flex items-center justify-center h-full w-full">
157
+ <div className="max-w-lg w-full p-6 space-y-6">
158
+ <div className="space-y-2">
159
+ <h2 className="text-lg font-medium text-theme-text-primary">Traffic Visibility</h2>
160
+ <p className="text-sm text-theme-text-secondary">
161
+ View service-to-service network flows in your cluster
162
+ </p>
163
+ </div>
164
+
165
+ {/* Cluster detection results */}
166
+ <div className="bg-theme-elevated/50 rounded-lg p-4 space-y-3">
167
+ <h3 className="text-sm font-medium text-theme-text-primary">Cluster Detection</h3>
168
+ <div className="grid grid-cols-2 gap-2 text-sm">
169
+ <div className="flex items-center gap-2 text-theme-text-secondary">
170
+ <CheckCircle2 className="h-4 w-4 text-green-500" />
171
+ <span>Platform: {cluster?.platform || 'generic'}</span>
172
+ </div>
173
+ <div className="flex items-center gap-2 text-theme-text-secondary">
174
+ {cluster?.cni && cluster.cni !== 'unknown' ? (
175
+ <CheckCircle2 className="h-4 w-4 text-green-500" />
176
+ ) : (
177
+ <XCircle className="h-4 w-4 text-yellow-500" />
178
+ )}
179
+ <span>CNI: {cluster?.cni || 'unknown'}</span>
180
+ </div>
181
+ {cluster?.cni === 'cilium' && (
182
+ <div className="flex items-center gap-2 col-span-2 text-theme-text-secondary">
183
+ {cluster.dataplaneV2 ? (
184
+ <CheckCircle2 className="h-4 w-4 text-green-500" />
185
+ ) : (
186
+ <XCircle className="h-4 w-4 text-yellow-500" />
187
+ )}
188
+ <span>
189
+ Hubble: {cluster.dataplaneV2 ? 'Enabled' : 'Not enabled'}
190
+ </span>
191
+ </div>
192
+ )}
193
+ </div>
194
+ </div>
195
+
196
+ {/* Detection errors */}
197
+ {sourcesData?.detected.filter(s => s.status === 'error').map(source => (
198
+ <div key={source.name} className="bg-red-500/10 border border-red-500/30 rounded-lg p-3">
199
+ <div className="flex items-start gap-2">
200
+ <AlertTriangle className="h-4 w-4 text-red-400 mt-0.5 shrink-0" />
201
+ <div className="text-sm">
202
+ <span className="font-medium text-red-400 capitalize">{source.name}</span>
203
+ <span className="text-theme-text-secondary"> detection failed: </span>
204
+ <span className="text-theme-text-tertiary">{source.message}</span>
205
+ </div>
206
+ </div>
207
+ </div>
208
+ ))}
209
+
210
+ {/* Recommendation */}
211
+ {recommendation && (
212
+ <div className="space-y-4">
213
+ {/* Primary option */}
214
+ <div className="border border-skyhook-500/30 bg-skyhook-500/5 rounded-lg p-4 space-y-3">
215
+ <div className="flex items-start gap-2">
216
+ <span className="badge btn-brand">
217
+ Recommended
218
+ </span>
219
+ <span className="font-medium capitalize text-theme-text-primary">{recommendation.name}</span>
220
+ </div>
221
+ <p className="text-sm text-theme-text-secondary">{recommendation.reason}</p>
222
+
223
+ {/* Helm install button if chart info available */}
224
+ {recommendation.helmChart ? (
225
+ <button
226
+ onClick={() => setShowHelmInstall(true)}
227
+ className="w-full flex items-center justify-center gap-2 px-4 py-2 text-sm font-medium rounded btn-brand"
228
+ >
229
+ <Package className="h-4 w-4" />
230
+ Install {recommendation.name} with Helm
231
+ </button>
232
+ ) : (
233
+ <button
234
+ onClick={() => setStep('install')}
235
+ className="w-full flex items-center justify-center gap-1 px-4 py-2 text-sm font-medium rounded btn-brand"
236
+ >
237
+ View install instructions
238
+ <ArrowRight className="h-4 w-4" />
239
+ </button>
240
+ )}
241
+
242
+ {/* Documentation link */}
243
+ {recommendation.docsUrl && (
244
+ <a
245
+ href={recommendation.docsUrl}
246
+ target="_blank"
247
+ rel="noopener noreferrer"
248
+ className="inline-flex items-center gap-1 text-sm text-blue-400 hover:underline"
249
+ >
250
+ View documentation
251
+ <ExternalLink className="h-4 w-4" />
252
+ </a>
253
+ )}
254
+ </div>
255
+
256
+ {/* Alternative option (if available) */}
257
+ {recommendation.alternativeName && (
258
+ <div className="border border-theme-border rounded-lg p-4 space-y-3">
259
+ <div className="flex items-start gap-2">
260
+ <span className="badge bg-theme-elevated text-theme-text-secondary">
261
+ Alternative
262
+ </span>
263
+ <span className="font-medium capitalize text-theme-text-primary">{recommendation.alternativeName}</span>
264
+ </div>
265
+ <p className="text-sm text-theme-text-secondary">{recommendation.alternativeReason}</p>
266
+ {recommendation.alternativeDocsUrl && (
267
+ <a
268
+ href={recommendation.alternativeDocsUrl}
269
+ target="_blank"
270
+ rel="noopener noreferrer"
271
+ className="inline-flex items-center gap-1 text-sm text-blue-400 hover:underline"
272
+ >
273
+ Learn more about {recommendation.alternativeName}
274
+ <ExternalLink className="h-4 w-4" />
275
+ </a>
276
+ )}
277
+ </div>
278
+ )}
279
+ </div>
280
+ )}
281
+
282
+ {/* No recommendation */}
283
+ {!recommendation && (
284
+ <div className="border border-theme-border rounded-lg p-4 space-y-3">
285
+ <p className="text-sm text-theme-text-secondary">
286
+ No traffic source detected. Install Cilium with Hubble for traffic visibility.
287
+ </p>
288
+ <a
289
+ href="https://docs.cilium.io/en/stable/gettingstarted/hubble/"
290
+ target="_blank"
291
+ rel="noopener noreferrer"
292
+ className="inline-flex items-center gap-1 px-3 py-2 text-sm rounded border border-theme-border text-theme-text-primary hover:bg-theme-hover transition-colors"
293
+ >
294
+ View Hubble Documentation
295
+ <ExternalLink className="h-4 w-4" />
296
+ </a>
297
+ </div>
298
+ )}
299
+ </div>
300
+ </div>
301
+ {helmInstallOverlay}
302
+ </>
303
+ )
304
+ }
305
+
306
+ // Step 2: Install instructions (for non-Helm installs like gcloud commands)
307
+ return (
308
+ <>
309
+ <div className="flex items-center justify-center h-full w-full">
310
+ <div className="max-w-lg w-full p-6 space-y-6">
311
+ <div className="space-y-2">
312
+ <h2 className="text-lg font-medium text-theme-text-primary">Enable {recommendation?.name || 'Hubble'}</h2>
313
+ <p className="text-sm text-theme-text-secondary">
314
+ Run the following command to enable traffic observability
315
+ </p>
316
+ </div>
317
+
318
+ {/* Install command */}
319
+ <div className="bg-theme-elevated rounded-lg p-4 space-y-3">
320
+ <div className="flex items-center justify-between">
321
+ <span className="text-xs font-medium text-theme-text-tertiary">Command</span>
322
+ <button
323
+ onClick={() => copyCommand(recommendation?.installCommand || '')}
324
+ className="p-1 rounded text-theme-text-secondary hover:text-theme-text-primary hover:bg-theme-hover transition-colors"
325
+ >
326
+ {copied ? (
327
+ <CheckCircle2 className="h-4 w-4 text-green-500" />
328
+ ) : (
329
+ <Copy className="h-4 w-4" />
330
+ )}
331
+ </button>
332
+ </div>
333
+ <pre className="text-sm font-mono whitespace-pre-wrap break-all bg-theme-surface rounded p-3 overflow-x-auto text-theme-text-primary">
334
+ {recommendation?.installCommand || 'No command available'}
335
+ </pre>
336
+ </div>
337
+
338
+ {/* Platform-specific notes */}
339
+ {cluster?.platform === 'gke' && cluster?.cni === 'cilium' && (
340
+ <div className="bg-skyhook-500/10 border border-skyhook-500/20 rounded-lg p-4 text-sm">
341
+ <p className="text-blue-400 font-medium">GKE Dataplane V2</p>
342
+ <p className="text-theme-text-secondary mt-1">
343
+ Your cluster uses Cilium natively. The command above enables the Hubble
344
+ observability layer which provides traffic visibility without any performance impact.
345
+ </p>
346
+ </div>
347
+ )}
348
+
349
+ {/* Documentation link */}
350
+ {recommendation?.docsUrl && (
351
+ <a
352
+ href={recommendation.docsUrl}
353
+ target="_blank"
354
+ rel="noopener noreferrer"
355
+ className="flex items-center gap-2 text-sm text-blue-400 hover:underline"
356
+ >
357
+ View full documentation
358
+ <ExternalLink className="h-4 w-4" />
359
+ </a>
360
+ )}
361
+
362
+ {/* Action buttons */}
363
+ <div className="flex gap-2">
364
+ <button
365
+ onClick={() => setStep('choice')}
366
+ className="flex items-center gap-1 px-3 py-2 text-sm rounded border border-theme-border text-theme-text-primary hover:bg-theme-hover transition-colors"
367
+ >
368
+ <ArrowLeft className="h-4 w-4" />
369
+ Back
370
+ </button>
371
+ <button
372
+ onClick={() => {
373
+ setState('checking')
374
+ setLastChecked(null)
375
+ }}
376
+ className="flex-1 px-4 py-2 text-sm font-medium rounded btn-brand"
377
+ >
378
+ I've run the command
379
+ </button>
380
+ </div>
381
+ </div>
382
+ </div>
383
+ {helmInstallOverlay}
384
+ </>
385
+ )
386
+ }
@@ -0,0 +1,3 @@
1
+ export { TrafficView } from './TrafficView'
2
+ export { TrafficWizard } from './TrafficWizard'
3
+ export { TrafficGraph } from './TrafficGraph'
@@ -0,0 +1,8 @@
1
+ import { type ComponentProps } from 'react'
2
+ import { CodeViewer as BaseCodeViewer } from '@skyhook-io/k8s-ui'
3
+ import { useTheme } from '../../context/ThemeContext'
4
+
5
+ export function CodeViewer(props: Omit<ComponentProps<typeof BaseCodeViewer>, 'theme'>) {
6
+ const { theme } = useTheme()
7
+ return <BaseCodeViewer {...props} theme={theme} />
8
+ }