Dashboard: Add unconfigured panel state to new panels (#102719)

* Update

* Update

* Update new panel title

* Update
This commit is contained in:
Torkel Ödegaard
2025-03-26 13:34:37 +01:00
committed by GitHub
parent ff6039567b
commit f2fc1d8575
11 changed files with 71 additions and 67 deletions
@@ -7,7 +7,7 @@ export enum PanelMenuItems {
Extensions = 'Extensions',
}
export const openPanelMenuItem = (menu: PanelMenuItems, panelTitle = 'Panel Title') => {
export const openPanelMenuItem = (menu: PanelMenuItems, panelTitle = 'New panel') => {
// we changed the way we open the panel menu in react panels with the new panel header
detectPanelType(panelTitle, (isAngularPanel) => {
if (isAngularPanel) {
@@ -20,7 +20,7 @@ export const openPanelMenuItem = (menu: PanelMenuItems, panelTitle = 'Panel Titl
});
};
export const openPanelMenuExtension = (extensionTitle: string, panelTitle = 'Panel Title') => {
export const openPanelMenuExtension = (extensionTitle: string, panelTitle = 'New panel') => {
const menuItem = PanelMenuItems.Extensions;
// we changed the way we open the panel menu in react panels with the new panel header
detectPanelType(panelTitle, (isAngularPanel) => {
@@ -139,7 +139,7 @@ test.describe('edit panel plugin settings', () => {
const panelOptions = panelEditPage.getPanelOptions();
const title = panelOptions.getTextInput('Title');
await expect(title).toHaveValue('Panel Title');
await expect(title).toHaveValue('New panel');
await title.clear();
await expect(title).toHaveValue('');
});
+2 -2
View File
@@ -7,7 +7,7 @@ export enum PanelMenuItems {
Extensions = 'Extensions',
}
export const openPanelMenuItem = (menu: PanelMenuItems, panelTitle = 'Panel Title') => {
export const openPanelMenuItem = (menu: PanelMenuItems, panelTitle = 'New panel') => {
// we changed the way we open the panel menu in react panels with the new panel header
detectPanelType(panelTitle, (isAngularPanel) => {
if (isAngularPanel) {
@@ -20,7 +20,7 @@ export const openPanelMenuItem = (menu: PanelMenuItems, panelTitle = 'Panel Titl
});
};
export const openPanelMenuExtension = (extensionTitle: string, panelTitle = 'Panel Title') => {
export const openPanelMenuExtension = (extensionTitle: string, panelTitle = 'New panel') => {
const menuItem = PanelMenuItems.Extensions;
// we changed the way we open the panel menu in react panels with the new panel header
detectPanelType(panelTitle, (isAngularPanel) => {
@@ -166,7 +166,6 @@ export interface GrafanaConfig {
appSubUrl: string;
windowTitlePrefix: string;
buildInfo: BuildInfo;
newPanelTitle: string;
bootData: BootData;
externalUserMngLinkUrl: string;
externalUserMngLinkName: string;
+3 -2
View File
@@ -68,7 +68,6 @@ export class GrafanaBootConfig implements GrafanaConfig {
namespace = 'default';
windowTitlePrefix = '';
buildInfo: BuildInfo;
newPanelTitle = '';
bootData: BootData;
externalUserMngLinkUrl = '';
externalUserMngLinkName = '';
@@ -217,7 +216,6 @@ export class GrafanaBootConfig implements GrafanaConfig {
datasources: {},
windowTitlePrefix: 'Grafana - ',
panels: {},
newPanelTitle: 'Panel Title',
playlist_timespan: '1m',
unsaved_changes_warning: true,
appUrl: '',
@@ -251,6 +249,9 @@ export class GrafanaBootConfig implements GrafanaConfig {
this.bootData.user.lightTheme = this.theme2.isLight;
this.theme = this.theme2.v1;
}
geomapDefaultBaseLayer?: MapLayerOptions<any> | undefined;
listDashboardScopesEndpoint?: string | undefined;
listScopesEndpoint?: string | undefined;
}
// localstorage key: grafana.featureToggles
@@ -1,10 +1,9 @@
import { css, cx } from '@emotion/css';
import { useMemo } from 'react';
import { GrafanaTheme2, textUtil } from '@grafana/data';
import { locationService } from '@grafana/runtime';
import { sceneGraph, VizPanel } from '@grafana/scenes';
import { useStyles2, Text, Icon, Stack, Tooltip } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { Stack, Button } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor';
@@ -104,57 +103,19 @@ type OpenPanelEditVizProps = {
};
const OpenPanelEditViz = ({ panel }: OpenPanelEditVizProps) => {
const styles = useStyles2(getStyles);
const plugin = panel.getPlugin();
const imgSrc = plugin?.meta.info.logos.small;
return (
<Stack alignItems="center" width="100%">
{plugin ? (
<Tooltip content={t('dashboard.viz-panel.options.open-edit', 'Open panel editor')}>
<a
href={textUtil.sanitizeUrl(getEditPanelUrl(getPanelIdForVizPanel(panel)))}
className={cx(styles.pluginDescriptionWrapper)}
>
<img
className={styles.panelVizImg}
src={imgSrc}
alt={t('dashboard.viz-panel.options.plugin-type-image', 'Image of plugin type')}
/>
<Text truncate>{plugin.meta.name}</Text>
<Icon className={styles.panelVizIcon} name="sliders-v-alt" />
</a>
</Tooltip>
) : null}
<Button
onClick={() => {
locationService.push(getEditPanelUrl(getPanelIdForVizPanel(panel)));
}}
icon="sliders-v-alt"
fullWidth
size="sm"
tooltip={t('dashboard.viz-panel.options.configure-button-tooltip', 'Edit queries and visualization options')}
>
<Trans i18nKey="dashboard.new-panel.configure-button">Configure panel</Trans>
</Button>
</Stack>
);
};
const getStyles = (theme: GrafanaTheme2) => ({
pluginDescriptionWrapper: css({
display: 'flex',
flexWrap: 'nowrap',
alignItems: 'center',
columnGap: theme.spacing(1),
rowGap: theme.spacing(0.5),
minHeight: theme.spacing(4),
backgroundColor: theme.colors.secondary.main,
border: `1px solid ${theme.colors.secondary.border}`,
borderRadius: theme.shape.radius.default,
paddingInline: theme.spacing(1),
paddingBlock: theme.spacing(0.5),
flexGrow: 1,
'&:hover': {
backgroundColor: theme.colors.secondary.shade,
},
}),
panelVizImg: css({
width: '16px',
height: '16px',
marginRight: theme.spacing(1),
}),
panelVizIcon: css({
marginLeft: 'auto',
}),
});
@@ -21,6 +21,7 @@ import { saveLibPanel } from 'app/features/library-panels/state/api';
import { DashboardSceneChangeTracker } from '../saving/DashboardSceneChangeTracker';
import { getPanelChanges } from '../saving/getDashboardChanges';
import { UNCONFIGURED_PANEL_PLUGIN_ID } from '../scene/UnconfiguredPanel';
import { DashboardLayoutItem, isDashboardLayoutItem } from '../scene/types/DashboardLayoutItem';
import { vizPanelToPanel } from '../serialization/transformSceneToSaveModel';
import {
@@ -76,6 +77,11 @@ export class PanelEditor extends SceneObjectBase<PanelEditorState> {
private _activationHandler() {
const panel = this.state.panelRef.resolve();
if (panel.state.pluginId === UNCONFIGURED_PANEL_PLUGIN_ID) {
panel.changePluginType('timeseries');
}
const deactivateParents = activateSceneObjectAndParentTree(panel);
this.waitForPlugin();
@@ -0,0 +1,29 @@
import { PanelPlugin, PanelProps } from '@grafana/data';
import { locationService } from '@grafana/runtime';
import { sceneUtils } from '@grafana/scenes';
import { Box, Button, Stack } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
export const UNCONFIGURED_PANEL_PLUGIN_ID = '__unconfigured-panel';
const UnconfiguredPanel = new PanelPlugin(UnconfiguredPanelComp);
function UnconfiguredPanelComp(props: PanelProps) {
const onConfigure = () => {
locationService.partial({ editPanel: props.id });
};
return (
<Stack direction={'row'} alignItems={'center'} height={'100%'} justifyContent={'center'}>
<Box paddingBottom={2}>
<Button icon="sliders-v-alt" onClick={onConfigure}>
<Trans i18nKey="dashboard.new-panel.configure-button">Configure panel</Trans>
</Button>
</Box>
</Stack>
);
}
sceneUtils.registerRuntimePanelPlugin({
pluginId: UNCONFIGURED_PANEL_PLUGIN_ID,
plugin: UnconfiguredPanel,
});
@@ -1,5 +1,5 @@
import { getDataSourceRef, IntervalVariableModel } from '@grafana/data';
import { getDataSourceSrv } from '@grafana/runtime';
import { config, getDataSourceSrv } from '@grafana/runtime';
import {
CancelActivationHandler,
CustomVariable,
@@ -13,6 +13,7 @@ import {
VizPanelMenu,
} from '@grafana/scenes';
import { useElementSelection, UseElementSelectionResult } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { initialIntervalVariableModelState } from 'app/features/variables/interval/reducer';
import { DashboardDatasourceBehaviour } from '../scene/DashboardDatasourceBehaviour';
@@ -20,6 +21,7 @@ import { DashboardScene, DashboardSceneState } from '../scene/DashboardScene';
import { LibraryPanelBehavior } from '../scene/LibraryPanelBehavior';
import { VizPanelLinks, VizPanelLinksMenu } from '../scene/PanelLinks';
import { panelMenuBehavior } from '../scene/PanelMenuBehavior';
import { UNCONFIGURED_PANEL_PLUGIN_ID } from '../scene/UnconfiguredPanel';
import { DashboardGridItem } from '../scene/layout-default/DashboardGridItem';
import { ResponsiveGridItem } from '../scene/layout-responsive-grid/ResponsiveGridItem';
import { RowItem } from '../scene/layout-rows/RowItem';
@@ -322,9 +324,12 @@ export function getClosestVizPanel(sceneObject: SceneObject): VizPanel | null {
}
export function getDefaultVizPanel(): VizPanel {
const defaultPluginId = config.featureToggles.dashboardNewLayouts ? UNCONFIGURED_PANEL_PLUGIN_ID : 'timeseries';
const newPanelTitle = t('dashboard.new-panel-title', 'New panel');
return new VizPanel({
title: 'Panel Title',
pluginId: 'timeseries',
title: newPanelTitle,
pluginId: defaultPluginId,
titleItems: [new VizPanelLinks({ menu: new VizPanelLinksMenu({}) })],
hoverHeaderOffset: 0,
$behaviors: [],
@@ -9,7 +9,7 @@ import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
import { calculateNewPanelGridPos } from 'app/features/dashboard/utils/panel';
export const NEW_PANEL_TITLE = 'Panel Title';
export const NEW_PANEL_TITLE = 'New panel';
export function onCreateNewPanel(dashboard: DashboardModel, datasource?: string): number | undefined {
const newPanel: Partial<PanelModel> = {
+5 -2
View File
@@ -1492,6 +1492,10 @@
"layout": "Layout"
}
},
"new-panel": {
"configure-button": "Configure panel"
},
"new-panel-title": "New panel",
"options": {
"description": "Description",
"title-option": "Title"
@@ -1722,9 +1726,8 @@
},
"viz-panel": {
"options": {
"configure-button-tooltip": "Edit queries and visualization options",
"description": "Description",
"open-edit": "Open panel editor",
"plugin-type-image": "Image of plugin type",
"title-option": "Title",
"transparent-background": "Transparent background"
}