@skyhook-io/radar-app 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/package.json +2 -2
  2. package/src/App.tsx +81 -18
  3. package/src/api/client.ts +200 -26
  4. package/src/api/rbac.ts +57 -0
  5. package/src/components/compare/CompareViewRoute.tsx +116 -0
  6. package/src/components/compare/useCompareCandidates.ts +27 -0
  7. package/src/components/compare/useCompareLauncher.tsx +76 -0
  8. package/src/components/cost/CostView.tsx +1 -1
  9. package/src/components/gitops/GitOpsView.tsx +258 -1862
  10. package/src/components/helm/ChartBrowser.tsx +61 -10
  11. package/src/components/helm/HelmView.tsx +28 -11
  12. package/src/components/helm/InstallWizard.tsx +5 -5
  13. package/src/components/helm/ManifestDiffViewer.tsx +1 -1
  14. package/src/components/helm/ValuesViewer.tsx +3 -39
  15. package/src/components/helm/helm-utils.ts +4 -0
  16. package/src/components/home/HomeView.tsx +18 -2
  17. package/src/components/resource/HPACharts.tsx +232 -0
  18. package/src/components/resource/PVCUsageBar.tsx +59 -0
  19. package/src/components/resource/PrometheusCharts.tsx +151 -434
  20. package/src/components/resource/PrometheusChartsGrid.tsx +339 -0
  21. package/src/components/resource/RestartChart.tsx +124 -0
  22. package/src/components/resource/RightsizingStrip.tsx +167 -0
  23. package/src/components/resources/CompositeRenderer.tsx +101 -0
  24. package/src/components/resources/renderers/HPARenderer.tsx +17 -1
  25. package/src/components/resources/renderers/NamespaceRenderer.tsx +22 -0
  26. package/src/components/resources/renderers/PVCRenderer.tsx +19 -1
  27. package/src/components/resources/renderers/PodRenderer.tsx +13 -0
  28. package/src/components/resources/renderers/RoleBindingRenderer.tsx +43 -1
  29. package/src/components/resources/renderers/RoleRenderer.tsx +27 -1
  30. package/src/components/resources/renderers/ServiceAccountRenderer.tsx +28 -1
  31. package/src/components/resources/renderers/WorkloadRenderer.tsx +12 -0
  32. package/src/components/resources/renderers/index.ts +1 -0
  33. package/src/components/settings/MyPermissionsDialog.tsx +231 -0
  34. package/src/components/ui/DiagnosticsOverlay.tsx +1 -0
  35. package/src/components/workload/WorkloadView.tsx +107 -3
  36. package/src/context/NavCustomization.tsx +13 -0
  37. package/src/contexts/CapabilitiesContext.tsx +8 -3
  38. package/src/components/gitops/RollbackDialog.tsx +0 -107
  39. package/src/components/gitops/SyncOptionsDialog.tsx +0 -144
