@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.
- package/package.json +2 -2
- package/src/App.tsx +81 -18
- package/src/api/client.ts +200 -26
- package/src/api/rbac.ts +57 -0
- package/src/components/compare/CompareViewRoute.tsx +116 -0
- package/src/components/compare/useCompareCandidates.ts +27 -0
- package/src/components/compare/useCompareLauncher.tsx +76 -0
- package/src/components/cost/CostView.tsx +1 -1
- package/src/components/gitops/GitOpsView.tsx +258 -1862
- package/src/components/helm/ChartBrowser.tsx +61 -10
- package/src/components/helm/HelmView.tsx +28 -11
- package/src/components/helm/InstallWizard.tsx +5 -5
- package/src/components/helm/ManifestDiffViewer.tsx +1 -1
- package/src/components/helm/ValuesViewer.tsx +3 -39
- package/src/components/helm/helm-utils.ts +4 -0
- package/src/components/home/HomeView.tsx +18 -2
- package/src/components/resource/HPACharts.tsx +232 -0
- package/src/components/resource/PVCUsageBar.tsx +59 -0
- package/src/components/resource/PrometheusCharts.tsx +151 -434
- package/src/components/resource/PrometheusChartsGrid.tsx +339 -0
- package/src/components/resource/RestartChart.tsx +124 -0
- package/src/components/resource/RightsizingStrip.tsx +167 -0
- package/src/components/resources/CompositeRenderer.tsx +101 -0
- package/src/components/resources/renderers/HPARenderer.tsx +17 -1
- package/src/components/resources/renderers/NamespaceRenderer.tsx +22 -0
- package/src/components/resources/renderers/PVCRenderer.tsx +19 -1
- package/src/components/resources/renderers/PodRenderer.tsx +13 -0
- package/src/components/resources/renderers/RoleBindingRenderer.tsx +43 -1
- package/src/components/resources/renderers/RoleRenderer.tsx +27 -1
- package/src/components/resources/renderers/ServiceAccountRenderer.tsx +28 -1
- package/src/components/resources/renderers/WorkloadRenderer.tsx +12 -0
- package/src/components/resources/renderers/index.ts +1 -0
- package/src/components/settings/MyPermissionsDialog.tsx +231 -0
- package/src/components/ui/DiagnosticsOverlay.tsx +1 -0
- package/src/components/workload/WorkloadView.tsx +107 -3
- package/src/context/NavCustomization.tsx +13 -0
- package/src/contexts/CapabilitiesContext.tsx +8 -3
- package/src/components/gitops/RollbackDialog.tsx +0 -107
- 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-
|
|
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">
|