Skip to content

Commit

Permalink
feat: add dashboard renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
tomivirkki committed Oct 8, 2024
1 parent a059915 commit c0eda22
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 20 deletions.
84 changes: 84 additions & 0 deletions dev/pages/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import {
Dashboard,
type DashboardItem,
type DashboardProps,
} from '../../packages/react-components-pro/src/Dashboard.js';
import { DashboardWidget } from '../../packages/react-components-pro/src/DashboardWidget.js';
import './dashboard-styles.css';

type TestItem = DashboardItem & {
title?: string;
content?: string;
type?: 'kpi' | 'chart';
header?: string;
};

export default function () {
const items: DashboardProps<TestItem>['items'] = [
{
title: 'Total cost',
content: '+203%',
type: 'kpi',
header: '2023-2024',
},
{
title: 'Sales',
type: 'chart',
header: '2023-2024',
colspan: 2,
},
{
title: 'Section',
items: [
{
title: 'Sales closed this month',
rowspan: 2,
content: '54 000€',
type: 'kpi',
},
{
title: 'Just some number',
content: '1234',
type: 'kpi',
header: '2014-2024',
},
],
},
{
title: 'Activity since 2023',
type: 'chart',
},
];

return (
<Dashboard<TestItem>
editable
items={items}
onDashboardItemMoved={(e) => {
console.log('dashboard-item-moved', e.detail);
}}
onDashboardItemRemoved={(e) => {
console.log('dashboard-item-removed', e.detail);
}}
onDashboardItemResized={(e) => {
console.log('dashboard-item-resized', e.detail);
}}
onDashboardItemSelectedChanged={(e) => {
console.log('dashboard-item-selected-changed', e.detail);
}}
onDashboardItemMoveModeChanged={(e) => {
console.log('dashboard-item-move-mode-changed', e.detail);
}}
onDashboardItemResizeModeChanged={(e) => {
console.log('dashboard-item-resize-mode-changed', e.detail);
}}
>
{({ item }) => (
<DashboardWidget widgetTitle={item.title}>
<span slot="header-content">{item.header || ''}</span>
{item.type === 'chart' ? <div className="chart"></div> : <div className="kpi-number">{item.content}</div>}
</DashboardWidget>
)}
</Dashboard>
);
}
51 changes: 33 additions & 18 deletions dev/pages/DashboardLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,45 @@
import { DashboardLayout } from '../../packages/react-components-pro/src/DashboardLayout.js';
import { DashboardWidget } from '../../packages/react-components-pro/src/DashboardWidget.js';
import { DashboardSection } from '../../packages/react-components-pro/src/DashboardSection.js';
import type { CSSProperties } from 'react';
import './dashboard-styles.css';

