@checkstack/ui 1.2.1 → 1.3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # @checkstack/ui
2
2
 
3
+ ## 1.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 26d8bae: Distributed satellite health checks and Assignment IDE page
8
+
9
+ **Satellite System**
10
+
11
+ - New `satellite-backend`, `satellite-common`, `satellite-frontend`, and `satellite` agent packages for distributed health check execution
12
+ - WebSocket-based satellite connectivity with authentication, heartbeats, and live configuration push
13
+ - Satellite management UI with create dialog, status badges, and list page
14
+
15
+ **Live Configuration Updates**
16
+
17
+ - Added `assignmentChanged` hook to `healthcheck-backend` for cross-plugin communication
18
+ - `satellite-backend` subscribes to assignment changes and pushes config updates to connected satellites in real-time
19
+
20
+ **Assignment IDE Page**
21
+
22
+ - Replaced the 1028-line modal-based `SystemHealthCheckAssignment` component with a full-page IDE layout
23
+ - New modular components: `AssignmentTree`, `GeneralPanel`, `ThresholdsPanel`, `RetentionPanel`, `ExecutionPanel`
24
+ - Added unassign capability and sorted assignment lists for stable ordering
25
+
26
+ **Shared IDE Primitives**
27
+
28
+ - Extracted `IDETreeNode`, `IDETreeSection`, `IDEStatusBar`, `IDELayout` to `@checkstack/ui` for cross-plugin reuse
29
+ - Migrated existing health check IDE editor to use shared primitives
30
+
31
+ **Infrastructure**
32
+
33
+ - Added `Dockerfile.satellite` for containerized satellite deployment
34
+ - WebSocket route registry in `@checkstack/backend` and `@checkstack/backend-api`
35
+
3
36
  ## 1.2.1
4
37
 
5
38
  ### Patch Changes
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@checkstack/ui",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "dependencies": {
7
- "@checkstack/common": "0.6.4",
8
- "@checkstack/frontend-api": "0.3.8",
7
+ "@checkstack/common": "0.6.5",
8
+ "@checkstack/frontend-api": "0.3.9",
9
9
  "@monaco-editor/react": "^4.7.0",
10
10
  "@radix-ui/react-accordion": "^1.2.12",
11
11
  "@radix-ui/react-dialog": "^1.1.15",
