@object-ui/plugin-dashboard 3.1.4 → 3.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/.turbo/turbo-build.log +14 -10
- package/CHANGELOG.md +27 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +809 -668
- package/dist/index.umd.cjs +3 -3
- package/dist/packages/plugin-dashboard/src/DashboardConfigPanel.d.ts.map +1 -0
- package/dist/packages/plugin-dashboard/src/DashboardConfigPanel.stories.d.ts.map +1 -0
- package/dist/packages/plugin-dashboard/src/DashboardGridLayout.d.ts.map +1 -0
- package/dist/packages/plugin-dashboard/src/DashboardRenderer.d.ts.map +1 -0
- package/dist/packages/plugin-dashboard/src/DashboardRenderer.stories.d.ts.map +1 -0
- package/dist/packages/plugin-dashboard/src/DashboardWithConfig.d.ts.map +1 -0
- package/dist/{src → packages/plugin-dashboard/src}/MetricCard.d.ts +4 -0
- package/dist/packages/plugin-dashboard/src/MetricCard.d.ts.map +1 -0
- package/dist/{src → packages/plugin-dashboard/src}/MetricWidget.d.ts +5 -1
- package/dist/packages/plugin-dashboard/src/MetricWidget.d.ts.map +1 -0
- package/dist/packages/plugin-dashboard/src/ObjectDataTable.d.ts.map +1 -0
- package/dist/packages/plugin-dashboard/src/ObjectMetricWidget.d.ts +57 -0
- package/dist/packages/plugin-dashboard/src/ObjectMetricWidget.d.ts.map +1 -0
- package/dist/packages/plugin-dashboard/src/ObjectPivotTable.d.ts.map +1 -0
- package/dist/packages/plugin-dashboard/src/PivotTable.d.ts.map +1 -0
- package/dist/packages/plugin-dashboard/src/WidgetConfigPanel.d.ts.map +1 -0
- package/dist/{src → packages/plugin-dashboard/src}/index.d.ts +4 -2
- package/dist/packages/plugin-dashboard/src/index.d.ts.map +1 -0
- package/dist/packages/plugin-dashboard/src/utils.d.ts.map +1 -0
- package/package.json +11 -11
- package/src/DashboardRenderer.tsx +34 -0
- package/src/MetricCard.tsx +38 -18
- package/src/MetricWidget.tsx +38 -18
- package/src/ObjectMetricWidget.tsx +159 -0
- package/src/__tests__/DashboardRenderer.widgetData.test.tsx +130 -2
- package/src/__tests__/MetricCard.test.tsx +25 -0
- package/src/__tests__/ObjectMetricWidget.test.tsx +196 -0
- package/src/index.tsx +23 -1
- package/vite.config.ts +1 -0
- package/dist/src/DashboardConfigPanel.d.ts.map +0 -1
- package/dist/src/DashboardConfigPanel.stories.d.ts.map +0 -1
- package/dist/src/DashboardGridLayout.d.ts.map +0 -1
- package/dist/src/DashboardRenderer.d.ts.map +0 -1
- package/dist/src/DashboardRenderer.stories.d.ts.map +0 -1
- package/dist/src/DashboardWithConfig.d.ts.map +0 -1
- package/dist/src/MetricCard.d.ts.map +0 -1
- package/dist/src/MetricWidget.d.ts.map +0 -1
- package/dist/src/ObjectDataTable.d.ts.map +0 -1
- package/dist/src/ObjectPivotTable.d.ts.map +0 -1
- package/dist/src/PivotTable.d.ts.map +0 -1
- package/dist/src/WidgetConfigPanel.d.ts.map +0 -1
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/utils.d.ts.map +0 -1
- /package/dist/{src → packages/plugin-dashboard/src}/DashboardConfigPanel.d.ts +0 -0
- /package/dist/{src → packages/plugin-dashboard/src}/DashboardConfigPanel.stories.d.ts +0 -0
- /package/dist/{src → packages/plugin-dashboard/src}/DashboardGridLayout.d.ts +0 -0
- /package/dist/{src → packages/plugin-dashboard/src}/DashboardRenderer.d.ts +0 -0
- /package/dist/{src → packages/plugin-dashboard/src}/DashboardRenderer.stories.d.ts +0 -0
- /package/dist/{src → packages/plugin-dashboard/src}/DashboardWithConfig.d.ts +0 -0
- /package/dist/{src → packages/plugin-dashboard/src}/ObjectDataTable.d.ts +0 -0
- /package/dist/{src → packages/plugin-dashboard/src}/ObjectPivotTable.d.ts +0 -0
- /package/dist/{src → packages/plugin-dashboard/src}/PivotTable.d.ts +0 -0
- /package/dist/{src → packages/plugin-dashboard/src}/WidgetConfigPanel.d.ts +0 -0
- /package/dist/{src → packages/plugin-dashboard/src}/utils.d.ts +0 -0
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { describe, it, expect } from 'vitest';
|
|
10
|
-
import { render } from '@testing-library/react';
|
|
9
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
10
|
+
import { render, waitFor } from '@testing-library/react';
|
|
11
|
+
import { SchemaRendererProvider } from '@object-ui/react';
|
|
11
12
|
import { DashboardRenderer } from '../DashboardRenderer';
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -1280,4 +1281,131 @@ describe('DashboardRenderer widget data extraction', () => {
|
|
|
1280
1281
|
expect((card as HTMLElement).style.gridColumn).toBe('span 3');
|
|
1281
1282
|
}
|
|
1282
1283
|
});
|
|
1284
|
+
|
|
1285
|
+
// --- Metric widget with object binding → object-metric ---
|
|
1286
|
+
// When widget.type === 'metric' AND widget.object is set, DashboardRenderer
|
|
1287
|
+
// routes to the registered 'object-metric' component (ObjectMetricWidget).
|
|
1288
|
+
// Without a dataSource in context, it renders the static fallbackValue.
|
|
1289
|
+
|
|
1290
|
+
it('should route metric widgets with object binding to object-metric (renders fallback without dataSource)', () => {
|
|
1291
|
+
const schema = {
|
|
1292
|
+
type: 'dashboard' as const,
|
|
1293
|
+
name: 'test',
|
|
1294
|
+
title: 'Test',
|
|
1295
|
+
widgets: [
|
|
1296
|
+
{
|
|
1297
|
+
type: 'metric',
|
|
1298
|
+
object: 'opportunity',
|
|
1299
|
+
layout: { x: 0, y: 0, w: 1, h: 1 },
|
|
1300
|
+
options: {
|
|
1301
|
+
label: 'Total Revenue',
|
|
1302
|
+
value: '$652,000',
|
|
1303
|
+
icon: 'DollarSign',
|
|
1304
|
+
},
|
|
1305
|
+
},
|
|
1306
|
+
],
|
|
1307
|
+
} as any;
|
|
1308
|
+
|
|
1309
|
+
const { container } = render(<DashboardRenderer schema={schema} />);
|
|
1310
|
+
|
|
1311
|
+
// ObjectMetricWidget renders fallbackValue when no dataSource is present
|
|
1312
|
+
expect(container.textContent).toContain('Total Revenue');
|
|
1313
|
+
expect(container.textContent).toContain('$652,000');
|
|
1314
|
+
});
|
|
1315
|
+
|
|
1316
|
+
it('should keep static metric widgets as-is when no object binding', () => {
|
|
1317
|
+
const schema = {
|
|
1318
|
+
type: 'dashboard' as const,
|
|
1319
|
+
name: 'test',
|
|
1320
|
+
title: 'Test',
|
|
1321
|
+
widgets: [
|
|
1322
|
+
{
|
|
1323
|
+
type: 'metric',
|
|
1324
|
+
layout: { x: 0, y: 0, w: 1, h: 1 },
|
|
1325
|
+
options: {
|
|
1326
|
+
label: 'Static Metric',
|
|
1327
|
+
value: '42',
|
|
1328
|
+
},
|
|
1329
|
+
},
|
|
1330
|
+
],
|
|
1331
|
+
} as any;
|
|
1332
|
+
|
|
1333
|
+
const { container } = render(<DashboardRenderer schema={schema} />);
|
|
1334
|
+
|
|
1335
|
+
// Static metrics without object binding should render the value directly
|
|
1336
|
+
expect(container.textContent).toContain('Static Metric');
|
|
1337
|
+
expect(container.textContent).toContain('42');
|
|
1338
|
+
});
|
|
1339
|
+
|
|
1340
|
+
it('should route metric with data.provider object to object-metric (renders fallback without dataSource)', () => {
|
|
1341
|
+
const schema = {
|
|
1342
|
+
type: 'dashboard' as const,
|
|
1343
|
+
name: 'test',
|
|
1344
|
+
title: 'Test',
|
|
1345
|
+
widgets: [
|
|
1346
|
+
{
|
|
1347
|
+
type: 'metric',
|
|
1348
|
+
object: 'opportunity',
|
|
1349
|
+
layout: { x: 0, y: 0, w: 1, h: 1 },
|
|
1350
|
+
options: {
|
|
1351
|
+
label: 'Revenue Sum',
|
|
1352
|
+
value: '$0',
|
|
1353
|
+
data: {
|
|
1354
|
+
provider: 'object',
|
|
1355
|
+
object: 'opportunity',
|
|
1356
|
+
aggregate: { field: 'amount', function: 'sum', groupBy: '_all' },
|
|
1357
|
+
},
|
|
1358
|
+
},
|
|
1359
|
+
},
|
|
1360
|
+
],
|
|
1361
|
+
} as any;
|
|
1362
|
+
|
|
1363
|
+
const { container } = render(<DashboardRenderer schema={schema} />);
|
|
1364
|
+
|
|
1365
|
+
// ObjectMetricWidget renders fallbackValue when no dataSource is present
|
|
1366
|
+
expect(container.textContent).toContain('Revenue Sum');
|
|
1367
|
+
expect(container.textContent).toContain('$0');
|
|
1368
|
+
});
|
|
1369
|
+
|
|
1370
|
+
it('should show error state when object-metric dataSource fails', async () => {
|
|
1371
|
+
const dataSource = {
|
|
1372
|
+
aggregate: vi.fn().mockRejectedValue(new Error('Cube name is required')),
|
|
1373
|
+
find: vi.fn(),
|
|
1374
|
+
};
|
|
1375
|
+
|
|
1376
|
+
const schema = {
|
|
1377
|
+
type: 'dashboard' as const,
|
|
1378
|
+
name: 'test',
|
|
1379
|
+
title: 'Test',
|
|
1380
|
+
widgets: [
|
|
1381
|
+
{
|
|
1382
|
+
type: 'metric',
|
|
1383
|
+
object: 'opportunity',
|
|
1384
|
+
aggregate: 'sum',
|
|
1385
|
+
valueField: 'amount',
|
|
1386
|
+
layout: { x: 0, y: 0, w: 1, h: 1 },
|
|
1387
|
+
options: {
|
|
1388
|
+
label: 'Revenue',
|
|
1389
|
+
value: '$999',
|
|
1390
|
+
},
|
|
1391
|
+
},
|
|
1392
|
+
],
|
|
1393
|
+
} as any;
|
|
1394
|
+
|
|
1395
|
+
const { container } = render(
|
|
1396
|
+
<SchemaRendererProvider dataSource={dataSource}>
|
|
1397
|
+
<DashboardRenderer schema={schema} />
|
|
1398
|
+
</SchemaRendererProvider>,
|
|
1399
|
+
);
|
|
1400
|
+
|
|
1401
|
+
// Should display the error from the failing aggregate, not the fallback value
|
|
1402
|
+
await waitFor(() => {
|
|
1403
|
+
const errorEl = container.querySelector('[data-testid="metric-error"]');
|
|
1404
|
+
expect(errorEl).toBeTruthy();
|
|
1405
|
+
});
|
|
1406
|
+
|
|
1407
|
+
expect(container.textContent).toContain('Revenue');
|
|
1408
|
+
expect(container.textContent).toContain('Cube name is required');
|
|
1409
|
+
expect(container.textContent).not.toContain('$999');
|
|
1410
|
+
});
|
|
1283
1411
|
});
|
|
@@ -79,4 +79,29 @@ describe('MetricCard', () => {
|
|
|
79
79
|
|
|
80
80
|
expect(screen.getByText('vs last month')).toBeInTheDocument();
|
|
81
81
|
});
|
|
82
|
+
|
|
83
|
+
it('should show loading state when loading prop is true', () => {
|
|
84
|
+
const { container } = render(
|
|
85
|
+
<MetricCard title="Revenue" value="$45,231" loading={true} />
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const loadingEl = container.querySelector('[data-testid="metric-card-loading"]');
|
|
89
|
+
expect(loadingEl).toBeTruthy();
|
|
90
|
+
// Value should not be rendered during loading
|
|
91
|
+
expect(container.textContent).not.toContain('$45,231');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should show error state when error prop is set', () => {
|
|
95
|
+
const { container } = render(
|
|
96
|
+
<MetricCard title="Revenue" value="$45,231" error="Connection refused" />
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const errorEl = container.querySelector('[data-testid="metric-card-error"]');
|
|
100
|
+
expect(errorEl).toBeTruthy();
|
|
101
|
+
expect(screen.getByText('Connection refused')).toBeInTheDocument();
|
|
102
|
+
// Value should not be rendered during error
|
|
103
|
+
expect(container.textContent).not.toContain('$45,231');
|
|
104
|
+
// Title should still be visible
|
|
105
|
+
expect(screen.getByText('Revenue')).toBeInTheDocument();
|
|
106
|
+
});
|
|
82
107
|
});
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
10
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
|
11
|
+
import React from 'react';
|
|
12
|
+
import '@testing-library/jest-dom';
|
|
13
|
+
import { ObjectMetricWidget } from '../ObjectMetricWidget';
|
|
14
|
+
import { SchemaRendererProvider } from '@object-ui/react';
|
|
15
|
+
|
|
16
|
+
// Suppress console.error from expected fetch errors
|
|
17
|
+
const originalConsoleError = console.error;
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
console.error = vi.fn();
|
|
20
|
+
});
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
console.error = originalConsoleError;
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('ObjectMetricWidget', () => {
|
|
26
|
+
const baseProps = {
|
|
27
|
+
objectName: 'opportunity',
|
|
28
|
+
label: 'Total Revenue',
|
|
29
|
+
fallbackValue: '$652,000',
|
|
30
|
+
icon: 'DollarSign',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
it('should show fallback value when no dataSource is available', () => {
|
|
34
|
+
render(<ObjectMetricWidget {...baseProps} />);
|
|
35
|
+
|
|
36
|
+
expect(screen.getByText('Total Revenue')).toBeInTheDocument();
|
|
37
|
+
expect(screen.getByText('$652,000')).toBeInTheDocument();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should show loading state while fetching', async () => {
|
|
41
|
+
const dataSource = {
|
|
42
|
+
find: vi.fn(() => new Promise(() => {})), // Never resolves
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const { container } = render(
|
|
46
|
+
<SchemaRendererProvider dataSource={dataSource}>
|
|
47
|
+
<ObjectMetricWidget {...baseProps} />
|
|
48
|
+
</SchemaRendererProvider>,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
await waitFor(() => {
|
|
52
|
+
const loadingEl = container.querySelector('[data-testid="metric-loading"]');
|
|
53
|
+
expect(loadingEl).toBeTruthy();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should show error state when data fetch fails', async () => {
|
|
58
|
+
const dataSource = {
|
|
59
|
+
find: vi.fn().mockRejectedValue(new Error('Cube name is required')),
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const { container } = render(
|
|
63
|
+
<SchemaRendererProvider dataSource={dataSource}>
|
|
64
|
+
<ObjectMetricWidget {...baseProps} />
|
|
65
|
+
</SchemaRendererProvider>,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
await waitFor(() => {
|
|
69
|
+
const errorEl = container.querySelector('[data-testid="metric-error"]');
|
|
70
|
+
expect(errorEl).toBeTruthy();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
expect(screen.getByText('Cube name is required')).toBeInTheDocument();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should show error state when aggregate fails', async () => {
|
|
77
|
+
const dataSource = {
|
|
78
|
+
aggregate: vi.fn().mockRejectedValue(new Error('Connection refused')),
|
|
79
|
+
find: vi.fn(),
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const propsWithAggregate = {
|
|
83
|
+
...baseProps,
|
|
84
|
+
aggregate: { field: 'amount', function: 'sum', groupBy: 'stage' },
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const { container } = render(
|
|
88
|
+
<SchemaRendererProvider dataSource={dataSource}>
|
|
89
|
+
<ObjectMetricWidget {...propsWithAggregate} />
|
|
90
|
+
</SchemaRendererProvider>,
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
await waitFor(() => {
|
|
94
|
+
const errorEl = container.querySelector('[data-testid="metric-error"]');
|
|
95
|
+
expect(errorEl).toBeTruthy();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
expect(screen.getByText('Connection refused')).toBeInTheDocument();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should display fetched value from find()', async () => {
|
|
102
|
+
const dataSource = {
|
|
103
|
+
find: vi.fn().mockResolvedValue({
|
|
104
|
+
data: [
|
|
105
|
+
{ name: 'A', amount: 100 },
|
|
106
|
+
{ name: 'B', amount: 200 },
|
|
107
|
+
{ name: 'C', amount: 300 },
|
|
108
|
+
],
|
|
109
|
+
}),
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
render(
|
|
113
|
+
<SchemaRendererProvider dataSource={dataSource}>
|
|
114
|
+
<ObjectMetricWidget {...baseProps} />
|
|
115
|
+
</SchemaRendererProvider>,
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
// When no aggregate config, it falls back to counting records
|
|
119
|
+
await waitFor(() => {
|
|
120
|
+
expect(screen.getByText('3')).toBeInTheDocument();
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('should display aggregated value from aggregate()', async () => {
|
|
125
|
+
const dataSource = {
|
|
126
|
+
aggregate: vi.fn().mockResolvedValue([
|
|
127
|
+
{ stage: 'All', amount: 652000 },
|
|
128
|
+
]),
|
|
129
|
+
find: vi.fn(),
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const propsWithAggregate = {
|
|
133
|
+
...baseProps,
|
|
134
|
+
aggregate: { field: 'amount', function: 'sum', groupBy: '_all' },
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
render(
|
|
138
|
+
<SchemaRendererProvider dataSource={dataSource}>
|
|
139
|
+
<ObjectMetricWidget {...propsWithAggregate} />
|
|
140
|
+
</SchemaRendererProvider>,
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
await waitFor(() => {
|
|
144
|
+
expect(screen.getByText('652000')).toBeInTheDocument();
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Should have called aggregate, not find
|
|
148
|
+
expect(dataSource.aggregate).toHaveBeenCalledWith('opportunity', {
|
|
149
|
+
field: 'amount',
|
|
150
|
+
function: 'sum',
|
|
151
|
+
groupBy: '_all',
|
|
152
|
+
filter: undefined,
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should render label even in error state', async () => {
|
|
157
|
+
const dataSource = {
|
|
158
|
+
find: vi.fn().mockRejectedValue(new Error('Server error')),
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
render(
|
|
162
|
+
<SchemaRendererProvider dataSource={dataSource}>
|
|
163
|
+
<ObjectMetricWidget {...baseProps} />
|
|
164
|
+
</SchemaRendererProvider>,
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
await waitFor(() => {
|
|
168
|
+
expect(screen.getByText('Server error')).toBeInTheDocument();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Label should still be visible
|
|
172
|
+
expect(screen.getByText('Total Revenue')).toBeInTheDocument();
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('should use prop dataSource over context dataSource', async () => {
|
|
176
|
+
const contextDs = {
|
|
177
|
+
find: vi.fn().mockResolvedValue({ data: [{ a: 1 }] }),
|
|
178
|
+
};
|
|
179
|
+
const propDs = {
|
|
180
|
+
find: vi.fn().mockResolvedValue({ data: [{ a: 1 }, { a: 2 }] }),
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
render(
|
|
184
|
+
<SchemaRendererProvider dataSource={contextDs}>
|
|
185
|
+
<ObjectMetricWidget {...baseProps} dataSource={propDs} />
|
|
186
|
+
</SchemaRendererProvider>,
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
await waitFor(() => {
|
|
190
|
+
expect(screen.getByText('2')).toBeInTheDocument();
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
expect(propDs.find).toHaveBeenCalled();
|
|
194
|
+
expect(contextDs.find).not.toHaveBeenCalled();
|
|
195
|
+
});
|
|
196
|
+
});
|
package/src/index.tsx
CHANGED
|
@@ -11,6 +11,7 @@ import { DashboardRenderer } from './DashboardRenderer';
|
|
|
11
11
|
import { DashboardGridLayout } from './DashboardGridLayout';
|
|
12
12
|
import { MetricWidget } from './MetricWidget';
|
|
13
13
|
import { MetricCard } from './MetricCard';
|
|
14
|
+
import { ObjectMetricWidget } from './ObjectMetricWidget';
|
|
14
15
|
import { PivotTable } from './PivotTable';
|
|
15
16
|
import { ObjectPivotTable } from './ObjectPivotTable';
|
|
16
17
|
import { ObjectDataTable } from './ObjectDataTable';
|
|
@@ -18,7 +19,7 @@ import { DashboardConfigPanel } from './DashboardConfigPanel';
|
|
|
18
19
|
import { WidgetConfigPanel } from './WidgetConfigPanel';
|
|
19
20
|
import { DashboardWithConfig } from './DashboardWithConfig';
|
|
20
21
|
|
|
21
|
-
export { DashboardRenderer, DashboardGridLayout, MetricWidget, MetricCard, PivotTable, ObjectPivotTable, ObjectDataTable, DashboardConfigPanel, WidgetConfigPanel, DashboardWithConfig };
|
|
22
|
+
export { DashboardRenderer, DashboardGridLayout, MetricWidget, MetricCard, ObjectMetricWidget, PivotTable, ObjectPivotTable, ObjectDataTable, DashboardConfigPanel, WidgetConfigPanel, DashboardWithConfig };
|
|
22
23
|
|
|
23
24
|
// Register dashboard component
|
|
24
25
|
ComponentRegistry.register(
|
|
@@ -83,6 +84,26 @@ ComponentRegistry.register(
|
|
|
83
84
|
}
|
|
84
85
|
);
|
|
85
86
|
|
|
87
|
+
// Register object-aware metric widget (async data loading with error states)
|
|
88
|
+
ComponentRegistry.register(
|
|
89
|
+
'object-metric',
|
|
90
|
+
ObjectMetricWidget,
|
|
91
|
+
{
|
|
92
|
+
namespace: 'plugin-dashboard',
|
|
93
|
+
label: 'Object Metric',
|
|
94
|
+
category: 'Dashboard',
|
|
95
|
+
inputs: [
|
|
96
|
+
{ name: 'objectName', type: 'string', label: 'Object Name', required: true },
|
|
97
|
+
{ name: 'label', type: 'string', label: 'Label' },
|
|
98
|
+
{ name: 'aggregate', type: 'object', label: 'Aggregate', description: 'Aggregation config: { field, function, groupBy }' },
|
|
99
|
+
{ name: 'icon', type: 'string', label: 'Icon (Lucide name)' },
|
|
100
|
+
],
|
|
101
|
+
defaultProps: {
|
|
102
|
+
label: 'Metric',
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
|
|
86
107
|
// Register pivot table component
|
|
87
108
|
ComponentRegistry.register(
|
|
88
109
|
'pivot',
|
|
@@ -205,6 +226,7 @@ export const dashboardComponents = {
|
|
|
205
226
|
DashboardGridLayout,
|
|
206
227
|
MetricWidget,
|
|
207
228
|
MetricCard,
|
|
229
|
+
ObjectMetricWidget,
|
|
208
230
|
PivotTable,
|
|
209
231
|
ObjectPivotTable,
|
|
210
232
|
ObjectDataTable,
|
package/vite.config.ts
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardConfigPanel.d.ts","sourceRoot":"","sources":["../../src/DashboardConfigPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAwGH,MAAM,WAAW,yBAAyB;IACxC,gCAAgC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,oBAAoB;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,iCAAiC;IACjC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IAC9C,oCAAoC;IACpC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;CACrD;AAMD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,IAAI,EACJ,OAAO,EACP,MAAM,EACN,MAAM,EACN,aAAa,GACd,EAAE,yBAAyB,2CAiB3B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardConfigPanel.stories.d.ts","sourceRoot":"","sources":["../../src/DashboardConfigPanel.stories.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAOvD,QAAA,MAAM,UAAU;;;;;;CAMA,CAAC;AAEjB,eAAe,UAAU,CAAC;AAC1B,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,UAAU,CAAC,CAAC;AAmCzC,eAAO,MAAM,YAAY,EAAE,KAE1B,CAAC;AA+EF,eAAO,MAAM,wBAAwB,EAAE,KAEtC,CAAC;AAkBF,eAAO,MAAM,yBAAyB,EAAE,KAEvC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardGridLayout.d.ts","sourceRoot":"","sources":["../../src/DashboardGridLayout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAA2C,KAAK,UAAU,IAAI,SAAS,EAAuC,MAAM,mBAAmB,CAAC;AAC/I,OAAO,kCAAkC,CAAC;AAI1C,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,kBAAkB,CAAC;AA2B/E,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAoUlE,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardRenderer.d.ts","sourceRoot":"","sources":["../../src/DashboardRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,kBAAkB,CAAC;AAuB/E,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,WAAW,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACrE,kEAAkE;IAClE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gDAAgD;IAChD,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,uDAAuD;IACvD,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAClD,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,eAAO,MAAM,iBAAiB,gIA2Y7B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardRenderer.stories.d.ts","sourceRoot":"","sources":["../../src/DashboardRenderer.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAIvD,QAAA,MAAM,IAAI;;;;;;;;;;;;;;;;CAUW,CAAC;AAEtB,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAInC,eAAO,MAAM,OAAO,EAAE,KAiCrB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAgD7B,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,KAkElC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardWithConfig.d.ts","sourceRoot":"","sources":["../../src/DashboardWithConfig.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,kBAAkB,CAAC;AAU/E,MAAM,WAAW,wBAAwB;IACvC,qCAAqC;IACrC,MAAM,EAAE,eAAe,CAAC;IACxB,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,6DAA6D;IAC7D,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IACpD,iEAAiE;IACjE,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IACvE,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,WAAW,EACX,iBAAyB,EACzB,SAAS,GACV,EAAE,wBAAwB,2CAiJ1B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MetricCard.d.ts","sourceRoot":"","sources":["../../src/MetricCard.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAa1B,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzD,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA8ChD,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MetricWidget.d.ts","sourceRoot":"","sources":["../../src/MetricWidget.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAavC,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,GAAG;YAAE,GAAG,CAAC,EAAE,MAAM,CAAC;YAAC,YAAY,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACzD,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;KACvC,CAAC;IACF,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAChE;AAED,eAAO,MAAM,YAAY,GAAI,iEAQ1B,iBAAiB,4CAyCnB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ObjectDataTable.d.ts","sourceRoot":"","sources":["../../src/ObjectDataTable.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAKxE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACrD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,GAAG,CAAC;QACb,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;QAChB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;IACF,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,6EAA6E;AAC7E,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,gBAAgB,EAAE,CAiB9F;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAiJ1D,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ObjectPivotTable.d.ts","sourceRoot":"","sources":["../../src/ObjectPivotTable.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA0C,MAAM,OAAO,CAAC;AAK/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,gBAAgB,GAAG;QACzB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACrD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,GAAG,CAAC;KACd,CAAC;IACF,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAyH5D,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PivotTable.d.ts","sourceRoot":"","sources":["../../src/PivotTable.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,gBAAgB,EAAoB,MAAM,kBAAkB,CAAC;AAG3E,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAqED;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA2KhD,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetConfigPanel.d.ts","sourceRoot":"","sources":["../../src/WidgetConfigPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAwE/B,MAAM,MAAM,YAAY,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAuX5D,MAAM,WAAW,sBAAsB;IACrC,gCAAgC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,oBAAoB;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,wCAAwC;IACxC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IAC9C,oCAAoC;IACpC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IACpD,oEAAoE;IACpE,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,2DAA2D;IAC3D,gBAAgB,CAAC,EAAE,YAAY,EAAE,CAAC;IAClC,+EAA+E;IAC/E,eAAe,CAAC,EAAE,YAAY,EAAE,CAAC;CAClC;AAiBD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,OAAO,EACP,MAAM,EACN,MAAM,EACN,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,eAAe,GAChB,EAAE,sBAAsB,2CA8BxB"}
|
package/dist/src/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,eAAe,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,CAAC;AAsLzL,eAAO,MAAM,mBAAmB;;;;;;;;;;;CAW/B,CAAC"}
|
package/dist/src/utils.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,4FAA4F;AAC5F,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,OAAO,GAAG,UAAU,IAAI;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,GAAG,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAE,CAO1I"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|