@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.
Files changed (117) hide show
  1. package/README.md +2 -9
  2. package/package.json +6 -6
  3. package/src/App.tsx +142 -334
  4. package/src/RadarApp.tsx +3 -8
  5. package/src/api/client.admission.test.ts +34 -0
  6. package/src/api/client.jobset.test.ts +18 -0
  7. package/src/api/client.resource-identity.test.ts +44 -0
  8. package/src/api/client.rightsizing.test.ts +7 -3
  9. package/src/api/client.ts +267 -78
  10. package/src/api/preferences.test.ts +54 -0
  11. package/src/api/preferences.ts +38 -0
  12. package/src/api/usage-data.fixtures.ts +33 -0
  13. package/src/api/usage-data.ts +165 -0
  14. package/src/components/CloudFunnelButton.test.tsx +155 -0
  15. package/src/components/CloudFunnelButton.tsx +113 -63
  16. package/src/components/ContextSwitcher.tsx +13 -132
  17. package/src/components/SelfManagedStart.tsx +96 -0
  18. package/src/components/applications/ApplicationsView.identity.test.ts +39 -0
  19. package/src/components/applications/ApplicationsView.tsx +5 -3
  20. package/src/components/audit/AuditSettingsDialog.tsx +15 -11
  21. package/src/components/cloudConnectHandoff.test.ts +1 -1
  22. package/src/components/cloudConnectHandoff.ts +1 -1
  23. package/src/components/diagnose/ActivityTurn.tsx +3 -2
  24. package/src/components/diagnose/AgentControls.tsx +26 -3
  25. package/src/components/diagnose/ApplyDialog.tsx +4 -2
  26. package/src/components/diagnose/DiagnoseContext.tsx +1 -0
  27. package/src/components/diagnose/agentCatalog.ts +6 -0
  28. package/src/components/diagnose/launch.test.ts +23 -0
  29. package/src/components/diagnose/launch.ts +4 -0
  30. package/src/components/diagnose/parts.test.tsx +18 -0
  31. package/src/components/dialog-names.test.ts +69 -0
  32. package/src/components/dock/NodeTerminalTab.test.tsx +34 -0
  33. package/src/components/dock/NodeTerminalTab.tsx +5 -3
  34. package/src/components/dock/WorkloadLogsTab.test.tsx +66 -0
  35. package/src/components/dock/WorkloadLogsTab.tsx +2 -1
  36. package/src/components/execution/BatchExecutionView.render.test.tsx +2 -1
  37. package/src/components/execution/BatchExecutionView.test.ts +52 -1
  38. package/src/components/execution/BatchExecutionView.tsx +324 -65
  39. package/src/components/execution/JobSetAdmission.test.tsx +165 -0
  40. package/src/components/execution/JobSetAdmission.tsx +26 -0
  41. package/src/components/execution/JobSetMemberComparison.test.tsx +30 -0
  42. package/src/components/execution/JobSetMemberComparison.tsx +88 -0
  43. package/src/components/execution/batch-run-actions.test.ts +1 -0
  44. package/src/components/execution/batch-timeline.test.ts +3 -0
  45. package/src/components/execution/execution-definition.test.ts +15 -1
  46. package/src/components/execution/execution-definition.ts +4 -0
  47. package/src/components/execution/member-collection.render.test.tsx +142 -0
  48. package/src/components/gitops/GitOpsView.tsx +33 -2
  49. package/src/components/gitops/destination-toast.test.ts +33 -0
  50. package/src/components/gitops/destination-toast.ts +46 -0
  51. package/src/components/gitops/useDestinationCluster.ts +30 -0
  52. package/src/components/helm/TrackChartSourceDialog.tsx +25 -14
  53. package/src/components/home/HomeView.tsx +6 -2
  54. package/src/components/home/MCPSetupDialog.tsx +10 -0
  55. package/src/components/home/RadarVersionLine.test.tsx +14 -0
  56. package/src/components/home/RadarVersionLine.tsx +28 -3
  57. package/src/components/logs/ScheduledWorkloadLogsViewer.tsx +75 -22
  58. package/src/components/logs/WorkloadLogsViewer.tsx +7 -4
  59. package/src/components/nav/PrimaryNavRail.test.tsx +10 -1
  60. package/src/components/nav/PrimaryNavRail.tsx +27 -8
  61. package/src/components/resource/PVCUsageBar.render.test.tsx +168 -0
  62. package/src/components/resource/PVCUsageBar.tsx +62 -16
  63. package/src/components/resource/PrometheusChartsGrid.render.test.tsx +1 -1
  64. package/src/components/resources/ResourcesView.tsx +3 -3
  65. package/src/components/resources/renderers/CAPIClusterRenderer.tsx +8 -0
  66. package/src/components/resources/renderers/JobAdmissionRenderers.test.tsx +18 -0
  67. package/src/components/resources/renderers/JobAdmissionRenderers.tsx +18 -0
  68. package/src/components/resources/renderers/KueueWorkloadRenderer.test.tsx +39 -0
  69. package/src/components/resources/renderers/KueueWorkloadRenderer.tsx +37 -0
  70. package/src/components/resources/renderers/RayClusterRenderer.test.tsx +18 -0
  71. package/src/components/resources/renderers/RayClusterRenderer.tsx +17 -0
  72. package/src/components/resources/renderers/RayJobRenderer.test.tsx +40 -0
  73. package/src/components/resources/renderers/RayJobRenderer.tsx +45 -0
  74. package/src/components/resources/renderers/RayServiceRenderer.test.tsx +69 -0
  75. package/src/components/resources/renderers/RayServiceRenderer.tsx +38 -0
  76. package/src/components/rightsizing/RightsizingScanView.tsx +34 -22
  77. package/src/components/rightsizing/copy.test.ts +7 -0
  78. package/src/components/rightsizing/model.test.ts +2 -1
  79. package/src/components/rightsizing/notices.test.tsx +4 -3
  80. package/src/components/settings/OperatorManagedNotice.tsx +17 -0
  81. package/src/components/settings/PrivacySection.test.tsx +84 -0
  82. package/src/components/settings/PrivacySection.tsx +140 -0
  83. package/src/components/settings/SettingsDialog.tsx +168 -92
  84. package/src/components/settings/controls.tsx +55 -0
  85. package/src/components/settings/settings-state.test.ts +18 -0
  86. package/src/components/settings/settings-state.ts +19 -0
  87. package/src/components/timeline/TimelineView.tsx +9 -3
  88. package/src/components/timeline/TimelineView.urlparams.test.ts +18 -1
  89. package/src/components/ui/ErrorBoundary.tsx +5 -0
  90. package/src/components/ui/Omnibar.tsx +16 -0
  91. package/src/components/ui/UpdateNotification.tsx +13 -9
  92. package/src/components/ui/command-items.ts +14 -3
  93. package/src/components/usage-data/UsageDataAsk.test.tsx +41 -0
  94. package/src/components/usage-data/UsageDataAsk.tsx +106 -0
  95. package/src/components/usage-data/UsageDataPrompt.test.ts +53 -0
  96. package/src/components/usage-data/UsageDataPrompt.tsx +148 -0
  97. package/src/components/useContextSwitchFlow.tsx +147 -0
  98. package/src/components/whats-new/WhatsNew.test.ts +110 -0
  99. package/src/components/whats-new/WhatsNew.tsx +423 -0
  100. package/src/components/whats-new/WhatsNewDialog.test.tsx +229 -0
  101. package/src/components/whats-new/check-whats-new.test.ts +65 -0
  102. package/src/components/whats-new/releaseNotes.ts +121 -0
  103. package/src/components/workload/WorkloadView.test.ts +17 -1
  104. package/src/components/workload/WorkloadView.tsx +47 -19
  105. package/src/context/ContextSwitchContext.tsx +18 -2
  106. package/src/context/NavCustomization.tsx +4 -58
  107. package/src/context/ThemeContext.tsx +3 -11
  108. package/src/hooks/useClusterLoadState.ts +2 -2
  109. package/src/hooks/useFavorites.ts +3 -5
  110. package/src/k8s-ui-exports.test.ts +73 -0
  111. package/src/utils/auditBadges.ts +1 -1
  112. package/src/utils/navigation.test.ts +34 -1
  113. package/src/utils/navigation.ts +28 -5
  114. package/src/utils/topology-selection.test.ts +56 -0
  115. package/src/utils/topology-selection.ts +9 -9
  116. package/src/utils/version.ts +11 -0
  117. 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
+ }