Skip to content

Commit

Permalink
feat(dashboard): adding new property panel layout
Browse files Browse the repository at this point in the history
  • Loading branch information
mnischay authored and chejimmy committed Feb 28, 2024
1 parent 3106695 commit 39a8271
Show file tree
Hide file tree
Showing 19 changed files with 515 additions and 51 deletions.
54 changes: 31 additions & 23 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

75 changes: 75 additions & 0 deletions packages/dashboard/e2e/tests/propertyPanel/propertyPanel.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { test } from '../test';
import { expect } from '@playwright/test';

test.describe('Property Panel Tests', () => {
test.skip();
test('test if the property panel is visible in the new layout', async ({
dashboardWithPropertyPanel,
}) => {
const propPanel = dashboardWithPropertyPanel.page.locator(
'div[class="property-panel-container"]'
);
await expect(propPanel).toBeVisible();
});

test('test if the property panel opens on clicking the header', async ({
dashboardWithPropertyPanel,
}) => {
const propPanel = dashboardWithPropertyPanel.page.locator(
'div[class="property-panel-container"]'
);
await propPanel.click();
const boundingBox = await propPanel.boundingBox();
expect(boundingBox.height > 62).toBeTruthy();
});

test('test if the property panel opens when a widget is selected', async ({
dashboardWithPropertyPanel,
}) => {
await dashboardWithPropertyPanel.addAWidgetByType('line');
const propPanel = dashboardWithPropertyPanel.page.locator(
'div[class="property-panel-container"]'
);
const boundingBox = await propPanel.boundingBox();
expect(boundingBox.height > 62).toBeTruthy();
});

test('test if the property panel stays open when a widget is deselected', async ({
dashboardWithPropertyPanel,
page,
}) => {
await dashboardWithPropertyPanel.addAWidgetByType('line');
const boundingBox = await dashboardWithPropertyPanel.gridArea.boundingBox();
await page.mouse.dblclick(boundingBox.x + 10, boundingBox.y + 10);
const propPanel = dashboardWithPropertyPanel.page.locator(
'div[class="property-panel-container"]'
);
const propPanelBoundingBox = await propPanel.boundingBox();
expect(propPanelBoundingBox.height > 62).toBeTruthy();
});

test('test if the property panel resizes ', async ({
dashboardWithPropertyPanel,
page,
}) => {
const propPanel = dashboardWithPropertyPanel.page.locator(
'div[class="property-panel-container"]'
);
await propPanel.click();
const handle = propPanel.locator(
'span[class="react-resizable-handle react-resizable-handle-n"]'
);
await expect(handle).toBeVisible();
const propPanelBeforeMoveBoundingBox = await propPanel.boundingBox();
const handleBoundingBox = await handle.boundingBox();
await handle.hover();
await page.mouse.down();
await page.mouse.move(handleBoundingBox.x, handleBoundingBox.y - 100);
await page.mouse.up();

expect(
(await propPanel.boundingBox()).height >
propPanelBeforeMoveBoundingBox.height
).toBeTruthy();
});
});
22 changes: 22 additions & 0 deletions packages/dashboard/e2e/tests/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface Fixtures {
dashboardWithKPIWidget: DashboardPage;
dashboardWithStatusWidget: DashboardPage;
dashboardWithTableWidget: DashboardPage;
dashboardWithPropertyPanel: DashboardPage;
resourceExplorer: ResourceExplorer;
configPanel: ConfigPanel;
}
Expand Down Expand Up @@ -70,6 +71,12 @@ export const test = base.extend<Fixtures>({

return use(dashboardWithKPIWidget);
},
dashboardWithPropertyPanel: async ({ page, browser }, use) => {
const dashboardWithLineWidgetPropertyPanel =
await createNewDashboardWithPropertyPanel(page, browser);

return use(dashboardWithLineWidgetPropertyPanel);
},
configPanel: async ({ page }, use) => {
const configPanel = new ConfigPanel({ page });
await use(configPanel);
Expand All @@ -93,3 +100,18 @@ const createNewDashboardWithWidget = async (
}
return dashboard;
};

const createNewDashboardWithPropertyPanel = async (
page: Page,
browser: Browser
) => {
const dashboard = new DashboardPage({ page, browser });
await dashboard.goto();
await page.evaluate(() =>
localStorage.setItem('SHOW_DASHBOARD_LAYOUT', 'true')
);
await page.reload();
await dashboard.makeViewportToAbsolute();

return dashboard;
};
2 changes: 2 additions & 0 deletions packages/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"@types/papaparse": "^5.3.10",
"@types/react": "^18.2.12",
"@types/react-dom": "^18.2.5",
"@types/react-resizable": "^3.0.7",
"css-loader": "6.8.1",
"dotenv": "^16.3.1",
"eslint-config-iot-app-kit": "9.15.0",
Expand Down Expand Up @@ -120,6 +121,7 @@
"react-hook-form": "^7.46.1",
"react-hotkeys": "^2.0.0",
"react-popper": "^2.3.0",
"react-resizable": "^3.0.5",
"react-use": "17.4.0",
"tiny-invariant": "^1.3.1",
"turbowatch": "^2.29.4",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import { render, fireEvent, cleanup } from '@testing-library/react';
import CustomOrangeButton from './index';

describe('CustomOrangeButton', () => {
const title = 'Test Button';
const handleClick = jest.fn();

beforeEach(() => {
cleanup();
handleClick.mockReset();
});
test('renders button with correct title', () => {
const { getByText } = render(
<CustomOrangeButton title={title} handleClick={handleClick} />
Expand All @@ -20,4 +23,16 @@ describe('CustomOrangeButton', () => {
fireEvent.click(button);
expect(handleClick).toHaveBeenCalledTimes(1);
});
test('does not calls handleClick when clicked but disabled', () => {
const { getByRole } = render(
<CustomOrangeButton
title={title}
handleClick={handleClick}
disabled={true}
/>
);
const button = getByRole('button');
button.click();
expect(handleClick).toHaveBeenCalledTimes(0);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,16 @@ import './index.css';
const CustomOrangeButton = ({
title,
handleClick,
disabled,
...rest
}: { title: string; handleClick?: () => void } & ButtonProps) => {
if (disabled) {
return (
<Button variant='primary' disabled={true}>
{title}
</Button>
);
}
return (
<Button
className='btn-custom-primary'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const CONFIG_PANEL_OPEN_WIDTH_PIXELS = 500;
export const CONFIG_PANEL_COLLAPSED_WIDTH_PIXELS = 80;
export const CONFIG_PANEL_BORDER_WIDTH = 2;
export const PROPERTY_PANEL_DRAG_HANDLE_ICON_SIZE = 20;
export const PROPERTY_PANEL_COLLAPSED_HEIGHT_PIXELS = 62;
export const PROPERTY_PANEL_OPEN_DEFAULT_HEIGHT_PIXELS = 159;
export const PROPERTY_PANEL_DEFAULT_HEIGHT_PIXELS = 299;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.dashboard-layout-container {
height: calc(100vh - 160px);
display: flex;
width: 100%;
}

.dashboard-layout-center-pane-container {
overflow: scroll;
width: 100%;
position: relative;
}

.dashboard-layout-config-container {
z-index: 2;
margin-left: auto;
height: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { ReactNode, useState } from 'react';
import PropertiesPanelIcon from '~/components/resizablePanes/assets/propertiesPane.svg';
import { CollapsiblePanel } from '~/components/internalDashboard/collapsiblePanel';
import {
CONFIG_PANEL_COLLAPSED_WIDTH_PIXELS,
CONFIG_PANEL_OPEN_WIDTH_PIXELS,
} from '~/components/dashboardLayout/constants';
import './dashboardLayout.css';
import { PropertyPanel } from '~/components/dashboardLayout/propertyPanel/propertyPanel';

export const DashboardLayout = ({
centerPane,
rightPane,
leftPane,
}: {
centerPane: ReactNode;
rightPane: ReactNode;
leftPane: ReactNode;
}) => {
const [isConfigPanelCollapsed, setIsConfigPanelCollapsed] = useState(true);

return (
<div
className='dashboard-layout-container' // important
>
{/*main area*/}
<div className='dashboard-layout-center-pane-container'>{centerPane}</div>

{/*bottom drawer */}
<PropertyPanel
resourceExplorer={leftPane}
isConfigPanelCollapsed={isConfigPanelCollapsed}
/>

{/*right config panel*/}
<div className='dashboard-layout-config-container'>
<CollapsiblePanel
isPanelCollapsed={isConfigPanelCollapsed}
panelWidth={
isConfigPanelCollapsed
? CONFIG_PANEL_COLLAPSED_WIDTH_PIXELS
: CONFIG_PANEL_OPEN_WIDTH_PIXELS
}
onCollapsedPanelClick={() => {
setIsConfigPanelCollapsed(!isConfigPanelCollapsed);
}}
panelContent={rightPane}
icon={PropertiesPanelIcon}
side='right'
headerText='Widget Configuration'
/>
</div>
</div>
);
};

0 comments on commit 39a8271

Please sign in to comment.