diff --git a/.betterer.results b/.betterer.results index c236525c595..80d88469839 100644 --- a/.betterer.results +++ b/.betterer.results @@ -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"] ], diff --git a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx index 773e6de1709..116b6d8b645 100644 --- a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx @@ -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 { height={height} /> ) : ( - ({ profiler: { @@ -69,14 +69,14 @@ function setupTestContext(options: Partial) { const props = { ...defaults, ...options }; const { rerender } = render( - + ); 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( - + ); diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelStateWrapper.tsx similarity index 79% rename from public/app/features/dashboard/dashgrid/PanelChrome.tsx rename to public/app/features/dashboard/dashgrid/PanelStateWrapper.tsx index c9da152b671..a5690d9319a 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelStateWrapper.tsx @@ -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 { +export class PanelStateWrapper extends PureComponent { private readonly timeSrv: TimeSrv = getTimeSrv(); private subs = new Subscription(); private eventFilter: EventFilterOptions = { onlyLocal: true }; @@ -429,6 +437,56 @@ export class PanelChrome extends PureComponent { ); } + 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 ( + <> + + + + + ); + } + 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 { [`panel-alert-state--${alertState}`]: alertState !== undefined, }); - return ( -
- - panel.getQueryRunner().cancelQuery(); + const title = panel.getDisplayTitle(); + const noPadding: PanelPadding = plugin.noPadding ? 'none' : 'md'; + const leftItems = [ + , + ]; + + if (config.featureToggles.newPanelChromeUI) { + return ( + + {(innerWidth, innerHeight) => ( + <> + + {({ error }) => { + if (error) { + return null; + } + return this.renderPanelContent(innerWidth, innerHeight); + }} + + + )} + + ); + } else { + return ( +
- {({ error }) => { - if (error) { - return null; - } - return this.renderPanel(width, height); - }} - -
- ); + + + {({ error }) => { + if (error) { + return null; + } + return this.renderPanel(width, height); + }} + +
+ ); + } } } diff --git a/public/app/features/dashboard/dashgrid/liveTimer.ts b/public/app/features/dashboard/dashgrid/liveTimer.ts index 65b37811ea3..fe686e0185d 100644 --- a/public/app/features/dashboard/dashgrid/liveTimer.ts +++ b/public/app/features/dashboard/dashgrid/liveTimer.ts @@ -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; }