Files
grafana/public/app/features/dashboard/dashgrid/DashboardGrid.tsx

205 lines
5.5 KiB
TypeScript
Raw Normal View History

2017-10-09 17:24:10 +02:00
import React from 'react';
import ReactGridLayout from 'react-grid-layout';
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT } from 'app/core/constants';
import { DashboardPanel } from './DashboardPanel';
import { DashboardModel } from '../dashboard_model';
import { PanelContainer } from './PanelContainer';
import { PanelModel } from '../panel_model';
import classNames from 'classnames';
2017-10-09 17:24:10 +02:00
import sizeMe from 'react-sizeme';
2017-10-11 21:36:03 +02:00
let lastGridWidth = 1200;
2017-10-09 17:24:10 +02:00
function GridWrapper({
size,
layout,
onLayoutChange,
children,
onDragStop,
onResize,
onResizeStop,
onWidthChange,
className,
isResizable,
isDraggable,
}) {
if (size.width === 0) {
console.log('size is zero!');
2017-10-09 17:24:10 +02:00
}
const width = size.width > 0 ? size.width : lastGridWidth;
if (width !== lastGridWidth) {
onWidthChange();
lastGridWidth = width;
2017-10-11 21:36:03 +02:00
}
2017-10-09 17:24:10 +02:00
return (
<ReactGridLayout
width={lastGridWidth}
2017-12-08 12:17:09 +01:00
className={className}
isDraggable={isDraggable}
isResizable={isResizable}
measureBeforeMount={false}
containerPadding={[0, 0]}
useCSSTransforms={true}
margin={[GRID_CELL_VMARGIN, GRID_CELL_VMARGIN]}
cols={GRID_COLUMN_COUNT}
rowHeight={GRID_CELL_HEIGHT}
draggableHandle=".grid-drag-handle"
layout={layout}
onResize={onResize}
onResizeStop={onResizeStop}
onDragStop={onDragStop}
onLayoutChange={onLayoutChange}>
{children}
</ReactGridLayout>
);
2017-10-09 17:24:10 +02:00
}
const SizedReactLayoutGrid = sizeMe({ monitorWidth: true })(GridWrapper);
2017-10-09 17:24:10 +02:00
export interface DashboardGridProps {
2017-10-10 09:34:14 +02:00
getPanelContainer: () => PanelContainer;
2017-10-09 17:24:10 +02:00
}
export class DashboardGrid extends React.Component<DashboardGridProps, any> {
gridToPanelMap: any;
2017-10-10 09:34:14 +02:00
panelContainer: PanelContainer;
2017-10-10 17:57:53 +02:00
dashboard: DashboardModel;
panelMap: { [id: string]: PanelModel };
2017-10-09 17:24:10 +02:00
constructor(props) {
super(props);
2017-10-10 09:34:14 +02:00
this.panelContainer = this.props.getPanelContainer();
2017-10-09 17:24:10 +02:00
this.onLayoutChange = this.onLayoutChange.bind(this);
2017-10-10 17:57:53 +02:00
this.onResize = this.onResize.bind(this);
2017-10-11 21:36:03 +02:00
this.onResizeStop = this.onResizeStop.bind(this);
this.onDragStop = this.onDragStop.bind(this);
2017-10-11 21:36:03 +02:00
this.onWidthChange = this.onWidthChange.bind(this);
2017-10-10 17:57:53 +02:00
this.state = { animated: false };
2017-12-08 12:17:09 +01:00
2017-10-10 17:57:53 +02:00
// subscribe to dashboard events
this.dashboard = this.panelContainer.getDashboard();
2017-10-11 16:32:05 +02:00
this.dashboard.on('panel-added', this.triggerForceUpdate.bind(this));
2017-10-12 19:01:02 +02:00
this.dashboard.on('panel-removed', this.triggerForceUpdate.bind(this));
2017-10-12 21:37:27 +02:00
this.dashboard.on('repeats-processed', this.triggerForceUpdate.bind(this));
2017-10-11 16:32:05 +02:00
this.dashboard.on('view-mode-changed', this.triggerForceUpdate.bind(this));
2017-10-17 14:53:52 +02:00
this.dashboard.on('row-collapsed', this.triggerForceUpdate.bind(this));
this.dashboard.on('row-expanded', this.triggerForceUpdate.bind(this));
2017-10-09 17:24:10 +02:00
}
buildLayout() {
const layout = [];
this.panelMap = {};
2017-10-10 09:34:14 +02:00
2017-10-10 17:57:53 +02:00
for (let panel of this.dashboard.panels) {
let stringId = panel.id.toString();
this.panelMap[stringId] = panel;
if (!panel.gridPos) {
console.log('panel without gridpos');
continue;
}
2017-10-16 16:09:23 +02:00
let panelPos: any = {
i: stringId,
x: panel.gridPos.x,
y: panel.gridPos.y,
w: panel.gridPos.w,
h: panel.gridPos.h,
2017-10-16 16:09:23 +02:00
};
if (panel.type === 'row') {
panelPos.w = GRID_COLUMN_COUNT;
panelPos.h = 1;
panelPos.isResizable = false;
2017-10-17 14:53:52 +02:00
panelPos.isDraggable = panel.collapsed;
2017-10-16 16:09:23 +02:00
}
layout.push(panelPos);
2017-10-09 17:24:10 +02:00
}
2017-10-10 09:34:14 +02:00
2017-10-09 17:24:10 +02:00
return layout;
}
onLayoutChange(newLayout) {
for (const newPos of newLayout) {
this.panelMap[newPos.i].updateGridPos(newPos);
}
this.dashboard.sortPanelsByGridPos();
}
2017-10-09 17:24:10 +02:00
2017-10-11 16:32:05 +02:00
triggerForceUpdate() {
2017-10-10 17:57:53 +02:00
this.forceUpdate();
}
2017-10-11 21:36:03 +02:00
onWidthChange() {
for (const panel of this.dashboard.panels) {
panel.resizeDone();
}
}
updateGridPos(item, layout) {
this.panelMap[item.i].updateGridPos(item);
// react-grid-layout has a bug (#670), and onLayoutChange() is only called when the component is mounted.
// So it's required to call it explicitly when panel resized or moved to save layout changes.
this.onLayoutChange(layout);
}
2017-10-10 17:57:53 +02:00
onResize(layout, oldItem, newItem) {
this.panelMap[newItem.i].updateGridPos(newItem);
}
2017-10-11 21:36:03 +02:00
onResizeStop(layout, oldItem, newItem) {
this.updateGridPos(newItem, layout);
2017-10-11 21:36:03 +02:00
this.panelMap[newItem.i].resizeDone();
}
onDragStop(layout, oldItem, newItem) {
this.updateGridPos(newItem, layout);
}
2017-12-08 12:17:09 +01:00
componentDidMount() {
setTimeout(() => {
this.setState(() => {
return { animated: true };
2017-12-08 12:17:09 +01:00
});
});
}
2017-10-09 17:24:10 +02:00
renderPanels() {
const panelElements = [];
2017-10-10 09:34:14 +02:00
2017-10-10 17:57:53 +02:00
for (let panel of this.dashboard.panels) {
const panelClasses = classNames({ panel: true, 'panel--fullscreen': panel.fullscreen });
2017-10-09 17:24:10 +02:00
panelElements.push(
<div key={panel.id.toString()} className={panelClasses}>
<DashboardPanel panel={panel} getPanelContainer={this.props.getPanelContainer} />
2017-10-09 17:24:10 +02:00
</div>,
);
}
2017-10-10 09:34:14 +02:00
2017-10-09 17:24:10 +02:00
return panelElements;
}
render() {
return (
2017-10-11 21:36:03 +02:00
<SizedReactLayoutGrid
className={classNames({ layout: true, animated: this.state.animated })}
2017-10-11 21:36:03 +02:00
layout={this.buildLayout()}
isResizable={this.dashboard.meta.canEdit}
isDraggable={this.dashboard.meta.canEdit}
2017-10-11 21:36:03 +02:00
onLayoutChange={this.onLayoutChange}
onWidthChange={this.onWidthChange}
onDragStop={this.onDragStop}
2017-10-11 21:36:03 +02:00
onResize={this.onResize}
onResizeStop={this.onResizeStop}>
2017-10-09 17:24:10 +02:00
{this.renderPanels()}
</SizedReactLayoutGrid>
);
}
}