diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index a3f28c53917..6916434c112 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -29,6 +29,7 @@ Some stable features are enabled by default. You can disable a stable feature by | `internationalization` | Enables internationalization | Yes | | `topnav` | Enables new top navigation and page layouts | Yes | | `cloudWatchCrossAccountQuerying` | Enables cross-account querying in CloudWatch datasources | Yes | +| `newPanelChromeUI` | Show updated look and feel of grafana-ui PanelChrome: panel header, icons, and menu | Yes | | `accessTokenExpirationCheck` | Enable OAuth access_token expiration check and token refresh using the refresh_token | | | `emptyDashboardPage` | Enable the redesigned user interface of a dashboard page that includes no panels | Yes | | `disablePrometheusExemplarSampling` | Disable Prometheus exemplar sampling | | @@ -78,7 +79,6 @@ Alpha features might be changed or removed without prior notice. | `logRequestsInstrumentedAsUnknown` | Logs the path for requests that are instrumented as unknown | | `redshiftAsyncQueryDataSupport` | Enable async query data support for Redshift | | `athenaAsyncQueryDataSupport` | Enable async query data support for Athena | -| `newPanelChromeUI` | Show updated look and feel of grafana-ui PanelChrome: panel header, icons, and menu | | `showDashboardValidationWarnings` | Show warnings when dashboards do not validate against the schema | | `mysqlAnsiQuotes` | Use double quotes to escape keyword in a MySQL query | | `elasticsearchBackendMigration` | Use Elasticsearch as backend data source | diff --git a/e2e/panels-suite/panelEdit_base.spec.ts b/e2e/panels-suite/panelEdit_base.spec.ts index 8eb18531ddd..44c3e8d25ee 100644 --- a/e2e/panels-suite/panelEdit_base.spec.ts +++ b/e2e/panels-suite/panelEdit_base.spec.ts @@ -13,7 +13,7 @@ e2e.scenario({ e2e.flows.openDashboard({ uid: 'TkZXxlNG3' }); e2e().wait('@query'); - e2e.flows.openPanelMenuItem(e2e.flows.PanelMenuItems.Edit, PANEL_UNDER_TEST); + e2e.flows.openPanelMenuItem(e2e.flows.PanelMenuItems.Edit, PANEL_UNDER_TEST, true); // New panel editor opens when navigating from Panel menu e2e.components.PanelEditor.General.content().should('be.visible'); diff --git a/e2e/various-suite/inspect-drawer.spec.ts b/e2e/various-suite/inspect-drawer.spec.ts index 51087db4e7f..e8ce12099b6 100644 --- a/e2e/various-suite/inspect-drawer.spec.ts +++ b/e2e/various-suite/inspect-drawer.spec.ts @@ -1,6 +1,6 @@ import { e2e } from '@grafana/e2e'; -const PANEL_UNDER_TEST = '2 yaxis and axis labels'; +const PANEL_UNDER_TEST = 'Value reducers 1'; e2e.scenario({ describeName: 'Inspect drawer tests', @@ -34,10 +34,10 @@ e2e.scenario({ }); const viewPortWidth = e2e.config().viewportWidth; - e2e.flows.openDashboard({ uid: '5SdHCadmz' }); + e2e.flows.openDashboard({ uid: 'wfTJJL5Wz' }); // testing opening inspect drawer directly by clicking on Inspect in header menu - e2e.flows.openPanelMenuItem(e2e.flows.PanelMenuItems.Inspect, PANEL_UNDER_TEST); + e2e.flows.openPanelMenuItem(e2e.flows.PanelMenuItems.Inspect, PANEL_UNDER_TEST, true); expectDrawerTabsAndContent(); @@ -49,7 +49,7 @@ e2e.scenario({ expectSubMenuScenario('Query'); expectSubMenuScenario('Panel JSON', 'JSON'); - e2e.flows.openPanelMenuItem(e2e.flows.PanelMenuItems.Edit, PANEL_UNDER_TEST); + e2e.flows.openPanelMenuItem(e2e.flows.PanelMenuItems.Edit, PANEL_UNDER_TEST, true); e2e.components.QueryTab.queryInspectorButton().should('be.visible').click(); @@ -135,10 +135,13 @@ const expectSubMenuScenario = (subMenu: string, tabTitle?: string) => { tabTitle = tabTitle ?? subMenu; // testing opening inspect drawer from sub menus under Inspect in header menu e2e.components.Panels.Panel.title(PANEL_UNDER_TEST).scrollIntoView().should('be.visible').click(); - + e2e.components.Panels.Panel.menu(PANEL_UNDER_TEST).click({ force: true }); // force click because menu is hidden and show on hover // sub menus are in the DOM but not visible and because there is no hover support in Cypress force click // https://github.com/cypress-io/cypress-example-recipes/blob/master/examples/testing-dom__hover-hidden-elements/cypress/integration/hover-hidden-elements-spec.js - e2e.components.Panels.Panel.headerItems(subMenu).click({ force: true }); + + // simulate hover on Inspector menu item to display sub menus + e2e.components.Panels.Panel.menuItems('Inspect').trigger('mouseover', { force: true }); + e2e.components.Panels.Panel.menuItems(subMenu).click({ force: true }); // data should be the default tab e2e.components.Tab.title(tabTitle).should('be.visible'); diff --git a/packages/grafana-e2e-selectors/src/selectors/components.ts b/packages/grafana-e2e-selectors/src/selectors/components.ts index 8b0191d220f..245ec1d342a 100644 --- a/packages/grafana-e2e-selectors/src/selectors/components.ts +++ b/packages/grafana-e2e-selectors/src/selectors/components.ts @@ -73,6 +73,7 @@ export const Components = { title: (title: string) => `data-testid Panel header ${title}`, headerItems: (item: string) => `Panel header item ${item}`, menuItems: (item: string) => `data-testid Panel menu item ${item}`, + menu: (title: string) => `data-testid Panel menu ${title}`, containerByTitle: (title: string) => `${title} panel`, headerCornerInfo: (mode: string) => `Panel header ${mode}`, }, diff --git a/packages/grafana-e2e/src/flows/importDashboard.ts b/packages/grafana-e2e/src/flows/importDashboard.ts index 9f415c85483..d3b01c2be6b 100644 --- a/packages/grafana-e2e/src/flows/importDashboard.ts +++ b/packages/grafana-e2e/src/flows/importDashboard.ts @@ -50,8 +50,8 @@ export const importDashboard = (dashboardToImport: Dashboard, queryTimeout?: num if (!skipPanelValidation) { dashboardToImport.panels.forEach((panel) => { // Look at the json data - e2e.components.Panels.Panel.title(panel.title).should('be.visible').click(); - e2e.components.Panels.Panel.headerItems('Inspect').should('be.visible').click(); + e2e.components.Panels.Panel.menu(panel.title).click({ force: true }); // force click because menu is hidden and show on hover + e2e.components.Panels.Panel.menuItems('Inspect').should('be.visible').click(); e2e.components.Tab.title('JSON').should('be.visible').click(); e2e.components.PanelInspector.Json.content().should('be.visible').contains('Panel JSON').click({ force: true }); e2e.components.Select.option().should('be.visible').contains('Panel data').click(); diff --git a/packages/grafana-e2e/src/flows/openPanelMenuItem.ts b/packages/grafana-e2e/src/flows/openPanelMenuItem.ts index 2477b268e7d..7a08cd9440f 100644 --- a/packages/grafana-e2e/src/flows/openPanelMenuItem.ts +++ b/packages/grafana-e2e/src/flows/openPanelMenuItem.ts @@ -7,10 +7,16 @@ export enum PanelMenuItems { Extensions = 'Extensions', } -export const openPanelMenuItem = (menu: PanelMenuItems, panelTitle = 'Panel Title') => { - e2e.components.Panels.Panel.title(panelTitle).should('be.visible').click(); - - e2e.components.Panels.Panel.headerItems(menu).should('be.visible').click(); +export const openPanelMenuItem = (menu: PanelMenuItems, panelTitle = 'Panel Title', isReactPanel = false) => { + // we changed the way we open the panel menu in react panels with the new panel header + if (isReactPanel) { + e2e.components.Panels.Panel.menu(panelTitle).click({ force: true }); // force click because menu is hidden and show on hover + e2e.components.Panels.Panel.menuItems(menu).should('be.visible').click(); + } else { + // this is the old way of opening the panel menu from the title + e2e.components.Panels.Panel.title(panelTitle).should('be.visible').click(); + e2e.components.Panels.Panel.headerItems(menu).should('be.visible').click(); + } }; export const openPanelMenuExtension = (extensionTitle: string, panelTitle = 'Panel Title') => { diff --git a/packages/grafana-ui/src/components/PanelChrome/PanelChrome.tsx b/packages/grafana-ui/src/components/PanelChrome/PanelChrome.tsx index b98b816908e..ba8310352f1 100644 --- a/packages/grafana-ui/src/components/PanelChrome/PanelChrome.tsx +++ b/packages/grafana-ui/src/components/PanelChrome/PanelChrome.tsx @@ -114,7 +114,7 @@ export function PanelChrome({ actions = leftItems; } - const ariaLabel = title ? selectors.components.Panels.Panel.containerByTitle(title) : 'Panel'; + const testid = title ? selectors.components.Panels.Panel.title(title) : 'Panel'; const headerContent = ( <> @@ -152,7 +152,7 @@ export function PanelChrome({ ); return ( -
+
{loadingState === LoadingState.Loading ? : null}
diff --git a/packages/grafana-ui/src/components/PanelChrome/PanelMenu.tsx b/packages/grafana-ui/src/components/PanelChrome/PanelMenu.tsx index e5ad7b1ee64..c9180fe2882 100644 --- a/packages/grafana-ui/src/components/PanelChrome/PanelMenu.tsx +++ b/packages/grafana-ui/src/components/PanelChrome/PanelMenu.tsx @@ -1,6 +1,8 @@ import { cx } from '@emotion/css'; import React, { ReactElement } from 'react'; +import { selectors } from '@grafana/e2e-selectors'; + import { Dropdown } from '../Dropdown/Dropdown'; import { ToolbarButton } from '../ToolbarButton'; import { TooltipPlacement } from '../Tooltip'; @@ -24,6 +26,7 @@ export function PanelMenu({ menuButtonClass, onVisibleChange, }: PanelMenuProps) { + const testId = title ? selectors.components.Panels.Panel.menu(title) : `panel-menu-button`; return ( diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index b89e22528a8..35e63af4483 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -274,8 +274,9 @@ var ( { Name: "newPanelChromeUI", Description: "Show updated look and feel of grafana-ui PanelChrome: panel header, icons, and menu", - State: FeatureStateAlpha, + State: FeatureStateStable, FrontendOnly: true, + Expression: "true", // enabled by default Owner: grafanaDashboardsSquad, }, { diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index b889e5b506e..89f4f467682 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -39,7 +39,7 @@ entityStore,alpha,@grafana/grafana-app-platform-squad,true,false,false,false cloudWatchCrossAccountQuerying,stable,@grafana/aws-plugins,false,false,false,false redshiftAsyncQueryDataSupport,alpha,@grafana/aws-plugins,false,false,false,true athenaAsyncQueryDataSupport,alpha,@grafana/aws-plugins,false,false,false,true -newPanelChromeUI,alpha,@grafana/dashboards-squad,false,false,false,true +newPanelChromeUI,stable,@grafana/dashboards-squad,false,false,false,true showDashboardValidationWarnings,alpha,@grafana/dashboards-squad,false,false,false,false mysqlAnsiQuotes,alpha,@grafana/backend-platform,false,false,false,false accessControlOnCall,beta,@grafana/grafana-authnz-team,false,false,false,false