Dashboard smaller panel grid dimensions (#16763)

* change panel height from 100 to 20

* scale default height

* change number of grid columns to 48 so there is better control of panel width

* remove input controls resize test since its using EUI components and no longer needs to be functionally tested

* fix dashboard_grid_container test

* clean up rebase artifacts

* scale x and y in panel_state test

* make DASHBOARD_GRID_HEIGHT a constant
This commit is contained in:
Nathan Reese 2018-03-12 08:15:32 -06:00 committed by GitHub
parent ec1ee938a6
commit f5aaad396f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 109 additions and 110 deletions

View file

@ -4,9 +4,10 @@ export const DashboardConstants = {
LANDING_PAGE_PATH: '/dashboards',
CREATE_NEW_DASHBOARD_URL: '/dashboard',
};
export const DEFAULT_PANEL_WIDTH = 6;
export const DEFAULT_PANEL_HEIGHT = 3;
export const DASHBOARD_GRID_COLUMN_COUNT = 12;
export const DASHBOARD_GRID_COLUMN_COUNT = 48;
export const DASHBOARD_GRID_HEIGHT = 20;
export const DEFAULT_PANEL_WIDTH = DASHBOARD_GRID_COLUMN_COUNT / 2;
export const DEFAULT_PANEL_HEIGHT = 15;
export function createDashboardEditUrl(id) {
return `/dashboard/${id}`;

View file

@ -7,7 +7,10 @@ import classNames from 'classnames';
import { PanelUtils } from '../panel/panel_utils';
import { DashboardViewMode } from '../dashboard_view_mode';
import { DashboardPanel } from '../panel';
import { DASHBOARD_GRID_COLUMN_COUNT } from '../dashboard_constants';
import {
DASHBOARD_GRID_COLUMN_COUNT,
DASHBOARD_GRID_HEIGHT,
} from '../dashboard_constants';
import sizeMe from 'react-sizeme';
const config = { monitorWidth: true };
@ -58,7 +61,7 @@ function ResponsiveGrid({
isResizable={true}
margin={[MARGINS, MARGINS]}
cols={DASHBOARD_GRID_COLUMN_COUNT}
rowHeight={100}
rowHeight={DASHBOARD_GRID_HEIGHT}
draggableHandle={isViewMode ? '.doesnt-exist' : '.panel-title'}
layout={layout}
onLayoutChange={onLayoutChange}
@ -95,9 +98,17 @@ export class DashboardGrid extends React.Component {
buildLayoutFromPanels() {
return _.map(this.props.panels, panel => {
if (!panel.version) {
PanelUtils.convertOldPanelData(panel);
// panel version numbers added in 6.1. Any panel without version number is assumed to be 6.0.0
const panelVersion = panel.version ? PanelUtils.parseVersion(panel.version) : PanelUtils.parseVersion('6.0.0');
if (panelVersion.major < 6 || (panelVersion.major === 6 && panelVersion.minor < 1)) {
PanelUtils.convertPanelDataPre_6_1(panel);
}
if (panelVersion.major < 6 || (panelVersion.major === 6 && panelVersion.minor < 3)) {
PanelUtils.convertPanelDataPre_6_3(panel);
}
return panel.gridData;
});
}

View file

@ -10,7 +10,7 @@ import { store } from '../../store';
import { DashboardGridContainer } from './dashboard_grid_container';
import { updatePanels } from '../actions';
jest.mock('ui/chrome', () => ({ getKibanaVersion: () => '6.0.0' }), { virtual: true });
jest.mock('ui/chrome', () => ({ getKibanaVersion: () => '6.3.0' }), { virtual: true });
function getProps(props = {}) {
const defaultTestProps = {
@ -75,7 +75,7 @@ test('loads old panel data in the right order', () => {
const foo8Panel = _.find(panels, panel => panel.id === 'foo8');
expect(foo8Panel.row).toBe(undefined);
expect(foo8Panel.gridData.y).toBe(7);
expect(foo8Panel.gridData.y).toBe(35);
expect(foo8Panel.gridData.x).toBe(0);
grid.unmount();

View file

@ -13,35 +13,35 @@ function createPanelWithDimensions(x, y, w, h) {
describe('Panel state', function () {
it('finds a spot on the right', function () {
// Default setup after a single panel, of default size, is on the grid
const panels = [createPanelWithDimensions(0, 0, 6, 6)];
const panels = [createPanelWithDimensions(0, 0, 24, 30)];
const panel = createPanelState('1', 'a type', '1', panels);
expect(panel.gridData.x).to.equal(6);
expect(panel.gridData.x).to.equal(24);
expect(panel.gridData.y).to.equal(0);
});
it('finds a spot on the right when the panel is taller than any other panel on the grid', function () {
// Should be a little empty spot on the right.
const panels = [
createPanelWithDimensions(0, 0, 6, 9),
createPanelWithDimensions(6, 0, 6, 6),
createPanelWithDimensions(0, 0, 24, 45),
createPanelWithDimensions(24, 0, 24, 30),
];
const panel = createPanelState('1', 'a type', '1', panels);
expect(panel.gridData.x).to.equal(6);
expect(panel.gridData.y).to.equal(6);
expect(panel.gridData.x).to.equal(24);
expect(panel.gridData.y).to.equal(30);
});
it('finds an empty spot in the middle of the grid', function () {
const panels = [
createPanelWithDimensions(0, 0, 12, 1),
createPanelWithDimensions(0, 1, 1, 6),
createPanelWithDimensions(10, 1, 1, 6),
createPanelWithDimensions(0, 11, 12, 1),
createPanelWithDimensions(0, 0, 48, 5),
createPanelWithDimensions(0, 5, 4, 30),
createPanelWithDimensions(40, 5, 4, 30),
createPanelWithDimensions(0, 55, 48, 5),
];
const panel = createPanelState('1', 'a type', '1', panels);
expect(panel.gridData.x).to.equal(1);
expect(panel.gridData.y).to.equal(1);
expect(panel.gridData.x).to.equal(4);
expect(panel.gridData.y).to.equal(5);
});
});

View file

@ -1,18 +0,0 @@
import expect from 'expect.js';
import { PanelUtils } from '../panel_utils';
import { DEFAULT_PANEL_WIDTH, DEFAULT_PANEL_HEIGHT } from '../../dashboard_constants';
describe('PanelUtils', function () {
it('convertOldPanelData gives supplies width and height when missing', () => {
const panelData = [
{ col: 3, id: 'foo1', row: 1, type: 'visualization', panelIndex: 1 },
{ col: 3, id: 'foo2', row: 1, size_x: 3, size_y: 2, type: 'visualization', panelIndex: 2 }
];
panelData.forEach(oldPanel => PanelUtils.convertOldPanelData(oldPanel));
expect(panelData[0].gridData.w = DEFAULT_PANEL_WIDTH);
expect(panelData[0].gridData.h = DEFAULT_PANEL_HEIGHT);
expect(panelData[1].gridData.w = 3);
expect(panelData[1].gridData.h = 2);
});
});

View file

@ -1,9 +1,13 @@
import { DEFAULT_PANEL_WIDTH, DEFAULT_PANEL_HEIGHT } from '../dashboard_constants';
import chrome from 'ui/chrome';
const PANEL_HEIGHT_SCALE_FACTOR = 5;
const PANEL_WIDTH_SCALE_FACTOR = 4;
export class PanelUtils {
static convertOldPanelData(panel) {
// 6.1 switched from gridster to react grid. React grid uses different variables for tracking layout
static convertPanelDataPre_6_1(panel) { // eslint-disable-line camelcase
panel.gridData = {
x: panel.col - 1,
y: panel.row - 1,
@ -21,6 +25,31 @@ export class PanelUtils {
return panel;
}
// 6.3 changed the panel dimensions to allow finer control over sizing
// 1) decrease column height from 100 to 20.
// 2) increase rows from 12 to 48
// Need to scale pre 6.3 panels so they maintain the same layout
static convertPanelDataPre_6_3(panel) { // eslint-disable-line camelcase
panel.gridData.w = panel.gridData.w * PANEL_WIDTH_SCALE_FACTOR;
panel.gridData.x = panel.gridData.x * PANEL_WIDTH_SCALE_FACTOR;
panel.gridData.h = panel.gridData.h * PANEL_HEIGHT_SCALE_FACTOR;
panel.gridData.y = panel.gridData.y * PANEL_HEIGHT_SCALE_FACTOR;
panel.version = chrome.getKibanaVersion();
return panel;
}
static parseVersion(version = '6.0.0') {
const versionSplit = version.split('.');
if (versionSplit.length < 3) {
throw new Error(`Invalid version, ${version}, expected <major>.<minor>.<patch>`);
}
return {
major: parseInt(versionSplit[0], 10),
minor: parseInt(versionSplit[1], 10)
};
}
static initPanelIndexes(panels) {
// find the largest panelIndex in all the panels
let maxIndex = this.getMaxPanelIndex(panels);

View file

@ -0,0 +1,46 @@
jest.mock('ui/chrome',
() => ({
getKibanaVersion: () => '6.3.0',
}), { virtual: true });
import { PanelUtils } from './panel_utils';
import { DEFAULT_PANEL_WIDTH, DEFAULT_PANEL_HEIGHT } from '../dashboard_constants';
test('parseVersion', () => {
const { major, minor } = PanelUtils.parseVersion('6.2.0');
expect(major).toBe(6);
expect(minor).toBe(2);
});
test('convertPanelDataPre_6_1 gives supplies width and height when missing', () => {
const panelData = [
{ col: 3, id: 'foo1', row: 1, type: 'visualization', panelIndex: 1 },
{ col: 3, id: 'foo2', row: 1, size_x: 3, size_y: 2, type: 'visualization', panelIndex: 2 }
];
panelData.forEach(oldPanel => PanelUtils.convertPanelDataPre_6_1(oldPanel));
expect(panelData[0].gridData.w).toBe(DEFAULT_PANEL_WIDTH);
expect(panelData[0].gridData.h).toBe(DEFAULT_PANEL_HEIGHT);
expect(panelData[0].version).toBe('6.3.0');
expect(panelData[1].gridData.w).toBe(3);
expect(panelData[1].gridData.h).toBe(2);
expect(panelData[1].version).toBe('6.3.0');
});
test('convertPanelDataPre_6_3 scales panel dimensions', () => {
const oldPanel = {
gridData: {
h: 3,
w: 7,
x: 2,
y: 5,
},
version: '6.2.0'
};
const updatedPanel = PanelUtils.convertPanelDataPre_6_3(oldPanel);
expect(updatedPanel.gridData.w).toBe(28);
expect(updatedPanel.gridData.h).toBe(15);
expect(updatedPanel.gridData.x).toBe(8);
expect(updatedPanel.gridData.y).toBe(25);
expect(updatedPanel.version).toBe('6.3.0');
});

View file

@ -1,10 +1,8 @@
import expect from 'expect.js';
export default function ({ getService, getPageObjects }) {
const retry = getService('retry');
const find = getService('find');
const remote = getService('remote');
const testSubjects = getService('testSubjects');
const PageObjects = getPageObjects(['dashboard', 'header', 'common']);
describe('dashboard grid', () => {
@ -46,73 +44,5 @@ export default function ({ getService, getPageObjects }) {
expect(position1.y).to.be.greaterThan(position2.y);
});
});
describe('resize panel', () => {
describe('input control panel', () => {
before(async () => {
await PageObjects.common.navigateToApp('dashboard');
await PageObjects.dashboard.clickNewDashboard();
await PageObjects.dashboard.addVisualizations(['Visualization InputControl']);
});
it('Should position controls in horizontal layout when panel is short and long', async () => {
const resizeIcons = await find.allByCssSelector('.react-resizable-handle');
expect(resizeIcons.length).to.equal(1);
remote
.moveMouseTo(resizeIcons[0])
.pressMouseButton()
.moveMouseTo(null, 300, 0)
.releaseMouseButton();
await retry.try(async () => {
const controls = await testSubjects.findAll('inputControlItem');
expect(controls.length).to.equal(3);
const control0Position = await controls[0].getPosition();
const control1Position = await controls[1].getPosition();
const control2Position = await controls[2].getPosition();
expect(control0Position.y).to.equal(control1Position.y);
expect(control1Position.y).to.equal(control2Position.y);
});
});
it('Should position controls in vertical layout when panel is tall and skinny', async () => {
const resizeIcons = await find.allByCssSelector('.react-resizable-handle');
expect(resizeIcons.length).to.equal(1);
remote
.moveMouseTo(resizeIcons[0])
.pressMouseButton()
.moveMouseTo(null, -400, 200)
.releaseMouseButton();
await retry.try(async () => {
const controls = await testSubjects.findAll('inputControlItem');
expect(controls.length).to.equal(3);
const control0Position = await controls[0].getPosition();
const control1Position = await controls[1].getPosition();
const control2Position = await controls[2].getPosition();
expect(control2Position.y).to.be.greaterThan(control1Position.y);
expect(control1Position.y).to.be.greaterThan(control0Position.y);
});
});
it('Should position controls inside panel', async () => {
const controls = await testSubjects.findAll('inputControlItem');
expect(controls.length).to.equal(3);
const control0Size = await controls[0].getSize();
const control1Size = await controls[1].getSize();
const control2Size = await controls[2].getSize();
const panels = await find.allByCssSelector('.dashboard-panel');
expect(panels.length).to.equal(1);
const panelSize = await panels[0].getSize();
expect(control0Size.width).to.be.lessThan(panelSize.width);
expect(control1Size.width).to.be.lessThan(panelSize.width);
expect(control2Size.width).to.be.lessThan(panelSize.width);
});
});
});
});
}