Files
grafana/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx
Ivana Huckova 431f454d57 @grafana/ui: Create Icon component and replace part of the icons (#23402)
* Part1: Unicons implementation (#23197)

* Create a new Icon component

* Update icons in main sidebar

* Update icons in Useful links and in react components on  main site

* Update icons in Useful links and in main top navigation

* Adjust sizing

* Update panel navigation and timepicker

* Update icons in Panel menu

* NewPanelEditor: Fixed so that test alert rule works in new edit mode (#23179)

* Update icons in add panel widget

* Resolve merge conflict

* Fix part of the test errors and type errors

* Fix storybook errors

* Update getAvailableIcons import in storybook knobs

* Fix import path

* Fix SyntaxError: Cannot use import statement outside a module in test environment error

* Remove dynamic imports

* Remove types as using @ts-ignore

* Update snapshot test

* Add @iconscout/react-unicons to the shouldExclude list as it is blundled with es2015 syntax

* Remove color prop from icon, remove color implemetation in mono icons

* Update navbar styling

* Move toPascalCase to utils/string

Co-authored-by: Torkel Ödegaard <torkel@grafana.com>

* Resolve type errors resulted from merge

* Part2: Unicons implementation (#23266)

* Create a new Icon component

* Update icons in main sidebar

* Update icons in Useful links and in react components on  main site

* Update icons in Useful links and in main top navigation

* Adjust sizing

* Update panel navigation and timepicker

* Update icons in Panel menu

* Update icons in add panel widget

* Resolve merge conflict

* Fix part of the test errors and type errors

* Fix storybook errors

* Update getAvailableIcons import in storybook knobs

* Fix import path

* Fix SyntaxError: Cannot use import statement outside a module in test environment error

* Remove dynamic imports

* Remove types as using @ts-ignore

* Update snapshot test

* Add @iconscout/react-unicons to the shouldExclude list as it is blundled with es2015 syntax

* Implment icons in Tabs

* Implement icons in search items and  empty  list

* Update buttons

* Update button-related snapshot tests

* Update icons in modals and page headers

* Create anfular wrapper and update all icons on search screen

* Update sizing, remove colors, update snapshot tests

* Remove color prop from icon, remove color implemetation in mono icons

* Remove color props from monochrome icons

* Complete update of icons for search screen

* Update icons for infor tooltips, playlist, permissions

* Support temporarly font awesome icons used in enterprise grafana

* Part1: Unicons implementation (#23197)

* Create a new Icon component

* Update icons in main sidebar

* Update icons in Useful links and in react components on  main site

* Update icons in Useful links and in main top navigation

* Adjust sizing

* Update panel navigation and timepicker

* Update icons in Panel menu

* NewPanelEditor: Fixed so that test alert rule works in new edit mode (#23179)

* Update icons in add panel widget

* Resolve merge conflict

* Fix part of the test errors and type errors

* Fix storybook errors

* Update getAvailableIcons import in storybook knobs

* Fix import path

* Fix SyntaxError: Cannot use import statement outside a module in test environment error

* Remove dynamic imports

* Remove types as using @ts-ignore

* Update snapshot test

* Add @iconscout/react-unicons to the shouldExclude list as it is blundled with es2015 syntax

* Remove color prop from icon, remove color implemetation in mono icons

* Update navbar styling

* Move toPascalCase to utils/string

Co-authored-by: Torkel Ödegaard <torkel@grafana.com>

* Icons update

* Add optional chaining to for isFontAwesome variable

Co-authored-by: Torkel Ödegaard <torkel@grafana.com>

* Part3:  Unicons implementation (#23356)

* Create a new Icon component

* Update icons in main sidebar

* Update icons in Useful links and in react components on  main site

* Update icons in Useful links and in main top navigation

* Adjust sizing

* Update panel navigation and timepicker

* Update icons in Panel menu

* Update icons in add panel widget

* Resolve merge conflict

* Fix part of the test errors and type errors

* Fix storybook errors

* Update getAvailableIcons import in storybook knobs

* Fix import path

* Fix SyntaxError: Cannot use import statement outside a module in test environment error

* Remove dynamic imports

* Remove types as using @ts-ignore

* Update snapshot test

* Add @iconscout/react-unicons to the shouldExclude list as it is blundled with es2015 syntax

* Implment icons in Tabs

* Implement icons in search items and  empty  list

* Update buttons

* Update button-related snapshot tests

* Update icons in modals and page headers

* Create anfular wrapper and update all icons on search screen

* Update sizing, remove colors, update snapshot tests

* Remove color prop from icon, remove color implemetation in mono icons

* Remove color props from monochrome icons

* Complete update of icons for search screen

* Update icons for infor tooltips, playlist, permissions

* Support temporarly font awesome icons used in enterprise grafana

* Part1: Unicons implementation (#23197)

* Create a new Icon component

* Update icons in main sidebar

* Update icons in Useful links and in react components on  main site

* Update icons in Useful links and in main top navigation

* Adjust sizing

* Update panel navigation and timepicker

* Update icons in Panel menu

* NewPanelEditor: Fixed so that test alert rule works in new edit mode (#23179)

* Update icons in add panel widget

* Resolve merge conflict

* Fix part of the test errors and type errors

* Fix storybook errors

* Update getAvailableIcons import in storybook knobs

* Fix import path

* Fix SyntaxError: Cannot use import statement outside a module in test environment error

* Remove dynamic imports

* Remove types as using @ts-ignore

* Update snapshot test

* Add @iconscout/react-unicons to the shouldExclude list as it is blundled with es2015 syntax

* Remove color prop from icon, remove color implemetation in mono icons

* Update navbar styling

* Move toPascalCase to utils/string

Co-authored-by: Torkel Ödegaard <torkel@grafana.com>

* Update icons in Explore

* Update icons in alerting

* Update + and x buttons

* Update icons in configurations and settings

* Update close icons

* Update icons in rich history

* Update alert messages

* Add optional chaining to for isFontAwesome variable

* Remove icon mock, set up jest.config

* Fix navbar plus icon

* Fir enable-bacground to enableBackgournd

Co-authored-by: Torkel Ödegaard <torkel@grafana.com>

* Merge remote branch origin master to icons-unicons

* Revert "Merge remote branch origin master to icons-unicons"

This reverts commit 3f25d50a39.

* Size-up dashnav icons

* Fix alerting icons, panel headers, update tests

* Fix typecheck error

* Adjustments - add panel icon, spacing

* Set TerserPlugin sourceMap to false to prevent running out of memory when publishing storybook

Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
2020-04-08 14:33:31 +02:00

186 lines
5.4 KiB
TypeScript

import React, { Component } from 'react';
import classNames from 'classnames';
import { isEqual } from 'lodash';
import { DataLink, ScopedVars, PanelMenuItem, PanelData, LoadingState, QueryResultMetaNotice } from '@grafana/data';
import { AngularComponent } from '@grafana/runtime';
import { ClickOutsideWrapper, Tooltip, Icon } from '@grafana/ui';
import { e2e } from '@grafana/e2e';
import PanelHeaderCorner from './PanelHeaderCorner';
import { PanelHeaderMenu } from './PanelHeaderMenu';
import templateSrv from 'app/features/templating/template_srv';
import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
import { getPanelLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
import { getPanelMenu } from 'app/features/dashboard/utils/getPanelMenu';
import { updateLocation } from 'app/core/actions';
export interface Props {
panel: PanelModel;
dashboard: DashboardModel;
title?: string;
description?: string;
scopedVars?: ScopedVars;
angularComponent?: AngularComponent | null;
links?: DataLink[];
error?: string;
isFullscreen: boolean;
data: PanelData;
updateLocation: typeof updateLocation;
}
interface ClickCoordinates {
x: number;
y: number;
}
interface State {
panelMenuOpen: boolean;
menuItems: PanelMenuItem[];
}
export class PanelHeader extends Component<Props, State> {
clickCoordinates: ClickCoordinates = { x: 0, y: 0 };
state: State = {
panelMenuOpen: false,
menuItems: [],
};
eventToClickCoordinates = (event: React.MouseEvent<HTMLDivElement>) => {
return {
x: event.clientX,
y: event.clientY,
};
};
onMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {
this.clickCoordinates = this.eventToClickCoordinates(event);
};
isClick = (clickCoordinates: ClickCoordinates) => {
return isEqual(clickCoordinates, this.clickCoordinates);
};
onMenuToggle = (event: React.MouseEvent<HTMLDivElement>) => {
if (!this.isClick(this.eventToClickCoordinates(event))) {
return;
}
event.stopPropagation();
const { dashboard, panel, angularComponent } = this.props;
const menuItems = getPanelMenu(dashboard, panel, angularComponent);
this.setState({
panelMenuOpen: !this.state.panelMenuOpen,
menuItems,
});
};
closeMenu = () => {
this.setState({
panelMenuOpen: false,
});
};
private renderLoadingState(): JSX.Element {
return (
<div className="panel-loading">
<i className="fa fa-spinner fa-spin" />
</div>
);
}
openInspect = (e: React.SyntheticEvent, tab: string) => {
const { updateLocation, panel } = this.props;
e.stopPropagation();
updateLocation({
query: { inspect: panel.id, tab },
partial: true,
});
};
renderNotice = (notice: QueryResultMetaNotice) => {
return (
<Tooltip content={notice.text} key={notice.severity}>
{notice.inspect ? (
<div className="panel-info-notice" onClick={e => this.openInspect(e, notice.inspect!)}>
<Icon name="info-circle" style={{ marginRight: '8px' }} />
</div>
) : (
<a className="panel-info-notice" href={notice.link} target="_blank">
<Icon name="info-circle" style={{ marginRight: '8px' }} />
</a>
)}
</Tooltip>
);
};
render() {
const { panel, scopedVars, error, isFullscreen, data } = this.props;
const { menuItems } = this.state;
const title = templateSrv.replaceWithText(panel.title, scopedVars);
const panelHeaderClass = classNames({
'panel-header': true,
'grid-drag-handle': !isFullscreen,
});
// dedupe on severity
const notices: Record<string, QueryResultMetaNotice> = {};
for (const series of data.series) {
if (series.meta && series.meta.notices) {
for (const notice of series.meta.notices) {
notices[notice.severity] = notice;
}
}
}
return (
<>
{data.state === LoadingState.Loading && this.renderLoadingState()}
<div className={panelHeaderClass}>
<PanelHeaderCorner
panel={panel}
title={panel.title}
description={panel.description}
scopedVars={panel.scopedVars}
links={getPanelLinksSupplier(panel)}
error={error}
/>
<div
className="panel-title-container"
onClick={this.onMenuToggle}
onMouseDown={this.onMouseDown}
aria-label={e2e.pages.Dashboard.Panels.Panel.selectors.title(title)}
>
<div className="panel-title">
{Object.values(notices).map(this.renderNotice)}
<span className="icon-gf panel-alert-icon" />
<span className="panel-title-text">
{title}
<Icon name="angle-down" className="panel-menu-toggle" />
</span>
{this.state.panelMenuOpen && (
<ClickOutsideWrapper onClick={this.closeMenu}>
<PanelHeaderMenu items={menuItems} />
</ClickOutsideWrapper>
)}
{data.request && data.request.timeInfo && (
<span className="panel-time-info">
<Icon name="clock-nine" /> {data.request.timeInfo}
</span>
)}
</div>
</div>
</div>
</>
);
}
}