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": [ "public/app/features/dashboard/dashgrid/LazyLoader.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"] [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.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"] [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": [ "public/app/features/dashboard/dashgrid/SeriesVisibilityConfigFactory.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"] [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 { DashboardModel, PanelModel } from '../state';
import { LazyLoader } from './LazyLoader'; import { LazyLoader } from './LazyLoader';
import { PanelChrome } from './PanelChrome';
import { PanelChromeAngular } from './PanelChromeAngular'; import { PanelChromeAngular } from './PanelChromeAngular';
import { PanelStateWrapper } from './PanelStateWrapper';
export interface OwnProps { export interface OwnProps {
panel: PanelModel; panel: PanelModel;
@ -86,7 +86,7 @@ export class DashboardPanelUnconnected extends PureComponent<Props> {
height={height} height={height}
/> />
) : ( ) : (
<PanelChrome <PanelStateWrapper
plugin={plugin} plugin={plugin}
panel={panel} panel={panel}
dashboard={dashboard} dashboard={dashboard}

View File

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

View File

@ -22,7 +22,14 @@ import {
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { config, locationService, RefreshEvent } from '@grafana/runtime'; import { config, locationService, RefreshEvent } from '@grafana/runtime';
import { VizLegendOptions } from '@grafana/schema'; 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 { PANEL_BORDER } from 'app/core/constants';
import { profiler } from 'app/core/profiler'; import { profiler } from 'app/core/profiler';
import { applyPanelTimeOverrides } from 'app/features/dashboard/utils/panel'; import { applyPanelTimeOverrides } from 'app/features/dashboard/utils/panel';
@ -37,6 +44,7 @@ import { DashboardModel, PanelModel } from '../state';
import { loadSnapshotData } from '../utils/loadSnapshotData'; import { loadSnapshotData } from '../utils/loadSnapshotData';
import { PanelHeader } from './PanelHeader/PanelHeader'; import { PanelHeader } from './PanelHeader/PanelHeader';
import { PanelHeaderLoadingIndicator } from './PanelHeader/PanelHeaderLoadingIndicator';
import { seriesVisibilityConfigFactory } from './SeriesVisibilityConfigFactory'; import { seriesVisibilityConfigFactory } from './SeriesVisibilityConfigFactory';
import { liveTimer } from './liveTimer'; import { liveTimer } from './liveTimer';
@ -64,7 +72,7 @@ export interface State {
liveTime?: TimeRange; liveTime?: TimeRange;
} }
export class PanelChrome extends PureComponent<Props, State> { export class PanelStateWrapper extends PureComponent<Props, State> {
private readonly timeSrv: TimeSrv = getTimeSrv(); private readonly timeSrv: TimeSrv = getTimeSrv();
private subs = new Subscription(); private subs = new Subscription();
private eventFilter: EventFilterOptions = { onlyLocal: true }; 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) { renderPanel(width: number, height: number) {
const { panel, plugin, dashboard } = this.props; const { panel, plugin, dashboard } = this.props;
const { renderCounter, data } = this.state; const { renderCounter, data } = this.state;
@ -517,36 +575,67 @@ export class PanelChrome extends PureComponent<Props, State> {
[`panel-alert-state--${alertState}`]: alertState !== undefined, [`panel-alert-state--${alertState}`]: alertState !== undefined,
}); });
return ( // for new panel header design
<section const onCancelQuery = () => panel.getQueryRunner().cancelQuery();
className={containerClassNames} const title = panel.getDisplayTitle();
aria-label={selectors.components.Panels.Panel.containerByTitle(panel.title)} const noPadding: PanelPadding = plugin.noPadding ? 'none' : 'md';
> const leftItems = [
<PanelHeader <PanelHeaderLoadingIndicator state={data.state} onClick={onCancelQuery} key="loading-indicator" />,
panel={panel} ];
dashboard={dashboard}
title={panel.title} if (config.featureToggles.newPanelChromeUI) {
description={panel.description} return (
links={panel.links} <PanelChrome width={width} height={height} title={title} leftItems={leftItems} padding={noPadding}>
error={errorMessage} {(innerWidth, innerHeight) => (
isEditing={isEditing} <>
isViewing={isViewing} <ErrorBoundary
alertState={alertState} dependencies={[data, plugin, panel.getOptions()]}
data={data} onError={this.onPanelError}
/> onRecover={this.onPanelErrorRecover}
<ErrorBoundary >
dependencies={[data, plugin, panel.getOptions()]} {({ error }) => {
onError={this.onPanelError} if (error) {
onRecover={this.onPanelErrorRecover} return null;
}
return this.renderPanelContent(innerWidth, innerHeight);
}}
</ErrorBoundary>
</>
)}
</PanelChrome>
);
} else {
return (
<section
className={containerClassNames}
aria-label={selectors.components.Panels.Panel.containerByTitle(panel.title)}
> >
{({ error }) => { <PanelHeader
if (error) { panel={panel}
return null; dashboard={dashboard}
} title={panel.title}
return this.renderPanel(width, height); description={panel.description}
}} links={panel.links}
</ErrorBoundary> error={errorMessage}
</section> 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 { 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 // target is 20hz (50ms), but we poll at 100ms to smooth out jitter
const interval = 100; const interval = 100;
@ -10,7 +10,7 @@ const interval = 100;
interface LiveListener { interface LiveListener {
last: number; last: number;
intervalMs: number; intervalMs: number;
panel: PanelChrome; panel: PanelStateWrapper;
} }
class LiveTimer { class LiveTimer {
@ -41,7 +41,7 @@ class LiveTimer {
} }
} }
listen(panel: PanelChrome) { listen(panel: PanelStateWrapper) {
this.listeners.push({ this.listeners.push({
last: this.lastUpdate, last: this.lastUpdate,
panel: panel, panel: panel,
@ -52,11 +52,11 @@ class LiveTimer {
}); });
} }
remove(panel: PanelChrome) { remove(panel: PanelStateWrapper) {
this.listeners = this.listeners.filter((v) => v.panel !== panel); this.listeners = this.listeners.filter((v) => v.panel !== panel);
} }
updateInterval(panel: PanelChrome) { updateInterval(panel: PanelStateWrapper) {
if (!this.timeRange || !this.isLive) { if (!this.timeRange || !this.isLive) {
return; return;
} }