Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Dashboard and DashboardLayout components #259

Merged
merged 6 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>
);
}
45 changes: 45 additions & 0 deletions dev/pages/DashboardLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +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 colspan2 = {
'--vaadin-dashboard-item-colspan': '2',
} as CSSProperties;

const rowspan2 = {
'--vaadin-dashboard-item-rowspan': '2',
} as CSSProperties;

export default function () {
return (
<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);
}
21 changes: 21 additions & 0 deletions packages/react-components-pro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@vaadin/charts": "24.5.0-beta1",
"@vaadin/cookie-consent": "24.5.0-beta1",
"@vaadin/crud": "24.5.0-beta1",
"@vaadin/dashboard": "24.6.0-alpha0",
web-padawan marked this conversation as resolved.
Show resolved Hide resolved
"@vaadin/grid-pro": "24.5.0-beta1",
"@vaadin/map": "24.5.0-beta1",
"@vaadin/react-components": "24.5.0-beta1",
Expand Down Expand Up @@ -99,6 +100,22 @@
"types": "./CrudEditColumn.d.ts",
"default": "./CrudEditColumn.js"
},
"./Dashboard.js": {
"types": "./Dashboard.d.ts",
"default": "./Dashboard.js"
},
"./DashboardLayout.js": {
"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"
},
"./GridPro.js": {
"types": "./GridPro.d.ts",
"default": "./GridPro.js"
Expand All @@ -123,6 +140,10 @@
"./Crud": "./Crud.js",
"./CrudEdit": "./CrudEdit.js",
"./CrudEditColumn": "./CrudEditColumn.js",
"./Dashboard": "./Dashboard.js",
"./DashboardLayout": "./DashboardLayout.js",
"./DashboardSection": "./DashboardSection.js",
"./DashboardWidget": "./DashboardWidget.js",
"./GridPro": "./GridPro.js",
"./GridProEditColumn": "./GridProEditColumn.js",
"./Map": "./Map.js",
Expand Down
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/DashboardLayout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './generated/DashboardLayout.js';
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 packages/react-components-pro/src/DashboardWidget.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './generated/DashboardWidget.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
Loading