@skyhook-io/radar-app 1.14.5 → 1.15.0
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/README.md +2 -9
- package/package.json +6 -6
- package/src/App.tsx +142 -334
- package/src/RadarApp.tsx +3 -8
- package/src/api/client.admission.test.ts +34 -0
- package/src/api/client.jobset.test.ts +18 -0
- package/src/api/client.resource-identity.test.ts +44 -0
- package/src/api/client.rightsizing.test.ts +7 -3
- package/src/api/client.ts +267 -78
- package/src/api/preferences.test.ts +54 -0
- package/src/api/preferences.ts +38 -0
- package/src/api/usage-data.fixtures.ts +33 -0
- package/src/api/usage-data.ts +165 -0
- package/src/components/CloudFunnelButton.test.tsx +155 -0
- package/src/components/CloudFunnelButton.tsx +113 -63
- package/src/components/ContextSwitcher.tsx +13 -132
- package/src/components/SelfManagedStart.tsx +96 -0
- package/src/components/applications/ApplicationsView.identity.test.ts +39 -0
- package/src/components/applications/ApplicationsView.tsx +5 -3
- package/src/components/audit/AuditSettingsDialog.tsx +15 -11
- package/src/components/cloudConnectHandoff.test.ts +1 -1
- package/src/components/cloudConnectHandoff.ts +1 -1
- package/src/components/diagnose/ActivityTurn.tsx +3 -2
- package/src/components/diagnose/AgentControls.tsx +26 -3
- package/src/components/diagnose/ApplyDialog.tsx +4 -2
- package/src/components/diagnose/DiagnoseContext.tsx +1 -0
- package/src/components/diagnose/agentCatalog.ts +6 -0
- package/src/components/diagnose/launch.test.ts +23 -0
- package/src/components/diagnose/launch.ts +4 -0
- package/src/components/diagnose/parts.test.tsx +18 -0
- package/src/components/dialog-names.test.ts +69 -0
- package/src/components/dock/NodeTerminalTab.test.tsx +34 -0
- package/src/components/dock/NodeTerminalTab.tsx +5 -3
- package/src/components/dock/WorkloadLogsTab.test.tsx +66 -0
- package/src/components/dock/WorkloadLogsTab.tsx +2 -1
- package/src/components/execution/BatchExecutionView.render.test.tsx +2 -1
- package/src/components/execution/BatchExecutionView.test.ts +52 -1
- package/src/components/execution/BatchExecutionView.tsx +324 -65
- package/src/components/execution/JobSetAdmission.test.tsx +165 -0
- package/src/components/execution/JobSetAdmission.tsx +26 -0
- package/src/components/execution/JobSetMemberComparison.test.tsx +30 -0
- package/src/components/execution/JobSetMemberComparison.tsx +88 -0
- package/src/components/execution/batch-run-actions.test.ts +1 -0
- package/src/components/execution/batch-timeline.test.ts +3 -0
- package/src/components/execution/execution-definition.test.ts +15 -1
- package/src/components/execution/execution-definition.ts +4 -0
- package/src/components/execution/member-collection.render.test.tsx +142 -0
- package/src/components/gitops/GitOpsView.tsx +33 -2
- package/src/components/gitops/destination-toast.test.ts +33 -0
- package/src/components/gitops/destination-toast.ts +46 -0
- package/src/components/gitops/useDestinationCluster.ts +30 -0
- package/src/components/helm/TrackChartSourceDialog.tsx +25 -14
- package/src/components/home/HomeView.tsx +6 -2
- package/src/components/home/MCPSetupDialog.tsx +10 -0
- package/src/components/home/RadarVersionLine.test.tsx +14 -0
- package/src/components/home/RadarVersionLine.tsx +28 -3
- package/src/components/logs/ScheduledWorkloadLogsViewer.tsx +75 -22
- package/src/components/logs/WorkloadLogsViewer.tsx +7 -4
- package/src/components/nav/PrimaryNavRail.test.tsx +10 -1
- package/src/components/nav/PrimaryNavRail.tsx +27 -8
- package/src/components/resource/PVCUsageBar.render.test.tsx +168 -0
- package/src/components/resource/PVCUsageBar.tsx +62 -16
- package/src/components/resource/PrometheusChartsGrid.render.test.tsx +1 -1
- package/src/components/resources/ResourcesView.tsx +3 -3
- package/src/components/resources/renderers/CAPIClusterRenderer.tsx +8 -0
- package/src/components/resources/renderers/JobAdmissionRenderers.test.tsx +18 -0
- package/src/components/resources/renderers/JobAdmissionRenderers.tsx +18 -0
- package/src/components/resources/renderers/KueueWorkloadRenderer.test.tsx +39 -0
- package/src/components/resources/renderers/KueueWorkloadRenderer.tsx +37 -0
- package/src/components/resources/renderers/RayClusterRenderer.test.tsx +18 -0
- package/src/components/resources/renderers/RayClusterRenderer.tsx +17 -0
- package/src/components/resources/renderers/RayJobRenderer.test.tsx +40 -0
- package/src/components/resources/renderers/RayJobRenderer.tsx +45 -0
- package/src/components/resources/renderers/RayServiceRenderer.test.tsx +69 -0
- package/src/components/resources/renderers/RayServiceRenderer.tsx +38 -0
- package/src/components/rightsizing/RightsizingScanView.tsx +34 -22
- package/src/components/rightsizing/copy.test.ts +7 -0
- package/src/components/rightsizing/model.test.ts +2 -1
- package/src/components/rightsizing/notices.test.tsx +4 -3
- package/src/components/settings/OperatorManagedNotice.tsx +17 -0
- package/src/components/settings/PrivacySection.test.tsx +84 -0
- package/src/components/settings/PrivacySection.tsx +140 -0
- package/src/components/settings/SettingsDialog.tsx +168 -92
- package/src/components/settings/controls.tsx +55 -0
- package/src/components/settings/settings-state.test.ts +18 -0
- package/src/components/settings/settings-state.ts +19 -0
- package/src/components/timeline/TimelineView.tsx +9 -3
- package/src/components/timeline/TimelineView.urlparams.test.ts +18 -1
- package/src/components/ui/ErrorBoundary.tsx +5 -0
- package/src/components/ui/Omnibar.tsx +16 -0
- package/src/components/ui/UpdateNotification.tsx +13 -9
- package/src/components/ui/command-items.ts +14 -3
- package/src/components/usage-data/UsageDataAsk.test.tsx +41 -0
- package/src/components/usage-data/UsageDataAsk.tsx +106 -0
- package/src/components/usage-data/UsageDataPrompt.test.ts +53 -0
- package/src/components/usage-data/UsageDataPrompt.tsx +148 -0
- package/src/components/useContextSwitchFlow.tsx +147 -0
- package/src/components/whats-new/WhatsNew.test.ts +110 -0
- package/src/components/whats-new/WhatsNew.tsx +423 -0
- package/src/components/whats-new/WhatsNewDialog.test.tsx +229 -0
- package/src/components/whats-new/check-whats-new.test.ts +65 -0
- package/src/components/whats-new/releaseNotes.ts +121 -0
- package/src/components/workload/WorkloadView.test.ts +17 -1
- package/src/components/workload/WorkloadView.tsx +47 -19
- package/src/context/ContextSwitchContext.tsx +18 -2
- package/src/context/NavCustomization.tsx +4 -58
- package/src/context/ThemeContext.tsx +3 -11
- package/src/hooks/useClusterLoadState.ts +2 -2
- package/src/hooks/useFavorites.ts +3 -5
- package/src/k8s-ui-exports.test.ts +73 -0
- package/src/utils/auditBadges.ts +1 -1
- package/src/utils/navigation.test.ts +34 -1
- package/src/utils/navigation.ts +28 -5
- package/src/utils/topology-selection.test.ts +56 -0
- package/src/utils/topology-selection.ts +9 -9
- package/src/utils/version.ts +11 -0
- package/src/components/ui/CommandPalette.tsx +0 -261
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react'
|
|
2
|
+
import { ExternalLink } from 'lucide-react'
|
|
3
|
+
import { Collapse, CollapseChevron, useDisclosure } from '@skyhook-io/k8s-ui/components/ui/Collapse'
|
|
4
|
+
import { ConfigToggle, SubHeading } from './controls'
|
|
5
|
+
import { isRecording, useSetUsageData, useUsageData, type UsageDataStatus } from '../../api/usage-data'
|
|
6
|
+
|
|
7
|
+
const DOCS_URL = 'https://radarhq.io/docs/configuration/usage-stats'
|
|
8
|
+
|
|
9
|
+
export function PrivacySection({ active }: { active: boolean }) {
|
|
10
|
+
const { data: status, isLoading, error, refetch } = useUsageData(active, { fresh: true })
|
|
11
|
+
const setUsageData = useSetUsageData()
|
|
12
|
+
|
|
13
|
+
// The pane stays mounted while hidden, so refetch each time it is revealed.
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (active) void refetch()
|
|
16
|
+
}, [active, refetch])
|
|
17
|
+
|
|
18
|
+
if (isLoading) {
|
|
19
|
+
return <p className="text-sm text-theme-text-tertiary">Loading…</p>
|
|
20
|
+
}
|
|
21
|
+
if (error || !status) {
|
|
22
|
+
return <p className="text-sm text-theme-text-secondary">Couldn't load privacy settings.</p>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const recording = isRecording(status)
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div className="space-y-6">
|
|
29
|
+
<p className="text-sm text-theme-text-secondary">
|
|
30
|
+
{status.preview.mode === 'in-cluster' || status.preview.mode === 'cloud'
|
|
31
|
+
? 'Radar reads this cluster from inside it and keeps what it reads there.'
|
|
32
|
+
: 'Radar reads your cluster from this machine and keeps what it reads here.'}
|
|
33
|
+
</p>
|
|
34
|
+
|
|
35
|
+
<section className="space-y-3">
|
|
36
|
+
<SubHeading>Usage stats</SubHeading>
|
|
37
|
+
<ConfigToggle
|
|
38
|
+
label="Send anonymous usage stats"
|
|
39
|
+
description={<>Shows us which features get used, so we know what to build next.<br />Sent straight to us, with no third-party trackers.</>}
|
|
40
|
+
value={recording}
|
|
41
|
+
disabled={!status.canChange || setUsageData.isPending}
|
|
42
|
+
onChange={(v) => setUsageData.mutate(v)}
|
|
43
|
+
/>
|
|
44
|
+
<dl className="grid grid-cols-[auto_1fr] gap-x-3 gap-y-1.5 text-xs">
|
|
45
|
+
<dt className="text-theme-text-tertiary">What's sent</dt>
|
|
46
|
+
<dd className="text-theme-text-secondary">
|
|
47
|
+
The views you open, the actions and MCP tools you use, and each cluster's version,
|
|
48
|
+
platform, size range and known integrations.
|
|
49
|
+
</dd>
|
|
50
|
+
<dt className="text-theme-text-tertiary">What isn't</dt>
|
|
51
|
+
<dd className="text-theme-text-secondary">
|
|
52
|
+
Names, contents, logs, identifiers, timestamps, or the resources in your clusters.
|
|
53
|
+
</dd>
|
|
54
|
+
</dl>
|
|
55
|
+
<ManagedReason status={status} />
|
|
56
|
+
<SharedNote status={status} />
|
|
57
|
+
<ReportPreview status={status} />
|
|
58
|
+
</section>
|
|
59
|
+
|
|
60
|
+
</div>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function ManagedReason({ status }: { status: UsageDataStatus }) {
|
|
65
|
+
let text: string | null = null
|
|
66
|
+
switch (status.source) {
|
|
67
|
+
case 'env':
|
|
68
|
+
text = status.shared && status.preview.mode === 'in-cluster'
|
|
69
|
+
? 'Set for everyone by the Helm value usageReporting.enabled.'
|
|
70
|
+
: `Set by RADAR_USAGE_REPORTING=${status.state}.`
|
|
71
|
+
break
|
|
72
|
+
case 'deployment':
|
|
73
|
+
text = 'Radar Cloud manages usage data for this installation.'
|
|
74
|
+
break
|
|
75
|
+
}
|
|
76
|
+
if (!text && status.developmentBuild && isRecording(status)) {
|
|
77
|
+
text = 'Development build: reports go to the log, never sent.'
|
|
78
|
+
}
|
|
79
|
+
return text ? <p className="text-xs text-theme-text-tertiary">{text}</p> : null
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// A shared Radar is decided by its configuration; say where, while nothing set it.
|
|
83
|
+
function SharedNote({ status }: { status: UsageDataStatus }) {
|
|
84
|
+
if (!status.shared || status.source !== 'default') return null
|
|
85
|
+
return (
|
|
86
|
+
<p className="text-xs text-theme-text-tertiary">
|
|
87
|
+
Applies to everyone using this Radar. Set it with{' '}
|
|
88
|
+
{status.preview.mode === 'in-cluster'
|
|
89
|
+
? <>the Helm value <code className="inline-code">usageReporting.enabled</code></>
|
|
90
|
+
: <code className="inline-code">RADAR_USAGE_REPORTING=on</code>}.
|
|
91
|
+
</p>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function ReportPreview({ status }: { status: UsageDataStatus }) {
|
|
96
|
+
const recording = isRecording(status)
|
|
97
|
+
const [open, setOpen] = useState(false)
|
|
98
|
+
const disclosure = useDisclosure(open)
|
|
99
|
+
// Development builds write the report to the log instead of sending it.
|
|
100
|
+
const logsOnly = status.developmentBuild
|
|
101
|
+
const next = status.nextReportAt ? new Date(status.nextReportAt) : null
|
|
102
|
+
return (
|
|
103
|
+
<div className="space-y-1.5">
|
|
104
|
+
<div className="flex items-center justify-between gap-3">
|
|
105
|
+
<button
|
|
106
|
+
type="button"
|
|
107
|
+
onClick={() => setOpen(o => !o)}
|
|
108
|
+
{...disclosure.buttonProps}
|
|
109
|
+
className="flex items-center gap-1 text-xs font-medium text-theme-text-secondary hover:text-theme-text-primary"
|
|
110
|
+
>
|
|
111
|
+
<CollapseChevron open={open} />
|
|
112
|
+
{recording ? 'See the next report' : 'See an example report'}
|
|
113
|
+
{recording && next && (
|
|
114
|
+
<span className="font-normal text-theme-text-tertiary">
|
|
115
|
+
{' '}· {logsOnly ? 'logs' : 'sends'} {next.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })}
|
|
116
|
+
</span>
|
|
117
|
+
)}
|
|
118
|
+
</button>
|
|
119
|
+
<a
|
|
120
|
+
href={DOCS_URL}
|
|
121
|
+
target="_blank"
|
|
122
|
+
rel="noopener noreferrer"
|
|
123
|
+
className="inline-flex items-center gap-1 text-xs text-theme-text-secondary hover:text-theme-text-primary hover:underline"
|
|
124
|
+
>
|
|
125
|
+
How it works <ExternalLink className="w-3 h-3" aria-hidden />
|
|
126
|
+
</a>
|
|
127
|
+
</div>
|
|
128
|
+
<Collapse open={open} id={disclosure.panelId}>
|
|
129
|
+
<pre className="max-h-80 overflow-auto rounded-md border border-theme-border bg-theme-elevated px-3 py-2 text-[11px] leading-relaxed font-mono text-theme-text-primary">
|
|
130
|
+
{JSON.stringify(status.preview, null, 2)}
|
|
131
|
+
</pre>
|
|
132
|
+
</Collapse>
|
|
133
|
+
{recording && status.canChange && (
|
|
134
|
+
<p className="text-xs text-theme-text-tertiary">
|
|
135
|
+
Waiting in <code className="inline-code">~/.radar/usage-report.json</code>. Turning this off deletes it.
|
|
136
|
+
</p>
|
|
137
|
+
)}
|
|
138
|
+
</div>
|
|
139
|
+
)
|
|
140
|
+
}
|