@@ -0,0 +1,200 @@
1
+ import React from "react";
2
+ import { AlertCircle, CheckCircle2 } from "lucide-react";
3
+ import { Badge } from "../Badge";
4
+
5
+ // =============================================================================
6
+ // SHARED TYPES
7
+ // =============================================================================
8
+
9
+ /**
10
+ * Generic validation issue for IDE-style editors.
11
+ * nodeId identifies which tree node the issue belongs to.
12
+ */
13
+ export interface ValidationIssue {
14
+ nodeId: string;
15
+ message: string;
16
+ }
17
+
18
+ // =============================================================================
19
+ // VALIDATION DOT
20
+ // =============================================================================
21
+
22
+ /**
23
+ * Small red dot indicator shown on tree nodes with validation issues.
24
+ */
25
+ export function IDEValidationDot({
26
+ nodeId,
27
+ issues,
28
+ }: {
29
+ nodeId: string;
30
+ issues: ValidationIssue[];
31
+ }) {
32
+ const nodeIssues = issues.filter((i) => i.nodeId === nodeId);
33
+ if (nodeIssues.length === 0) return;
34
+
35
+ return (
36
+ <span className="ml-auto flex h-2 w-2 rounded-full bg-destructive shrink-0" />
37
+ );
38
+ }
39
+
40
+ // =============================================================================
41
+ // TREE NODE
42
+ // =============================================================================
43
+
44
+ interface IDETreeNodeProps {
45
+ nodeId: string;
46
+ label: string;
47
+ icon: React.ElementType;
48
+ selected: boolean;
49
+ onClick: () => void;
50
+ issues?: ValidationIssue[];
51
+ indent?: boolean;
52
+ badge?: string;
53
+ }
54
+
55
+ /**
56
+ * Generic tree node for IDE-style left panel navigation.
57
+ * Highlights when selected, shows validation dots and optional badges.
58
+ */
59
+ export const IDETreeNode: React.FC<IDETreeNodeProps> = ({
60
+ nodeId,
61
+ label,
62
+ icon: Icon,
63
+ selected,
64
+ onClick,
65
+ issues = [],
66
+ indent = false,
67
+ badge,
68
+ }) => {
69
+ return (
70
+ <button
71
+ type="button"
72
+ onClick={onClick}
73
+ className={`flex items-center gap-2 w-full px-3 py-2 text-sm text-left transition-colors ${
74
+ indent ? "pl-7" : ""
75
+ } ${
76
+ selected
77
+ ? "bg-primary/10 text-primary border-l-2 border-primary"
78
+ : "hover:bg-muted/50 border-l-2 border-transparent"
79
+ }`}
80
+ >
81
+ <Icon className="h-4 w-4 shrink-0 opacity-60" />
82
+ <span className="truncate flex-1">{label}</span>
83
+ {badge && (
84
+ <Badge variant="secondary" className="text-[10px] shrink-0">
85
+ {badge}
86
+ </Badge>
87
+ )}
88
+ <IDEValidationDot nodeId={nodeId} issues={issues} />
89
+ </button>
90
+ );
91
+ };
92
+
93
+ // =============================================================================
94
+ // TREE SECTION HEADER
95
+ // =============================================================================
96
+
97
+ /**
98
+ * Section header for grouping tree nodes (e.g., "Check Items", "Permissions").
99
+ */
100
+ export const IDETreeSection: React.FC<{ label: string }> = ({ label }) => (
101
+ <div className="px-3 pt-4 pb-1">
102
+ <span className="text-[11px] font-semibold text-muted-foreground uppercase tracking-wider">
103
+ {label}
104
+ </span>
105
+ </div>
106
+ );
107
+
108
+ // =============================================================================
109
+ // STATUS BAR
110
+ // =============================================================================
111
+
112
+ interface IDEStatusBarProps {
113
+ issues: ValidationIssue[];
114
+ onIssueClick: (nodeId: string) => void;
115
+ }
116
+
117
+ /**
118
+ * Bottom status bar showing validation issue count with clickable navigation.
119
+ */
120
+ export const IDEStatusBar: React.FC<IDEStatusBarProps> = ({
121
+ issues,
122
+ onIssueClick,
123
+ }) => {
124
+ if (issues.length === 0) {
125
+ return (
126
+ <div className="flex items-center gap-2 px-4 py-2 mt-2 rounded-md border bg-card text-xs text-muted-foreground">
127
+ <CheckCircle2 className="h-3.5 w-3.5 text-green-500" />
128
+ <span>No issues found</span>
129
+ </div>
130
+ );
131
+ }
132
+
133
+ return (
134
+ <div className="flex items-center gap-3 px-4 py-2 mt-2 rounded-md border bg-card text-xs">
135
+ <div className="flex items-center gap-1.5 text-destructive shrink-0">
136
+ <AlertCircle className="h-3.5 w-3.5" />
137
+ <span className="font-medium">
138
+ {issues.length} {issues.length === 1 ? "issue" : "issues"}
139
+ </span>
140
+ </div>
141
+ <div className="flex items-center gap-2 overflow-x-auto">
142
+ {issues.map((issue, i) => (
143
+ <button
144
+ key={`${issue.nodeId}-${i}`}
145
+ type="button"
146
+ onClick={() => onIssueClick(issue.nodeId)}
147
+ className="text-muted-foreground hover:text-foreground transition-colors whitespace-nowrap underline-offset-2 hover:underline"
148
+ >
149
+ {issue.message}
150
+ </button>
151
+ ))}
152
+ </div>
153
+ </div>
154
+ );
155
+ };
156
+
157
+ // =============================================================================
158
+ // IDE LAYOUT
159
+ // =============================================================================
160
+
161
+ interface IDELayoutProps {
162
+ /** Left panel tree content */
163
+ tree: React.ReactNode;
164
+ /** Right panel editor content */
165
+ panel: React.ReactNode;
166
+ /** Optional status bar issues (renders IDEStatusBar automatically) */
167
+ issues?: ValidationIssue[];
168
+ /** Callback when a status bar issue is clicked */
169
+ onIssueClick?: (nodeId: string) => void;
170
+ }
171
+
172
+ /**
173
+ * Two-column IDE layout shell: left tree panel + right editor panel + status bar.
174
+ * Used by health check configuration editor and assignment editor.
175
+ */
176
+ export const IDELayout: React.FC<IDELayoutProps> = ({
177
+ tree,
178
+ panel,
179
+ issues,
180
+ onIssueClick,
181
+ }) => {
182
+ return (
183
+ <>
184
+ <div className="flex flex-col lg:flex-row gap-0 min-h-[60vh] border rounded-lg bg-card overflow-hidden">
185
+ {/* Explorer Tree — Left Panel */}
186
+ <div className="w-full lg:w-64 shrink-0 border-b lg:border-b-0 lg:border-r bg-muted/30">
187
+ {tree}
188
+ </div>
189
+
190
+ {/* Editor Panel — Right Panel */}
191
+ <div className="flex-1 min-w-0">{panel}</div>
192
+ </div>
193
+
194
+ {/* Status Bar */}
195
+ {issues && onIssueClick && (
196
+ <IDEStatusBar issues={issues} onIssueClick={onIssueClick} />
197
+ )}
198
+ </>
199
+ );
200
+ };
package/src/index.ts CHANGED
@@ -53,3 +53,4 @@ export * from "./components/AmbientBackground";
53
53
  export * from "./components/CodeEditor";
54
54
  export * from "./components/AnimatedNumber";
55
55
  export * from "./hooks/useAnimatedNumber";
56
+ export * from "./components/IDELayout";