@skyhook-io/k8s-ui 1.7.11 → 1.7.13

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 (70) hide show
  1. package/package.json +1 -1
  2. package/src/components/applications/AppChips.tsx +109 -0
  3. package/src/components/applications/AppTooltips.tsx +199 -0
  4. package/src/components/applications/ApplicationDetail.tsx +671 -0
  5. package/src/components/applications/ApplicationsList.tsx +569 -0
  6. package/src/components/applications/ReadyBar.tsx +22 -0
  7. package/src/components/applications/index.ts +8 -0
  8. package/src/components/audit/AuditFindingsTable.tsx +3 -25
  9. package/src/components/dock/TerminalTab.tsx +4 -2
  10. package/src/components/gitops/insights/GitOpsInsightViews.tsx +1 -0
  11. package/src/components/issues/IssuesView.tsx +64 -17
  12. package/src/components/issues/index.ts +1 -1
  13. package/src/components/issues/issues.test.ts +4 -4
  14. package/src/components/issues/severity.ts +5 -0
  15. package/src/components/issues/types.ts +43 -0
  16. package/src/components/logs/LogCore.tsx +13 -2
  17. package/src/components/logs/LogToolbarSelects.tsx +6 -2
  18. package/src/components/logs/LogsViewer.tsx +66 -10
  19. package/src/components/logs/WorkloadLogsViewer.tsx +68 -13
  20. package/src/components/logs/useLogStream.ts +41 -3
  21. package/src/components/resources/ResourcesView.tsx +550 -52
  22. package/src/components/resources/column-filter-serialization.test.ts +26 -0
  23. package/src/components/resources/get-default-container-name.test.ts +31 -0
  24. package/src/components/resources/renderers/DeviceClassRenderer.tsx +49 -0
  25. package/src/components/resources/renderers/NodeRenderer.tsx +7 -0
  26. package/src/components/resources/renderers/NvidiaClusterPolicyRenderer.tsx +57 -0
  27. package/src/components/resources/renderers/NvidiaDriverRenderer.tsx +47 -0
  28. package/src/components/resources/renderers/PodRenderer.tsx +2 -2
  29. package/src/components/resources/renderers/ResourceClaimRenderer.tsx +118 -0
  30. package/src/components/resources/renderers/ResourceClaimTemplateRenderer.tsx +39 -0
  31. package/src/components/resources/renderers/ResourceSliceRenderer.tsx +72 -0
  32. package/src/components/resources/renderers/WorkloadRenderer.tsx +5 -4
  33. package/src/components/resources/renderers/dra-cells.tsx +80 -0
  34. package/src/components/resources/renderers/index.ts +8 -0
  35. package/src/components/resources/renderers/nvidia-cells.tsx +43 -0
  36. package/src/components/resources/resource-utils-dra.ts +90 -0
  37. package/src/components/resources/resource-utils-nvidia.ts +63 -0
  38. package/src/components/resources/resource-utils.ts +62 -4
  39. package/src/components/shared/DetailShell.tsx +14 -7
  40. package/src/components/shared/EditableYamlView.tsx +37 -17
  41. package/src/components/shared/ResourceActionsBar.tsx +5 -4
  42. package/src/components/shared/ResourceRendererDispatch.test.tsx +103 -0
  43. package/src/components/shared/ResourceRendererDispatch.tsx +27 -2
  44. package/src/components/timeline/TimelineList.tsx +3 -32
  45. package/src/components/timeline/TimelineSwimlanes.tsx +3 -31
  46. package/src/components/topology/K8sResourceNode.tsx +26 -5
  47. package/src/components/topology/TopologyGraph.tsx +102 -3
  48. package/src/components/topology/layout.ts +36 -11
  49. package/src/components/ui/CenteredEmpty.tsx +27 -0
  50. package/src/components/ui/ConfirmDialog.tsx +1 -1
  51. package/src/components/ui/SearchBox.tsx +85 -0
  52. package/src/components/ui/drawer-components.tsx +23 -1
  53. package/src/components/ui/index.ts +1 -0
  54. package/src/components/workload/WorkloadView.tsx +167 -33
  55. package/src/components/workload/index.ts +1 -1
  56. package/src/hooks/useKeyboardShortcuts.tsx +3 -1
  57. package/src/index.ts +4 -0
  58. package/src/types/core.ts +1 -0
  59. package/src/utils/api-resources.ts +21 -0
  60. package/src/utils/applications.test.ts +207 -0
  61. package/src/utils/applications.ts +674 -0
  62. package/src/utils/custom-columns.test.ts +111 -0
  63. package/src/utils/custom-columns.ts +49 -0
  64. package/src/utils/extended-resources.test.ts +152 -0
  65. package/src/utils/extended-resources.ts +121 -0
  66. package/src/utils/format.ts +11 -0
  67. package/src/utils/index.ts +3 -0
  68. package/src/utils/topology-neighborhood.test.ts +185 -0
  69. package/src/utils/topology-neighborhood.ts +262 -0
  70. package/src/utils/workload-colors.ts +36 -0
