DashboardGrid.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. import React from 'react';
  2. import coreModule from 'app/core/core_module';
  3. import ReactGridLayout from 'react-grid-layout';
  4. import {GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT} from 'app/core/constants';
  5. import {DashboardPanel} from './DashboardPanel';
  6. import {DashboardModel} from '../dashboard_model';
  7. import {PanelContainer} from './PanelContainer';
  8. import {PanelModel} from '../panel_model';
  9. import classNames from 'classnames';
  10. import sizeMe from 'react-sizeme';
  11. let lastGridWidth = 1200;
  12. function GridWrapper({size, layout, onLayoutChange, children, onResize, onResizeStop, onWidthChange}) {
  13. if (size.width === 0) {
  14. console.log('size is zero!');
  15. }
  16. const width = size.width > 0 ? size.width : lastGridWidth;
  17. if (width !== lastGridWidth) {
  18. onWidthChange();
  19. lastGridWidth = width;
  20. }
  21. return (
  22. <ReactGridLayout
  23. width={lastGridWidth}
  24. className="layout"
  25. isDraggable={true}
  26. isResizable={true}
  27. measureBeforeMount={false}
  28. containerPadding={[0, 0]}
  29. useCSSTransforms={false}
  30. margin={[GRID_CELL_VMARGIN, GRID_CELL_VMARGIN]}
  31. cols={GRID_COLUMN_COUNT}
  32. rowHeight={GRID_CELL_HEIGHT}
  33. draggableHandle=".grid-drag-handle"
  34. layout={layout}
  35. onResize={onResize}
  36. onResizeStop={onResizeStop}
  37. onLayoutChange={onLayoutChange}>
  38. {children}
  39. </ReactGridLayout>
  40. );
  41. }
  42. const SizedReactLayoutGrid = sizeMe({monitorWidth: true})(GridWrapper);
  43. export interface DashboardGridProps {
  44. getPanelContainer: () => PanelContainer;
  45. }
  46. export class DashboardGrid extends React.Component<DashboardGridProps, any> {
  47. gridToPanelMap: any;
  48. panelContainer: PanelContainer;
  49. dashboard: DashboardModel;
  50. panelMap: {[id: string]: PanelModel};
  51. constructor(props) {
  52. super(props);
  53. this.panelContainer = this.props.getPanelContainer();
  54. this.onLayoutChange = this.onLayoutChange.bind(this);
  55. this.onResize = this.onResize.bind(this);
  56. this.onResizeStop = this.onResizeStop.bind(this);
  57. this.onWidthChange = this.onWidthChange.bind(this);
  58. // subscribe to dashboard events
  59. this.dashboard = this.panelContainer.getDashboard();
  60. this.dashboard.on('panel-added', this.triggerForceUpdate.bind(this));
  61. this.dashboard.on('panel-removed', this.triggerForceUpdate.bind(this));
  62. this.dashboard.on('repeats-processed', this.triggerForceUpdate.bind(this));
  63. this.dashboard.on('view-mode-changed', this.triggerForceUpdate.bind(this));
  64. this.dashboard.on('row-collapsed', this.triggerForceUpdate.bind(this));
  65. this.dashboard.on('row-expanded', this.triggerForceUpdate.bind(this));
  66. }
  67. buildLayout() {
  68. const layout = [];
  69. this.panelMap = {};
  70. for (let panel of this.dashboard.panels) {
  71. let stringId = panel.id.toString();
  72. this.panelMap[stringId] = panel;
  73. if (!panel.gridPos) {
  74. console.log('panel without gridpos');
  75. continue;
  76. }
  77. let panelPos: any = {
  78. i: stringId,
  79. x: panel.gridPos.x,
  80. y: panel.gridPos.y,
  81. w: panel.gridPos.w,
  82. h: panel.gridPos.h,
  83. };
  84. if (panel.type === 'row') {
  85. panelPos.w = GRID_COLUMN_COUNT;
  86. panelPos.h = 1;
  87. panelPos.isResizable = false;
  88. panelPos.isDraggable = panel.collapsed;
  89. }
  90. layout.push(panelPos);
  91. }
  92. return layout;
  93. }
  94. onLayoutChange(newLayout) {
  95. for (const newPos of newLayout) {
  96. this.panelMap[newPos.i].updateGridPos(newPos);
  97. }
  98. this.dashboard.sortPanelsByGridPos();
  99. }
  100. triggerForceUpdate() {
  101. this.forceUpdate();
  102. }
  103. onWidthChange() {
  104. for (const panel of this.dashboard.panels) {
  105. panel.resizeDone();
  106. }
  107. }
  108. onResize(layout, oldItem, newItem) {
  109. this.panelMap[newItem.i].updateGridPos(newItem);
  110. }
  111. onResizeStop(layout, oldItem, newItem) {
  112. this.panelMap[newItem.i].resizeDone();
  113. }
  114. renderPanels() {
  115. const panelElements = [];
  116. for (let panel of this.dashboard.panels) {
  117. const panelClasses = classNames({panel: true, 'panel--fullscreen': panel.fullscreen});
  118. panelElements.push(
  119. <div key={panel.id.toString()} className={panelClasses}>
  120. <DashboardPanel panel={panel} getPanelContainer={this.props.getPanelContainer} />
  121. </div>,
  122. );
  123. }
  124. return panelElements;
  125. }
  126. render() {
  127. return (
  128. <SizedReactLayoutGrid
  129. layout={this.buildLayout()}
  130. onLayoutChange={this.onLayoutChange}
  131. onWidthChange={this.onWidthChange}
  132. onResize={this.onResize}
  133. onResizeStop={this.onResizeStop}>
  134. {this.renderPanels()}
  135. </SizedReactLayoutGrid>
  136. );
  137. }
  138. }
  139. coreModule.directive('dashboardGrid', function(reactDirective) {
  140. return reactDirective(DashboardGrid, [['getPanelContainer', {watchDepth: 'reference', wrapApply: false}]]);
  141. });