Chore: Rename grafana core PanelChrome and use grafana-ui - PanelChrome component (#56659)

This commit is contained in:
Alexa V 2022-10-17 16:03:38 +02:00 committed by GitHub
parent de1cfc120f
commit 6524a0b437
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 136 additions and 47 deletions

View File

@ -3645,14 +3645,14 @@ exports[`better eslint`] = {
"public/app/features/dashboard/dashgrid/LazyLoader.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/dashboard/dashgrid/PanelChrome.tsx:5381": [
"public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenuItem.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/features/dashboard/dashgrid/PanelStateWrapper.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
"public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenuItem.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/features/dashboard/dashgrid/SeriesVisibilityConfigFactory.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],

View File

@ -8,8 +8,8 @@ import { setPanelInstanceState } from '../../panel/state/reducers';
import { DashboardModel, PanelModel } from '../state';
import { LazyLoader } from './LazyLoader';
import { PanelChrome } from './PanelChrome';
import { PanelChromeAngular } from './PanelChromeAngular';
import { PanelStateWrapper } from './PanelStateWrapper';
export interface OwnProps {
panel: PanelModel;
@ -86,7 +86,7 @@ export class DashboardPanelUnconnected extends PureComponent<Props> {
height={height}
/>
) : (
<PanelChrome
<PanelStateWrapper
plugin={plugin}
panel={panel}
dashboard={dashboard}

View File

@ -10,7 +10,7 @@ import { PanelQueryRunner } from '../../query/state/PanelQueryRunner';
import { setTimeSrv, TimeSrv } from '../services/TimeSrv';
import { DashboardModel, PanelModel } from '../state';
import { PanelChrome, Props } from './PanelChrome';
import { PanelStateWrapper, Props } from './PanelStateWrapper';
jest.mock('app/core/profiler', () => ({
profiler: {
@ -69,14 +69,14 @@ function setupTestContext(options: Partial<Props>) {
const props = { ...defaults, ...options };
const { rerender } = render(
<Provider store={store}>
<PanelChrome {...props} />
<PanelStateWrapper {...props} />
</Provider>
);
return { rerender, props, subject, store };
}
describe('PanelChrome', () => {
describe('PanelStateWrapper', () => {
describe('when the user scrolls by a panel so fast that it starts loading data but scrolls out of view', () => {
it('then it should load the panel successfully when scrolled into view again', () => {
const { rerender, props, subject, store } = setupTestContext({});
@ -91,7 +91,7 @@ describe('PanelChrome', () => {
const newProps = { ...props, isInView: true };
rerender(
<Provider store={store}>
<PanelChrome {...newProps} />
<PanelStateWrapper {...newProps} />
</Provider>
);

View File

@ -22,7 +22,14 @@ import {
import { selectors } from '@grafana/e2e-selectors';
import { config, locationService, RefreshEvent } from '@grafana/runtime';
import { VizLegendOptions } from '@grafana/schema';
import { ErrorBoundary, PanelContext, PanelContextProvider, SeriesVisibilityChangeMode } from '@grafana/ui';
import {
ErrorBoundary,
PanelChrome,
PanelContext,
PanelContextProvider,
PanelPadding,
SeriesVisibilityChangeMode,
} from '@grafana/ui';
import { PANEL_BORDER } from 'app/core/constants';
import { profiler } from 'app/core/profiler';
import { applyPanelTimeOverrides } from 'app/features/dashboard/utils/panel';
@ -37,6 +44,7 @@ import { DashboardModel, PanelModel } from '../state';
import { loadSnapshotData } from '../utils/loadSnapshotData';
import { PanelHeader } from './PanelHeader/PanelHeader';
import { PanelHeaderLoadingIndicator } from './PanelHeader/PanelHeaderLoadingIndicator';
import { seriesVisibilityConfigFactory } from './SeriesVisibilityConfigFactory';
import { liveTimer } from './liveTimer';
@ -64,7 +72,7 @@ export interface State {
liveTime?: TimeRange;
}
export class PanelChrome extends PureComponent<Props, State> {
export class PanelStateWrapper extends PureComponent<Props, State> {
private readonly timeSrv: TimeSrv = getTimeSrv();
private subs = new Subscription();
private eventFilter: EventFilterOptions = { onlyLocal: true };
@ -429,6 +437,56 @@ export class PanelChrome extends PureComponent<Props, State> {
);
}
renderPanelContent(innerWidth: number, innerHeight: number) {
const { panel, plugin, dashboard } = this.props;
const { renderCounter, data } = this.state;
const { state: loadingState } = data;
// do not render component until we have first data
if (this.skipFirstRender(loadingState)) {
return null;
}
// This is only done to increase a counter that is used by backend
// image rendering to know when to capture image
if (this.shouldSignalRenderingCompleted(loadingState, plugin.meta)) {
profiler.renderingCompleted();
}
const PanelComponent = plugin.panel!;
const timeRange = this.state.liveTime ?? data.timeRange ?? this.timeSrv.timeRange();
const panelOptions = panel.getOptions();
// Update the event filter (dashboard settings may have changed)
// Yes this is called ever render for a function that is triggered on every mouse move
this.eventFilter.onlyLocal = dashboard.graphTooltip === 0;
return (
<>
<PanelContextProvider value={this.state.context}>
<PanelComponent
id={panel.id}
data={data}
title={panel.title}
timeRange={timeRange}
timeZone={this.props.dashboard.getTimezone()}
options={panelOptions}
fieldConfig={panel.fieldConfig}
transparent={panel.transparent}
width={innerWidth}
height={innerHeight}
renderCounter={renderCounter}
replaceVariables={panel.replaceVariables}
onOptionsChange={this.onOptionsChange}
onFieldConfigChange={this.onFieldConfigChange}
onChangeTimeRange={this.onChangeTimeRange}
eventBus={dashboard.events}
/>
</PanelContextProvider>
</>
);
}
renderPanel(width: number, height: number) {
const { panel, plugin, dashboard } = this.props;
const { renderCounter, data } = this.state;
@ -517,36 +575,67 @@ export class PanelChrome extends PureComponent<Props, State> {
[`panel-alert-state--${alertState}`]: alertState !== undefined,
});
return (
<section
className={containerClassNames}
aria-label={selectors.components.Panels.Panel.containerByTitle(panel.title)}
>
<PanelHeader
panel={panel}
dashboard={dashboard}
title={panel.title}
description={panel.description}
links={panel.links}
error={errorMessage}
isEditing={isEditing}
isViewing={isViewing}
alertState={alertState}
data={data}
/>
<ErrorBoundary
dependencies={[data, plugin, panel.getOptions()]}
onError={this.onPanelError}
onRecover={this.onPanelErrorRecover}
// for new panel header design
const onCancelQuery = () => panel.getQueryRunner().cancelQuery();
const title = panel.getDisplayTitle();
const noPadding: PanelPadding = plugin.noPadding ? 'none' : 'md';
const leftItems = [
<PanelHeaderLoadingIndicator state={data.state} onClick={onCancelQuery} key="loading-indicator" />,
];
if (config.featureToggles.newPanelChromeUI) {
return (
<PanelChrome width={width} height={height} title={title} leftItems={leftItems} padding={noPadding}>
{(innerWidth, innerHeight) => (
<>
<ErrorBoundary
dependencies={[data, plugin, panel.getOptions()]}
onError={this.onPanelError}
onRecover={this.onPanelErrorRecover}
>
{({ error }) => {
if (error) {
return null;
}
return this.renderPanelContent(innerWidth, innerHeight);
}}
</ErrorBoundary>
</>
)}
</PanelChrome>
);
} else {
return (
<section
className={containerClassNames}
aria-label={selectors.components.Panels.Panel.containerByTitle(panel.title)}
>
{({ error }) => {
if (error) {
return null;
}
return this.renderPanel(width, height);
}}
</ErrorBoundary>
</section>
);
<PanelHeader
panel={panel}
dashboard={dashboard}
title={panel.title}
description={panel.description}
links={panel.links}
error={errorMessage}
isEditing={isEditing}
isViewing={isViewing}
alertState={alertState}
data={data}
/>
<ErrorBoundary
dependencies={[data, plugin, panel.getOptions()]}
onError={this.onPanelError}
onRecover={this.onPanelErrorRecover}
>
{({ error }) => {
if (error) {
return null;
}
return this.renderPanel(width, height);
}}
</ErrorBoundary>
</section>
);
}
}
}

View File

@ -2,7 +2,7 @@ import { BehaviorSubject } from 'rxjs';
import { dateMath, dateTime, TimeRange } from '@grafana/data';
import { PanelChrome } from './PanelChrome';
import { PanelStateWrapper } from './PanelStateWrapper';
// target is 20hz (50ms), but we poll at 100ms to smooth out jitter
const interval = 100;
@ -10,7 +10,7 @@ const interval = 100;
interface LiveListener {
last: number;
intervalMs: number;
panel: PanelChrome;
panel: PanelStateWrapper;
}
class LiveTimer {
@ -41,7 +41,7 @@ class LiveTimer {
}
}
listen(panel: PanelChrome) {
listen(panel: PanelStateWrapper) {
this.listeners.push({
last: this.lastUpdate,
panel: panel,
@ -52,11 +52,11 @@ class LiveTimer {
});
}
remove(panel: PanelChrome) {
remove(panel: PanelStateWrapper) {
this.listeners = this.listeners.filter((v) => v.panel !== panel);
}
updateInterval(panel: PanelChrome) {
updateInterval(panel: PanelStateWrapper) {
if (!this.timeRange || !this.isLive) {
return;
}