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 { PanelModel } from '../panel_model'; import classNames from 'classnames'; import sizeMe from 'react-sizeme'; let lastGridWidth = 1200; function GridWrapper({ size, layout, onLayoutChange, children, onDragStop, onResize, onResizeStop, onWidthChange, className, isResizable, isDraggable, }) { if (size.width === 0) { console.log('size is zero!'); } const width = size.width > 0 ? size.width : lastGridWidth; if (width !== lastGridWidth) { onWidthChange(); lastGridWidth = width; } return ( {children} ); } const SizedReactLayoutGrid = sizeMe({ monitorWidth: true })(GridWrapper); export interface DashboardGridProps { dashboard: DashboardModel; } export class DashboardGrid extends React.Component { gridToPanelMap: any; panelMap: { [id: string]: PanelModel }; constructor(props) { super(props); this.onLayoutChange = this.onLayoutChange.bind(this); this.onResize = this.onResize.bind(this); this.onResizeStop = this.onResizeStop.bind(this); this.onDragStop = this.onDragStop.bind(this); this.onWidthChange = this.onWidthChange.bind(this); this.state = { animated: false }; // subscribe to dashboard events let dashboard = this.props.dashboard; dashboard.on('panel-added', this.triggerForceUpdate.bind(this)); dashboard.on('panel-removed', this.triggerForceUpdate.bind(this)); dashboard.on('repeats-processed', this.triggerForceUpdate.bind(this)); dashboard.on('view-mode-changed', this.onViewModeChanged.bind(this)); dashboard.on('row-collapsed', this.triggerForceUpdate.bind(this)); dashboard.on('row-expanded', this.triggerForceUpdate.bind(this)); } buildLayout() { const layout = []; this.panelMap = {}; for (let panel of this.props.dashboard.panels) { let stringId = panel.id.toString(); this.panelMap[stringId] = panel; if (!panel.gridPos) { console.log('panel without gridpos'); continue; } let panelPos: any = { i: stringId, x: panel.gridPos.x, y: panel.gridPos.y, w: panel.gridPos.w, h: panel.gridPos.h, }; if (panel.type === 'row') { panelPos.w = GRID_COLUMN_COUNT; panelPos.h = 1; panelPos.isResizable = false; panelPos.isDraggable = panel.collapsed; } layout.push(panelPos); } return layout; } onLayoutChange(newLayout) { for (const newPos of newLayout) { this.panelMap[newPos.i].updateGridPos(newPos); } this.props.dashboard.sortPanelsByGridPos(); } triggerForceUpdate() { this.forceUpdate(); } onWidthChange() { for (const panel of this.props.dashboard.panels) { panel.resizeDone(); } } onViewModeChanged(payload) { this.setState({ animated: payload.fullscreen }); } 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); } onResize(layout, oldItem, newItem) { this.panelMap[newItem.i].updateGridPos(newItem); } onResizeStop(layout, oldItem, newItem) { this.updateGridPos(newItem, layout); this.panelMap[newItem.i].resizeDone(); } onDragStop(layout, oldItem, newItem) { this.updateGridPos(newItem, layout); } componentDidMount() { setTimeout(() => { this.setState({ animated: true }); }); } renderPanels() { const panelElements = []; for (let panel of this.props.dashboard.panels) { const panelClasses = classNames({ panel: true, 'panel--fullscreen': panel.fullscreen }); panelElements.push(
); } return panelElements; } render() { return ( {this.renderPanels()} ); } }