+
evt.stopPropagation()}
+ onPointerDown={(evt) => evt.stopPropagation()}
+ >
- {totalPages > 1 && (
-
- )}
);
};
@@ -277,18 +286,9 @@ function getStyles(theme: GrafanaTheme2) {
return {
resultsContainer: css({
width: '100%',
- position: 'relative',
flex: 1,
overflow: 'auto',
- }),
- paginationWrapper: css({
- position: 'sticky',
- bottom: 0,
- backgroundColor: theme.colors.background.primary,
- padding: theme.spacing(2),
- display: 'flex',
- justifyContent: 'flex-end',
- zIndex: 2,
+ paddingBottom: theme.spacing(2),
}),
};
}
diff --git a/public/app/features/dashboard/dashgrid/DashboardLibrary/DashboardCard.test.tsx b/public/app/features/dashboard/dashgrid/DashboardLibrary/DashboardCard.test.tsx
index 939f1bcdb89..5af933ceec1 100644
--- a/public/app/features/dashboard/dashgrid/DashboardLibrary/DashboardCard.test.tsx
+++ b/public/app/features/dashboard/dashgrid/DashboardLibrary/DashboardCard.test.tsx
@@ -1,41 +1,8 @@
import { screen } from '@testing-library/react';
import { render } from 'test/test-utils';
-import { PluginDashboard } from 'app/types/plugins';
-
import { DashboardCard } from './DashboardCard';
-import { GnetDashboard } from './types';
-
-// Helper functions for creating mock objects
-const createMockPluginDashboard = (overrides: Partial
= {}): PluginDashboard => ({
- dashboardId: 1,
- description: 'Test description',
- imported: false,
- importedRevision: 0,
- importedUri: '',
- importedUrl: '',
- path: '',
- pluginId: 'test-plugin',
- removed: false,
- revision: 1,
- slug: 'test-dashboard',
- title: 'Test Dashboard',
- uid: 'test-uid',
- ...overrides,
-});
-
-const createMockGnetDashboard = (overrides: Partial = {}): GnetDashboard => ({
- id: 123,
- name: 'Test Dashboard',
- description: 'Test description',
- datasource: 'Prometheus',
- orgName: 'Test Org',
- userName: 'testuser',
- publishedAt: '',
- updatedAt: '',
- downloads: 0,
- ...overrides,
-});
+import { createMockGnetDashboard, createMockPluginDashboard } from './utils/test-utils';
const createMockDetails = (overrides = {}) => ({
id: '123',
diff --git a/public/app/features/dashboard/dashgrid/DashboardLibrary/DashboardLibrarySection.test.tsx b/public/app/features/dashboard/dashgrid/DashboardLibrary/DashboardLibrarySection.test.tsx
new file mode 100644
index 00000000000..1147967acd1
--- /dev/null
+++ b/public/app/features/dashboard/dashgrid/DashboardLibrary/DashboardLibrarySection.test.tsx
@@ -0,0 +1,273 @@
+import { screen, waitFor, within } from '@testing-library/react';
+import { render } from 'test/test-utils';
+
+import { locationService } from '@grafana/runtime';
+
+import { DashboardLibrarySection } from './DashboardLibrarySection';
+import { fetchProvisionedDashboards } from './api/dashboardLibraryApi';
+import { DashboardLibraryInteractions } from './interactions';
+import { createMockPluginDashboard } from './utils/test-utils';
+
+jest.mock('./api/dashboardLibraryApi', () => ({
+ fetchProvisionedDashboards: jest.fn(),
+}));
+
+jest.mock('@grafana/runtime', () => ({
+ ...jest.requireActual('@grafana/runtime'),
+ getDataSourceSrv: () => ({
+ getInstanceSettings: jest.fn((uid?: string) => {
+ if (uid) {
+ return {
+ uid,
+ name: `DataSource ${uid}`,
+ type: 'test-datasource',
+ };
+ }
+ return null;
+ }),
+ }),
+ locationService: {
+ push: jest.fn(),
+ getHistory: jest.fn(() => ({
+ listen: jest.fn(() => jest.fn()),
+ })),
+ },
+}));
+
+jest.mock('./interactions', () => ({
+ ...jest.requireActual('./interactions'),
+ DashboardLibraryInteractions: {
+ loaded: jest.fn(),
+ itemClicked: jest.fn(),
+ },
+}));
+
+jest.mock('./DashboardCard', () => {
+ const DashboardCardComponent = ({ title, onClick }: { title: string; onClick: () => void }) => (
+
+ {title}
+
+ );
+
+ const DashboardCardSkeleton = () => Skeleton
;
+
+ return {
+ DashboardCard: Object.assign(DashboardCardComponent, {
+ Skeleton: DashboardCardSkeleton,
+ }),
+ };
+});
+
+const mockFetchProvisionedDashboards = fetchProvisionedDashboards as jest.MockedFunction<
+ typeof fetchProvisionedDashboards
+>;
+const mockLocationServicePush = locationService.push as jest.MockedFunction;
+const mockDashboardLibraryInteractionsLoaded = DashboardLibraryInteractions.loaded as jest.MockedFunction<
+ typeof DashboardLibraryInteractions.loaded
+>;
+const mockDashboardLibraryInteractionsItemClicked = DashboardLibraryInteractions.itemClicked as jest.MockedFunction<
+ typeof DashboardLibraryInteractions.itemClicked
+>;
+
+describe('DashboardLibrarySection', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('should render dashboards when they are available', async () => {
+ const dashboards = [
+ createMockPluginDashboard({ title: 'Dashboard 1', uid: 'uid-1' }),
+ createMockPluginDashboard({ title: 'Dashboard 2', uid: 'uid-2' }),
+ ];
+
+ mockFetchProvisionedDashboards.mockResolvedValue(dashboards);
+
+ render(, {
+ historyOptions: {
+ initialEntries: ['/test?dashboardLibraryDatasourceUid=test-uid'],
+ },
+ });
+
+ await waitFor(() => {
+ expect(screen.getByTestId('dashboard-card-Dashboard 1')).toBeInTheDocument();
+ expect(screen.getByTestId('dashboard-card-Dashboard 2')).toBeInTheDocument();
+ });
+ });
+
+ it('should show empty state when there are no dashboards', async () => {
+ mockFetchProvisionedDashboards.mockResolvedValue([]);
+
+ render(, {
+ historyOptions: {
+ initialEntries: ['/test?dashboardLibraryDatasourceUid=test-uid'],
+ },
+ });
+
+ await waitFor(() => {
+ expect(screen.getByText('No test-datasource provisioned dashboards found')).toBeInTheDocument();
+ expect(
+ screen.getByText(
+ 'Provisioned dashboards are provided by data source plugins. You can find more plugins on Grafana.com.'
+ )
+ ).toBeInTheDocument();
+ const browseButton = screen.getByRole('button', { name: 'Browse plugins' });
+ expect(browseButton).toBeInTheDocument();
+ });
+ });
+
+ it('should show empty state without datasource type when datasourceUid is not provided', async () => {
+ mockFetchProvisionedDashboards.mockResolvedValue([]);
+
+ render(, {
+ historyOptions: {
+ initialEntries: ['/test'],
+ },
+ });
+
+ await waitFor(() => {
+ expect(screen.getByText('No provisioned dashboards found')).toBeInTheDocument();
+ });
+ });
+
+ it('should render pagination when there are more than 9 dashboards', async () => {
+ const dashboards = Array.from({ length: 18 }, (_, i) =>
+ createMockPluginDashboard({ title: `Dashboard ${i + 1}`, uid: `uid-${i + 1}` })
+ );
+
+ mockFetchProvisionedDashboards.mockResolvedValue(dashboards);
+
+ render(, {
+ historyOptions: {
+ initialEntries: ['/test?dashboardLibraryDatasourceUid=test-uid'],
+ },
+ });
+
+ await waitFor(() => {
+ const pagination = screen.getByRole('navigation');
+ expect(pagination).toBeInTheDocument();
+ expect(within(pagination).getByText('1')).toBeInTheDocument();
+ expect(within(pagination).getByText('2')).toBeInTheDocument();
+ });
+ });
+
+ it('should not render pagination when there are 9 or fewer dashboards', async () => {
+ const dashboards = Array.from({ length: 9 }, (_, i) =>
+ createMockPluginDashboard({ title: `Dashboard ${i + 1}`, uid: `uid-${i + 1}` })
+ );
+
+ mockFetchProvisionedDashboards.mockResolvedValue(dashboards);
+
+ render(, {
+ historyOptions: {
+ initialEntries: ['/test?dashboardLibraryDatasourceUid=test-uid'],
+ },
+ });
+
+ await waitFor(() => {
+ expect(screen.getByTestId('dashboard-card-Dashboard 1')).toBeInTheDocument();
+ });
+
+ const pagination = screen.queryByRole('navigation');
+ expect(pagination).not.toBeInTheDocument();
+ });
+
+ it('should navigate to template route when clicking on a dashboard', async () => {
+ const dashboard = createMockPluginDashboard({
+ title: 'Test Dashboard',
+ uid: 'test-uid-123',
+ pluginId: 'test-plugin',
+ path: 'test/path.json',
+ });
+
+ mockFetchProvisionedDashboards.mockResolvedValue([dashboard]);
+
+ render(, {
+ historyOptions: {
+ initialEntries: ['/test?dashboardLibraryDatasourceUid=test-uid'],
+ },
+ });
+
+ await waitFor(() => {
+ expect(screen.getByTestId('dashboard-card-Test Dashboard')).toBeInTheDocument();
+ });
+
+ const dashboardCard = screen.getByTestId('dashboard-card-Test Dashboard');
+ dashboardCard.click();
+
+ await waitFor(() => {
+ expect(mockLocationServicePush).toHaveBeenCalled();
+ const callArgs = mockLocationServicePush.mock.calls[0][0];
+ expect(callArgs).toContain('/dashboard/template');
+ expect(callArgs).toContain('datasource=test-uid');
+
+ expect(callArgs).toContain('title=Test+Dashboard');
+ expect(callArgs).toContain('pluginId=test-plugin');
+ expect(callArgs).toContain('path=test%2Fpath.json');
+ expect(callArgs).toContain('libraryItemId=test-uid-123');
+ });
+ });
+
+ it('should track analytics when dashboards are loaded', async () => {
+ const dashboards = [
+ createMockPluginDashboard({ title: 'Dashboard 1', uid: 'uid-1' }),
+ createMockPluginDashboard({ title: 'Dashboard 2', uid: 'uid-2' }),
+ ];
+
+ mockFetchProvisionedDashboards.mockResolvedValue(dashboards);
+
+ render(, {
+ historyOptions: {
+ initialEntries: ['/test?dashboardLibraryDatasourceUid=test-uid'],
+ },
+ });
+
+ await waitFor(() => {
+ expect(screen.getByTestId('dashboard-card-Dashboard 1')).toBeInTheDocument();
+ });
+
+ await waitFor(() => {
+ expect(mockDashboardLibraryInteractionsLoaded).toHaveBeenCalledWith({
+ numberOfItems: 2,
+ contentKinds: ['datasource_dashboard'],
+ datasourceTypes: ['test-datasource'],
+ sourceEntryPoint: 'datasource_page',
+ eventLocation: 'suggested_dashboards_modal_provisioned_tab',
+ });
+ });
+ });
+
+ it('should track analytics when a dashboard is clicked', async () => {
+ const dashboard = createMockPluginDashboard({
+ title: 'Test Dashboard',
+ uid: 'test-uid-123',
+ pluginId: 'test-plugin',
+ });
+
+ mockFetchProvisionedDashboards.mockResolvedValue([dashboard]);
+
+ render(, {
+ historyOptions: {
+ initialEntries: ['/test?dashboardLibraryDatasourceUid=test-uid'],
+ },
+ });
+
+ await waitFor(() => {
+ expect(screen.getByTestId('dashboard-card-Test Dashboard')).toBeInTheDocument();
+ });
+
+ const dashboardCard = screen.getByTestId('dashboard-card-Test Dashboard');
+ dashboardCard.click();
+
+ await waitFor(() => {
+ expect(mockDashboardLibraryInteractionsItemClicked).toHaveBeenCalledWith({
+ contentKind: 'datasource_dashboard',
+ datasourceTypes: ['test-plugin'],
+ libraryItemId: 'test-uid-123',
+ libraryItemTitle: 'Test Dashboard',
+ sourceEntryPoint: 'datasource_page',
+ eventLocation: 'suggested_dashboards_modal_provisioned_tab',
+ discoveryMethod: 'browse',
+ });
+ });
+ });
+});
diff --git a/public/app/features/dashboard/dashgrid/DashboardLibrary/SuggestedDashboards.test.tsx b/public/app/features/dashboard/dashgrid/DashboardLibrary/SuggestedDashboards.test.tsx
new file mode 100644
index 00000000000..4109a198f05
--- /dev/null
+++ b/public/app/features/dashboard/dashgrid/DashboardLibrary/SuggestedDashboards.test.tsx
@@ -0,0 +1,186 @@
+import { screen, waitFor } from '@testing-library/react';
+import { render } from 'test/test-utils';
+
+import { SuggestedDashboards } from './SuggestedDashboards';
+import { fetchCommunityDashboards, fetchProvisionedDashboards } from './api/dashboardLibraryApi';
+import { createMockGnetDashboard, createMockPluginDashboard } from './utils/test-utils';
+
+jest.mock('./api/dashboardLibraryApi', () => ({
+ fetchProvisionedDashboards: jest.fn(),
+ fetchCommunityDashboards: jest.fn(),
+}));
+
+jest.mock('./utils/communityDashboardHelpers', () => ({
+ ...jest.requireActual('./utils/communityDashboardHelpers'),
+ onUseCommunityDashboard: jest.fn(),
+}));
+
+jest.mock('./SuggestedDashboardsModal', () => ({
+ SuggestedDashboardsModal: () => Modal
,
+}));
+
+jest.mock('./DashboardCard', () => {
+ const DashboardCardComponent = ({ title, onClick }: { title: string; onClick: () => void }) => (
+
+ {title}
+
+ );
+
+ const DashboardCardSkeleton = () => Skeleton
;
+
+ return {
+ DashboardCard: Object.assign(DashboardCardComponent, {
+ Skeleton: DashboardCardSkeleton,
+ }),
+ };
+});
+
+jest.mock('@grafana/runtime', () => ({
+ ...jest.requireActual('@grafana/runtime'),
+ getDataSourceSrv: () => ({
+ getInstanceSettings: jest.fn((uid?: string) => {
+ if (uid) {
+ return {
+ uid,
+ name: `DataSource ${uid}`,
+ type: 'test-datasource',
+ };
+ }
+ return null;
+ }),
+ }),
+}));
+
+jest.mock('./interactions', () => ({
+ ...jest.requireActual('./interactions'),
+ DashboardLibraryInteractions: {
+ loaded: jest.fn(),
+ itemClicked: jest.fn(),
+ },
+}));
+
+const mockFetchProvisionedDashboards = fetchProvisionedDashboards as jest.MockedFunction<
+ typeof fetchProvisionedDashboards
+>;
+const mockFetchCommunityDashboards = fetchCommunityDashboards as jest.MockedFunction;
+
+describe('SuggestedDashboards', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('should render when there are dashboards', async () => {
+ mockFetchProvisionedDashboards.mockResolvedValue([createMockPluginDashboard()]);
+ mockFetchCommunityDashboards.mockResolvedValue({
+ page: 1,
+ pages: 1,
+ items: [createMockGnetDashboard()],
+ });
+
+ render();
+
+ await waitFor(() => {
+ expect(screen.getByTestId('suggested-dashboards')).toBeInTheDocument();
+ });
+ });
+
+ it('should not render when there are no dashboards', async () => {
+ mockFetchProvisionedDashboards.mockResolvedValue([]);
+ mockFetchCommunityDashboards.mockResolvedValue({
+ page: 1,
+ pages: 1,
+ items: [],
+ });
+
+ render();
+
+ await waitFor(() => {
+ expect(screen.queryByTestId('suggested-dashboards')).not.toBeInTheDocument();
+ });
+ });
+
+ it('should render provisioned dashboard cards', async () => {
+ const provisionedDashboard = createMockPluginDashboard({ title: 'Provisioned Dashboard 1' });
+ mockFetchProvisionedDashboards.mockResolvedValue([provisionedDashboard]);
+ mockFetchCommunityDashboards.mockResolvedValue({
+ page: 1,
+ pages: 1,
+ items: [],
+ });
+
+ render();
+
+ await waitFor(() => {
+ expect(screen.getByTestId('dashboard-card-Provisioned Dashboard 1')).toBeInTheDocument();
+ });
+ });
+
+ it('should render community dashboard cards', async () => {
+ const communityDashboard = createMockGnetDashboard({ name: 'Community Dashboard 1' });
+ mockFetchProvisionedDashboards.mockResolvedValue([]);
+ mockFetchCommunityDashboards.mockResolvedValue({
+ page: 1,
+ pages: 1,
+ items: [communityDashboard],
+ });
+
+ render();
+
+ await waitFor(() => {
+ expect(screen.getByTestId('dashboard-card-Community Dashboard 1')).toBeInTheDocument();
+ });
+ });
+
+ it('should show "View all" button when hasMoreDashboards is true', async () => {
+ mockFetchProvisionedDashboards.mockResolvedValue([
+ createMockPluginDashboard(),
+ createMockPluginDashboard({ title: 'Provisioned Dashboard 2' }),
+ ]);
+ mockFetchCommunityDashboards.mockResolvedValue({
+ page: 1,
+ pages: 1,
+ items: [],
+ });
+
+ render();
+
+ await waitFor(() => {
+ expect(screen.getByRole('button', { name: 'View all' })).toBeInTheDocument();
+ });
+ });
+
+ it('should not show "View all" button when hasMoreDashboards is false', async () => {
+ mockFetchProvisionedDashboards.mockResolvedValue([createMockPluginDashboard()]);
+ mockFetchCommunityDashboards.mockResolvedValue({
+ page: 1,
+ pages: 1,
+ items: [createMockGnetDashboard()],
+ });
+
+ render();
+
+ await waitFor(() => {
+ expect(screen.queryByRole('button', { name: 'View all' })).not.toBeInTheDocument();
+ });
+ });
+
+ it('should render title and subtitle with datasource type when datasourceUid is provided', async () => {
+ mockFetchProvisionedDashboards.mockResolvedValue([createMockPluginDashboard()]);
+ mockFetchCommunityDashboards.mockResolvedValue({
+ page: 1,
+ pages: 1,
+ items: [],
+ });
+
+ render();
+
+ await waitFor(() => {
+ expect(
+ screen.getByText('Build a dashboard using suggested options for your test-datasource data source')
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText('Browse and select from data-source provided or community dashboards')
+ ).toBeInTheDocument();
+ });
+ });
+});
diff --git a/public/app/features/dashboard/dashgrid/DashboardLibrary/SuggestedDashboards.tsx b/public/app/features/dashboard/dashgrid/DashboardLibrary/SuggestedDashboards.tsx
index d0384e9746d..2a4a051b7cf 100644
--- a/public/app/features/dashboard/dashgrid/DashboardLibrary/SuggestedDashboards.tsx
+++ b/public/app/features/dashboard/dashgrid/DashboardLibrary/SuggestedDashboards.tsx
@@ -1,12 +1,12 @@
import { css } from '@emotion/css';
import { useEffect, useMemo, useRef, useState } from 'react';
import { useSearchParams } from 'react-router-dom-v5-compat';
-import { useAsync } from 'react-use';
+import { useAsync, useAsyncFn } from 'react-use';
import { GrafanaTheme2 } from '@grafana/data';
import { Trans, t } from '@grafana/i18n';
import { getDataSourceSrv, locationService } from '@grafana/runtime';
-import { Button, useStyles2, Grid } from '@grafana/ui';
+import { Button, useStyles2, Grid, Alert } from '@grafana/ui';
import { PluginDashboard } from 'app/types/plugins';
import { DashboardCard } from './DashboardCard';
@@ -26,6 +26,8 @@ import {
getLogoUrl,
buildDashboardDetails,
onUseCommunityDashboard,
+ COMMUNITY_PAGE_SIZE_QUERY,
+ COMMUNITY_RESULT_SIZE,
} from './utils/communityDashboardHelpers';
import { getProvisionedDashboardImageUrl } from './utils/provisionedDashboardHelpers';
@@ -43,7 +45,7 @@ type SuggestedDashboardsResult = {
};
// Constants for suggested dashboards API params
-const SUGGESTED_COMMUNITY_PAGE_SIZE = 2;
+const MAX_SUGGESTED_DASHBOARDS_PREVIEW = 2;
const DEFAULT_SORT_ORDER = 'downloads';
const DEFAULT_SORT_DIRECTION = 'desc';
const INCLUDE_SCREENSHOTS = true;
@@ -91,14 +93,14 @@ export const SuggestedDashboards = ({ datasourceUid }: Props) => {
orderBy: DEFAULT_SORT_ORDER,
direction: DEFAULT_SORT_DIRECTION,
page: 1,
- pageSize: SUGGESTED_COMMUNITY_PAGE_SIZE,
+ pageSize: COMMUNITY_PAGE_SIZE_QUERY,
includeScreenshots: INCLUDE_SCREENSHOTS,
dataSourceSlugIn: ds.type,
includeLogo: INCLUDE_LOGO,
}),
]);
- const community = communityResponse.items;
+ const community = communityResponse.items.slice(0, COMMUNITY_RESULT_SIZE);
// Mix: 1 provisioned + 2 community
const mixed: MixedDashboard[] = [];
@@ -130,7 +132,7 @@ export const SuggestedDashboards = ({ datasourceUid }: Props) => {
// Determine if there are more dashboards available beyond what we're showing
// Show "View all" if: more than 1 provisioned exists OR we got the full page size of community dashboards
- const hasMoreDashboards = provisioned.length > 1 || community.length >= SUGGESTED_COMMUNITY_PAGE_SIZE;
+ const hasMoreDashboards = provisioned.length > 1 || community.length > MAX_SUGGESTED_DASHBOARDS_PREVIEW;
return { dashboards: mixed, hasMoreDashboards };
} catch (error) {
@@ -233,35 +235,38 @@ export const SuggestedDashboards = ({ datasourceUid }: Props) => {
locationService.push(`/dashboard/template?${params.toString()}`);
};
- const onPreviewCommunityDashboard = (dashboard: GnetDashboard) => {
- if (!datasourceUid) {
- return;
- }
+ const [{ error: isPreviewCommunityDashboardError }, onPreviewCommunityDashboard] = useAsyncFn(
+ async (dashboard: GnetDashboard) => {
+ if (!datasourceUid) {
+ return;
+ }
- const ds = getDataSourceSrv().getInstanceSettings(datasourceUid);
- if (!ds) {
- return;
- }
+ const ds = getDataSourceSrv().getInstanceSettings(datasourceUid);
+ if (!ds) {
+ return;
+ }
- // Track item click
- DashboardLibraryInteractions.itemClicked({
- contentKind: CONTENT_KINDS.COMMUNITY_DASHBOARD,
- datasourceTypes: [ds.type],
- libraryItemId: String(dashboard.id),
- libraryItemTitle: dashboard.name,
- sourceEntryPoint: SOURCE_ENTRY_POINTS.DATASOURCE_PAGE,
- eventLocation: EVENT_LOCATIONS.EMPTY_DASHBOARD,
- discoveryMethod: DISCOVERY_METHODS.BROWSE,
- });
+ // Track item click
+ DashboardLibraryInteractions.itemClicked({
+ contentKind: CONTENT_KINDS.COMMUNITY_DASHBOARD,
+ datasourceTypes: [ds.type],
+ libraryItemId: String(dashboard.id),
+ libraryItemTitle: dashboard.name,
+ sourceEntryPoint: SOURCE_ENTRY_POINTS.DATASOURCE_PAGE,
+ eventLocation: EVENT_LOCATIONS.EMPTY_DASHBOARD,
+ discoveryMethod: DISCOVERY_METHODS.BROWSE,
+ });
- onUseCommunityDashboard({
- dashboard,
- datasourceUid,
- datasourceType: ds.type,
- eventLocation: EVENT_LOCATIONS.EMPTY_DASHBOARD,
- onShowMapping: onShowMapping,
- });
- };
+ await onUseCommunityDashboard({
+ dashboard,
+ datasourceUid,
+ datasourceType: ds.type,
+ eventLocation: EVENT_LOCATIONS.EMPTY_DASHBOARD,
+ onShowMapping: onShowMapping,
+ });
+ },
+ [datasourceUid, onShowMapping]
+ );
// Don't render if no dashboards or still loading
if (!loading && (!result || result.dashboards.length === 0)) {
@@ -297,7 +302,16 @@ export const SuggestedDashboards = ({ datasourceUid }: Props) => {
)}
-
+ {isPreviewCommunityDashboardError && (
+