@principal-ai/principal-view-react 0.14.14 → 0.14.15

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 (63) hide show
  1. package/dist/components/dashboard/DashboardRenderer.d.ts +9 -0
  2. package/dist/components/dashboard/DashboardRenderer.d.ts.map +1 -0
  3. package/dist/components/dashboard/DashboardRenderer.js +179 -0
  4. package/dist/components/dashboard/DashboardRenderer.js.map +1 -0
  5. package/dist/components/dashboard/MetricPanel.d.ts +9 -0
  6. package/dist/components/dashboard/MetricPanel.d.ts.map +1 -0
  7. package/dist/components/dashboard/MetricPanel.js +103 -0
  8. package/dist/components/dashboard/MetricPanel.js.map +1 -0
  9. package/dist/components/dashboard/MockDataProvider.d.ts +30 -0
  10. package/dist/components/dashboard/MockDataProvider.d.ts.map +1 -0
  11. package/dist/components/dashboard/MockDataProvider.js +270 -0
  12. package/dist/components/dashboard/MockDataProvider.js.map +1 -0
  13. package/dist/components/dashboard/components/BarChart.d.ts +9 -0
  14. package/dist/components/dashboard/components/BarChart.d.ts.map +1 -0
  15. package/dist/components/dashboard/components/BarChart.js +167 -0
  16. package/dist/components/dashboard/components/BarChart.js.map +1 -0
  17. package/dist/components/dashboard/components/LineChart.d.ts +9 -0
  18. package/dist/components/dashboard/components/LineChart.d.ts.map +1 -0
  19. package/dist/components/dashboard/components/LineChart.js +141 -0
  20. package/dist/components/dashboard/components/LineChart.js.map +1 -0
  21. package/dist/components/dashboard/components/MetricCard.d.ts +8 -0
  22. package/dist/components/dashboard/components/MetricCard.d.ts.map +1 -0
  23. package/dist/components/dashboard/components/MetricCard.js +163 -0
  24. package/dist/components/dashboard/components/MetricCard.js.map +1 -0
  25. package/dist/components/dashboard/components/SourceLink.d.ts +8 -0
  26. package/dist/components/dashboard/components/SourceLink.d.ts.map +1 -0
  27. package/dist/components/dashboard/components/SourceLink.js +39 -0
  28. package/dist/components/dashboard/components/SourceLink.js.map +1 -0
  29. package/dist/components/dashboard/components/TimeRangeSelector.d.ts +8 -0
  30. package/dist/components/dashboard/components/TimeRangeSelector.d.ts.map +1 -0
  31. package/dist/components/dashboard/components/TimeRangeSelector.js +167 -0
  32. package/dist/components/dashboard/components/TimeRangeSelector.js.map +1 -0
  33. package/dist/components/dashboard/components/index.d.ts +6 -0
  34. package/dist/components/dashboard/components/index.d.ts.map +1 -0
  35. package/dist/components/dashboard/components/index.js +6 -0
  36. package/dist/components/dashboard/components/index.js.map +1 -0
  37. package/dist/components/dashboard/index.d.ts +6 -0
  38. package/dist/components/dashboard/index.d.ts.map +1 -0
  39. package/dist/components/dashboard/index.js +8 -0
  40. package/dist/components/dashboard/index.js.map +1 -0
  41. package/dist/components/dashboard/types.d.ts +74 -0
  42. package/dist/components/dashboard/types.d.ts.map +1 -0
  43. package/dist/components/dashboard/types.js +8 -0
  44. package/dist/components/dashboard/types.js.map +1 -0
  45. package/dist/index.d.ts +2 -0
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +2 -0
  48. package/dist/index.js.map +1 -1
  49. package/package.json +3 -3
  50. package/src/components/dashboard/DashboardRenderer.tsx +317 -0
  51. package/src/components/dashboard/MetricPanel.tsx +243 -0
  52. package/src/components/dashboard/MockDataProvider.ts +330 -0
  53. package/src/components/dashboard/components/BarChart.tsx +299 -0
  54. package/src/components/dashboard/components/LineChart.tsx +279 -0
  55. package/src/components/dashboard/components/MetricCard.tsx +270 -0
  56. package/src/components/dashboard/components/SourceLink.tsx +63 -0
  57. package/src/components/dashboard/components/TimeRangeSelector.tsx +280 -0
  58. package/src/components/dashboard/components/index.ts +5 -0
  59. package/src/components/dashboard/index.ts +47 -0
  60. package/src/components/dashboard/types.ts +126 -0
  61. package/src/index.ts +49 -0
  62. package/src/stories/dashboard/DashboardRenderer.stories.tsx +263 -0
  63. package/src/stories/dashboard/sample-dashboards/activity-feed-analytics.dashboard.json +300 -0