const dashboardLayoutItemStyle = {
backgroundColor: '#f5f5f5',
border: '1px solid #e0e0e0',
borderRadius: '4px',
padding: '1em',
textAlign: 'center',
margin: '0.5em',
boxSizing: 'border-box',
height: '100px',
const colspan2 = {
'--vaadin-dashboard-item-colspan': '2',
} as CSSProperties;

const dashboardLayoutStyle = {
'--vaadin-dashboard-col-min-width': '200px',
'--vaadin-dashboard-col-max-width': '300px',
const rowspan2 = {
'--vaadin-dashboard-item-rowspan': '2',
} as CSSProperties;

export default function () {
return (
<DashboardLayout style={dashboardLayoutStyle}>
<div style={dashboardLayoutItemStyle}>Item 0</div>
<div style={dashboardLayoutItemStyle}>Item 1</div>
<div style={dashboardLayoutItemStyle}>Item 2</div>
<div style={dashboardLayoutItemStyle}>Item 3</div>
<div style={dashboardLayoutItemStyle}>Item 4</div>
<DashboardLayout>
<DashboardWidget widgetTitle="Total cost">
<span slot="header-content">2023-2024</span>
<div className="kpi-number">+203%</div>
</DashboardWidget>

<DashboardWidget style={colspan2} widgetTitle="Sales">
<span slot="header-content">2023-2024</span>
<div className="chart"></div>
</DashboardWidget>

<DashboardSection sectionTitle="Section">
<DashboardWidget style={rowspan2} widgetTitle="Sales closed this month">
<div className="kpi-number">54 000€</div>
</DashboardWidget>

<DashboardWidget widgetTitle="Just some number">
<span slot="header-content">2014-2024</span>
<div className="kpi-number">1234</div>
</DashboardWidget>
</DashboardSection>

<DashboardWidget>
<h2 slot="title">Activity since 2023</h2>
<div className="chart"></div>
</DashboardWidget>
</DashboardLayout>
);
}
21 changes: 21 additions & 0 deletions dev/pages/dashboard-styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
html {
--vaadin-dashboard-col-min-width: 300px;
--vaadin-dashboard-col-max-width: 500px;
--vaadin-dashboard-col-max-count: 3;
--vaadin-dashboard-row-min-height: 300px;
}

.kpi-number {
font-size: 80px;
font-weight: bold;
color: #4caf50;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}

.chart {
height: 100%;
background: repeating-linear-gradient(45deg, #e0e0e0, #e0e0e0 10px, #f5f5f5 10px, #f5f5f5 20px);
}
7 changes: 6 additions & 1 deletion packages/react-components-pro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@
"types": "./DashboardLayout.d.ts",
"default": "./DashboardLayout.js"
},
"./DashboardSection.js": {
"types": "./DashboardSection.d.ts",
"default": "./DashboardSection.js"
},
"./DashboardWidget.js": {
"types": "./DashboardWidget.d.ts",
"default": "./DashboardWidget.js"
Expand Down Expand Up @@ -138,6 +142,7 @@
"./CrudEditColumn": "./CrudEditColumn.js",
"./Dashboard": "./Dashboard.js",
"./DashboardLayout": "./DashboardLayout.js",
"./DashboardSection": "./DashboardSection.js",
"./DashboardWidget": "./DashboardWidget.js",
"./GridPro": "./GridPro.js",
"./GridProEditColumn": "./GridProEditColumn.js",
Expand All @@ -148,4 +153,4 @@
"./utils/createComponent.js": "./utils/createComponent.js",
"./utils/createComponent.js.map": "./utils/createComponent.js.map"
}
}
}
1 change: 0 additions & 1 deletion packages/react-components-pro/src/Dashboard.ts

This file was deleted.

54 changes: 54 additions & 0 deletions packages/react-components-pro/src/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* @license
* Copyright (c) 2000 - 2024 Vaadin Ltd.
*
* This program is available under Vaadin Commercial License and Service Terms.
*
*
* See https://vaadin.com/commercial-license-and-service-terms for the full
* license.
*/
import { type ComponentType, type ForwardedRef, forwardRef, type ReactElement, type RefAttributes } from 'react';
import {
Dashboard as _Dashboard,
type DashboardItem,
type DashboardElement,
type DashboardProps as _DashboardProps,
type DashboardItemModel,
} from './generated/Dashboard.js';
import { type ReactModelRendererProps, useModelRenderer } from '@vaadin/react-components/renderers/useModelRenderer.js';

export * from './generated/Dashboard.js';

export type DashboardReactRendererProps<TItem extends DashboardItem> = ReactModelRendererProps<
TItem,
DashboardItemModel<TItem>,
DashboardElement<TItem>
>;

export type DashboardProps<TItem extends DashboardItem> = Partial<
Omit<_DashboardProps<TItem>, 'children' | 'renderer'>
> &
Readonly<{
children?: ComponentType<DashboardReactRendererProps<TItem>> | null;
renderer?: ComponentType<DashboardReactRendererProps<TItem>> | null;
}>;

function Dashboard<TItem extends DashboardItem = DashboardItem>(
props: DashboardProps<TItem>,
ref: ForwardedRef<DashboardElement<TItem>>,
): ReactElement | null {
const [portals, renderer] = useModelRenderer(props.renderer ?? props.children);

return (
<_Dashboard<TItem> {...props} ref={ref} renderer={renderer as any}>
{portals}
</_Dashboard>
);
}

const ForwardedDashboard = forwardRef(Dashboard) as <TItem extends DashboardItem = DashboardItem>(
props: DashboardProps<TItem> & RefAttributes<DashboardElement<TItem>>,
) => ReactElement | null;

export { ForwardedDashboard as Dashboard };
1 change: 1 addition & 0 deletions packages/react-components-pro/src/DashboardSection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './generated/DashboardSection.js';
1 change: 1 addition & 0 deletions scripts/utils/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const genericElements = new Map<string, GenericElementInfo>([
['ComboBox', { numberOfGenerics: 1 }],
['ComboBoxLight', { numberOfGenerics: 1 }],
['Crud', { numberOfGenerics: 1 }],
['Dashboard', { numberOfGenerics: 1, typeConstraints: ['DashboardItem'] }],
['Grid', { numberOfGenerics: 1 }],
['GridColumn', { numberOfGenerics: 1, nonGenericInterfaces: [NonGenericInterface.EVENT_MAP] }],
['GridFilterColumn', { numberOfGenerics: 1, nonGenericInterfaces: [NonGenericInterface.EVENT_MAP] }],
Expand Down

0 comments on commit c0eda22

Please sign in to comment.