wip: Initial commit for PanelHeaderMenu

This commit is contained in:
Johannes Schill 2018-10-25 12:47:09 +02:00
parent b28b79100a
commit 9f6683de2c
8 changed files with 199 additions and 86 deletions

View File

@ -38,7 +38,6 @@ export class DataPanel extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
loading: LoadingState.NotStarted,
response: {

View File

@ -5,7 +5,7 @@ import React, { ComponentClass, PureComponent } from 'react';
import { getTimeSrv } from '../time_srv';
// Components
import { PanelHeader } from './PanelHeader';
import { PanelHeader } from './PanelHeader/PanelHeader';
import { DataPanel } from './DataPanel';
// Types

View File

@ -1,83 +0,0 @@
import React from 'react';
import classNames from 'classnames';
import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model';
import { store } from 'app/store/configureStore';
import { updateLocation } from 'app/core/actions';
interface PanelHeaderProps {
panel: PanelModel;
dashboard: DashboardModel;
}
export class PanelHeader extends React.Component<PanelHeaderProps, any> {
onEditPanel = () => {
store.dispatch(
updateLocation({
query: {
panelId: this.props.panel.id,
edit: true,
fullscreen: true,
},
})
);
};
onViewPanel = () => {
store.dispatch(
updateLocation({
query: {
panelId: this.props.panel.id,
edit: false,
fullscreen: true,
},
})
);
};
render() {
const isFullscreen = false;
const isLoading = false;
const panelHeaderClass = classNames({ 'panel-header': true, 'grid-drag-handle': !isFullscreen });
return (
<div className={panelHeaderClass}>
<span className="panel-info-corner">
<i className="fa" />
<span className="panel-info-corner-inner" />
</span>
{isLoading && (
<span className="panel-loading">
<i className="fa fa-spinner fa-spin" />
</span>
)}
<div className="panel-title-container">
<span className="panel-title">
<span className="icon-gf panel-alert-icon" />
<span className="panel-title-text">{this.props.panel.title}</span>
<span className="panel-menu-container dropdown">
<span className="fa fa-caret-down panel-menu-toggle" data-toggle="dropdown" />
<ul className="dropdown-menu dropdown-menu--menu panel-menu" role="menu">
<li>
<a onClick={this.onEditPanel}>
<i className="fa fa-fw fa-edit" /> Edit
</a>
</li>
<li>
<a onClick={this.onViewPanel}>
<i className="fa fa-fw fa-eye" /> View
</a>
</li>
</ul>
</span>
<span className="panel-time-info">
<i className="fa fa-clock-o" /> 4m
</span>
</span>
</div>
</div>
);
}
}

View File

@ -0,0 +1,50 @@
import React from 'react';
import classNames from 'classnames';
import { PanelModel } from 'app/features/dashboard/panel_model';
import { DashboardModel } from 'app/features/dashboard/dashboard_model';
// import { store } from 'app/store/configureStore';
// import { updateLocation } from 'app/core/actions';
import { PanelHeaderMenu } from './PanelHeaderMenu';
// import appEvents from 'app/core/app_events';
interface PanelHeaderProps {
panel: PanelModel;
dashboard: DashboardModel;
}
export class PanelHeader extends React.Component<PanelHeaderProps, any> {
render() {
const isFullscreen = false;
const isLoading = false;
const panelHeaderClass = classNames({ 'panel-header': true, 'grid-drag-handle': !isFullscreen });
return (
<div className={panelHeaderClass}>
<span className="panel-info-corner">
<i className="fa" />
<span className="panel-info-corner-inner" />
</span>
{isLoading && (
<span className="panel-loading">
<i className="fa fa-spinner fa-spin" />
</span>
)}
<div className="panel-title-container">
<div className="panel-title">
<span className="icon-gf panel-alert-icon" />
<span className="panel-title-text" data-toggle="dropdown">
{this.props.panel.title} <span className="fa fa-caret-down panel-menu-toggle" />
</span>
<PanelHeaderMenu panelId={this.props.panel.id} />
<span className="panel-time-info">
<i className="fa fa-clock-o" /> 4m
</span>
</div>
</div>
</div>
);
}
}

View File

@ -0,0 +1,109 @@
import React, { PureComponent } from 'react';
// import { store } from 'app/store/configureStore';
import { PanelHeaderMenuItem, PanelHeaderMenuItemTypes } from './PanelHeaderMenuItem';
import appEvents from 'app/core/app_events';
import { store } from 'app/store/configureStore';
import { updateLocation } from 'app/core/actions';
export interface PanelHeaderMenuProps {
panelId: number;
}
export class PanelHeaderMenu extends PureComponent<PanelHeaderMenuProps, any> {
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,
},
})
);
};
onRemovePanel = () => {
appEvents.emit('panel-remove', {
panelId: this.props.panelId,
});
};
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={() => {}}
shortcut="p s"
/>
<PanelHeaderMenuItem
type={PanelHeaderMenuItemTypes.SubMenu}
text="More ..."
iconClassName="fa fa-fw fa-cube"
handleClick={() => {}}
>
<ul className="dropdown-menu dropdown-menu--menu panel-menu">
<PanelHeaderMenuItem
type={PanelHeaderMenuItemTypes.Link}
text="Duplicate"
iconClassName=""
handleClick={() => {}}
shortcut="p d"
/>
<PanelHeaderMenuItem type={PanelHeaderMenuItemTypes.Link} text="Copy" handleClick={() => {}} />
<PanelHeaderMenuItem type={PanelHeaderMenuItemTypes.Link} text="Panel JSON" handleClick={() => {}} />
<PanelHeaderMenuItem type={PanelHeaderMenuItemTypes.Link} text="Export CSV" handleClick={() => {}} />
<PanelHeaderMenuItem
type={PanelHeaderMenuItemTypes.Link}
text="Toggle legend"
handleClick={() => {}}
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>
);
}
}

View File

@ -0,0 +1,34 @@
import React, { SFC } from 'react';
export enum PanelHeaderMenuItemTypes {
Button = 'Button', // ?
Divider = 'Divider',
Link = 'Link',
SubMenu = 'SubMenu',
}
export interface PanelHeaderMenuItemProps {
type: PanelHeaderMenuItemTypes;
text?: string;
iconClassName?: string;
handleClick?: () => void;
shortcut?: string;
children?: any;
}
export const PanelHeaderMenuItem: SFC<PanelHeaderMenuItemProps> = props => {
const isSubMenu = props.type === PanelHeaderMenuItemTypes.SubMenu;
const isDivider = props.type === PanelHeaderMenuItemTypes.Divider;
return isDivider ? (
<li className="divider" />
) : (
<li className={isSubMenu ? 'dropdown-submenu' : null}>
<a onClick={props.handleClick}>
{props.iconClassName && <i className={props.iconClassName} />}
<span className="dropdown-item-text">{props.text}</span>
{props.shortcut && <span className="dropdown-menu-item-shortcut">{props.shortcut}</span>}
</a>
{props.children}
</li>
);
};

View File

@ -183,6 +183,11 @@
display: block;
}
& > .dropdown > .dropdown-menu {
// Panel menu. TODO: See if we can merge this with above
display: block;
}
&.cascade-open {
.dropdown-menu {
display: block;

View File

@ -138,7 +138,6 @@ div.flot-text {
padding: 3px 5px;
visibility: hidden;
opacity: 0;
position: absolute;
width: 16px;
height: 16px;
left: 1px;