@@ -0,0 +1,27 @@
1
+ import { useMemo } from 'react'
2
+ import type { CompareResourceRef } from '@skyhook-io/k8s-ui'
3
+ import { useResources } from '../../api/client'
4
+
5
+ /**
6
+ * Fetch candidates for the compare picker — same kind as the source.
7
+ * Pass `enabled=false` when the picker is closed to avoid hitting the API.
8
+ */
9
+ export function useCompareCandidates(kind: string, group: string | undefined, enabled: boolean) {
10
+ const query = useResources<{ metadata?: { name?: string; namespace?: string } }>(
11
+ enabled ? kind : '',
12
+ undefined,
13
+ group,
14
+ )
15
+ const candidates: CompareResourceRef[] = useMemo(() => {
16
+ if (!query.data) return []
17
+ return query.data
18
+ .filter(r => r?.metadata?.name)
19
+ .map(r => ({
20
+ kind,
21
+ namespace: r.metadata?.namespace ?? '',
22
+ name: r.metadata!.name!,
23
+ group,
24
+ }))
25
+ }, [query.data, kind, group])
26
+ return { candidates, isPending: query.isPending, error: query.error }
27
+ }
@@ -0,0 +1,76 @@
1
+ import { useCallback, useState } from 'react'
2
+ import { useNavigate } from 'react-router-dom'
3
+ import { CompareResourcePicker, refToParam, type CompareResourceRef } from '@skyhook-io/k8s-ui'
4
+ import { useCompareCandidates } from './useCompareCandidates'
5
+ import { useNavCustomization } from '../../context/NavCustomization'
6
+
7
+ interface UseCompareLauncherArgs {
8
+ /** API plural kind (e.g. "deployments") — must match the route segment used by `/api/resources/{kind}`. */
9
+ kind: string
10
+ namespace: string
11
+ name: string
12
+ /** API group for the resource — required for CRDs that collide with core kinds. */
13
+ group?: string
14
+ }
15
+
16
+ interface CompareLauncher {
17
+ /** Wire this to ResourceActionsBar's `onCompareTo` prop. */
18
+ onCompareTo: () => void
19
+ /**
20
+ * Wire this to ResourceActionsBar's `onCompareAcrossClusters` prop. Undefined
21
+ * when the host (NavCustomization.crossClusterCompareHref) hasn't opted in
22
+ * — keeps the standalone Radar experience identical.
23
+ */
24
+ onCompareAcrossClusters?: () => void
25
+ /** Render this anywhere in the same tree to surface the picker dialog. */
26
+ picker: React.ReactNode
27
+ }
28
+
29
+ export function useCompareLauncher({ kind, namespace, name, group }: UseCompareLauncherArgs): CompareLauncher {
30
+ const navigate = useNavigate()
31
+ const [open, setOpen] = useState(false)
32
+ const kindLower = kind.toLowerCase()
33
+ const { candidates, isPending, error } = useCompareCandidates(kindLower, group, open)
34
+ const { crossClusterCompareHref } = useNavCustomization()
35
+
36
+ const onCompareTo = useCallback(() => setOpen(true), [])
37
+
38
+ const onCompareAcrossClusters = useCallback(() => {
39
+ if (!crossClusterCompareHref) return
40
+ const href = crossClusterCompareHref({ kind: kindLower, namespace, name, group })
41
+ window.location.assign(href)
42
+ }, [crossClusterCompareHref, kindLower, namespace, name, group])
43
+
44
+ const handlePick = useCallback(
45
+ (picked: CompareResourceRef) => {
46
+ setOpen(false)
47
+ const params = new URLSearchParams()
48
+ params.set('kind', kindLower)
49
+ if (group) params.set('apiGroup', group)
50
+ params.set('a', refToParam({ namespace, name }))
51
+ params.set('b', refToParam({ namespace: picked.namespace, name: picked.name }))
52
+ navigate({ pathname: '/compare', search: params.toString() })
53
+ },
54
+ [navigate, kindLower, group, namespace, name],
55
+ )
56
+
57
+ const source: CompareResourceRef = { kind: kindLower, namespace, name, group }
58
+
59
+ const picker = (
60
+ <CompareResourcePicker
61
+ open={open}
62
+ onClose={() => setOpen(false)}
63
+ source={source}
64
+ candidates={candidates}
65
+ loading={open && isPending}
66
+ error={open ? error : null}
67
+ onPick={handlePick}
68
+ />
69
+ )
70
+
71
+ return {
72
+ onCompareTo,
73
+ onCompareAcrossClusters: crossClusterCompareHref ? onCompareAcrossClusters : undefined,
74
+ picker,
75
+ }
76
+ }
@@ -417,7 +417,7 @@ function CostHelpDialog({ onClose }: { onClose: () => void }) {
417
417
  return (
418
418
  <div className="fixed inset-0 z-50 flex items-center justify-center">
419
419
  <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" onClick={onClose} />
420
- <div className="relative dialog max-w-lg w-full mx-4 max-h-[80vh] overflow-y-auto">
420
+ <div className="relative dialog max-w-2xl w-full mx-4 max-h-[80vh] overflow-y-auto">
421
421
  {/* Header */}
422
422
  <div className="flex items-center justify-between p-4 border-b border-theme-border sticky top-0 bg-theme-surface rounded-t-lg">
423
423
  <div className="flex items-center gap-2">