浏览代码

wip: panel-header: Separate all panel actions to its own file so we decouple them from react

Johannes Schill 7 年之前
父节点
当前提交
f124b9de6a

+ 26 - 133
public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenu.tsx

@@ -1,16 +1,7 @@
-import React, { PureComponent } from 'react';
+import React, { PureComponent, Fragment } from 'react';
 import { DashboardModel } from 'app/features/dashboard/dashboard_model';
-import { PanelHeaderMenuItem, PanelHeaderMenuItemTypes } from './PanelHeaderMenuItem';
-import { store } from 'app/store/configureStore';
-import { updateLocation } from 'app/core/actions';
-import {
-  removePanel,
-  duplicatePanel,
-  copyPanel,
-  editPanelJson,
-  sharePanel,
-  toggleLegend,
-} from 'app/features/dashboard/utils/panel';
+import { PanelHeaderMenuItem, PanelHeaderMenuItemProps } from './PanelHeaderMenuItem';
+import { getPanelMenu } from 'app/features/dashboard/utils/panel_menu';
 
 export interface PanelHeaderMenuProps {
   panelId: number;
@@ -25,130 +16,32 @@ export class PanelHeaderMenu extends PureComponent<PanelHeaderMenuProps, any> {
     return panelInfo.panel;
   };
 
-  onEditPanel = () => {
-    store.dispatch(
-      updateLocation({
-        query: {
-          panelId: this.props.panelId,
-          edit: true,
-          fullscreen: true,
-        },
-      })
-    );
-  };
-
-  onViewPanel = () => {
-    store.dispatch(
-      updateLocation({
-        query: {
-          panelId: this.props.panelId,
-          edit: false,
-          fullscreen: true,
-        },
-      })
+  renderItems = (menu: PanelHeaderMenuItemProps[], isSubMenu = false) => {
+    return (
+      <ul className="dropdown-menu dropdown-menu--menu panel-menu" role={isSubMenu ? '' : 'menu'}>
+        {menu.map(menuItem => {
+          console.log(this);
+          return (
+            <Fragment>
+              <PanelHeaderMenuItem
+                type={menuItem.type}
+                text={menuItem.text}
+                iconClassName={menuItem.iconClassName}
+                handleClick={menuItem.handleClick}
+                shortcut={menuItem.shortcut}
+              >
+                {menuItem.subMenu && this.renderItems(menuItem.subMenu, true)}
+              </PanelHeaderMenuItem>
+            </Fragment>
+          );
+        })}
+      </ul>
     );
   };
 
-  onRemovePanel = () => {
-    const { dashboard } = this.props;
-    const panel = this.getPanel();
-    removePanel(dashboard, panel, true);
-  };
-
-  onSharePanel = () => {
-    const { dashboard } = this.props;
-    const panel = this.getPanel();
-
-    sharePanel(dashboard, panel);
-  };
-
-  onDuplicatePanel = () => {
-    const { dashboard } = this.props;
-    const panel = this.getPanel();
-
-    duplicatePanel(dashboard, panel);
-  };
-
-  onCopyPanel = () => {
-    const panel = this.getPanel();
-    copyPanel(panel);
-  };
-
-  onEditPanelJson = () => {
-    const { dashboard } = this.props;
-    const panel = this.getPanel();
-    editPanelJson(dashboard, panel);
-  };
-
-  onToggleLegend = () => {
-    const panel = this.getPanel();
-    toggleLegend(panel);
-  };
-
   render() {
-    return (
-      <div className="panel-menu-container dropdown">
-        <ul className="dropdown-menu dropdown-menu--menu panel-menu" role="menu">
-          <PanelHeaderMenuItem
-            type={PanelHeaderMenuItemTypes.Link}
-            text="View"
-            iconClassName="fa fa-fw fa-eye"
-            handleClick={this.onViewPanel}
-            shortcut="v"
-          />
-          <PanelHeaderMenuItem
-            type={PanelHeaderMenuItemTypes.Link}
-            text="Edit"
-            iconClassName="fa fa-fw fa-edit"
-            handleClick={this.onEditPanel}
-            shortcut="e"
-          />
-          <PanelHeaderMenuItem
-            type={PanelHeaderMenuItemTypes.Link}
-            text="Share"
-            iconClassName="fa fa-fw fa-share"
-            handleClick={this.onSharePanel}
-            shortcut="p s"
-          />
-          <PanelHeaderMenuItem
-            type={PanelHeaderMenuItemTypes.SubMenu}
-            text="More ..."
-            iconClassName="fa fa-fw fa-cube"
-            handleClick={null}
-          >
-            <ul className="dropdown-menu dropdown-menu--menu panel-menu">
-              <PanelHeaderMenuItem
-                type={PanelHeaderMenuItemTypes.Link}
-                text="Duplicate"
-                iconClassName=""
-                handleClick={this.onDuplicatePanel}
-                shortcut="p d"
-              />
-              <PanelHeaderMenuItem type={PanelHeaderMenuItemTypes.Link} text="Copy" handleClick={this.onCopyPanel} />
-              <PanelHeaderMenuItem
-                type={PanelHeaderMenuItemTypes.Link}
-                text="Panel JSON"
-                handleClick={this.onEditPanelJson}
-              />
-              <PanelHeaderMenuItem type={PanelHeaderMenuItemTypes.Link} text="Export CSV" handleClick={() => {}} />
-              <PanelHeaderMenuItem
-                type={PanelHeaderMenuItemTypes.Link}
-                text="Toggle legend"
-                handleClick={this.onToggleLegend}
-                shortcut="p l"
-              />
-            </ul>
-          </PanelHeaderMenuItem>
-          <PanelHeaderMenuItem type={PanelHeaderMenuItemTypes.Divider} />
-          <PanelHeaderMenuItem
-            type={PanelHeaderMenuItemTypes.Link}
-            text="Remove"
-            iconClassName="fa fa-fw fa-trash"
-            handleClick={this.onRemovePanel}
-            shortcut="p r"
-          />
-        </ul>
-      </div>
-    );
+    const { dashboard } = this.props;
+    const menu = getPanelMenu(dashboard, this.getPanel());
+    return <div className="panel-menu-container dropdown">{this.renderItems(menu)}</div>;
   }
 }

+ 3 - 1
public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenuItem.tsx

@@ -1,6 +1,6 @@
 import React, { SFC } from 'react';
 
-export enum PanelHeaderMenuItemTypes {
+export enum PanelHeaderMenuItemTypes { // TODO: Evaluate. Remove?
   Button = 'Button', // ?
   Divider = 'Divider',
   Link = 'Link',
@@ -14,6 +14,8 @@ export interface PanelHeaderMenuItemProps {
   handleClick?: () => void;
   shortcut?: string;
   children?: any;
+  subMenu?: PanelHeaderMenuItemProps[];
+  role?: string;
 }
 
 export const PanelHeaderMenuItem: SFC<PanelHeaderMenuItemProps> = props => {

+ 140 - 0
public/app/features/dashboard/utils/panel_menu.ts

@@ -0,0 +1,140 @@
+import { PanelHeaderMenuItemTypes, PanelHeaderMenuItemProps } from './../dashgrid/PanelHeader/PanelHeaderMenuItem';
+import { store } from 'app/store/configureStore';
+import { updateLocation } from 'app/core/actions';
+import { PanelModel } from 'app/features/dashboard/panel_model';
+import { DashboardModel } from 'app/features/dashboard/dashboard_model';
+import { removePanel, duplicatePanel, copyPanel, editPanelJson, sharePanel } from 'app/features/dashboard/utils/panel';
+
+export const getPanelMenu = (dashboard: DashboardModel, panel: PanelModel) => {
+  const onViewPanel = () => {
+    store.dispatch(
+      updateLocation({
+        query: {
+          panelId: panel.id,
+          edit: false,
+          fullscreen: true,
+        },
+      })
+    );
+  };
+
+  const onEditPanel = () => {
+    store.dispatch(
+      updateLocation({
+        query: {
+          panelId: panel.id,
+          edit: true,
+          fullscreen: true,
+        },
+      })
+    );
+  };
+
+  const onSharePanel = () => {
+    sharePanel(dashboard, panel);
+  };
+
+  const onDuplicatePanel = () => {
+    duplicatePanel(dashboard, panel);
+  };
+
+  const onCopyPanel = () => {
+    copyPanel(panel);
+  };
+
+  const onEditPanelJson = () => {
+    editPanelJson(dashboard, panel);
+  };
+
+  const onRemovePanel = () => {
+    removePanel(dashboard, panel, true);
+  };
+
+  const getSubMenu = () => {
+    const menu: PanelHeaderMenuItemProps[] = [];
+
+    if (!panel.fullscreen && dashboard.meta.canEdit) {
+      menu.push({
+        type: PanelHeaderMenuItemTypes.Link,
+        text: 'Duplicate',
+        handleClick: onDuplicatePanel,
+        shortcut: 'p d',
+        role: 'Editor',
+      });
+      menu.push({
+        type: PanelHeaderMenuItemTypes.Link,
+        text: 'Copy',
+        handleClick: onCopyPanel,
+        role: 'Editor',
+      });
+    }
+
+    menu.push({
+      type: PanelHeaderMenuItemTypes.Link,
+      text: 'Panel JSON',
+      handleClick: onEditPanelJson,
+    });
+
+    // TODO: Handle this somehow
+    // this.events.emit('init-panel-actions', menu);
+    return menu;
+  };
+
+  const menu: PanelHeaderMenuItemProps[] = [];
+
+  menu.push({
+    type: PanelHeaderMenuItemTypes.Link,
+    text: 'View',
+    iconClassName: 'fa fa-fw fa-eye',
+    handleClick: onViewPanel,
+    shortcut: 'v',
+  });
+
+  if (dashboard.meta.canEdit) {
+    menu.push({
+      type: PanelHeaderMenuItemTypes.Link,
+      text: 'Edit',
+      iconClassName: 'fa fa-fw fa-edit',
+      handleClick: onEditPanel,
+      shortcut: 'e',
+      role: 'Editor',
+    });
+  }
+
+  menu.push({
+    type: PanelHeaderMenuItemTypes.Link,
+    text: 'Share',
+    iconClassName: 'fa fa-fw fa-share',
+    handleClick: onSharePanel,
+    shortcut: 'p s',
+  });
+
+  const subMenu: PanelHeaderMenuItemProps[] = getSubMenu();
+
+  menu.push({
+    type: PanelHeaderMenuItemTypes.SubMenu,
+    text: 'More...',
+    iconClassName: 'fa fa-fw fa-cube',
+    handleClick: null,
+    subMenu: subMenu,
+  });
+
+  if (dashboard.meta.canEdit) {
+    menu.push({
+      type: PanelHeaderMenuItemTypes.Divider,
+      role: 'Editor',
+    });
+    menu.push({
+      type: PanelHeaderMenuItemTypes.Link,
+      text: 'Remove',
+      iconClassName: 'fa fa-fw fa-trash',
+      handleClick: onRemovePanel,
+      shortcut: 'p r',
+      role: 'Editor',
+    });
+  }
+
+  // Additional items from sub-class
+  // menu.push(...this.getAdditionalMenuItems());
+  return menu;
+};