Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8626a27aa | ||
|
|
7d3c56fdeb | ||
|
|
1d644eb092 | ||
|
|
fa13e050b5 | ||
|
|
dbb3a3a9f8 | ||
|
|
7b2acac9cb | ||
|
|
021adc58af |
@@ -3,7 +3,7 @@ import { test, expect } from '@grafana/plugin-e2e';
|
||||
test.use({
|
||||
featureToggles: {
|
||||
newVizSuggestions: true,
|
||||
externalVizSuggestions: false,
|
||||
externalVizSuggestions: true,
|
||||
},
|
||||
viewport: {
|
||||
width: 800,
|
||||
@@ -174,5 +174,40 @@ test.describe(
|
||||
'time series to be rendered inside the panel'
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('should not apply suggestion if you navigate back to the dashboard for a new panel', async ({
|
||||
page,
|
||||
selectors,
|
||||
gotoDashboardPage,
|
||||
}) => {
|
||||
// New dashboard
|
||||
const dashboardPage = await gotoDashboardPage({});
|
||||
|
||||
// Press the empty-state Create new panel button
|
||||
await dashboardPage
|
||||
.getByGrafanaSelector(selectors.pages.AddDashboard.itemButton('Create new panel button'))
|
||||
.click();
|
||||
await expect(dashboardPage.getByGrafanaSelector(selectors.components.PanelEditor.General.content)).toBeVisible();
|
||||
|
||||
// Verify we see suggestions on load (after closing the data source picker)
|
||||
await page.getByRole('button', { name: 'Close', exact: true }).click({ force: true });
|
||||
await expect(
|
||||
dashboardPage.getByGrafanaSelector(selectors.components.VisualizationPreview.card('Line chart')),
|
||||
'line chart suggestion to be rendered'
|
||||
).toBeVisible();
|
||||
|
||||
// Select a visualization
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.VisualizationPreview.card('Table')).click();
|
||||
await expect(page.getByRole('grid').getByRole('row').first(), 'table row to be rendered').toBeVisible();
|
||||
|
||||
// Verify that navigating back to the dashboard cancels the suggestion and restores the line chart.
|
||||
await dashboardPage
|
||||
.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.backToDashboardButton)
|
||||
.click();
|
||||
await expect(
|
||||
page.locator('[data-viz-panel-key="panel-1"]').locator('.uplot'),
|
||||
'time series to be rendered inside the panel'
|
||||
).toBeVisible();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ export const AddToDashboardFormExposedComponent = (props: Partial<Props<Absolute
|
||||
buildPanel={
|
||||
props.buildPanel ??
|
||||
(() => ({
|
||||
type: 'timeseries',
|
||||
type: 'timeseries', // TODO: should this be `getDefaultPluginId()`?
|
||||
title: t('dashboard-scene.add-to-dashboard-form-exposed.title.new-panel', 'New panel'),
|
||||
targets: [],
|
||||
}))
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
SceneObjectState,
|
||||
SceneObjectStateChangedEvent,
|
||||
SceneQueryRunner,
|
||||
sceneGraph,
|
||||
sceneUtils,
|
||||
VizPanel,
|
||||
} from '@grafana/scenes';
|
||||
@@ -21,8 +20,6 @@ import { Panel } from '@grafana/schema';
|
||||
import { OptionFilter } from 'app/features/dashboard/components/PanelEditor/OptionsPaneOptions';
|
||||
import { getLastUsedDatasourceFromStorage } from 'app/features/dashboard/utils/dashboard';
|
||||
import { saveLibPanel } from 'app/features/library-panels/state/api';
|
||||
import { getAllSuggestions } from 'app/features/panel/suggestions/getAllSuggestions';
|
||||
import { hasData } from 'app/features/panel/suggestions/utils';
|
||||
|
||||
import { DashboardEditActionEvent } from '../edit-pane/shared';
|
||||
import { DashboardSceneChangeTracker } from '../saving/DashboardSceneChangeTracker';
|
||||
@@ -34,6 +31,7 @@ import { vizPanelToPanel } from '../serialization/transformSceneToSaveModel';
|
||||
import {
|
||||
activateSceneObjectAndParentTree,
|
||||
getDashboardSceneFor,
|
||||
getDefaultVizPanel,
|
||||
getLibraryPanelBehavior,
|
||||
getPanelIdForVizPanel,
|
||||
} from '../utils/utils';
|
||||
@@ -91,12 +89,9 @@ export class PanelEditor extends SceneObjectBase<PanelEditorState> {
|
||||
// Need to clear selection here since selection is activated when panel edit mode is entered through the panel actions menu. This causes sidebar panel editor to be open when exiting panel edit mode
|
||||
dashboard.state.editPane.clearSelection();
|
||||
|
||||
if (panel.state.pluginId === UNCONFIGURED_PANEL_PLUGIN_ID) {
|
||||
if (config.featureToggles.newVizSuggestions) {
|
||||
this._autoSelectVisualization(panel);
|
||||
} else {
|
||||
panel.changePluginType('timeseries');
|
||||
}
|
||||
// this will be deleted when suggestions is fully rolled out.
|
||||
if (panel.state.pluginId === UNCONFIGURED_PANEL_PLUGIN_ID && !config.featureToggles.newVizSuggestions) {
|
||||
panel.changePluginType('timeseries');
|
||||
}
|
||||
|
||||
this._subs.add(
|
||||
@@ -119,28 +114,6 @@ export class PanelEditor extends SceneObjectBase<PanelEditorState> {
|
||||
};
|
||||
}
|
||||
|
||||
private async _autoSelectVisualization(panel: VizPanel) {
|
||||
const dataObject = sceneGraph.getData(panel);
|
||||
|
||||
this._subs.add(
|
||||
dataObject.subscribeToState(async () => {
|
||||
const { data } = dataObject.state;
|
||||
if (hasData(data) && panel.state.pluginId === UNCONFIGURED_PANEL_PLUGIN_ID) {
|
||||
const { suggestions } = await getAllSuggestions(data);
|
||||
|
||||
if (suggestions.length > 0) {
|
||||
const defaultFirstSuggestion = suggestions[0];
|
||||
await panel.changePluginType(
|
||||
defaultFirstSuggestion.pluginId,
|
||||
defaultFirstSuggestion.options,
|
||||
defaultFirstSuggestion.fieldConfig
|
||||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private commitChanges() {
|
||||
if (!this.state.isDirty && !this._changesHaveBeenMade) {
|
||||
// Nothing to commit
|
||||
@@ -152,7 +125,6 @@ export class PanelEditor extends SceneObjectBase<PanelEditorState> {
|
||||
const originalState = this._layoutItemState!;
|
||||
|
||||
this.setState({ editPreview: undefined });
|
||||
this.state.optionsPane?.setState({ editPreviewRef: undefined });
|
||||
|
||||
// Temp fix for old edit mode
|
||||
if (this._layoutItem instanceof DashboardGridItem && !config.featureToggles.dashboardNewLayouts) {
|
||||
@@ -242,7 +214,6 @@ export class PanelEditor extends SceneObjectBase<PanelEditorState> {
|
||||
// First time initialization
|
||||
if (this.state.isInitializing) {
|
||||
this.setOriginalState(this.state.panelRef);
|
||||
|
||||
this._setupChangeDetection();
|
||||
this._updateDataPane(plugin);
|
||||
|
||||
@@ -255,17 +226,13 @@ export class PanelEditor extends SceneObjectBase<PanelEditorState> {
|
||||
})
|
||||
);
|
||||
|
||||
const isUnconfigured = Boolean(
|
||||
config.featureToggles.newVizSuggestions && panel.state.pluginId === UNCONFIGURED_PANEL_PLUGIN_ID
|
||||
);
|
||||
|
||||
// Setup options pane
|
||||
const optionsPane = new PanelOptionsPane({
|
||||
panelRef: this.state.panelRef,
|
||||
editPreviewRef: this.state.editPreview?.getRef(),
|
||||
searchQuery: '',
|
||||
listMode: OptionFilter.All,
|
||||
isVizPickerOpen: isUnconfigured,
|
||||
isVizPickerOpen: this.state.isNewPanel,
|
||||
isNewPanel: this.state.isNewPanel,
|
||||
});
|
||||
|
||||
@@ -274,23 +241,23 @@ export class PanelEditor extends SceneObjectBase<PanelEditorState> {
|
||||
isInitializing: false,
|
||||
});
|
||||
|
||||
this._subs.add(
|
||||
this.subscribeToState((newState, oldState) => {
|
||||
if (newState.editPreview !== oldState.editPreview) {
|
||||
optionsPane.setState({ editPreviewRef: newState.editPreview?.getRef() });
|
||||
}
|
||||
})
|
||||
);
|
||||
this._subs.add(
|
||||
optionsPane.subscribeToState((newState, oldState) => {
|
||||
if (newState.isVizPickerOpen !== oldState.isVizPickerOpen) {
|
||||
const panel = this.state.panelRef.resolve();
|
||||
let editPreview: VizPanel | undefined;
|
||||
if (newState.isVizPickerOpen) {
|
||||
// we just "pick" timeseries, viz type will likely be overridden by Suggestions.
|
||||
const editPreviewBuilder = PanelBuilders.timeseries()
|
||||
.setTitle(panel.state.title)
|
||||
.setDescription(panel.state.description);
|
||||
if (panel.state.$data) {
|
||||
editPreviewBuilder.setData(new DataProviderSharer({ source: panel.state.$data.getRef() }));
|
||||
}
|
||||
editPreview = editPreviewBuilder.build();
|
||||
const panel = this.state.panelRef.resolve();
|
||||
const editPreview = PanelEditor.buildEditPreview(panel);
|
||||
this.setState({ editPreview });
|
||||
} else {
|
||||
this.setState({ editPreview: undefined });
|
||||
}
|
||||
this.setState({ editPreview });
|
||||
optionsPane.setState({ editPreviewRef: editPreview?.getRef() });
|
||||
}
|
||||
})
|
||||
);
|
||||
@@ -442,6 +409,16 @@ export class PanelEditor extends SceneObjectBase<PanelEditorState> {
|
||||
.build(),
|
||||
});
|
||||
};
|
||||
|
||||
public static buildEditPreview(panel: VizPanel): VizPanel {
|
||||
const editPreview = getDefaultVizPanel();
|
||||
editPreview.setState({
|
||||
title: panel.state.title,
|
||||
description: panel.state.description,
|
||||
$data: panel.state.$data ? new DataProviderSharer({ source: panel.state.$data.getRef() }) : undefined,
|
||||
});
|
||||
return editPreview;
|
||||
}
|
||||
}
|
||||
|
||||
export function buildPanelEditScene(panel: VizPanel, isNewPanel = false): PanelEditor {
|
||||
@@ -449,5 +426,6 @@ export function buildPanelEditScene(panel: VizPanel, isNewPanel = false): PanelE
|
||||
isInitializing: true,
|
||||
panelRef: panel.getRef(),
|
||||
isNewPanel,
|
||||
editPreview: isNewPanel ? PanelEditor.buildEditPreview(panel) : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { findEditPanel, getLibraryPanelBehavior } from '../utils/utils';
|
||||
|
||||
import { DashboardScene, DashboardSceneState } from './DashboardScene';
|
||||
import { LibraryPanelBehavior } from './LibraryPanelBehavior';
|
||||
import { UNCONFIGURED_PANEL_PLUGIN_ID } from './UnconfiguredPanel';
|
||||
import { DefaultGridLayoutManager } from './layout-default/DefaultGridLayoutManager';
|
||||
|
||||
export class DashboardSceneUrlSync implements SceneObjectUrlSyncHandler {
|
||||
@@ -91,7 +92,7 @@ export class DashboardSceneUrlSync implements SceneObjectUrlSyncHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
update.editPanel = buildPanelEditScene(panel);
|
||||
update.editPanel = buildPanelEditScene(panel, panel.state.pluginId === UNCONFIGURED_PANEL_PLUGIN_ID);
|
||||
} else if (editPanel && values.editPanel === null) {
|
||||
update.editPanel = undefined;
|
||||
}
|
||||
@@ -126,7 +127,9 @@ export class DashboardSceneUrlSync implements SceneObjectUrlSyncHandler {
|
||||
private _waitForLibPanelToLoadBeforeEnteringPanelEdit(panel: VizPanel, libPanel: LibraryPanelBehavior) {
|
||||
const sub = libPanel.subscribeToState((state) => {
|
||||
if (state.isLoaded) {
|
||||
this._scene.setState({ editPanel: buildPanelEditScene(panel) });
|
||||
this._scene.setState({
|
||||
editPanel: buildPanelEditScene(panel, panel.state.pluginId === UNCONFIGURED_PANEL_PLUGIN_ID),
|
||||
});
|
||||
sub.unsubscribe();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -482,7 +482,7 @@ export function buildGridItemForPanel(panel: PanelModel): DashboardGridItem {
|
||||
key: getVizPanelKeyForPanelId(panel.id),
|
||||
title: panel.title?.substring(0, 5000),
|
||||
description: panel.description,
|
||||
pluginId: panel.type ?? 'timeseries',
|
||||
pluginId: panel.type ?? 'timeseries', // TODO: should this be `getDefaultPluginId()`?
|
||||
options: panel.options ?? {},
|
||||
fieldConfig: panel.fieldConfig,
|
||||
pluginVersion: panel.pluginVersion,
|
||||
|
||||
@@ -279,17 +279,22 @@ export function getClosestVizPanel(sceneObject: SceneObject): VizPanel | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getDefaultPluginId(): string {
|
||||
return config.featureToggles.dashboardNewLayouts || config.featureToggles.newVizSuggestions
|
||||
? UNCONFIGURED_PANEL_PLUGIN_ID
|
||||
: 'timeseries';
|
||||
}
|
||||
|
||||
export function getDefaultVizPanel(): VizPanel {
|
||||
const defaultPluginId =
|
||||
config.featureToggles.dashboardNewLayouts || config.featureToggles.newVizSuggestions
|
||||
? UNCONFIGURED_PANEL_PLUGIN_ID
|
||||
: 'timeseries';
|
||||
const defaultPluginId = getDefaultPluginId();
|
||||
|
||||
const newPanelTitle =
|
||||
config.featureToggles.newVizSuggestions && defaultPluginId === UNCONFIGURED_PANEL_PLUGIN_ID
|
||||
? ''
|
||||
: t('dashboard.new-panel-title', 'New panel');
|
||||
|
||||
const datasourceSettings = getDataSourceSrv().getInstanceSettings(null);
|
||||
|
||||
return new VizPanel({
|
||||
title: newPanelTitle,
|
||||
pluginId: defaultPluginId,
|
||||
@@ -307,14 +312,16 @@ export function getDefaultVizPanel(): VizPanel {
|
||||
headerActions: new VizPanelHeaderActions({
|
||||
hideGroupByAction: !config.featureToggles.panelGroupBy,
|
||||
}),
|
||||
$data: new SceneDataTransformer({
|
||||
$data: new SceneQueryRunner({
|
||||
queries: [{ refId: 'A' }],
|
||||
datasource: getDataSourceRef(getDataSourceSrv().getInstanceSettings(null)!),
|
||||
$behaviors: [new DashboardDatasourceBehaviour({})],
|
||||
}),
|
||||
transformations: [],
|
||||
}),
|
||||
$data: datasourceSettings
|
||||
? new SceneDataTransformer({
|
||||
$data: new SceneQueryRunner({
|
||||
queries: [{ refId: 'A' }],
|
||||
datasource: getDataSourceRef(datasourceSettings),
|
||||
$behaviors: [new DashboardDatasourceBehaviour({})],
|
||||
}),
|
||||
transformations: [],
|
||||
})
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user