2018-12-05 07:57:57 -06:00
|
|
|
import React, { Component } from 'react';
|
2018-10-25 05:47:09 -05:00
|
|
|
import classNames from 'classnames';
|
2019-01-30 08:38:59 -06:00
|
|
|
import { isEqual } from 'lodash';
|
2019-12-09 02:14:25 -06:00
|
|
|
import { DataLink, ScopedVars } from '@grafana/data';
|
|
|
|
import { ClickOutsideWrapper } from '@grafana/ui';
|
|
|
|
import { e2e } from '@grafana/e2e';
|
2018-10-25 05:47:09 -05:00
|
|
|
|
2018-11-15 09:52:39 -06:00
|
|
|
import PanelHeaderCorner from './PanelHeaderCorner';
|
2018-11-07 06:55:02 -06:00
|
|
|
import { PanelHeaderMenu } from './PanelHeaderMenu';
|
2019-01-15 10:15:46 -06:00
|
|
|
import templateSrv from 'app/features/templating/template_srv';
|
2018-11-07 06:55:02 -06:00
|
|
|
|
2019-01-31 01:56:17 -06:00
|
|
|
import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
|
|
|
|
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
|
2019-08-28 01:50:43 -05:00
|
|
|
import { getPanelLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
|
2018-11-07 06:55:02 -06:00
|
|
|
|
|
|
|
export interface Props {
|
|
|
|
panel: PanelModel;
|
|
|
|
dashboard: DashboardModel;
|
2018-11-08 07:44:12 -06:00
|
|
|
timeInfo: string;
|
2018-12-05 07:57:57 -06:00
|
|
|
title?: string;
|
|
|
|
description?: string;
|
2019-03-04 03:42:59 -06:00
|
|
|
scopedVars?: ScopedVars;
|
2019-06-25 04:38:51 -05:00
|
|
|
links?: DataLink[];
|
2019-02-12 10:01:07 -06:00
|
|
|
error?: string;
|
2019-02-17 01:11:57 -06:00
|
|
|
isFullscreen: boolean;
|
2018-10-25 05:47:09 -05:00
|
|
|
}
|
2018-11-03 17:36:40 -05:00
|
|
|
|
2019-01-30 08:38:59 -06:00
|
|
|
interface ClickCoordinates {
|
|
|
|
x: number;
|
|
|
|
y: number;
|
|
|
|
}
|
|
|
|
|
2018-11-13 10:00:28 -06:00
|
|
|
interface State {
|
|
|
|
panelMenuOpen: boolean;
|
|
|
|
}
|
|
|
|
|
2018-12-05 07:57:57 -06:00
|
|
|
export class PanelHeader extends Component<Props, State> {
|
2019-02-13 04:14:53 -06:00
|
|
|
clickCoordinates: ClickCoordinates = { x: 0, y: 0 };
|
2018-11-13 10:00:28 -06:00
|
|
|
state = {
|
|
|
|
panelMenuOpen: false,
|
2019-02-13 04:14:53 -06:00
|
|
|
clickCoordinates: { x: 0, y: 0 },
|
2019-01-30 08:38:59 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
eventToClickCoordinates = (event: React.MouseEvent<HTMLDivElement>) => {
|
|
|
|
return {
|
|
|
|
x: event.clientX,
|
2019-02-13 04:14:53 -06:00
|
|
|
y: event.clientY,
|
2019-01-30 08:38:59 -06:00
|
|
|
};
|
2019-02-13 04:14:53 -06:00
|
|
|
};
|
2019-01-30 08:38:59 -06:00
|
|
|
|
|
|
|
onMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {
|
|
|
|
this.clickCoordinates = this.eventToClickCoordinates(event);
|
2018-11-13 10:00:28 -06:00
|
|
|
};
|
|
|
|
|
2019-01-30 08:38:59 -06:00
|
|
|
isClick = (clickCoordinates: ClickCoordinates) => {
|
|
|
|
return isEqual(clickCoordinates, this.clickCoordinates);
|
2019-02-13 04:14:53 -06:00
|
|
|
};
|
2019-01-30 08:38:59 -06:00
|
|
|
|
|
|
|
onMenuToggle = (event: React.MouseEvent<HTMLDivElement>) => {
|
|
|
|
if (this.isClick(this.eventToClickCoordinates(event))) {
|
|
|
|
event.stopPropagation();
|
2018-11-13 10:00:28 -06:00
|
|
|
|
2019-01-30 08:38:59 -06:00
|
|
|
this.setState(prevState => ({
|
|
|
|
panelMenuOpen: !prevState.panelMenuOpen,
|
|
|
|
}));
|
|
|
|
}
|
2018-11-13 10:00:28 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
closeMenu = () => {
|
|
|
|
this.setState({
|
|
|
|
panelMenuOpen: false,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2018-10-25 05:47:09 -05:00
|
|
|
render() {
|
2019-02-17 01:11:57 -06:00
|
|
|
const { panel, dashboard, timeInfo, scopedVars, error, isFullscreen } = this.props;
|
2019-01-15 10:15:46 -06:00
|
|
|
const title = templateSrv.replaceWithText(panel.title, scopedVars);
|
|
|
|
|
2019-05-06 08:26:09 -05:00
|
|
|
const panelHeaderClass = classNames({
|
|
|
|
'panel-header': true,
|
|
|
|
'grid-drag-handle': !isFullscreen,
|
|
|
|
});
|
|
|
|
|
2018-10-25 05:47:09 -05:00
|
|
|
return (
|
2018-11-15 07:30:59 -06:00
|
|
|
<>
|
|
|
|
<div className={panelHeaderClass}>
|
2019-05-10 04:35:55 -05:00
|
|
|
<PanelHeaderCorner
|
|
|
|
panel={panel}
|
|
|
|
title={panel.title}
|
|
|
|
description={panel.description}
|
|
|
|
scopedVars={panel.scopedVars}
|
2019-08-28 01:50:43 -05:00
|
|
|
links={getPanelLinksSupplier(panel)}
|
2019-05-10 04:35:55 -05:00
|
|
|
error={error}
|
|
|
|
/>
|
2019-05-08 09:50:21 -05:00
|
|
|
<div
|
|
|
|
className="panel-title-container"
|
|
|
|
onClick={this.onMenuToggle}
|
|
|
|
onMouseDown={this.onMouseDown}
|
2019-12-17 23:13:58 -06:00
|
|
|
aria-label={e2e.pages.Dashboard.Panels.Panel.selectors.title(title)}
|
2019-05-08 09:50:21 -05:00
|
|
|
>
|
2018-11-15 07:30:59 -06:00
|
|
|
<div className="panel-title">
|
|
|
|
<span className="icon-gf panel-alert-icon" />
|
|
|
|
<span className="panel-title-text">
|
2019-01-15 10:15:46 -06:00
|
|
|
{title} <span className="fa fa-caret-down panel-menu-toggle" />
|
2018-11-15 07:30:59 -06:00
|
|
|
</span>
|
|
|
|
{this.state.panelMenuOpen && (
|
|
|
|
<ClickOutsideWrapper onClick={this.closeMenu}>
|
|
|
|
<PanelHeaderMenu panel={panel} dashboard={dashboard} />
|
|
|
|
</ClickOutsideWrapper>
|
|
|
|
)}
|
|
|
|
{timeInfo && (
|
|
|
|
<span className="panel-time-info">
|
|
|
|
<i className="fa fa-clock-o" /> {timeInfo}
|
|
|
|
</span>
|
|
|
|
)}
|
|
|
|
</div>
|
2018-10-25 05:47:09 -05:00
|
|
|
</div>
|
|
|
|
</div>
|
2018-11-15 07:30:59 -06:00
|
|
|
</>
|
2018-10-25 05:47:09 -05:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|