mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
DashboardScene: Do not show data pane for panels with skipDataQuery
(#81934)
* Bump scenes * Don't show data pane for panels without data support * Add tests * Review
This commit is contained in:
parent
8616f2e80a
commit
a385ae4fa5
@ -51,6 +51,7 @@ export class PanelDataPane extends SceneObjectBase<PanelDataPaneState> {
|
||||
constructor(panelMgr: VizPanelManager) {
|
||||
super({
|
||||
tab: TabId.Queries,
|
||||
tabs: [],
|
||||
});
|
||||
|
||||
this.panelManager = panelMgr;
|
||||
@ -97,6 +98,7 @@ export class PanelDataPane extends SceneObjectBase<PanelDataPaneState> {
|
||||
private buildTabs() {
|
||||
const panelManager = this.panelManager;
|
||||
const panel = panelManager.state.panel;
|
||||
|
||||
const runner = this.panelManager.queryRunner;
|
||||
const tabs: PanelDataPaneTab[] = [];
|
||||
|
||||
@ -104,7 +106,6 @@ export class PanelDataPane extends SceneObjectBase<PanelDataPaneState> {
|
||||
const plugin = panel.getPlugin();
|
||||
|
||||
if (!plugin) {
|
||||
this.setState({ tabs });
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,95 @@
|
||||
import { PanelPlugin, PanelPluginMeta, PluginType } from '@grafana/data';
|
||||
import { SceneFlexItem, SplitLayout, VizPanel } from '@grafana/scenes';
|
||||
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { activateFullSceneTree } from '../utils/test-utils';
|
||||
|
||||
import { PanelDataPane } from './PanelDataPane/PanelDataPane';
|
||||
import { buildPanelEditScene } from './PanelEditor';
|
||||
|
||||
let pluginToLoad: PanelPlugin | undefined;
|
||||
jest.mock('@grafana/runtime', () => ({
|
||||
...jest.requireActual('@grafana/runtime'),
|
||||
getPluginImportUtils: () => ({
|
||||
getPanelPluginFromCache: jest.fn(() => pluginToLoad),
|
||||
}),
|
||||
config: {
|
||||
panels: {
|
||||
text: {
|
||||
skipDataQuery: true,
|
||||
},
|
||||
timeseries: {
|
||||
skipDataQuery: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('PanelEditor', () => {
|
||||
describe('PanelDataPane', () => {
|
||||
it('should not exist if panel is skipDataQuery', () => {
|
||||
pluginToLoad = getTestPanelPlugin({ id: 'text', skipDataQuery: true });
|
||||
|
||||
const panel = new VizPanel({
|
||||
key: 'panel-1',
|
||||
pluginId: 'text',
|
||||
});
|
||||
const editScene = buildPanelEditScene(panel);
|
||||
const scene = new DashboardScene({
|
||||
editPanel: editScene,
|
||||
});
|
||||
|
||||
activateFullSceneTree(scene);
|
||||
|
||||
expect(((editScene.state.body as SplitLayout).state.primary as SplitLayout).state.secondary).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should exist if panel is supporting querying', () => {
|
||||
pluginToLoad = getTestPanelPlugin({ id: 'timeseries' });
|
||||
|
||||
const panel = new VizPanel({
|
||||
key: 'panel-1',
|
||||
pluginId: 'timeseries',
|
||||
});
|
||||
const editScene = buildPanelEditScene(panel);
|
||||
const scene = new DashboardScene({
|
||||
editPanel: editScene,
|
||||
});
|
||||
|
||||
activateFullSceneTree(scene);
|
||||
const secondaryPane = ((editScene.state.body as SplitLayout).state.primary as SplitLayout).state.secondary;
|
||||
|
||||
expect(secondaryPane).toBeInstanceOf(SceneFlexItem);
|
||||
expect((secondaryPane as SceneFlexItem).state.body).toBeInstanceOf(PanelDataPane);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
export function getTestPanelPlugin(options: Partial<PanelPluginMeta>): PanelPlugin {
|
||||
const plugin = new PanelPlugin(() => null);
|
||||
plugin.meta = {
|
||||
id: options.id!,
|
||||
type: PluginType.panel,
|
||||
name: options.id!,
|
||||
sort: options.sort || 1,
|
||||
info: {
|
||||
author: {
|
||||
name: options.id + 'name',
|
||||
},
|
||||
description: '',
|
||||
links: [],
|
||||
logos: {
|
||||
large: '',
|
||||
small: '',
|
||||
},
|
||||
screenshots: [],
|
||||
updated: '',
|
||||
version: '1.0.',
|
||||
},
|
||||
hideFromList: options.hideFromList === true,
|
||||
module: options.module ?? '',
|
||||
baseUrl: '',
|
||||
skipDataQuery: options.skipDataQuery ?? false,
|
||||
};
|
||||
return plugin;
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import * as H from 'history';
|
||||
|
||||
import { NavIndex } from '@grafana/data';
|
||||
import { locationService } from '@grafana/runtime';
|
||||
import { config, locationService } from '@grafana/runtime';
|
||||
import {
|
||||
SceneFlexItem,
|
||||
SceneFlexLayout,
|
||||
@ -118,14 +118,12 @@ export function buildPanelEditScene(panel: VizPanel): PanelEditor {
|
||||
direction: 'row',
|
||||
primary: new SplitLayout({
|
||||
direction: 'column',
|
||||
$behaviors: [conditionalDataPaneBehavior],
|
||||
primary: new SceneFlexLayout({
|
||||
direction: 'column',
|
||||
minHeight: 200,
|
||||
children: [vizPanelMgr],
|
||||
}),
|
||||
secondary: new SceneFlexItem({
|
||||
body: new PanelDataPane(vizPanelMgr),
|
||||
}),
|
||||
primaryPaneStyles: {
|
||||
minHeight: 0,
|
||||
overflow: 'hidden',
|
||||
@ -147,3 +145,45 @@ export function buildPanelEditScene(panel: VizPanel): PanelEditor {
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
// This function is used to conditionally add the data pane to the panel editor,
|
||||
// depending on the type of a panel being edited.
|
||||
function conditionalDataPaneBehavior(scene: SplitLayout) {
|
||||
const dashboard = getDashboardSceneFor(scene);
|
||||
|
||||
const editor = dashboard.state.editPanel;
|
||||
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const panelManager = editor.state.panelRef.resolve();
|
||||
const panel = panelManager.state.panel;
|
||||
|
||||
const getDataPane = () =>
|
||||
new SceneFlexItem({
|
||||
body: new PanelDataPane(panelManager),
|
||||
});
|
||||
|
||||
if (!config.panels[panel.state.pluginId].skipDataQuery) {
|
||||
scene.setState({
|
||||
secondary: getDataPane(),
|
||||
});
|
||||
}
|
||||
|
||||
const sub = panelManager.subscribeToState((n, p) => {
|
||||
const hadDataSupport = !config.panels[p.panel.state.pluginId].skipDataQuery;
|
||||
const willHaveDataSupport = !config.panels[n.panel.state.pluginId].skipDataQuery;
|
||||
|
||||
if (hadDataSupport && !willHaveDataSupport) {
|
||||
locationService.partial({ tab: null }, true);
|
||||
scene.setState({ secondary: undefined });
|
||||
} else if (!hadDataSupport && willHaveDataSupport) {
|
||||
scene.setState({ secondary: getDataPane() });
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
sub.unsubscribe();
|
||||
};
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
isStandardFieldProp,
|
||||
restoreCustomOverrideRules,
|
||||
} from '@grafana/data';
|
||||
import { getDataSourceSrv, locationService } from '@grafana/runtime';
|
||||
import { config, getDataSourceSrv, locationService } from '@grafana/runtime';
|
||||
import {
|
||||
SceneObjectState,
|
||||
VizPanel,
|
||||
@ -24,13 +24,14 @@ import {
|
||||
} from '@grafana/scenes';
|
||||
import { DataQuery, DataTransformerConfig } from '@grafana/schema';
|
||||
import { getPluginVersion } from 'app/features/dashboard/state/PanelModel';
|
||||
import { getLastUsedDatasourceFromStorage } from 'app/features/dashboard/utils/dashboard';
|
||||
import { storeLastUsedDataSourceInLocalStorage } from 'app/features/datasources/components/picker/utils';
|
||||
import { updateQueries } from 'app/features/query/state/updateQueries';
|
||||
import { GrafanaQuery } from 'app/plugins/datasource/grafana/types';
|
||||
import { QueryGroupOptions } from 'app/types';
|
||||
|
||||
import { PanelTimeRange, PanelTimeRangeState } from '../scene/PanelTimeRange';
|
||||
import { getPanelIdForVizPanel, getQueryRunnerFor } from '../utils/utils';
|
||||
import { getDashboardSceneFor, getPanelIdForVizPanel, getQueryRunnerFor } from '../utils/utils';
|
||||
|
||||
interface VizPanelManagerState extends SceneObjectState {
|
||||
panel: VizPanel;
|
||||
@ -128,6 +129,27 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
|
||||
...restOfOldState,
|
||||
});
|
||||
|
||||
// When changing from non-data to data panel, we need to add a new data provider
|
||||
if (!restOfOldState.$data && !config.panels[pluginType].skipDataQuery) {
|
||||
let ds = getLastUsedDatasourceFromStorage(getDashboardSceneFor(this).state.uid!)?.datasourceUid;
|
||||
|
||||
if (!ds) {
|
||||
ds = config.defaultDatasource;
|
||||
}
|
||||
|
||||
newPanel.setState({
|
||||
$data: new SceneDataTransformer({
|
||||
$data: new SceneQueryRunner({
|
||||
datasource: {
|
||||
uid: ds,
|
||||
},
|
||||
queries: [{ refId: 'A' }],
|
||||
}),
|
||||
transformations: [],
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
const newPlugin = newPanel.getPlugin();
|
||||
const panel: PanelModel = {
|
||||
title: newPanel.state.title,
|
||||
@ -146,6 +168,7 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
|
||||
}
|
||||
|
||||
this.setState({ panel: newPanel });
|
||||
this.loadDataSource();
|
||||
}
|
||||
|
||||
public async changePanelDataSource(
|
||||
|
@ -25531,11 +25531,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"react-hook-form@npm:^7.49.2":
|
||||
version: 7.50.1
|
||||
resolution: "react-hook-form@npm:7.50.1"
|
||||
version: 7.50.0
|
||||
resolution: "react-hook-form@npm:7.50.0"
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17 || ^18
|
||||
checksum: 10/54a9daa2143c601a9867e96a2159a0bbe98707b5bbeb5953bfdf3342d2f04bfcaa6169907ed167c5c1f3a044630860d4f43685f4ac4e15b9cd892d1b00d54dde
|
||||
checksum: 10/3b85cc179053af72a2734f2e77767de8f9b3ecbefeee282b73e81141c4b7bb97308ec00da61fdc25a28299a2defb74bff66417bb85a66357f5ceddba7b697ae7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user