@@ -18,12 +18,24 @@ export interface LogStreamHandlers {
18
18
  */
19
19
  export function useLogStream() {
20
20
  const [isStreaming, setIsStreaming] = useState(false)
21
+ // Set when the connection fails (and not on a clean end — see endedRef).
22
+ const [streamError, setStreamError] = useState<string | null>(null)
23
+ // True from a start attempt until the stream first settles (connected / end /
24
+ // error / stop). Lets callers show a connecting spinner that won't reappear
25
+ // after a clean end. Starts true so an auto-stream viewer paints the spinner
26
+ // immediately instead of flashing the empty state.
27
+ const [connecting, setConnecting] = useState(true)
21
28
  const eventSourceRef = useRef<EventSource | null>(null)
29
+ // EventSource fires a generic 'error' on the normal close that follows the
30
+ // server's 'end'; this distinguishes a clean end from a real failure.
31
+ const endedRef = useRef(false)
22
32
 
23
33
  const stopStreaming = useCallback(() => {
24
34
  eventSourceRef.current?.close()
25
35
  eventSourceRef.current = null
26
36
  setIsStreaming(false)
37
+ setConnecting(false)
38
+ setStreamError(null)
27
39
  }, [])
28
40
 
29
41
  const startStreaming = useCallback((
@@ -32,10 +44,19 @@ export function useLogStream() {
32
44
  errorContext = 'Log stream error',
33
45
  ) => {
34
46
  eventSourceRef.current?.close()
47
+ endedRef.current = false
48
+ setStreamError(null)
49
+ setConnecting(true)
35
50
  const es = create()
51
+ // Ignore events from a superseded source: closing/replacing an EventSource
52
+ // (Stop, container switch, restart) can fire a late, async 'error' that
53
+ // would otherwise corrupt the new stream's state or show a false failure.
54
+ const isCurrent = () => eventSourceRef.current === es
36
55
 
37
56
  es.addEventListener('connected', (event) => {
57
+ if (!isCurrent()) return
38
58
  setIsStreaming(true)
59
+ setConnecting(false)
39
60
  if (handlers.onConnected) {
40
61
  try { handlers.onConnected(JSON.parse((event as MessageEvent).data)) } catch (e) {
41
62
  console.error('Failed to parse connected event:', e)
@@ -44,12 +65,15 @@ export function useLogStream() {
44
65
  })
45
66
 
46
67
  es.addEventListener('log', (event) => {
68
+ if (!isCurrent()) return
69
+ setConnecting(false)
47
70
  try { handlers.onLog(JSON.parse((event as MessageEvent).data)) } catch (e) {
48
71
  console.error('Failed to parse log event:', e)
49
72
  }
50
73
  })
51
74
 
52
75
  es.addEventListener('pod_added', (event) => {
76
+ if (!isCurrent()) return
53
77
  if (handlers.onPodAdded) {
54
78
  try { handlers.onPodAdded(JSON.parse((event as MessageEvent).data)) } catch (e) {
55
79
  console.error('Failed to parse pod_added event:', e)
@@ -58,6 +82,7 @@ export function useLogStream() {
58
82
  })
59
83
 
60
84
  es.addEventListener('pod_removed', (event) => {
85
+ if (!isCurrent()) return
61
86
  if (handlers.onPodRemoved) {
62
87
  try { handlers.onPodRemoved(JSON.parse((event as MessageEvent).data)) } catch (e) {
63
88
  console.error('Failed to parse pod_removed event:', e)
@@ -65,10 +90,23 @@ export function useLogStream() {
65
90
  }
66
91
  })
67
92
 
68
- es.addEventListener('end', () => setIsStreaming(false))
93
+ es.addEventListener('end', () => {
94
+ if (!isCurrent()) return
95
+ endedRef.current = true
96
+ setIsStreaming(false)
97
+ setConnecting(false)
98
+ })
69
99
 
70
100
  es.addEventListener('error', (event) => {
71
- handleSSEError(event, errorContext, () => { setIsStreaming(false); es.close() })
101
+ if (!isCurrent()) { es.close(); return }
102
+ setIsStreaming(false)
103
+ setConnecting(false)
104
+ es.close()
105
+ // The browser fires 'error' on the normal close that follows a clean
106
+ // 'end'; that's not a failure, so don't log it or surface it.
107
+ if (endedRef.current) return
108
+ handleSSEError(event, errorContext, () => {})
109
+ setStreamError(errorContext)
72
110
  })
73
111
 
74
112
  eventSourceRef.current = es
@@ -77,5 +115,5 @@ export function useLogStream() {
77
115
  // Cleanup on unmount
78
116
  useEffect(() => () => { eventSourceRef.current?.close() }, [])
79
117
 
80
- return { isStreaming, startStreaming, stopStreaming }
118
+ return { isStreaming, streamError, connecting, startStreaming, stopStreaming }
81
119
  }