@@ -0,0 +1,263 @@
1
+ /**
2
+ * DashboardRenderer Stories
3
+ *
4
+ * Storybook stories for testing and iterating on dashboard rendering.
5
+ */
6
+
7
+ import type { Meta, StoryObj } from '@storybook/react';
8
+ import { ThemeProvider, defaultEditorTheme } from '@principal-ade/industry-theme';
9
+ import { DashboardRenderer } from '../../components/dashboard';
10
+ import activityFeedDashboard from './sample-dashboards/activity-feed-analytics.dashboard.json';
11
+ import type { DashboardDefinition } from '../../components/dashboard';
12
+
13
+ const meta: Meta<typeof DashboardRenderer> = {
14
+ title: 'Dashboard/DashboardRenderer',
15
+ component: DashboardRenderer,
16
+ parameters: {
17
+ layout: 'fullscreen',
18
+ },
19
+ decorators: [
20
+ (Story) => (
21
+ <ThemeProvider theme={defaultEditorTheme}>
22
+ <div style={{ minHeight: '100vh' }}>
23
+ <Story />
24
+ </div>
25
+ </ThemeProvider>
26
+ ),
27
+ ],
28
+ };
29
+
30
+ export default meta;
31
+ type Story = StoryObj<typeof DashboardRenderer>;
32
+
33
+ /**
34
+ * Activity Feed Analytics Dashboard
35
+ *
36
+ * Full dashboard example based on the web-ade activity feed use case.
37
+ * Shows mobile vs desktop view percentages, traffic trends, and engagement metrics.
38
+ */
39
+ export const ActivityFeedAnalytics: Story = {
40
+ args: {
41
+ dashboard: activityFeedDashboard as DashboardDefinition,
42
+ },
43
+ };
44
+
45
+ /**
46
+ * With Metric Click Handler
47
+ *
48
+ * Demonstrates handling metric clicks - useful for drill-down navigation.
49
+ */
50
+ export const WithClickHandlers: Story = {
51
+ args: {
52
+ dashboard: activityFeedDashboard as DashboardDefinition,
53
+ onMetricClick: (metricId) => {
54
+ alert(`Clicked metric: ${metricId}`);
55
+ },
56
+ onSourceClick: (source) => {
57
+ alert(`Navigate to: ${source.storyboard}/${source.workflow}`);
58
+ },
59
+ },
60
+ };
61
+
62
+ /**
63
+ * Minimal Dashboard
64
+ *
65
+ * A simple dashboard with just a few metrics.
66
+ */
67
+ export const MinimalDashboard: Story = {
68
+ args: {
69
+ dashboard: {
70
+ id: 'minimal',
71
+ name: 'Minimal Dashboard',
72
+ description: 'A simple dashboard with basic metrics',
73
+ metrics: [
74
+ {
75
+ id: 'total-requests',
76
+ name: 'Total Requests',
77
+ type: 'counter',
78
+ unit: 'requests',
79
+ sources: [{ storyboard: 'api', workflow: 'request-handler' }],
80
+ query: { derivation: 'count', window: '1h' },
81
+ _mockData: { current: 145892, previous: 132456, trend: 'up' },
82
+ },
83
+ {
84
+ id: 'error-rate',
85
+ name: 'Error Rate',
86
+ type: 'gauge',
87
+ unit: '%',
88
+ sources: [{ storyboard: 'api', workflow: 'request-handler' }],
89
+ query: { derivation: 'error_rate', window: '1h' },
90
+ thresholds: { warning: 1.0, critical: 5.0 },
91
+ _mockData: { current: 0.3, previous: 0.5, trend: 'down' },
92
+ },
93
+ {
94
+ id: 'p99-latency',
95
+ name: 'P99 Latency',
96
+ type: 'histogram',
97
+ unit: 'ms',
98
+ sources: [{ storyboard: 'api', workflow: 'request-handler' }],
99
+ query: { derivation: 'p99' },
100
+ _mockData: { current: 245, previous: 312, trend: 'down' },
101
+ },
102
+ ],
103
+ layout: {
104
+ rows: [
105
+ {
106
+ title: 'Key Metrics',
107
+ panels: [
108
+ { id: 'total-requests', span: 4 },
109
+ { id: 'error-rate', span: 4 },
110
+ { id: 'p99-latency', span: 4 },
111
+ ],
112
+ },
113
+ ],
114
+ },
115
+ } as DashboardDefinition,
116
+ },
117
+ };
118
+
119
+ /**
120
+ * Time Series Focus
121
+ *
122
+ * Dashboard focused on time series visualizations.
123
+ */
124
+ export const TimeSeriesFocus: Story = {
125
+ args: {
126
+ dashboard: {
127
+ id: 'time-series',
128
+ name: 'Time Series Dashboard',
129
+ description: 'Focus on time-based trends',
130
+ metrics: [
131
+ {
132
+ id: 'hourly-requests',
133
+ name: 'Hourly Requests',
134
+ type: 'counter',
135
+ unit: 'requests',
136
+ sources: [{ storyboard: 'api', workflow: 'handler' }],
137
+ query: { derivation: 'count', timeGroup: 'hour' },
138
+ display: { component: 'LineChart', size: 'large' },
139
+ _mockData: {
140
+ series: [
141
+ { date: '00:00', value: 1200 },
142
+ { date: '04:00', value: 800 },
143
+ { date: '08:00', value: 2400 },
144
+ { date: '12:00', value: 3200 },
145
+ { date: '16:00', value: 2800 },
146
+ { date: '20:00', value: 1800 },
147
+ ],
148
+ },
149
+ },
150
+ {
151
+ id: 'requests-by-status',
152
+ name: 'Requests by Status',
153
+ type: 'counter',
154
+ unit: 'requests',
155
+ sources: [{ storyboard: 'api', workflow: 'handler' }],
156
+ query: { derivation: 'count', groupBy: ['status'], timeGroup: 'hour' },
157
+ display: { component: 'StackedBarChart', size: 'large' },
158
+ _mockData: {
159
+ series: [
160
+ { date: '00:00', success: 1150, error: 50 },
161
+ { date: '04:00', success: 780, error: 20 },
162
+ { date: '08:00', success: 2300, error: 100 },
163
+ { date: '12:00', success: 3050, error: 150 },
164
+ { date: '16:00', success: 2650, error: 150 },
165
+ { date: '20:00', success: 1720, error: 80 },
166
+ ],
167
+ },
168
+ },
169
+ ],
170
+ layout: {
171
+ rows: [
172
+ {
173
+ title: 'Traffic Over Time',
174
+ panels: [{ id: 'hourly-requests', span: 12 }],
175
+ },
176
+ {
177
+ title: 'Status Breakdown',
178
+ panels: [{ id: 'requests-by-status', span: 12 }],
179
+ },
180
+ ],
181
+ },
182
+ } as DashboardDefinition,
183
+ },
184
+ };
185
+
186
+ /**
187
+ * With Thresholds
188
+ *
189
+ * Shows metrics with warning and critical thresholds.
190
+ */
191
+ export const WithThresholds: Story = {
192
+ args: {
193
+ dashboard: {
194
+ id: 'thresholds',
195
+ name: 'SLO Dashboard',
196
+ description: 'Service level objectives with thresholds',
197
+ metrics: [
198
+ {
199
+ id: 'availability',
200
+ name: 'Availability',
201
+ type: 'gauge',
202
+ unit: '%',
203
+ sources: [{ storyboard: 'infra', workflow: 'health-check' }],
204
+ query: { derivation: 'success_rate' },
205
+ thresholds: { warning: 99.9, critical: 99.0 },
206
+ _mockData: { current: 99.95, trend: 'flat' },
207
+ },
208
+ {
209
+ id: 'error-budget',
210
+ name: 'Error Budget Remaining',
211
+ type: 'gauge',
212
+ unit: '%',
213
+ sources: [{ storyboard: 'infra', workflow: 'slo-tracker' }],
214
+ query: { derivation: 'percentage' },
215
+ thresholds: { warning: 25, critical: 10 },
216
+ _mockData: { current: 67.3, previous: 72.1, trend: 'down' },
217
+ },
218
+ {
219
+ id: 'latency-slo',
220
+ name: 'Latency SLO',
221
+ type: 'gauge',
222
+ unit: '%',
223
+ description: 'Percentage of requests under 200ms',
224
+ sources: [{ storyboard: 'api', workflow: 'handler' }],
225
+ query: { derivation: 'percentage', filter: 'duration < 200' },
226
+ thresholds: { warning: 95, critical: 90 },
227
+ _mockData: { current: 97.2, previous: 96.8, trend: 'up' },
228
+ },
229
+ ],
230
+ layout: {
231
+ rows: [
232
+ {
233
+ title: 'Service Level Objectives',
234
+ panels: [
235
+ { id: 'availability', span: 4 },
236
+ { id: 'error-budget', span: 4 },
237
+ { id: 'latency-slo', span: 4 },
238
+ ],
239
+ },
240
+ ],
241
+ },
242
+ } as DashboardDefinition,
243
+ },
244
+ };
245
+
246
+ /**
247
+ * Empty Dashboard
248
+ *
249
+ * Edge case: dashboard with no metrics.
250
+ */
251
+ export const EmptyDashboard: Story = {
252
+ args: {
253
+ dashboard: {
254
+ id: 'empty',
255
+ name: 'Empty Dashboard',
256
+ description: 'This dashboard has no metrics configured yet',
257
+ metrics: [],
258
+ layout: {
259
+ rows: [],
260
+ },
261
+ } as DashboardDefinition,
262
+ },
263
+ };
@@ -0,0 +1,300 @@
1
+ {
2
+ "$schema": "https://principal.ai/schemas/dashboard.v1.json",
3
+ "id": "activity-feed-analytics",
4
+ "name": "Activity Feed Analytics",
5
+ "description": "User engagement metrics for the activity feed home page",
6
+ "owner": "web-ade-team",
7
+
8
+ "externalLinks": {
9
+ "grafana": "https://grafana.internal/d/activity-feed",
10
+ "runbook": "https://wiki.internal/runbooks/activity-feed"
11
+ },
12
+
13
+ "metrics": [
14
+ {
15
+ "id": "mobile-view-percentage",
16
+ "name": "Mobile View %",
17
+ "description": "Percentage of activity feed loads on mobile devices",
18
+ "type": "gauge",
19
+ "unit": "%",
20
+
21
+ "sources": [{
22
+ "storyboard": "activity-feed",
23
+ "workflow": "feed-load",
24
+ "nodes": ["init-started"],
25
+ "event": "activity-feed.init.started"
26
+ }],
27
+
28
+ "query": {
29
+ "derivation": "percentage",
30
+ "filter": "isMobile = true",
31
+ "window": "1h"
32
+ },
33
+
34
+ "display": {
35
+ "component": "MetricCard",
36
+ "size": "medium",
37
+ "showTrend": true,
38
+ "showSparkline": true
39
+ },
40
+
41
+ "_mockData": {
42
+ "current": 34.2,
43
+ "previous": 31.8,
44
+ "trend": "up",
45
+ "series": [
46
+ { "date": "2024-03-27T00:00", "value": 31.2 },
47
+ { "date": "2024-03-27T01:00", "value": 32.1 },
48
+ { "date": "2024-03-27T02:00", "value": 33.0 },
49
+ { "date": "2024-03-27T03:00", "value": 32.5 },
50
+ { "date": "2024-03-27T04:00", "value": 33.8 },
51
+ { "date": "2024-03-27T05:00", "value": 34.2 }
52
+ ]
53
+ }
54
+ },
55
+ {
56
+ "id": "total-page-views",
57
+ "name": "Total Page Views",
58
+ "description": "Total home page views in the last hour",
59
+ "type": "counter",
60
+ "unit": "views",
61
+
62
+ "sources": [{
63
+ "storyboard": "activity-feed",
64
+ "workflow": "feed-load",
65
+ "event": "activity-feed.init.started"
66
+ }],
67
+
68
+ "query": {
69
+ "derivation": "count",
70
+ "window": "1h"
71
+ },
72
+
73
+ "display": {
74
+ "component": "MetricCard",
75
+ "size": "medium",
76
+ "showSparkline": true
77
+ },
78
+
79
+ "_mockData": {
80
+ "current": 28493,
81
+ "previous": 26102,
82
+ "trend": "up",
83
+ "series": [
84
+ { "date": "2024-03-27T00:00", "value": 25102 },
85
+ { "date": "2024-03-27T01:00", "value": 26234 },
86
+ { "date": "2024-03-27T02:00", "value": 25890 },
87
+ { "date": "2024-03-27T03:00", "value": 27102 },
88
+ { "date": "2024-03-27T04:00", "value": 28100 },
89
+ { "date": "2024-03-27T05:00", "value": 28493 }
90
+ ]
91
+ }
92
+ },
93
+ {
94
+ "id": "error-rate",
95
+ "name": "Error Rate",
96
+ "description": "Percentage of feed loads that resulted in errors",
97
+ "type": "gauge",
98
+ "unit": "%",
99
+
100
+ "sources": [{
101
+ "storyboard": "activity-feed",
102
+ "workflow": "feed-load",
103
+ "nodes": ["init-error"]
104
+ }],
105
+
106
+ "query": {
107
+ "derivation": "error_rate",
108
+ "window": "1h"
109
+ },
110
+
111
+ "thresholds": {
112
+ "warning": 2.0,
113
+ "critical": 5.0
114
+ },
115
+
116
+ "display": {
117
+ "component": "MetricCard",
118
+ "size": "medium",
119
+ "showTrend": true,
120
+ "showSparkline": true
121
+ },
122
+
123
+ "_mockData": {
124
+ "current": 0.8,
125
+ "previous": 1.2,
126
+ "trend": "down",
127
+ "series": [
128
+ { "date": "2024-03-27T00:00", "value": 1.4 },
129
+ { "date": "2024-03-27T01:00", "value": 1.2 },
130
+ { "date": "2024-03-27T02:00", "value": 1.1 },
131
+ { "date": "2024-03-27T03:00", "value": 0.9 },
132
+ { "date": "2024-03-27T04:00", "value": 0.85 },
133
+ { "date": "2024-03-27T05:00", "value": 0.8 }
134
+ ]
135
+ }
136
+ },
137
+ {
138
+ "id": "daily-home-page-views",
139
+ "name": "Daily Page Views",
140
+ "description": "Home page views per day for the last 7 days",
141
+ "type": "counter",
142
+ "unit": "views",
143
+
144
+ "sources": [{
145
+ "storyboard": "activity-feed",
146
+ "workflow": "feed-load",
147
+ "event": "activity-feed.init.started"
148
+ }],
149
+
150
+ "query": {
151
+ "derivation": "count",
152
+ "timeGroup": "day"
153
+ },
154
+
155
+ "display": {
156
+ "component": "LineChart",
157
+ "size": "large"
158
+ },
159
+
160
+ "_mockData": {
161
+ "series": [
162
+ { "date": "2024-03-21", "value": 28493 },
163
+ { "date": "2024-03-22", "value": 31247 },
164
+ { "date": "2024-03-23", "value": 29102 },
165
+ { "date": "2024-03-24", "value": 27856 },
166
+ { "date": "2024-03-25", "value": 30421 },
167
+ { "date": "2024-03-26", "value": 32109 },
168
+ { "date": "2024-03-27", "value": 29876 }
169
+ ]
170
+ }
171
+ },
172
+ {
173
+ "id": "views-by-viewport",
174
+ "name": "Views by Viewport",
175
+ "description": "Daily page views split by mobile vs desktop",
176
+ "type": "counter",
177
+ "unit": "views",
178
+
179
+ "sources": [{
180
+ "storyboard": "activity-feed",
181
+ "workflow": "feed-load",
182
+ "event": "activity-feed.init.started"
183
+ }],
184
+
185
+ "query": {
186
+ "derivation": "count",
187
+ "groupBy": ["isMobile"],
188
+ "timeGroup": "day"
189
+ },
190
+
191
+ "display": {
192
+ "component": "StackedBarChart",
193
+ "size": "large"
194
+ },
195
+
196
+ "_mockData": {
197
+ "series": [
198
+ { "date": "2024-03-21", "mobile": 9847, "desktop": 18646 },
199
+ { "date": "2024-03-22", "mobile": 11023, "desktop": 20224 },
200
+ { "date": "2024-03-23", "mobile": 10156, "desktop": 18946 },
201
+ { "date": "2024-03-24", "mobile": 9234, "desktop": 18622 },
202
+ { "date": "2024-03-25", "mobile": 10567, "desktop": 19854 },
203
+ { "date": "2024-03-26", "mobile": 11234, "desktop": 20875 },
204
+ { "date": "2024-03-27", "mobile": 10423, "desktop": 19453 }
205
+ ]
206
+ }
207
+ },
208
+ {
209
+ "id": "mobile-interaction-rate",
210
+ "name": "Mobile Interactions/Session",
211
+ "description": "Average number of interactions per mobile session",
212
+ "type": "gauge",
213
+ "unit": "interactions",
214
+
215
+ "sources": [{
216
+ "storyboard": "activity-feed",
217
+ "workflow": "mobile-interaction",
218
+ "nodes": ["card-swipe", "commit-browse"]
219
+ }],
220
+
221
+ "query": {
222
+ "derivation": "avg",
223
+ "window": "1h"
224
+ },
225
+
226
+ "display": {
227
+ "component": "MetricCard",
228
+ "size": "medium"
229
+ },
230
+
231
+ "_mockData": {
232
+ "current": 4.7,
233
+ "previous": 4.2,
234
+ "trend": "up"
235
+ }
236
+ },
237
+ {
238
+ "id": "desktop-search-usage",
239
+ "name": "Search Usage Rate",
240
+ "description": "Percentage of desktop sessions that use search",
241
+ "type": "gauge",
242
+ "unit": "%",
243
+
244
+ "sources": [{
245
+ "storyboard": "activity-feed",
246
+ "workflow": "desktop-interaction",
247
+ "nodes": ["search-and-select"]
248
+ }],
249
+
250
+ "query": {
251
+ "derivation": "percentage",
252
+ "window": "1h"
253
+ },
254
+
255
+ "display": {
256
+ "component": "MetricCard",
257
+ "size": "medium"
258
+ },
259
+
260
+ "_mockData": {
261
+ "current": 23.4,
262
+ "previous": 21.8,
263
+ "trend": "up"
264
+ }
265
+ }
266
+ ],
267
+
268
+ "layout": {
269
+ "columns": 12,
270
+ "gap": 16,
271
+ "breakpoints": {
272
+ "mobile": 768,
273
+ "tablet": 1024
274
+ },
275
+ "rows": [
276
+ {
277
+ "title": "Overview",
278
+ "panels": [
279
+ { "id": "mobile-view-percentage", "span": 4, "spanMobile": 12 },
280
+ { "id": "total-page-views", "span": 4, "spanMobile": 12 },
281
+ { "id": "error-rate", "span": 4, "spanMobile": 12 }
282
+ ]
283
+ },
284
+ {
285
+ "title": "Traffic Trends",
286
+ "panels": [
287
+ { "id": "daily-home-page-views", "span": 6, "spanMobile": 12, "minHeight": 280 },
288
+ { "id": "views-by-viewport", "span": 6, "spanMobile": 12, "minHeight": 280 }
289
+ ]
290
+ },
291
+ {
292
+ "title": "Engagement",
293
+ "panels": [
294
+ { "id": "mobile-interaction-rate", "span": 6, "spanMobile": 12 },
295
+ { "id": "desktop-search-usage", "span": 6, "spanMobile": 12 }
296
+ ]
297
+ }
298
+ ]
299
+ }
300
+ }