@object-ui/plugin-dashboard 0.1.1 → 0.5.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 +20 -0
- package/dist/index.css +1 -0
- package/dist/index.js +5797 -266
- package/dist/index.umd.cjs +5 -2
- package/dist/src/DashboardGridLayout.d.ts +11 -0
- package/dist/src/DashboardGridLayout.d.ts.map +1 -0
- package/dist/src/DashboardRenderer.d.ts +1 -1
- package/dist/src/DashboardRenderer.d.ts.map +1 -1
- package/dist/src/MetricCard.d.ts +16 -0
- package/dist/src/MetricCard.d.ts.map +1 -0
- package/dist/src/MetricWidget.d.ts +1 -1
- package/dist/src/MetricWidget.d.ts.map +1 -1
- package/dist/src/ReportBuilder.d.ts +11 -0
- package/dist/src/ReportBuilder.d.ts.map +1 -0
- package/dist/src/ReportRenderer.d.ts +15 -0
- package/dist/src/ReportRenderer.d.ts.map +1 -0
- package/dist/src/ReportViewer.d.ts +11 -0
- package/dist/src/ReportViewer.d.ts.map +1 -0
- package/dist/src/index.d.ts +19 -1
- package/dist/src/index.d.ts.map +1 -1
- package/package.json +10 -8
- package/src/DashboardGridLayout.tsx +210 -0
- package/src/DashboardRenderer.tsx +108 -20
- package/src/MetricCard.tsx +75 -0
- package/src/MetricWidget.tsx +13 -3
- package/src/ReportBuilder.tsx +625 -0
- package/src/ReportRenderer.tsx +89 -0
- package/src/ReportViewer.tsx +232 -0
- package/src/__tests__/DashboardGridLayout.test.tsx +199 -0
- package/src/__tests__/MetricCard.test.tsx +59 -0
- package/src/__tests__/ReportBuilder.test.tsx +115 -0
- package/src/__tests__/ReportViewer.test.tsx +107 -0
- package/src/index.tsx +122 -3
- package/vite.config.ts +19 -0
- package/vitest.config.ts +9 -0
- package/vitest.setup.tsx +18 -0
|
@@ -0,0 +1,107 @@
|
|
|
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 } from 'vitest';
|
|
10
|
+
import { render, screen } from '@testing-library/react';
|
|
11
|
+
import '@testing-library/jest-dom';
|
|
12
|
+
import { ReportViewer } from '../ReportViewer';
|
|
13
|
+
import type { ReportViewerSchema } from '@object-ui/types';
|
|
14
|
+
|
|
15
|
+
describe('ReportViewer', () => {
|
|
16
|
+
it('should render empty state when no report is provided', () => {
|
|
17
|
+
const schema: ReportViewerSchema = {
|
|
18
|
+
type: 'report-viewer',
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
render(<ReportViewer schema={schema} />);
|
|
22
|
+
|
|
23
|
+
expect(screen.getByText('No report to display')).toBeInTheDocument();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should render report with title and description', () => {
|
|
27
|
+
const schema: ReportViewerSchema = {
|
|
28
|
+
type: 'report-viewer',
|
|
29
|
+
report: {
|
|
30
|
+
type: 'report',
|
|
31
|
+
title: 'Sales Report',
|
|
32
|
+
description: 'Monthly sales analysis',
|
|
33
|
+
fields: [],
|
|
34
|
+
sections: [],
|
|
35
|
+
},
|
|
36
|
+
showToolbar: true,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
render(<ReportViewer schema={schema} />);
|
|
40
|
+
|
|
41
|
+
expect(screen.getByText('Sales Report')).toBeInTheDocument();
|
|
42
|
+
expect(screen.getByText('Monthly sales analysis')).toBeInTheDocument();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should render export and print buttons when enabled', () => {
|
|
46
|
+
const schema: ReportViewerSchema = {
|
|
47
|
+
type: 'report-viewer',
|
|
48
|
+
report: {
|
|
49
|
+
type: 'report',
|
|
50
|
+
title: 'Test Report',
|
|
51
|
+
showExportButtons: true,
|
|
52
|
+
fields: [],
|
|
53
|
+
sections: [],
|
|
54
|
+
},
|
|
55
|
+
showToolbar: true,
|
|
56
|
+
allowExport: true,
|
|
57
|
+
allowPrint: true,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
render(<ReportViewer schema={schema} />);
|
|
61
|
+
|
|
62
|
+
expect(screen.getByText('Export')).toBeInTheDocument();
|
|
63
|
+
expect(screen.getByText('Print')).toBeInTheDocument();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should render loading state', () => {
|
|
67
|
+
const schema: ReportViewerSchema = {
|
|
68
|
+
type: 'report-viewer',
|
|
69
|
+
report: {
|
|
70
|
+
type: 'report',
|
|
71
|
+
title: 'Test Report',
|
|
72
|
+
fields: [],
|
|
73
|
+
sections: [],
|
|
74
|
+
},
|
|
75
|
+
loading: true,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
render(<ReportViewer schema={schema} />);
|
|
79
|
+
|
|
80
|
+
expect(screen.getByText('Loading report data...')).toBeInTheDocument();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('should render report data in table when no sections defined', () => {
|
|
84
|
+
const schema: ReportViewerSchema = {
|
|
85
|
+
type: 'report-viewer',
|
|
86
|
+
report: {
|
|
87
|
+
type: 'report',
|
|
88
|
+
title: 'User Report',
|
|
89
|
+
fields: [
|
|
90
|
+
{ name: 'name', label: 'Name' },
|
|
91
|
+
{ name: 'email', label: 'Email' },
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
data: [
|
|
95
|
+
{ name: 'John Doe', email: 'john@example.com' },
|
|
96
|
+
{ name: 'Jane Smith', email: 'jane@example.com' },
|
|
97
|
+
],
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
render(<ReportViewer schema={schema} />);
|
|
101
|
+
|
|
102
|
+
expect(screen.getByText('Name')).toBeInTheDocument();
|
|
103
|
+
expect(screen.getByText('Email')).toBeInTheDocument();
|
|
104
|
+
expect(screen.getByText('John Doe')).toBeInTheDocument();
|
|
105
|
+
expect(screen.getByText('jane@example.com')).toBeInTheDocument();
|
|
106
|
+
});
|
|
107
|
+
});
|
package/src/index.tsx
CHANGED
|
@@ -8,15 +8,21 @@
|
|
|
8
8
|
|
|
9
9
|
import { ComponentRegistry } from '@object-ui/core';
|
|
10
10
|
import { DashboardRenderer } from './DashboardRenderer';
|
|
11
|
+
import { DashboardGridLayout } from './DashboardGridLayout';
|
|
11
12
|
import { MetricWidget } from './MetricWidget';
|
|
13
|
+
import { MetricCard } from './MetricCard';
|
|
14
|
+
import { ReportRenderer } from './ReportRenderer';
|
|
15
|
+
import { ReportViewer } from './ReportViewer';
|
|
16
|
+
import { ReportBuilder } from './ReportBuilder';
|
|
12
17
|
|
|
13
|
-
export { DashboardRenderer, MetricWidget };
|
|
18
|
+
export { DashboardRenderer, DashboardGridLayout, MetricWidget, MetricCard, ReportRenderer, ReportViewer, ReportBuilder };
|
|
14
19
|
|
|
15
20
|
// Register dashboard component
|
|
16
21
|
ComponentRegistry.register(
|
|
17
22
|
'dashboard',
|
|
18
23
|
DashboardRenderer,
|
|
19
24
|
{
|
|
25
|
+
namespace: 'plugin-dashboard',
|
|
20
26
|
label: 'Dashboard',
|
|
21
27
|
category: 'Complex',
|
|
22
28
|
icon: 'layout-dashboard',
|
|
@@ -32,12 +38,13 @@ ComponentRegistry.register(
|
|
|
32
38
|
}
|
|
33
39
|
);
|
|
34
40
|
|
|
35
|
-
// Register metric
|
|
41
|
+
// Register metric widget (legacy)
|
|
36
42
|
ComponentRegistry.register(
|
|
37
43
|
'metric',
|
|
38
44
|
MetricWidget,
|
|
39
45
|
{
|
|
40
|
-
|
|
46
|
+
namespace: 'plugin-dashboard',
|
|
47
|
+
label: 'Metric Widget',
|
|
41
48
|
category: 'Dashboard',
|
|
42
49
|
inputs: [
|
|
43
50
|
{ name: 'label', type: 'string', label: 'Label' },
|
|
@@ -45,3 +52,115 @@ ComponentRegistry.register(
|
|
|
45
52
|
]
|
|
46
53
|
}
|
|
47
54
|
);
|
|
55
|
+
|
|
56
|
+
// Register metric card (new standalone component)
|
|
57
|
+
ComponentRegistry.register(
|
|
58
|
+
'metric-card',
|
|
59
|
+
MetricCard,
|
|
60
|
+
{
|
|
61
|
+
namespace: 'plugin-dashboard',
|
|
62
|
+
label: 'Metric Card',
|
|
63
|
+
category: 'Dashboard',
|
|
64
|
+
inputs: [
|
|
65
|
+
{ name: 'title', type: 'string', label: 'Title' },
|
|
66
|
+
{ name: 'value', type: 'string', label: 'Value', required: true },
|
|
67
|
+
{ name: 'icon', type: 'string', label: 'Icon (Lucide name)' },
|
|
68
|
+
{ name: 'trend', type: 'enum', label: 'Trend', enum: [
|
|
69
|
+
{ label: 'Up', value: 'up' },
|
|
70
|
+
{ label: 'Down', value: 'down' },
|
|
71
|
+
{ label: 'Neutral', value: 'neutral' }
|
|
72
|
+
]},
|
|
73
|
+
{ name: 'trendValue', type: 'string', label: 'Trend Value (e.g., +12%)' },
|
|
74
|
+
{ name: 'description', type: 'string', label: 'Description' },
|
|
75
|
+
],
|
|
76
|
+
defaultProps: {
|
|
77
|
+
title: 'Metric',
|
|
78
|
+
value: '0'
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// Register report component (legacy)
|
|
84
|
+
ComponentRegistry.register(
|
|
85
|
+
'report',
|
|
86
|
+
ReportRenderer,
|
|
87
|
+
{
|
|
88
|
+
namespace: 'plugin-dashboard',
|
|
89
|
+
label: 'Report',
|
|
90
|
+
category: 'Dashboard',
|
|
91
|
+
inputs: [
|
|
92
|
+
{ name: 'title', type: 'string', label: 'Title' },
|
|
93
|
+
{ name: 'description', type: 'string', label: 'Description' },
|
|
94
|
+
{ name: 'chart', type: 'code', label: 'Chart Configuration' },
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
// Register report viewer component
|
|
100
|
+
ComponentRegistry.register(
|
|
101
|
+
'report-viewer',
|
|
102
|
+
ReportViewer,
|
|
103
|
+
{
|
|
104
|
+
namespace: 'plugin-dashboard',
|
|
105
|
+
label: 'Report Viewer',
|
|
106
|
+
category: 'Reports',
|
|
107
|
+
inputs: [
|
|
108
|
+
{ name: 'report', type: 'code', label: 'Report Configuration', required: true },
|
|
109
|
+
{ name: 'data', type: 'code', label: 'Report Data' },
|
|
110
|
+
{ name: 'showToolbar', type: 'boolean', label: 'Show Toolbar', defaultValue: true },
|
|
111
|
+
{ name: 'allowExport', type: 'boolean', label: 'Allow Export', defaultValue: true },
|
|
112
|
+
{ name: 'allowPrint', type: 'boolean', label: 'Allow Print', defaultValue: true },
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
// Register report builder component
|
|
118
|
+
ComponentRegistry.register(
|
|
119
|
+
'report-builder',
|
|
120
|
+
ReportBuilder,
|
|
121
|
+
{
|
|
122
|
+
namespace: 'plugin-dashboard',
|
|
123
|
+
label: 'Report Builder',
|
|
124
|
+
category: 'Reports',
|
|
125
|
+
inputs: [
|
|
126
|
+
{ name: 'report', type: 'code', label: 'Initial Report Config' },
|
|
127
|
+
{ name: 'dataSources', type: 'code', label: 'Available Data Sources' },
|
|
128
|
+
{ name: 'availableFields', type: 'code', label: 'Available Fields' },
|
|
129
|
+
{ name: 'showPreview', type: 'boolean', label: 'Show Preview', defaultValue: true },
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
// Register dashboard grid layout component
|
|
135
|
+
ComponentRegistry.register(
|
|
136
|
+
'dashboard-grid',
|
|
137
|
+
DashboardGridLayout,
|
|
138
|
+
{
|
|
139
|
+
namespace: 'plugin-dashboard',
|
|
140
|
+
label: 'Dashboard Grid (Editable)',
|
|
141
|
+
category: 'Complex',
|
|
142
|
+
icon: 'layout-grid',
|
|
143
|
+
inputs: [
|
|
144
|
+
{ name: 'title', type: 'string', label: 'Title' },
|
|
145
|
+
{ name: 'persistLayoutKey', type: 'string', label: 'Layout Storage Key', defaultValue: 'dashboard-layout' },
|
|
146
|
+
{ name: 'className', type: 'string', label: 'CSS Class' }
|
|
147
|
+
],
|
|
148
|
+
defaultProps: {
|
|
149
|
+
title: 'Dashboard',
|
|
150
|
+
widgets: [],
|
|
151
|
+
persistLayoutKey: 'dashboard-layout',
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
// Standard Export Protocol - for manual integration
|
|
157
|
+
export const dashboardComponents = {
|
|
158
|
+
DashboardRenderer,
|
|
159
|
+
DashboardGridLayout,
|
|
160
|
+
MetricWidget,
|
|
161
|
+
MetricCard,
|
|
162
|
+
ReportRenderer,
|
|
163
|
+
ReportViewer,
|
|
164
|
+
ReportBuilder,
|
|
165
|
+
};
|
|
166
|
+
|
package/vite.config.ts
CHANGED
|
@@ -9,8 +9,21 @@ export default defineConfig({
|
|
|
9
9
|
dts({
|
|
10
10
|
insertTypesEntry: true,
|
|
11
11
|
include: ['src'],
|
|
12
|
+
exclude: ['**/*.test.ts', '**/*.test.tsx', 'node_modules'],
|
|
13
|
+
skipDiagnostics: true,
|
|
12
14
|
}),
|
|
13
15
|
],
|
|
16
|
+
resolve: {
|
|
17
|
+
alias: {
|
|
18
|
+
'@': resolve(__dirname, './src'),
|
|
19
|
+
'@object-ui/core': resolve(__dirname, '../core/src'),
|
|
20
|
+
'@object-ui/types': resolve(__dirname, '../types/src'),
|
|
21
|
+
'@object-ui/react': resolve(__dirname, '../react/src'),
|
|
22
|
+
'@object-ui/components': resolve(__dirname, '../components/src'),
|
|
23
|
+
'@object-ui/fields': resolve(__dirname, '../fields/src'),
|
|
24
|
+
'@object-ui/plugin-grid': resolve(__dirname, '../plugin-grid/src'),
|
|
25
|
+
},
|
|
26
|
+
},
|
|
14
27
|
build: {
|
|
15
28
|
lib: {
|
|
16
29
|
entry: resolve(__dirname, 'src/index.tsx'),
|
|
@@ -41,4 +54,10 @@ export default defineConfig({
|
|
|
41
54
|
},
|
|
42
55
|
},
|
|
43
56
|
},
|
|
57
|
+
test: {
|
|
58
|
+
globals: true,
|
|
59
|
+
environment: 'happy-dom',
|
|
60
|
+
setupFiles: ['./vitest.setup.tsx'],
|
|
61
|
+
passWithNoTests: true,
|
|
62
|
+
},
|
|
44
63
|
});
|
package/vitest.config.ts
ADDED
package/vitest.setup.tsx
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
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 { expect, afterEach } from 'vitest';
|
|
10
|
+
import { cleanup } from '@testing-library/react';
|
|
11
|
+
import * as matchers from '@testing-library/jest-dom/matchers';
|
|
12
|
+
import '@testing-library/jest-dom';
|
|
13
|
+
|
|
14
|
+
expect.extend(matchers);
|
|
15
|
+
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
cleanup();
|
|
18
|
+
});
|