@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,9 @@
1
+ /**
2
+ * DashboardRenderer
3
+ *
4
+ * Main component for rendering a dashboard from a DashboardDefinition.
5
+ * Takes a dashboard definition JSON and a data provider, renders all metrics.
6
+ */
7
+ import type { DashboardRendererProps } from './types';
8
+ export declare function DashboardRenderer({ dashboard, dataProvider, timeRange: controlledTimeRange, onTimeRangeChange, refreshInterval: controlledRefreshInterval, onRefreshIntervalChange, timeRangeConfig, onMetricClick, onSourceClick, }: DashboardRendererProps): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=DashboardRenderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DashboardRenderer.d.ts","sourceRoot":"","sources":["../../../src/components/dashboard/DashboardRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAA4D,MAAM,SAAS,CAAC;AAkChH,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,YAAY,EACZ,SAAS,EAAE,mBAAmB,EAC9B,iBAAiB,EACjB,eAAe,EAAE,yBAAyB,EAC1C,uBAAuB,EACvB,eAAe,EACf,aAAa,EACb,aAAa,GACd,EAAE,sBAAsB,2CAuQxB"}
@@ -0,0 +1,179 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * DashboardRenderer
4
+ *
5
+ * Main component for rendering a dashboard from a DashboardDefinition.
6
+ * Takes a dashboard definition JSON and a data provider, renders all metrics.
7
+ */
8
+ import { useMemo, useState, useEffect } from 'react';
9
+ import { useTheme } from '@principal-ade/industry-theme';
10
+ import { MetricPanel } from './MetricPanel';
11
+ import { MockDataProvider } from './MockDataProvider';
12
+ import { TimeRangeSelector } from './components';
13
+ function useBreakpoint(breakpoints) {
14
+ const mobileBreak = breakpoints?.mobile ?? 768;
15
+ const tabletBreak = breakpoints?.tablet ?? 1024;
16
+ const [breakpoint, setBreakpoint] = useState(() => {
17
+ if (typeof window === 'undefined')
18
+ return 'desktop';
19
+ const width = window.innerWidth;
20
+ if (width < mobileBreak)
21
+ return 'mobile';
22
+ if (width < tabletBreak)
23
+ return 'tablet';
24
+ return 'desktop';
25
+ });
26
+ useEffect(() => {
27
+ const handleResize = () => {
28
+ const width = window.innerWidth;
29
+ if (width < mobileBreak)
30
+ setBreakpoint('mobile');
31
+ else if (width < tabletBreak)
32
+ setBreakpoint('tablet');
33
+ else
34
+ setBreakpoint('desktop');
35
+ };
36
+ window.addEventListener('resize', handleResize);
37
+ return () => window.removeEventListener('resize', handleResize);
38
+ }, [mobileBreak, tabletBreak]);
39
+ return breakpoint;
40
+ }
41
+ export function DashboardRenderer({ dashboard, dataProvider, timeRange: controlledTimeRange, onTimeRangeChange, refreshInterval: controlledRefreshInterval, onRefreshIntervalChange, timeRangeConfig, onMetricClick, onSourceClick, }) {
42
+ const { theme } = useTheme();
43
+ const breakpoint = useBreakpoint(dashboard.layout.breakpoints);
44
+ // Internal state for uncontrolled time range
45
+ const [internalTimeRange, setInternalTimeRange] = useState({
46
+ preset: timeRangeConfig?.defaultRange ?? 'last_1h',
47
+ });
48
+ const [internalRefreshInterval, setInternalRefreshInterval] = useState(timeRangeConfig?.defaultRefresh ?? 'off');
49
+ // Use controlled or internal state
50
+ const timeRange = controlledTimeRange ?? internalTimeRange;
51
+ const refreshInterval = controlledRefreshInterval ?? internalRefreshInterval;
52
+ const handleTimeRangeChange = (range) => {
53
+ if (onTimeRangeChange) {
54
+ onTimeRangeChange(range);
55
+ }
56
+ else {
57
+ setInternalTimeRange(range);
58
+ }
59
+ };
60
+ const handleRefreshIntervalChange = (interval) => {
61
+ if (onRefreshIntervalChange) {
62
+ onRefreshIntervalChange(interval);
63
+ }
64
+ else {
65
+ setInternalRefreshInterval(interval);
66
+ }
67
+ };
68
+ // Grid configuration
69
+ const gridColumns = dashboard.layout.columns ?? 12;
70
+ const gridGap = dashboard.layout.gap ?? 16;
71
+ // Use provided data provider or create a mock one
72
+ const data = useMemo(() => {
73
+ const provider = dataProvider || new MockDataProvider(dashboard);
74
+ return provider.getAll();
75
+ }, [dashboard, dataProvider]);
76
+ // Build a map of metric ID → metric definition for quick lookup
77
+ const metricsMap = useMemo(() => {
78
+ const map = new Map();
79
+ for (const metric of dashboard.metrics) {
80
+ map.set(metric.id, metric);
81
+ }
82
+ return map;
83
+ }, [dashboard.metrics]);
84
+ const handleSourceClick = (source) => {
85
+ if (onSourceClick) {
86
+ onSourceClick(source);
87
+ }
88
+ else {
89
+ // Default behavior: log to console
90
+ console.log('Source clicked:', source);
91
+ }
92
+ };
93
+ // Get span for current breakpoint
94
+ const getSpan = (placement, totalPanels) => {
95
+ // Mobile defaults to full width
96
+ if (breakpoint === 'mobile') {
97
+ return placement.spanMobile ?? gridColumns;
98
+ }
99
+ // Tablet uses spanTablet or falls back to span
100
+ if (breakpoint === 'tablet') {
101
+ return placement.spanTablet ?? placement.span ?? Math.floor(gridColumns / Math.min(totalPanels, 2));
102
+ }
103
+ // Desktop uses spanDesktop or span or auto-calculate
104
+ return placement.spanDesktop ?? placement.span ?? Math.floor(gridColumns / Math.min(totalPanels, 3));
105
+ };
106
+ return (_jsxs("div", { style: {
107
+ backgroundColor: theme.colors.background,
108
+ color: theme.colors.text,
109
+ padding: theme.space?.[4] || 24,
110
+ minHeight: '100%',
111
+ fontFamily: theme.fonts.body,
112
+ }, children: [_jsxs("div", { style: { marginBottom: theme.space?.[4] || 24 }, children: [_jsxs("div", { style: {
113
+ display: 'flex',
114
+ justifyContent: 'space-between',
115
+ alignItems: 'flex-start',
116
+ gap: theme.space?.[3] || 16,
117
+ flexWrap: 'wrap',
118
+ }, children: [_jsx("h1", { style: {
119
+ fontSize: theme.fontSizes[4],
120
+ fontWeight: theme.fontWeights.semibold,
121
+ fontFamily: theme.fonts.heading,
122
+ margin: 0,
123
+ color: theme.colors.text,
124
+ }, children: dashboard.name }), _jsx(TimeRangeSelector, { timeRange: timeRange, onTimeRangeChange: handleTimeRangeChange, refreshInterval: refreshInterval, onRefreshIntervalChange: handleRefreshIntervalChange, config: timeRangeConfig })] }), dashboard.description && (_jsx("p", { style: {
125
+ fontSize: theme.fontSizes[1],
126
+ color: theme.colors.textSecondary,
127
+ margin: 0,
128
+ marginTop: theme.space?.[2] || 8,
129
+ marginBottom: theme.space?.[3] || 12,
130
+ lineHeight: theme.lineHeights.body,
131
+ }, children: dashboard.description })), dashboard.externalLinks && Object.keys(dashboard.externalLinks).length > 0 && (_jsx("div", { style: { display: 'flex', gap: theme.space?.[3] || 12 }, children: Object.entries(dashboard.externalLinks).map(([name, url]) => (url && (_jsxs("a", { href: url, target: "_blank", rel: "noopener noreferrer", style: {
132
+ fontSize: theme.fontSizes[0],
133
+ color: theme.colors.primary || theme.colors.accent,
134
+ textDecoration: 'none',
135
+ display: 'flex',
136
+ alignItems: 'center',
137
+ gap: 4,
138
+ }, children: [_jsxs("svg", { width: 12, height: 12, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [_jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), _jsx("polyline", { points: "15 3 21 3 21 9" }), _jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }), name] }, name)))) }))] }), _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.space?.[4] || 24 }, children: dashboard.layout.rows.map((row, rowIndex) => (_jsxs("div", { children: [row.title && (_jsx("h2", { style: {
139
+ fontSize: theme.fontSizes[2],
140
+ fontWeight: theme.fontWeights.medium,
141
+ fontFamily: theme.fonts.heading,
142
+ margin: 0,
143
+ marginBottom: theme.space?.[3] || 12,
144
+ color: theme.colors.text,
145
+ paddingBottom: theme.space?.[2] || 8,
146
+ borderBottom: `1px solid ${theme.colors.border}`,
147
+ }, children: row.title })), _jsx("div", { style: {
148
+ display: 'grid',
149
+ gridTemplateColumns: `repeat(${gridColumns}, 1fr)`,
150
+ gap: gridGap,
151
+ }, children: row.panels.map((panel) => {
152
+ const span = getSpan(panel, row.panels.length);
153
+ const metric = metricsMap.get(panel.id);
154
+ const panelStyle = {
155
+ gridColumn: `span ${span}`,
156
+ minHeight: panel.minHeight,
157
+ height: panel.height === 'auto' ? 'auto' : panel.height,
158
+ };
159
+ if (!metric) {
160
+ return (_jsxs("div", { style: {
161
+ ...panelStyle,
162
+ backgroundColor: theme.colors.surface || theme.colors.background,
163
+ border: `1px solid ${theme.colors.error}`,
164
+ borderRadius: theme.radii?.[2] || 8,
165
+ padding: theme.space?.[3] || 16,
166
+ color: theme.colors.error,
167
+ fontSize: theme.fontSizes[1],
168
+ }, children: ["Metric not found: ", panel.id] }, panel.id));
169
+ }
170
+ return (_jsx("div", { style: panelStyle, children: _jsx(MetricPanel, { metric: metric, data: data[panel.id] || { error: 'No data' }, onMetricClick: onMetricClick, onSourceClick: handleSourceClick }) }, panel.id));
171
+ }) })] }, rowIndex))) }), dashboard.owner && (_jsxs("div", { style: {
172
+ marginTop: theme.space?.[5] || 32,
173
+ paddingTop: theme.space?.[3] || 16,
174
+ borderTop: `1px solid ${theme.colors.border}`,
175
+ fontSize: theme.fontSizes[0],
176
+ color: theme.colors.textSecondary,
177
+ }, children: ["Owner: ", dashboard.owner] }))] }));
178
+ }
179
+ //# sourceMappingURL=DashboardRenderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DashboardRenderer.js","sourceRoot":"","sources":["../../../src/components/dashboard/DashboardRenderer.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * MetricPanel
3
+ *
4
+ * Wrapper component that determines which visualization to render
5
+ * based on the metric definition and data.
6
+ */
7
+ import type { MetricPanelProps } from './types';
8
+ export declare function MetricPanel({ metric, data, onMetricClick, onSourceClick, }: MetricPanelProps): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=MetricPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetricPanel.d.ts","sourceRoot":"","sources":["../../../src/components/dashboard/MetricPanel.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,gBAAgB,EAIjB,MAAM,SAAS,CAAC;AAGjB,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,IAAI,EACJ,aAAa,EACb,aAAa,GACd,EAAE,gBAAgB,2CA6ElB"}
@@ -0,0 +1,103 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useTheme } from '@principal-ade/industry-theme';
3
+ import { MetricCard, LineChart, BarChart, SourceLink } from './components';
4
+ export function MetricPanel({ metric, data, onMetricClick, onSourceClick, }) {
5
+ const { theme } = useTheme();
6
+ // Determine which component to use
7
+ const componentType = getComponentType(metric, data);
8
+ // Render loading state
9
+ if (data.loading) {
10
+ return (_jsx("div", { style: {
11
+ backgroundColor: theme.colors.surface || theme.colors.background,
12
+ border: `1px solid ${theme.colors.border}`,
13
+ borderRadius: theme.radii?.[2] || 8,
14
+ padding: theme.space?.[3] || 16,
15
+ minHeight: 100,
16
+ display: 'flex',
17
+ alignItems: 'center',
18
+ justifyContent: 'center',
19
+ fontFamily: theme.fonts.body,
20
+ }, children: _jsx("span", { style: { color: theme.colors.textSecondary, fontSize: theme.fontSizes[1] }, children: "Loading..." }) }));
21
+ }
22
+ // Render error state
23
+ if (data.error) {
24
+ return (_jsxs("div", { style: {
25
+ backgroundColor: theme.colors.surface || theme.colors.background,
26
+ border: `1px solid ${theme.colors.error}`,
27
+ borderRadius: theme.radii?.[2] || 8,
28
+ padding: theme.space?.[3] || 16,
29
+ fontFamily: theme.fonts.body,
30
+ }, children: [_jsx("div", { style: {
31
+ color: theme.colors.error,
32
+ marginBottom: theme.space?.[2] || 8,
33
+ fontSize: theme.fontSizes[1],
34
+ fontWeight: theme.fontWeights.medium,
35
+ }, children: metric.name }), _jsx("div", { style: { color: theme.colors.textSecondary, fontSize: theme.fontSizes[0] }, children: data.error })] }));
36
+ }
37
+ const handleClick = () => {
38
+ onMetricClick?.(metric.id);
39
+ };
40
+ return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 8 }, children: [renderComponent(componentType, metric, data, handleClick), metric.sources && metric.sources.length > 0 && onSourceClick && (_jsx("div", { style: { display: 'flex', gap: 8, flexWrap: 'wrap' }, children: metric.sources.map((source, i) => (_jsx(SourceLink, { source: source, onClick: onSourceClick }, i))) }))] }));
41
+ }
42
+ /**
43
+ * Determine which component to render based on metric definition and data
44
+ */
45
+ function getComponentType(metric, data) {
46
+ // Explicit display hint takes precedence
47
+ if (metric.display?.component) {
48
+ return metric.display.component;
49
+ }
50
+ const { type, query } = metric;
51
+ // Time series data → chart
52
+ if (data.series && data.series.length > 0) {
53
+ if (query.groupBy && query.groupBy.length > 0) {
54
+ return 'StackedBarChart';
55
+ }
56
+ return 'LineChart';
57
+ }
58
+ // Histogram data
59
+ if (data.histogram) {
60
+ return 'Histogram';
61
+ }
62
+ // Counter with time grouping → line/bar chart (but no series data yet)
63
+ if (type === 'counter' && query.timeGroup) {
64
+ return query.groupBy?.length ? 'BarChart' : 'LineChart';
65
+ }
66
+ // Gauge (percentage) → gauge or metric card
67
+ if (type === 'gauge') {
68
+ return metric.thresholds ? 'GaugeChart' : 'MetricCard';
69
+ }
70
+ // Default to metric card
71
+ return 'MetricCard';
72
+ }
73
+ /**
74
+ * Render the appropriate component
75
+ */
76
+ function renderComponent(componentType, metric, data, onClick) {
77
+ switch (componentType) {
78
+ case 'MetricCard':
79
+ case 'GaugeChart': // Use MetricCard for now, can add GaugeChart later
80
+ return (_jsx(MetricCard, { title: metric.name, value: data.current ?? 0, unit: metric.unit, description: metric.description, trend: data.trend, changePercent: data.changePercent, showTrend: metric.display?.showTrend ?? true, showSparkline: metric.display?.showSparkline, sparklineData: data.series, thresholds: metric.thresholds, size: metric.display?.size || 'medium', onClick: onClick }));
81
+ case 'LineChart':
82
+ return (_jsx(LineChart, { title: metric.name, data: data.series || [], xKey: "date", yKey: "value", unit: metric.unit, onClick: onClick }));
83
+ case 'BarChart':
84
+ case 'StackedBarChart':
85
+ // Extract series keys from data
86
+ const series = data.series && data.series.length > 0
87
+ ? Object.keys(data.series[0]).filter(k => k !== 'date')
88
+ : metric.query.groupBy || [];
89
+ return (_jsx(BarChart, { title: metric.name, data: data.series || [], xKey: "date", series: series, stacked: componentType === 'StackedBarChart', unit: metric.unit, onClick: onClick }));
90
+ case 'Histogram':
91
+ // TODO: Implement Histogram component
92
+ return (_jsx(MetricCard, { title: metric.name, value: "Histogram (TODO)", description: metric.description, onClick: onClick }));
93
+ case 'PieChart':
94
+ // TODO: Implement PieChart component
95
+ return (_jsx(MetricCard, { title: metric.name, value: "PieChart (TODO)", description: metric.description, onClick: onClick }));
96
+ case 'DataTable':
97
+ // TODO: Implement DataTable component
98
+ return (_jsx(MetricCard, { title: metric.name, value: "DataTable (TODO)", description: metric.description, onClick: onClick }));
99
+ default:
100
+ return (_jsx(MetricCard, { title: metric.name, value: data.current ?? 0, unit: metric.unit, onClick: onClick }));
101
+ }
102
+ }
103
+ //# sourceMappingURL=MetricPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetricPanel.js","sourceRoot":"","sources":["../../../src/components/dashboard/MetricPanel.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * MockDataProvider
3
+ *
4
+ * Provides mock data for dashboard metrics during prototyping.
5
+ * Can use inline _mockData from the dashboard definition or generate realistic data.
6
+ */
7
+ import type { DashboardDefinition, MetricData, DataProvider } from './types';
8
+ export declare class MockDataProvider implements DataProvider {
9
+ private data;
10
+ constructor(dashboard: DashboardDefinition);
11
+ get(metricId: string): MetricData;
12
+ getAll(): Record<string, MetricData>;
13
+ private resolveData;
14
+ private transformMockData;
15
+ private generateData;
16
+ private generateTimeSeries;
17
+ private generateGaugeData;
18
+ private generateCounterData;
19
+ private generateHistogramData;
20
+ private getPointCount;
21
+ private getBaseValue;
22
+ private generateDates;
23
+ private getWeekNumber;
24
+ private getGroupValues;
25
+ }
26
+ /**
27
+ * Create a mock data provider from a dashboard definition
28
+ */
29
+ export declare function createMockDataProvider(dashboard: DashboardDefinition): DataProvider;
30
+ //# sourceMappingURL=MockDataProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockDataProvider.d.ts","sourceRoot":"","sources":["../../../src/components/dashboard/MockDataProvider.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,mBAAmB,EAEnB,UAAU,EACV,YAAY,EAEb,MAAM,SAAS,CAAC;AAEjB,qBAAa,gBAAiB,YAAW,YAAY;IACnD,OAAO,CAAC,IAAI,CAAkC;gBAElC,SAAS,EAAE,mBAAmB;IAM1C,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU;IAIjC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC;IAIpC,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,iBAAiB;IA4CzB,OAAO,CAAC,YAAY;IA4BpB,OAAO,CAAC,kBAAkB;IAqC1B,OAAO,CAAC,iBAAiB;IAmCzB,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,qBAAqB;IAqC7B,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,aAAa;IAqCrB,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,cAAc;CAcvB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,mBAAmB,GAAG,YAAY,CAEnF"}
@@ -0,0 +1,270 @@
1
+ /**
2
+ * MockDataProvider
3
+ *
4
+ * Provides mock data for dashboard metrics during prototyping.
5
+ * Can use inline _mockData from the dashboard definition or generate realistic data.
6
+ */
7
+ export class MockDataProvider {
8
+ constructor(dashboard) {
9
+ this.data = {};
10
+ for (const metric of dashboard.metrics) {
11
+ this.data[metric.id] = this.resolveData(metric);
12
+ }
13
+ }
14
+ get(metricId) {
15
+ return this.data[metricId] || { error: `No data for metric: ${metricId}` };
16
+ }
17
+ getAll() {
18
+ return this.data;
19
+ }
20
+ resolveData(metric) {
21
+ // Use inline mock data if provided
22
+ if (metric._mockData) {
23
+ return this.transformMockData(metric._mockData, metric);
24
+ }
25
+ // Generate data based on metric type and query
26
+ return this.generateData(metric);
27
+ }
28
+ transformMockData(mockData, _metric) {
29
+ const result = {};
30
+ if (mockData.current !== undefined) {
31
+ result.current = mockData.current;
32
+ }
33
+ if (mockData.previous !== undefined) {
34
+ result.previous = mockData.previous;
35
+ // Calculate change percent if not provided
36
+ if (result.current !== undefined) {
37
+ result.changePercent =
38
+ ((result.current - mockData.previous) / mockData.previous) * 100;
39
+ result.trend =
40
+ result.changePercent > 0
41
+ ? 'up'
42
+ : result.changePercent < 0
43
+ ? 'down'
44
+ : 'flat';
45
+ }
46
+ }
47
+ if (mockData.trend) {
48
+ result.trend = mockData.trend;
49
+ }
50
+ if (mockData.series) {
51
+ result.series = mockData.series;
52
+ }
53
+ if (mockData.breakdown) {
54
+ result.breakdown = mockData.breakdown;
55
+ }
56
+ if (mockData.histogram) {
57
+ result.histogram = mockData.histogram;
58
+ }
59
+ return result;
60
+ }
61
+ generateData(metric) {
62
+ const { type, query } = metric;
63
+ // Time series data
64
+ if (query.timeGroup) {
65
+ return this.generateTimeSeries(metric);
66
+ }
67
+ // Single value
68
+ if (type === 'gauge') {
69
+ return this.generateGaugeData(metric);
70
+ }
71
+ if (type === 'counter') {
72
+ return this.generateCounterData(metric);
73
+ }
74
+ if (type === 'histogram') {
75
+ return this.generateHistogramData(metric);
76
+ }
77
+ // Fallback
78
+ return {
79
+ current: Math.floor(Math.random() * 1000),
80
+ trend: 'flat',
81
+ };
82
+ }
83
+ generateTimeSeries(metric) {
84
+ const { query } = metric;
85
+ const points = this.getPointCount(query.timeGroup);
86
+ const series = [];
87
+ const baseValue = this.getBaseValue(metric);
88
+ const variance = 0.2;
89
+ // Generate dates
90
+ const dates = this.generateDates(query.timeGroup, points);
91
+ if (query.groupBy && query.groupBy.length > 0) {
92
+ // Grouped data (e.g., by isMobile)
93
+ const groups = this.getGroupValues(query.groupBy[0]);
94
+ for (let i = 0; i < points; i++) {
95
+ const point = { date: dates[i] };
96
+ for (const group of groups) {
97
+ point[group] = Math.floor(baseValue * (0.3 + Math.random() * 0.7) * (1 + (Math.random() - 0.5) * variance));
98
+ }
99
+ series.push(point);
100
+ }
101
+ }
102
+ else {
103
+ // Simple time series
104
+ for (let i = 0; i < points; i++) {
105
+ series.push({
106
+ date: dates[i],
107
+ value: Math.floor(baseValue * (1 + (Math.random() - 0.5) * variance)),
108
+ });
109
+ }
110
+ }
111
+ return { series };
112
+ }
113
+ generateGaugeData(metric) {
114
+ const { query } = metric;
115
+ // Percentage derivations
116
+ if (query.derivation === 'percentage' ||
117
+ query.derivation === 'error_rate' ||
118
+ query.derivation === 'success_rate') {
119
+ const current = Math.random() * 100;
120
+ const previous = Math.random() * 100;
121
+ return {
122
+ current: Math.round(current * 10) / 10,
123
+ previous: Math.round(previous * 10) / 10,
124
+ trend: current > previous ? 'up' : current < previous ? 'down' : 'flat',
125
+ changePercent: Math.round(((current - previous) / previous) * 100 * 10) / 10,
126
+ };
127
+ }
128
+ // Rate
129
+ if (query.derivation === 'rate') {
130
+ const current = Math.floor(Math.random() * 1000);
131
+ const previous = Math.floor(Math.random() * 1000);
132
+ return {
133
+ current,
134
+ previous,
135
+ trend: current > previous ? 'up' : current < previous ? 'down' : 'flat',
136
+ changePercent: Math.round(((current - previous) / previous) * 100),
137
+ };
138
+ }
139
+ const current = Math.floor(Math.random() * 10000);
140
+ return { current, trend: 'flat' };
141
+ }
142
+ generateCounterData(_metric) {
143
+ const current = Math.floor(Math.random() * 100000);
144
+ const previous = Math.floor(Math.random() * 100000);
145
+ return {
146
+ current,
147
+ previous,
148
+ trend: current > previous ? 'up' : current < previous ? 'down' : 'flat',
149
+ changePercent: Math.round(((current - previous) / previous) * 100),
150
+ };
151
+ }
152
+ generateHistogramData(metric) {
153
+ const { query } = metric;
154
+ // Percentile value
155
+ if (query.percentile) {
156
+ const values = [50, 120, 200, 350, 500, 800, 1200];
157
+ const percentileIndex = Math.min(Math.floor((query.percentile / 100) * values.length), values.length - 1);
158
+ const current = values[percentileIndex] + Math.floor(Math.random() * 100);
159
+ const previous = values[percentileIndex] + Math.floor(Math.random() * 100);
160
+ return {
161
+ current,
162
+ previous,
163
+ trend: current > previous ? 'up' : current < previous ? 'down' : 'flat',
164
+ changePercent: Math.round(((current - previous) / previous) * 100),
165
+ };
166
+ }
167
+ // Full histogram
168
+ return {
169
+ histogram: {
170
+ buckets: ['0-50ms', '50-100ms', '100-200ms', '200-500ms', '500ms-1s', '>1s'],
171
+ counts: [
172
+ Math.floor(Math.random() * 1000),
173
+ Math.floor(Math.random() * 800),
174
+ Math.floor(Math.random() * 400),
175
+ Math.floor(Math.random() * 200),
176
+ Math.floor(Math.random() * 100),
177
+ Math.floor(Math.random() * 50),
178
+ ],
179
+ },
180
+ };
181
+ }
182
+ getPointCount(timeGroup) {
183
+ switch (timeGroup) {
184
+ case 'minute':
185
+ return 60;
186
+ case 'hour':
187
+ return 24;
188
+ case 'day':
189
+ return 7;
190
+ case 'week':
191
+ return 12;
192
+ case 'month':
193
+ return 12;
194
+ default:
195
+ return 7;
196
+ }
197
+ }
198
+ getBaseValue(metric) {
199
+ // Estimate reasonable base value based on metric type
200
+ if (metric.query.derivation === 'percentage' || metric.query.derivation === 'error_rate') {
201
+ return 50;
202
+ }
203
+ if (metric.unit === 'views' || metric.unit === 'count') {
204
+ return 10000;
205
+ }
206
+ if (metric.unit === 'milliseconds' || metric.unit === 'ms') {
207
+ return 200;
208
+ }
209
+ return 1000;
210
+ }
211
+ generateDates(timeGroup, count) {
212
+ const dates = [];
213
+ const now = new Date();
214
+ for (let i = count - 1; i >= 0; i--) {
215
+ const date = new Date(now);
216
+ switch (timeGroup) {
217
+ case 'minute':
218
+ date.setMinutes(date.getMinutes() - i);
219
+ dates.push(date.toISOString().slice(11, 16)); // HH:MM
220
+ break;
221
+ case 'hour':
222
+ date.setHours(date.getHours() - i);
223
+ dates.push(date.toISOString().slice(11, 13) + ':00'); // HH:00
224
+ break;
225
+ case 'day':
226
+ date.setDate(date.getDate() - i);
227
+ dates.push(date.toISOString().slice(0, 10)); // YYYY-MM-DD
228
+ break;
229
+ case 'week':
230
+ date.setDate(date.getDate() - i * 7);
231
+ dates.push(`W${this.getWeekNumber(date)}`);
232
+ break;
233
+ case 'month':
234
+ date.setMonth(date.getMonth() - i);
235
+ dates.push(date.toISOString().slice(0, 7)); // YYYY-MM
236
+ break;
237
+ default:
238
+ date.setDate(date.getDate() - i);
239
+ dates.push(date.toISOString().slice(0, 10));
240
+ }
241
+ }
242
+ return dates;
243
+ }
244
+ getWeekNumber(date) {
245
+ const firstDayOfYear = new Date(date.getFullYear(), 0, 1);
246
+ const pastDaysOfYear = (date.getTime() - firstDayOfYear.getTime()) / 86400000;
247
+ return Math.ceil((pastDaysOfYear + firstDayOfYear.getDay() + 1) / 7);
248
+ }
249
+ getGroupValues(groupBy) {
250
+ // Common group values based on attribute name
251
+ if (groupBy === 'isMobile') {
252
+ return ['mobile', 'desktop'];
253
+ }
254
+ if (groupBy === 'status' || groupBy === 'status.code') {
255
+ return ['success', 'error'];
256
+ }
257
+ if (groupBy === 'user.tier') {
258
+ return ['free', 'pro', 'enterprise'];
259
+ }
260
+ // Default generic groups
261
+ return ['group_a', 'group_b'];
262
+ }
263
+ }
264
+ /**
265
+ * Create a mock data provider from a dashboard definition
266
+ */
267
+ export function createMockDataProvider(dashboard) {
268
+ return new MockDataProvider(dashboard);
269
+ }
270
+ //# sourceMappingURL=MockDataProvider.js.map