From 3c90af831a4c4ea8f4728ecfbbb00c83ac1b4287 Mon Sep 17 00:00:00 2001 From: Juan Cabanas Date: Mon, 13 Oct 2025 10:58:30 -0300 Subject: [PATCH] Dashboard Library: Modify EmptyPage boxes width when FF is enabled and query param is present (#112253) --- .../DashboardEmpty/DashboardEmpty.test.tsx | 53 ++++++++++++++++++- .../DashboardEmpty/DashboardEmpty.tsx | 17 ++++-- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/DashboardEmpty/DashboardEmpty.test.tsx b/public/app/features/dashboard/dashgrid/DashboardEmpty/DashboardEmpty.test.tsx index e4f9839fdfa..4c6ed9d33e3 100644 --- a/public/app/features/dashboard/dashgrid/DashboardEmpty/DashboardEmpty.test.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardEmpty/DashboardEmpty.test.tsx @@ -1,6 +1,6 @@ import { act, fireEvent, render, screen } from '@testing-library/react'; -import { locationService, reportInteraction } from '@grafana/runtime'; +import { config, locationService, reportInteraction } from '@grafana/runtime'; import { defaultDashboard } from '@grafana/schema'; import { createDashboardModelFixture } from '../../state/__fixtures__/dashboardFixtures'; @@ -40,6 +40,9 @@ const mockUseGetResourceRepositoryView = jest.mocked( require('app/features/provisioning/hooks/useGetResourceRepositoryView').useGetResourceRepositoryView ); +const mockSearchParams = new URLSearchParams(); +jest.spyOn(require('react-router-dom-v5-compat'), 'useSearchParams').mockReturnValue([mockSearchParams]); + function setup(options?: Partial) { const props = { dashboard: createDashboardModelFixture(defaultDashboard), @@ -150,3 +153,51 @@ it('renders with buttons disabled when repository is read-only', () => { expect(screen.getByRole('button', { name: 'Import dashboard' })).toBeDisabled(); expect(screen.getByRole('button', { name: 'Add library panel' })).toBeDisabled(); }); + +describe('wrapperMaxWidth CSS class', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('applies wrapperMaxWidth class when dashboardLibrary feature is disabled', () => { + config.featureToggles.dashboardLibrary = false; + + mockSearchParams.delete('dashboardLibraryDatasourceUid'); + + const { container } = render( + + ); + + const wrapperElement = container.querySelector('[class*="dashboard-empty-wrapper"]'); + expect(wrapperElement).toBeInTheDocument(); + expect(wrapperElement).toHaveStyle('max-width: 890px'); + }); + + it('applies wrapperMaxWidth class when dashboardLibrary feature is enabled but no dashboardLibraryDatasourceUid param', () => { + config.featureToggles.dashboardLibrary = true; + + mockSearchParams.delete('dashboardLibraryDatasourceUid'); + + const { container } = render( + + ); + + const wrapperElement = container.querySelector('[class*="dashboard-empty-wrapper"]'); + expect(wrapperElement).toBeInTheDocument(); + expect(wrapperElement).toHaveStyle('max-width: 890px'); + }); + + it('does not apply wrapperMaxWidth class when dashboardLibrary feature is enabled and dashboardLibraryDatasourceUid param exists', () => { + config.featureToggles.dashboardLibrary = true; + + mockSearchParams.set('dashboardLibraryDatasourceUid', 'test-uid'); + + const { container } = render( + + ); + + const wrapperElement = container.querySelector('[class*="dashboard-empty-wrapper"]'); + expect(wrapperElement).toBeInTheDocument(); + expect(wrapperElement).not.toHaveStyle('max-width: 890px'); + }); +}); diff --git a/public/app/features/dashboard/dashgrid/DashboardEmpty/DashboardEmpty.tsx b/public/app/features/dashboard/dashgrid/DashboardEmpty/DashboardEmpty.tsx index 06117bb795c..6369831a12c 100644 --- a/public/app/features/dashboard/dashgrid/DashboardEmpty/DashboardEmpty.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardEmpty/DashboardEmpty.tsx @@ -1,9 +1,11 @@ -import { css } from '@emotion/css'; +import { css, cx } from '@emotion/css'; import { useCallback } from 'react'; +import { useSearchParams } from 'react-router-dom-v5-compat'; import { GrafanaTheme2 } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { Trans } from '@grafana/i18n'; +import { config } from '@grafana/runtime'; import { Button, useStyles2, Text, Box, Stack, TextLink } from '@grafana/ui'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { DashboardScene } from 'app/features/dashboard-scene/scene/DashboardScene'; @@ -25,9 +27,16 @@ interface InternalProps { const InternalDashboardEmpty = ({ onAddVisualization, onAddLibraryPanel, onImportDashboard }: InternalProps) => { const styles = useStyles2(getStyles); + const [searchParams] = useSearchParams(); + const dashboardLibraryDatasourceUid = searchParams.get('dashboardLibraryDatasourceUid'); + return ( -
+
@@ -152,7 +161,6 @@ function getStyles(theme: GrafanaTheme2) { wrapper: css({ label: 'dashboard-empty-wrapper', flexDirection: 'column', - maxWidth: '890px', gap: theme.spacing.gridSize * 4, paddingTop: theme.spacing(2), @@ -160,5 +168,8 @@ function getStyles(theme: GrafanaTheme2) { paddingTop: theme.spacing(12), }, }), + wrapperMaxWidth: css({ + maxWidth: '890px', + }), }; }