Просмотр исходного кода

Merge pull request #15141 from grafana/14946-panel-menu-on-move

Don't show panel menu on move
Torkel Ödegaard 6 лет назад
Родитель
Сommit
c33e94f438

+ 2 - 0
package.json

@@ -25,7 +25,9 @@
     "@types/node": "^8.0.31",
     "@types/react": "^16.7.6",
     "@types/react-dom": "^16.0.9",
+    "@types/react-grid-layout": "^0.16.6",
     "@types/react-select": "^2.0.4",
+    "@types/react-virtualized": "^9.18.12",
     "angular-mocks": "1.6.6",
     "autoprefixer": "^6.4.0",
     "axios": "^0.17.1",

+ 33 - 23
public/app/features/dashboard/dashgrid/DashboardGrid.tsx

@@ -1,6 +1,6 @@
 import React from 'react';
 import { hot } from 'react-hot-loader';
-import ReactGridLayout from 'react-grid-layout';
+import ReactGridLayout, { ItemCallback } 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';
@@ -11,6 +11,21 @@ import sizeMe from 'react-sizeme';
 let lastGridWidth = 1200;
 let ignoreNextWidthChange = false;
 
+interface GridWrapperProps {
+  size: { width: number; };
+  layout: ReactGridLayout.Layout[];
+  onLayoutChange: (layout: ReactGridLayout.Layout[]) => void;
+  children: JSX.Element | JSX.Element[];
+  onDragStop: ItemCallback;
+  onResize: ItemCallback;
+  onResizeStop: ItemCallback;
+  onWidthChange: () => void;
+  className: string;
+  isResizable?: boolean;
+  isDraggable?: boolean;
+  isFullscreen?: boolean;
+}
+
 function GridWrapper({
   size,
   layout,
@@ -24,7 +39,7 @@ function GridWrapper({
   isResizable,
   isDraggable,
   isFullscreen,
-}) {
+}: GridWrapperProps)  {
   const width = size.width > 0 ? size.width : lastGridWidth;
 
   // logic to ignore width changes (optimization)
@@ -43,7 +58,6 @@ function GridWrapper({
       className={className}
       isDraggable={isDraggable}
       isResizable={isResizable}
-      measureBeforeMount={false}
       containerPadding={[0, 0]}
       useCSSTransforms={false}
       margin={[GRID_CELL_VMARGIN, GRID_CELL_VMARGIN]}
@@ -71,22 +85,17 @@ export class DashboardGrid extends React.Component<DashboardGridProps> {
   gridToPanelMap: any;
   panelMap: { [id: string]: PanelModel };
 
-  constructor(props) {
+  constructor(props: DashboardGridProps) {
     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);
 
     // subscribe to dashboard events
     const 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));
+    dashboard.on('panel-added', this.triggerForceUpdate);
+    dashboard.on('panel-removed', this.triggerForceUpdate);
+    dashboard.on('repeats-processed', this.triggerForceUpdate);
+    dashboard.on('view-mode-changed', this.onViewModeChanged);
+    dashboard.on('row-collapsed', this.triggerForceUpdate);
+    dashboard.on('row-expanded', this.triggerForceUpdate);
   }
 
   buildLayout() {
@@ -123,7 +132,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps> {
     return layout;
   }
 
-  onLayoutChange(newLayout) {
+  onLayoutChange = (newLayout: ReactGridLayout.Layout[]) => {
     for (const newPos of newLayout) {
       this.panelMap[newPos.i].updateGridPos(newPos);
     }
@@ -131,22 +140,22 @@ export class DashboardGrid extends React.Component<DashboardGridProps> {
     this.props.dashboard.sortPanelsByGridPos();
   }
 
-  triggerForceUpdate() {
+  triggerForceUpdate = () => {
     this.forceUpdate();
   }
 
-  onWidthChange() {
+  onWidthChange = () => {
     for (const panel of this.props.dashboard.panels) {
       panel.resizeDone();
     }
   }
 
-  onViewModeChanged(payload) {
+  onViewModeChanged = () => {
     ignoreNextWidthChange = true;
     this.forceUpdate();
   }
 
-  updateGridPos(item, layout) {
+  updateGridPos = (item: ReactGridLayout.Layout, layout: ReactGridLayout.Layout[]) => {
     this.panelMap[item.i].updateGridPos(item);
 
     // react-grid-layout has a bug (#670), and onLayoutChange() is only called when the component is mounted.
@@ -154,16 +163,17 @@ export class DashboardGrid extends React.Component<DashboardGridProps> {
     this.onLayoutChange(layout);
   }
 
-  onResize(layout, oldItem, newItem) {
+  onResize: ItemCallback = (layout, oldItem, newItem) => {
+    console.log();
     this.panelMap[newItem.i].updateGridPos(newItem);
   }
 
-  onResizeStop(layout, oldItem, newItem) {
+  onResizeStop: ItemCallback = (layout, oldItem, newItem) => {
     this.updateGridPos(newItem, layout);
     this.panelMap[newItem.i].resizeDone();
   }
 
-  onDragStop(layout, oldItem, newItem) {
+  onDragStop: ItemCallback = (layout, oldItem, newItem) => {
     this.updateGridPos(newItem, layout);
   }
 

+ 31 - 6
public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx

@@ -1,5 +1,6 @@
 import React, { Component } from 'react';
 import classNames from 'classnames';
+import { isEqual } from 'lodash';
 
 import PanelHeaderCorner from './PanelHeaderCorner';
 import { PanelHeaderMenu } from './PanelHeaderMenu';
@@ -19,21 +20,45 @@ export interface Props {
   links?: [];
 }
 
+interface ClickCoordinates {
+  x: number;
+  y: number;
+}
+
 interface State {
   panelMenuOpen: boolean;
 }
 
 export class PanelHeader extends Component<Props, State> {
+  clickCoordinates: ClickCoordinates = {x: 0, y: 0};
   state = {
     panelMenuOpen: false,
+    clickCoordinates: {x: 0, y: 0}
+  };
+
+  eventToClickCoordinates = (event: React.MouseEvent<HTMLDivElement>) => {
+    return {
+      x: event.clientX,
+      y: event.clientY
+    };
+  }
+
+  onMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {
+    this.clickCoordinates = this.eventToClickCoordinates(event);
   };
 
-  onMenuToggle = event => {
-    event.stopPropagation();
+  isClick = (clickCoordinates: ClickCoordinates) => {
+    return isEqual(clickCoordinates, this.clickCoordinates);
+  }
+
+  onMenuToggle = (event: React.MouseEvent<HTMLDivElement>) => {
+    if (this.isClick(this.eventToClickCoordinates(event))) {
+      event.stopPropagation();
 
-    this.setState(prevState => ({
-      panelMenuOpen: !prevState.panelMenuOpen,
-    }));
+      this.setState(prevState => ({
+        panelMenuOpen: !prevState.panelMenuOpen,
+      }));
+    }
   };
 
   closeMenu = () => {
@@ -64,7 +89,7 @@ export class PanelHeader extends Component<Props, State> {
               <i className="fa fa-spinner fa-spin" />
             </span>
           )}
-          <div className="panel-title-container" onClick={this.onMenuToggle}>
+          <div className="panel-title-container" onClick={this.onMenuToggle} onMouseDown={this.onMouseDown}>
             <div className="panel-title">
               <span className="icon-gf panel-alert-icon" />
               <span className="panel-title-text">

+ 3 - 3
public/app/features/dashboard/dashgrid/PanelResizer.tsx

@@ -1,6 +1,6 @@
 import React, { PureComponent } from 'react';
 import { throttle } from 'lodash';
-import Draggable from 'react-draggable';
+import Draggable, { DraggableEventHandler } from 'react-draggable';
 
 import { PanelModel } from '../panel_model';
 
@@ -42,7 +42,7 @@ export class PanelResizer extends PureComponent<Props, State> {
     return 100;
   }
 
-  changeHeight = height => {
+  changeHeight = (height: number) => {
     const sh = this.smallestHeight;
     const lh = this.largestHeight;
     height = height < sh ? sh : height;
@@ -54,7 +54,7 @@ export class PanelResizer extends PureComponent<Props, State> {
     });
   };
 
-  onDrag = (evt, data) => {
+  onDrag: DraggableEventHandler = (evt, data) => {
     const newHeight = this.state.editorHeight + data.y;
     this.throttledChangeHeight(newHeight);
     this.throttledResizeDone();

+ 15 - 0
yarn.lock

@@ -1773,6 +1773,13 @@
   dependencies:
     "@types/react" "*"
 
+"@types/react-grid-layout@^0.16.6":
+  version "0.16.6"
+  resolved "https://registry.yarnpkg.com/@types/react-grid-layout/-/react-grid-layout-0.16.6.tgz#9149efe128e05d59c54063c7781d18b8febe112c"
+  integrity sha512-Jp0VfCHJE4uxekPBPpRkADKOjoSHssF2ba1ZMMAfCEqkoSkE+K+3bhI39++fbd7MqGySaqADVHeOoxlBnA3p5g==
+  dependencies:
+    "@types/react" "*"
+
 "@types/react-select@^2.0.4":
   version "2.0.11"
   resolved "https://registry.yarnpkg.com/@types/react-select/-/react-select-2.0.11.tgz#9b2b1fdb12b67a5a617c5f572e15617636cc65af"
@@ -1796,6 +1803,14 @@
   dependencies:
     "@types/react" "*"
 
+"@types/react-virtualized@^9.18.12":
+  version "9.18.12"
+  resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.18.12.tgz#541e65c5e0b4629d6a1c6f339171c7943e016ecb"
+  integrity sha512-Msdpt9zvYlb5Ul4PA339QUkJ0/z2O+gaFxed1rG+2rZjbe6XdYo7jWfJe206KBnjj84DwPPIbPFQCtoGuNwNTQ==
+  dependencies:
+    "@types/prop-types" "*"
+    "@types/react" "*"
+
 "@types/react@*", "@types/react@16.7.6", "@types/react@^16.7.6":
   version "16.7.6"
   resolved "https://registry.yarnpkg.com/@types/react/-/react-16.7.6.tgz#80e4bab0d0731ad3ae51f320c4b08bdca5f03040"