react-dashstream 0.3.1 → 0.3.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/README.md +16 -1
- package/package.json +2 -2
- package/skills/dashstream-3d-dashboard/SKILL.md +318 -0
- package/skills/dashstream-component-dialogs/SKILL.md +287 -0
- package/skills/dashstream-core/SKILL.md +330 -0
- package/skills/dashstream-datacenter-view/SKILL.md +198 -0
- package/skills/dashstream-event-view/SKILL.md +212 -0
- package/skills/dashstream-live-data/SKILL.md +250 -0
- package/dashstream-skill.md +0 -1208
package/README.md
CHANGED
|
@@ -69,6 +69,21 @@ Click a service to expand its topology. Click a component to drill into its inte
|
|
|
69
69
|
|
|
70
70
|
---
|
|
71
71
|
|
|
72
|
+
## AI assistant skills
|
|
73
|
+
|
|
74
|
+
Published with the package under **`skills/`** — each folder is a small, topic-focused reference for coding agents (Cursor, OpenCode, etc.):
|
|
75
|
+
|
|
76
|
+
| Skill | Focus |
|
|
77
|
+
| ----- | ----- |
|
|
78
|
+
| `dashstream-core` | Package overview, install, theming, exports, types, pitfalls |
|
|
79
|
+
| `dashstream-3d-dashboard` | `AIOPsDashboard`, services, nodes, positioning, connections |
|
|
80
|
+
| `dashstream-live-data` | `DataProvider`, bindings, hooks, endpoint contract |
|
|
81
|
+
| `dashstream-component-dialogs` | Drill-down metrics, internals, sparklines, alerts |
|
|
82
|
+
| `dashstream-event-view` | `EventView`, event API, event-to-dashboard bridge |
|
|
83
|
+
| `dashstream-datacenter-view` | `DatacenterView`, topology, geography, buildings |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
72
87
|
## Theme (light / dark)
|
|
73
88
|
|
|
74
89
|
The dashboard ships with **light** and **dark** visual modes. `AIOPsDashboard` defaults to **light**; the header includes a control to toggle modes.
|
|
@@ -139,7 +154,7 @@ See `example/Dashboard.tsx` in this package for a complete two-service example w
|
|
|
139
154
|
|
|
140
155
|
The demo app (`src/App.tsx`) uses `example/SaudiMapView.tsx`, a thin wrapper around `DatacenterView` that composes the map with **`DatacenterSite`** / shape components (`TowerDC`, `FlatDC`, …). Scenario data (configs and drill-down services) lives in `example/saudiMapDemoData.tsx`; optional mock metric sliders use `example/DemoMetricPanel.tsx` + `example/DemoMetricPanel.css` (not part of the published package).
|
|
141
156
|
|
|
142
|
-
**Agent-oriented reference:** see **`dashstream-
|
|
157
|
+
**Agent-oriented reference:** see **`skills/dashstream-datacenter-view/SKILL.md`** for props, types, mock vs live data, and composition with `DataProvider`. Other topics live under **`skills/<name>/SKILL.md`** — see **AI assistant skills** below.
|
|
143
158
|
|
|
144
159
|
### Minimal import
|
|
145
160
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-dashstream",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Busaud",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"files": [
|
|
17
17
|
"dist",
|
|
18
18
|
"README.md",
|
|
19
|
-
"
|
|
19
|
+
"skills"
|
|
20
20
|
],
|
|
21
21
|
"main": "./dist/index.js",
|
|
22
22
|
"module": "./dist/index.js",
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dashstream-3d-dashboard
|
|
3
|
+
description: Build 3D carousel dashboards with AIOPsDashboard, services, and nodes
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: opencode
|
|
6
|
+
metadata:
|
|
7
|
+
audience: developers
|
|
8
|
+
workflow: react
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## What I do
|
|
12
|
+
|
|
13
|
+
- Guide building a 3D carousel dashboard with `AIOPsDashboard`
|
|
14
|
+
- Document `Service`, `ServerNode`, `DatabaseNode`, `WebDispatcherNode`, `MessageServerNode`, `HumanNode`
|
|
15
|
+
- Explain node positioning, connections, and compact offsets
|
|
16
|
+
- Provide minimal and full static dashboard examples
|
|
17
|
+
|
|
18
|
+
## When to use me
|
|
19
|
+
|
|
20
|
+
Use this when creating or modifying a 3D dashboard layout — adding services, positioning nodes, or configuring connections.
|
|
21
|
+
|
|
22
|
+
For live data wiring, see **dashstream-live-data**. For drill-down details, see **dashstream-component-dialogs**.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## AIOPsDashboard — the shell
|
|
27
|
+
|
|
28
|
+
The top-level component that renders the header, carousel, and optional data layer.
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import "react-dashstream/dist/index.css";
|
|
32
|
+
import { AIOPsDashboard, Service, ServerNode, DatabaseNode } from "react-dashstream";
|
|
33
|
+
|
|
34
|
+
<AIOPsDashboard
|
|
35
|
+
brandName="MY DASHBOARD"
|
|
36
|
+
brandTag="3D MONITOR"
|
|
37
|
+
services={[{ name: "Svc", status: "online" }]}
|
|
38
|
+
>
|
|
39
|
+
<Service name="Svc" status="online" connections={[...]}>
|
|
40
|
+
{/* nodes go here */}
|
|
41
|
+
</Service>
|
|
42
|
+
</AIOPsDashboard>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Key props (see **dashstream-core** for full `AIOPsDashboardProps`):
|
|
46
|
+
|
|
47
|
+
| Prop | Type | Default | Notes |
|
|
48
|
+
|------|------|---------|-------|
|
|
49
|
+
| `brandName` | `string` | `"BUSAUD AIOps"` | Header brand |
|
|
50
|
+
| `brandTag` | `string` | `"3D MONITOR"` | Header tag |
|
|
51
|
+
| `services` | `ServiceMeta[]` | — | Metadata for ServiceDialog panels |
|
|
52
|
+
| `backgroundImage` | `string` | — | Dark mode background |
|
|
53
|
+
| `lightBackgroundImage` | `string` | — | Light mode background |
|
|
54
|
+
| `theme` / `onThemeChange` | `DashboardTheme` | — | Controlled theme |
|
|
55
|
+
| `logoUrl` | `string` | — | Logo image URL |
|
|
56
|
+
| `carouselSpeed` | `number` | `0.006` | Rotation speed |
|
|
57
|
+
| `fontFamily` | `string` | — | CSS font-family |
|
|
58
|
+
| `children` | `ReactNode` | — | `Service` children |
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Service — per-service container
|
|
63
|
+
|
|
64
|
+
Each `Service` wraps one logical service's nodes and connections.
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
<Service
|
|
68
|
+
name="My Service"
|
|
69
|
+
status="online"
|
|
70
|
+
connections={[
|
|
71
|
+
{ from: [330, 200], to: [200, 380], visibleAtPhase: 3 },
|
|
72
|
+
{ from: [330, 200], to: [460, 380], visibleAtPhase: 3 },
|
|
73
|
+
{ from: [200, 380], to: [330, 520], visibleAtPhase: 4 },
|
|
74
|
+
{ from: [460, 380], to: [330, 520], visibleAtPhase: 4 },
|
|
75
|
+
]}
|
|
76
|
+
>
|
|
77
|
+
{/* compound nodes */}
|
|
78
|
+
</Service>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
- `name` must match keys in `dataBindings`, `serviceDataBindings`, and `ServiceMeta.name` exactly.
|
|
82
|
+
- `connections` are `ConnectionConfig[]` — animated SVG dashed lines between node positions.
|
|
83
|
+
|
|
84
|
+
### ConnectionConfig
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
interface ConnectionConfig {
|
|
88
|
+
from: [number, number]; // [x, y] matching source node's ex/ey
|
|
89
|
+
to: [number, number]; // [x, y] matching target node's ex/ey
|
|
90
|
+
visibleAtPhase?: number; // Default: 0
|
|
91
|
+
color?: string; // Default: "#00e5ff"
|
|
92
|
+
duration?: string; // Default: "1.2s"
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Compound nodes
|
|
99
|
+
|
|
100
|
+
All compound nodes share common positioning props:
|
|
101
|
+
|
|
102
|
+
| Prop | Type | Notes |
|
|
103
|
+
|------|------|-------|
|
|
104
|
+
| `name` | `string` | Display name + event bridge matching key |
|
|
105
|
+
| `subLabel` | `string` | Secondary label below name |
|
|
106
|
+
| `status` | `ComponentStatus` | `"online"` / `"warning"` / `"critical"` / `"offline"` |
|
|
107
|
+
| `ex` | `number` | X position in the ~660×640 scene |
|
|
108
|
+
| `ey` | `number` | Y position in the ~660×640 scene |
|
|
109
|
+
| `compactOffset` | `{ x, y }` | Offset in compact carousel view |
|
|
110
|
+
| `zIndex` | `number` | Z-order layering |
|
|
111
|
+
| `alert` | `AlertConfig` | Callout positioning (see dashstream-component-dialogs) |
|
|
112
|
+
| `dialogMetrics` | `ComponentDialogMetric[]` | Custom gauges (see dashstream-component-dialogs) |
|
|
113
|
+
| `subComponents` | `SubComponentConfig[]` | Custom drill-down internals (see dashstream-component-dialogs) |
|
|
114
|
+
| `graphSeries` | `GraphSeries[]` | Custom sparklines (see dashstream-component-dialogs) |
|
|
115
|
+
|
|
116
|
+
### ServerNode
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
<ServerNode
|
|
120
|
+
ex={200} ey={380}
|
|
121
|
+
compactOffset={{ x: -30, y: -20 }}
|
|
122
|
+
zIndex={8}
|
|
123
|
+
name="SRV-01"
|
|
124
|
+
subLabel="APP SERVER"
|
|
125
|
+
status="online"
|
|
126
|
+
cpuLoad={42}
|
|
127
|
+
memLoad={60}
|
|
128
|
+
/>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Extra props: `cpuLoad` (number), `memLoad` (number).
|
|
132
|
+
|
|
133
|
+
### DatabaseNode
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
<DatabaseNode
|
|
137
|
+
ex={460} ey={520}
|
|
138
|
+
compactOffset={{ x: 30, y: 20 }}
|
|
139
|
+
zIndex={7}
|
|
140
|
+
name="DB-01"
|
|
141
|
+
subLabel="PRIMARY"
|
|
142
|
+
status="online"
|
|
143
|
+
capacity={55}
|
|
144
|
+
/>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Extra props: `capacity` (number).
|
|
148
|
+
|
|
149
|
+
### WebDispatcherNode
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
<WebDispatcherNode
|
|
153
|
+
ex={330} ey={230}
|
|
154
|
+
compactOffset={{ x: 0, y: -30 }}
|
|
155
|
+
zIndex={9}
|
|
156
|
+
name="WD-01"
|
|
157
|
+
subLabel="DISPATCHER"
|
|
158
|
+
status="online"
|
|
159
|
+
traffic={45}
|
|
160
|
+
/>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Extra props: `traffic` (number).
|
|
164
|
+
|
|
165
|
+
### MessageServerNode
|
|
166
|
+
|
|
167
|
+
```tsx
|
|
168
|
+
<MessageServerNode
|
|
169
|
+
ex={330} ey={230}
|
|
170
|
+
compactOffset={{ x: 0, y: -30 }}
|
|
171
|
+
zIndex={9}
|
|
172
|
+
name="MSG-01"
|
|
173
|
+
subLabel="MESSAGE SERVER"
|
|
174
|
+
status="online"
|
|
175
|
+
queueDepth={30}
|
|
176
|
+
/>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Extra props: `queueDepth` (number).
|
|
180
|
+
|
|
181
|
+
### HumanNode
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
<HumanNode
|
|
185
|
+
ex={330} ey={100}
|
|
186
|
+
compactOffset={{ x: 0, y: -40 }}
|
|
187
|
+
zIndex={10}
|
|
188
|
+
name="USERS"
|
|
189
|
+
subLabel="500 ACTIVE"
|
|
190
|
+
status="online"
|
|
191
|
+
/>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Node positioning guide
|
|
197
|
+
|
|
198
|
+
The topology scene is ~660×640 pixels.
|
|
199
|
+
|
|
200
|
+
| Layer | Typical `ey` | `visibleAtPhase` | Component |
|
|
201
|
+
| ----- | ------------ | ---------------- | --------- |
|
|
202
|
+
| Users (top) | 100 | 2 | `HumanNode` |
|
|
203
|
+
| Dispatcher | 230 | 2 | `WebDispatcherNode` |
|
|
204
|
+
| App servers | 350–380 | 3 | `ServerNode` |
|
|
205
|
+
| Databases | 500–520 | 4 | `DatabaseNode` |
|
|
206
|
+
|
|
207
|
+
Center X = `330`. Left/right columns: `200` / `460`. Three-column: `165` / `330` / `495`.
|
|
208
|
+
|
|
209
|
+
`compactOffset` controls node position in the compact carousel view relative to center.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Usage patterns
|
|
214
|
+
|
|
215
|
+
### Minimal static dashboard
|
|
216
|
+
|
|
217
|
+
```tsx
|
|
218
|
+
import "react-dashstream/dist/index.css";
|
|
219
|
+
import { AIOPsDashboard, Service, ServerNode, DatabaseNode } from "react-dashstream";
|
|
220
|
+
|
|
221
|
+
<AIOPsDashboard brandName="MY DASHBOARD" services={[{ name: "Svc", status: "online" }]}>
|
|
222
|
+
<Service
|
|
223
|
+
name="Svc"
|
|
224
|
+
status="online"
|
|
225
|
+
connections={[{ from: [330, 200], to: [330, 380], visibleAtPhase: 3 }]}
|
|
226
|
+
>
|
|
227
|
+
<ServerNode
|
|
228
|
+
ex={330} ey={380}
|
|
229
|
+
compactOffset={{ x: 0, y: 0 }}
|
|
230
|
+
zIndex={8}
|
|
231
|
+
name="SRV-01"
|
|
232
|
+
status="online"
|
|
233
|
+
cpuLoad={42}
|
|
234
|
+
memLoad={60}
|
|
235
|
+
/>
|
|
236
|
+
</Service>
|
|
237
|
+
</AIOPsDashboard>
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Multi-node service
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
function MyService({ name, status, cpuLoad, memLoad, dbCapacity, dbStatus }: any) {
|
|
244
|
+
return (
|
|
245
|
+
<Service
|
|
246
|
+
name={name}
|
|
247
|
+
status={status ?? "online"}
|
|
248
|
+
connections={[
|
|
249
|
+
{ from: [330, 200], to: [200, 380], visibleAtPhase: 3 },
|
|
250
|
+
{ from: [330, 200], to: [460, 380], visibleAtPhase: 3 },
|
|
251
|
+
{ from: [200, 380], to: [330, 520], visibleAtPhase: 4 },
|
|
252
|
+
{ from: [460, 380], to: [330, 520], visibleAtPhase: 4 },
|
|
253
|
+
]}
|
|
254
|
+
>
|
|
255
|
+
<ServerNode
|
|
256
|
+
ex={200} ey={380}
|
|
257
|
+
compactOffset={{ x: -30, y: -20 }}
|
|
258
|
+
zIndex={8}
|
|
259
|
+
name="SRV-01"
|
|
260
|
+
subLabel="APP SERVER"
|
|
261
|
+
status={status ?? "online"}
|
|
262
|
+
cpuLoad={cpuLoad ?? 42}
|
|
263
|
+
memLoad={memLoad ?? 60}
|
|
264
|
+
alert={{ offsetX: -160, offsetY: -60, align: "left" }}
|
|
265
|
+
/>
|
|
266
|
+
<DatabaseNode
|
|
267
|
+
ex={460} ey={380}
|
|
268
|
+
compactOffset={{ x: 30, y: -20 }}
|
|
269
|
+
zIndex={7}
|
|
270
|
+
name="DB-01"
|
|
271
|
+
subLabel="PRIMARY"
|
|
272
|
+
status={dbStatus ?? "online"}
|
|
273
|
+
capacity={dbCapacity ?? 55}
|
|
274
|
+
alert={{ offsetX: 160, offsetY: -60, align: "right" }}
|
|
275
|
+
/>
|
|
276
|
+
</Service>
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Multi-component services (flat prefix convention)
|
|
282
|
+
|
|
283
|
+
When a service has multiple nodes of the same type, use flat prefixed props:
|
|
284
|
+
|
|
285
|
+
```tsx
|
|
286
|
+
interface ServiceXProps {
|
|
287
|
+
name: string;
|
|
288
|
+
status?: ComponentStatus;
|
|
289
|
+
srv1CpuLoad?: number;
|
|
290
|
+
srv1MemLoad?: number;
|
|
291
|
+
srv1Status?: ComponentStatus;
|
|
292
|
+
srv2CpuLoad?: number;
|
|
293
|
+
srv2MemLoad?: number;
|
|
294
|
+
srv2Status?: ComponentStatus;
|
|
295
|
+
dbCapacity?: number;
|
|
296
|
+
dbStatus?: ComponentStatus;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function ServiceX({
|
|
300
|
+
name, status = "online",
|
|
301
|
+
srv1CpuLoad = 54, srv1MemLoad = 58, srv1Status = "online",
|
|
302
|
+
srv2CpuLoad = 63, srv2MemLoad = 66, srv2Status = "online",
|
|
303
|
+
dbCapacity = 68, dbStatus = "online",
|
|
304
|
+
}: ServiceXProps) {
|
|
305
|
+
return (
|
|
306
|
+
<Service name={name} status={status} connections={[/* ... */]}>
|
|
307
|
+
<ServerNode name="SRV-X1" status={srv1Status}
|
|
308
|
+
cpuLoad={srv1CpuLoad} memLoad={srv1MemLoad} ... />
|
|
309
|
+
<ServerNode name="SRV-X2" status={srv2Status}
|
|
310
|
+
cpuLoad={srv2CpuLoad} memLoad={srv2MemLoad} ... />
|
|
311
|
+
<DatabaseNode name="DB-X1" status={dbStatus}
|
|
312
|
+
capacity={dbCapacity} ... />
|
|
313
|
+
</Service>
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
Use a consistent convention like `srv1CpuLoad`, `srv2CpuLoad`. The service component maps each prefixed prop to the correct node.
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dashstream-component-dialogs
|
|
3
|
+
description: Configure drill-down dialogs with custom metrics, internals, sparklines, and alerts
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: opencode
|
|
6
|
+
metadata:
|
|
7
|
+
audience: developers
|
|
8
|
+
workflow: react
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## What I do
|
|
12
|
+
|
|
13
|
+
- Document the ComponentDialog system (gauges, drill-down internals, sparkline graphs)
|
|
14
|
+
- Explain `dialogMetrics`, `subComponents`, and `graphSeries` props
|
|
15
|
+
- Cover automatic threshold-based alerts and custom alert positioning
|
|
16
|
+
- Show how to wire live data into dialog metrics via service props
|
|
17
|
+
|
|
18
|
+
## When to use me
|
|
19
|
+
|
|
20
|
+
Use this when customizing what appears in the drill-down panel when a user clicks a node — custom gauges, internal 3D sub-components, sparkline charts, or alert callouts.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Component dialog — default gauges
|
|
25
|
+
|
|
26
|
+
The **ComponentDialog** appears when clicking a node. Default gauges are derived from node type:
|
|
27
|
+
|
|
28
|
+
- **Server**: CPU (from `cpuLoad`), Memory (from `memLoad`), Storage
|
|
29
|
+
- **Database**: Capacity (from `capacity`), Memory, Storage
|
|
30
|
+
- **Dispatcher**: Traffic (from `traffic`), Memory, Storage
|
|
31
|
+
- **Message Server**: Queue (from `queueDepth`), Memory, Storage
|
|
32
|
+
|
|
33
|
+
Default thresholds: warn at 70, critical at 85.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Custom dialogMetrics
|
|
38
|
+
|
|
39
|
+
Override default gauges with `dialogMetrics` on any compound node:
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
<ServerNode
|
|
43
|
+
name="SRV-01"
|
|
44
|
+
status="online"
|
|
45
|
+
cpuLoad={67}
|
|
46
|
+
memLoad={72}
|
|
47
|
+
ex={200} ey={380}
|
|
48
|
+
compactOffset={{ x: -30, y: -20 }}
|
|
49
|
+
zIndex={8}
|
|
50
|
+
dialogMetrics={[
|
|
51
|
+
{ id: "cpu", label: "CPU", sublabel: "PROCESSOR", value: 67, unit: "%" },
|
|
52
|
+
{ id: "mem", label: "MEMORY", sublabel: "HEAP USAGE", value: 72, unit: "%" },
|
|
53
|
+
{ id: "iops", label: "IOPS", sublabel: "DISK OPS", value: 45, unit: "k/s", icon: "disk" },
|
|
54
|
+
{
|
|
55
|
+
id: "threads",
|
|
56
|
+
label: "THREADS",
|
|
57
|
+
sublabel: "ACTIVE",
|
|
58
|
+
value: 82,
|
|
59
|
+
unit: "%",
|
|
60
|
+
warnAt: 60,
|
|
61
|
+
critAt: 80,
|
|
62
|
+
icon: "cpu",
|
|
63
|
+
},
|
|
64
|
+
]}
|
|
65
|
+
/>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
interface ComponentDialogMetric {
|
|
70
|
+
id: string; // Unique key
|
|
71
|
+
label: string; // Upper label
|
|
72
|
+
sublabel: string; // Lower label
|
|
73
|
+
value: number; // 0–100
|
|
74
|
+
unit?: string; // Default "%"
|
|
75
|
+
icon?: "cpu" | "mem" | "disk"; // Default "cpu"
|
|
76
|
+
warnAt?: number; // Default 70
|
|
77
|
+
critAt?: number; // Default 85
|
|
78
|
+
color?: string; // Override bar color (bypasses threshold coloring)
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
All compound nodes accept `dialogMetrics`: `ServerNode`, `DatabaseNode`, `WebDispatcherNode`, `MessageServerNode`.
|
|
83
|
+
|
|
84
|
+
**When provided, all default gauges are removed** — you must define every metric you want shown.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Drill-down internals — custom subComponents
|
|
89
|
+
|
|
90
|
+
When clicking a node, the drill-down shows internal 3D sub-components. Default sub-components are auto-generated per type. Override with `subComponents`:
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import { CPU3D, Memory3D, DriveBay3D, ThreadPool3D, NetworkBlock3D, Platter3D, Port3D } from "react-dashstream";
|
|
94
|
+
import type { SubComponentConfig } from "react-dashstream";
|
|
95
|
+
|
|
96
|
+
const internals: SubComponentConfig[] = [
|
|
97
|
+
{ id: "cpu-0", label: "CPU-0", status: "online",
|
|
98
|
+
element: <CPU3D label="CPU-0" load={67} color="#00e5ff" /> },
|
|
99
|
+
{ id: "heap", label: "HEAP", status: "warning",
|
|
100
|
+
element: <Memory3D label="HEAP" usedPercent={92} color="#8855ee" status="warning" /> },
|
|
101
|
+
{ id: "drive", label: "DRIVE-0", status: "online",
|
|
102
|
+
element: <DriveBay3D label="DRIVE-0" color="#00e5ff" activity={true} /> },
|
|
103
|
+
{ id: "threads", label: "THREADS", status: "online",
|
|
104
|
+
element: <ThreadPool3D label="THREADS" color="#00e5ff" /> },
|
|
105
|
+
{ id: "net", label: "NET", status: "online",
|
|
106
|
+
element: <NetworkBlock3D label="NET" color="#00e5ff" /> },
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
<ServerNode subComponents={internals} ... />
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
interface SubComponentConfig {
|
|
114
|
+
id: string; // Unique key
|
|
115
|
+
label: string; // Display name
|
|
116
|
+
status: ComponentStatus; // LED color
|
|
117
|
+
detail?: string; // Fault description
|
|
118
|
+
element: ReactNode; // 3D element to render
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
All compound nodes accept `subComponents`. **When provided, all auto-generated sub-components are removed.**
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Graph series — custom sparklines
|
|
127
|
+
|
|
128
|
+
The drill-down's historical panel shows sparkline charts. Default graphs are auto-generated. Override with `graphSeries`:
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
import type { GraphSeries } from "react-dashstream";
|
|
132
|
+
|
|
133
|
+
const graphs: GraphSeries[] = [
|
|
134
|
+
{ id: "cpu", label: "CPU-0", unit: "%", color: "#00e5ff", data: [45, 52, 67, 71, 68, 55] },
|
|
135
|
+
{ id: "mem", label: "HEAP", unit: "%", color: "#8855ee", data: [60, 65, 72, 78, 82, 75] },
|
|
136
|
+
{ id: "iops", label: "DISK", unit: "k/s", color: "#ff8c00", data: [12, 15, 22, 18, 25, 20] },
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
<ServerNode graphSeries={graphs} ... />
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
interface GraphSeries {
|
|
144
|
+
id: string; // Unique key
|
|
145
|
+
label: string; // Label above sparkline
|
|
146
|
+
unit: string; // Suffix
|
|
147
|
+
color: string; // Line color
|
|
148
|
+
data: number[]; // Points (most recent last)
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
All compound nodes accept `graphSeries`. **When provided, all auto-generated sparklines are removed.**
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Alerts — automatic threshold detection
|
|
157
|
+
|
|
158
|
+
Nodes auto-render `NodeCallout` alerts when metrics breach thresholds:
|
|
159
|
+
|
|
160
|
+
- **Warning** at 70% → orange callout
|
|
161
|
+
- **Critical** at 85% → red callout
|
|
162
|
+
|
|
163
|
+
Sources (checked in priority order):
|
|
164
|
+
|
|
165
|
+
1. `dialogMetrics` values vs their `warnAt`/`critAt`
|
|
166
|
+
2. Context values (`cpuLoad`, `memLoad`, `traffic`, `queueDepth`, `capacity`) vs default thresholds
|
|
167
|
+
|
|
168
|
+
```tsx
|
|
169
|
+
// Auto-alert from cpuLoad > 85
|
|
170
|
+
<ServerNode cpuLoad={92} memLoad={64}
|
|
171
|
+
alert={{ offsetX: -160, offsetY: -60, align: "left" }}
|
|
172
|
+
... />
|
|
173
|
+
|
|
174
|
+
// Custom message
|
|
175
|
+
<ServerNode cpuLoad={92}
|
|
176
|
+
alert={{ msg: "CPU overload — scale out", offsetX: -160, offsetY: -60, align: "left" }}
|
|
177
|
+
... />
|
|
178
|
+
|
|
179
|
+
// Custom thresholds via dialogMetrics
|
|
180
|
+
<ServerNode
|
|
181
|
+
dialogMetrics={[
|
|
182
|
+
{ id: "cpu", label: "CPU", sublabel: "PROCESSOR", value: 67,
|
|
183
|
+
warnAt: 50, critAt: 75 },
|
|
184
|
+
]}
|
|
185
|
+
alert={{ offsetX: -160, offsetY: -60, align: "left" }}
|
|
186
|
+
... />
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Alert prop shape
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
alert?: {
|
|
193
|
+
msg?: string; // Custom message (auto-generated if omitted)
|
|
194
|
+
offsetX?: number; // X offset from node (default 110)
|
|
195
|
+
offsetY?: number; // Y offset from node (default -30)
|
|
196
|
+
align?: "left" | "right" | "top" | "bottom"; // Default "right"
|
|
197
|
+
internalRef?: string; // Sub-component ID
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Alert `align` options: `"left"`, `"right"`, `"top"`, `"bottom"`.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## ServiceDialog — static and live metrics
|
|
206
|
+
|
|
207
|
+
The **ServiceDialog** panel shows KPIs when a service is expanded.
|
|
208
|
+
|
|
209
|
+
### Static metrics via ServiceMeta
|
|
210
|
+
|
|
211
|
+
```tsx
|
|
212
|
+
const services: ServiceMeta[] = [
|
|
213
|
+
{
|
|
214
|
+
name: "My Service",
|
|
215
|
+
status: "online",
|
|
216
|
+
metrics: [
|
|
217
|
+
{ label: "Uptime", value: "99.99%", color: "#00ff88" },
|
|
218
|
+
{ label: "Avg Latency", value: "8ms", color: "#00e5ff" },
|
|
219
|
+
],
|
|
220
|
+
alerts: [
|
|
221
|
+
{ level: "info", message: "All Systems Nominal" },
|
|
222
|
+
{ level: "warning", message: "High CPU on SRV-01" },
|
|
223
|
+
{ level: "critical", message: "DB connection pool exhausted" },
|
|
224
|
+
],
|
|
225
|
+
},
|
|
226
|
+
];
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Live metrics via serviceDataBindings
|
|
230
|
+
|
|
231
|
+
See **dashstream-live-data** for `serviceDataBindings` configuration.
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Full example — service with all dialog features
|
|
236
|
+
|
|
237
|
+
```tsx
|
|
238
|
+
import { CPU3D, Memory3D } from "react-dashstream";
|
|
239
|
+
|
|
240
|
+
function MyService({ name, status, cpuLoad, memLoad, dbCapacity, dbStatus }: any) {
|
|
241
|
+
return (
|
|
242
|
+
<Service
|
|
243
|
+
name={name}
|
|
244
|
+
status={status ?? "online"}
|
|
245
|
+
connections={[
|
|
246
|
+
{ from: [330, 200], to: [200, 380], visibleAtPhase: 3 },
|
|
247
|
+
{ from: [330, 200], to: [460, 380], visibleAtPhase: 3 },
|
|
248
|
+
]}
|
|
249
|
+
>
|
|
250
|
+
<ServerNode
|
|
251
|
+
ex={200} ey={380}
|
|
252
|
+
compactOffset={{ x: -30, y: -20 }}
|
|
253
|
+
zIndex={8}
|
|
254
|
+
name="SRV-01"
|
|
255
|
+
subLabel="APP SERVER"
|
|
256
|
+
status={status ?? "online"}
|
|
257
|
+
cpuLoad={cpuLoad ?? 42}
|
|
258
|
+
memLoad={memLoad ?? 60}
|
|
259
|
+
alert={{ offsetX: -160, offsetY: -60, align: "left" }}
|
|
260
|
+
dialogMetrics={[
|
|
261
|
+
{ id: "cpu", label: "CPU", sublabel: "PROCESSOR", value: cpuLoad ?? 42 },
|
|
262
|
+
{ id: "mem", label: "MEMORY", sublabel: "HEAP", value: memLoad ?? 60 },
|
|
263
|
+
]}
|
|
264
|
+
subComponents={[
|
|
265
|
+
{ id: "cpu", label: "CPU-0", status: "online",
|
|
266
|
+
element: <CPU3D label="CPU-0" load={cpuLoad ?? 42} /> },
|
|
267
|
+
{ id: "mem", label: "HEAP", status: "online",
|
|
268
|
+
element: <Memory3D label="HEAP" usedPercent={memLoad ?? 60} /> },
|
|
269
|
+
]}
|
|
270
|
+
graphSeries={[
|
|
271
|
+
{ id: "cpu", label: "CPU", unit: "%", color: "#00e5ff", data: [45, 52, 67, 71, 68] },
|
|
272
|
+
]}
|
|
273
|
+
/>
|
|
274
|
+
<DatabaseNode
|
|
275
|
+
ex={460} ey={380}
|
|
276
|
+
compactOffset={{ x: 30, y: -20 }}
|
|
277
|
+
zIndex={7}
|
|
278
|
+
name="DB-01"
|
|
279
|
+
subLabel="PRIMARY"
|
|
280
|
+
status={dbStatus ?? "online"}
|
|
281
|
+
capacity={dbCapacity ?? 55}
|
|
282
|
+
alert={{ offsetX: 160, offsetY: -60, align: "right" }}
|
|
283
|
+
/>
|
|
284
|
+
</Service>
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
```
|