diff --git a/packages/grafana-e2e-selectors/src/selectors/components.ts b/packages/grafana-e2e-selectors/src/selectors/components.ts
index 3a763ec3fe5..677fe0d0d84 100644
--- a/packages/grafana-e2e-selectors/src/selectors/components.ts
+++ b/packages/grafana-e2e-selectors/src/selectors/components.ts
@@ -603,4 +603,7 @@ export const Components = {
headerOrderSwitch: 'data-testid header-order-switch',
headerPreviewSwitch: 'data-testid header-preview-switch',
},
+ EntityNotFound: {
+ container: 'data-testid entity-not-found',
+ },
};
diff --git a/public/app/core/components/PageNotFound/EntityNotFound.tsx b/public/app/core/components/PageNotFound/EntityNotFound.tsx
index 24edfa76f5c..c749d30aa19 100644
--- a/public/app/core/components/PageNotFound/EntityNotFound.tsx
+++ b/public/app/core/components/PageNotFound/EntityNotFound.tsx
@@ -2,6 +2,7 @@ import { css } from '@emotion/css';
import React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
+import { selectors } from '@grafana/e2e-selectors';
import { EmptyState, TextLink, useStyles2 } from '@grafana/ui';
export interface Props {
@@ -15,7 +16,7 @@ export function EntityNotFound({ entity = 'Page' }: Props) {
const styles = useStyles2(getStyles);
return (
-
+
We're looking but can't seem to find this {entity.toLowerCase()}. Try returning{' '}
home or seeking help on the{' '}
diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.tsx
index e2bc1828f39..2b04bec57de 100644
--- a/public/app/features/dashboard-scene/scene/DashboardScene.tsx
+++ b/public/app/features/dashboard-scene/scene/DashboardScene.tsx
@@ -392,6 +392,10 @@ export class DashboardScene extends SceneObjectBase {
public getPageNav(location: H.Location, navIndex: NavIndex) {
const { meta, viewPanelScene, editPanel } = this.state;
+ if (meta.dashboardNotFound) {
+ return { text: 'Not found' };
+ }
+
let pageNav: NavModelItem = {
text: this.state.title,
url: getDashboardUrl({
diff --git a/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.test.tsx b/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.test.tsx
new file mode 100644
index 00000000000..47d5cd076b3
--- /dev/null
+++ b/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.test.tsx
@@ -0,0 +1,65 @@
+import { render, screen } from '@testing-library/react';
+import React from 'react';
+import { Provider } from 'react-redux';
+import { Router } from 'react-router';
+import { getGrafanaContextMock } from 'test/mocks/getGrafanaContextMock';
+
+import { selectors } from '@grafana/e2e-selectors';
+import { locationService } from '@grafana/runtime';
+import { GrafanaContext } from 'app/core/context/GrafanaContext';
+import { configureStore } from 'app/store/configureStore';
+
+import { transformSaveModelToScene } from '../serialization/transformSaveModelToScene';
+
+describe('DashboardSceneRenderer', () => {
+ it('should render Not Found notice when dashboard is not found', async () => {
+ const scene = transformSaveModelToScene({
+ meta: {
+ isSnapshot: true,
+ dashboardNotFound: true,
+ canStar: false,
+ canDelete: false,
+ canSave: false,
+ canEdit: false,
+ canShare: false,
+ },
+ dashboard: {
+ title: 'Not found',
+ uid: 'uid',
+ schemaVersion: 0,
+ // Disabling build in annotations to avoid mocking Grafana data source
+ annotations: {
+ list: [
+ {
+ builtIn: 1,
+ datasource: {
+ type: 'grafana',
+ uid: '-- Grafana --',
+ },
+ enable: false,
+ hide: true,
+ iconColor: 'rgba(0, 211, 255, 1)',
+ name: 'Annotations & Alerts',
+ type: 'dashboard',
+ },
+ ],
+ },
+ },
+ });
+
+ const store = configureStore({});
+ const context = getGrafanaContextMock();
+
+ render(
+
+
+
+
+
+
+
+ );
+
+ expect(await screen.findByTestId(selectors.components.EntityNotFound.container)).toBeInTheDocument();
+ });
+});
diff --git a/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx b/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx
index 553710923cf..7687efa6107 100644
--- a/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx
+++ b/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx
@@ -7,6 +7,7 @@ import { selectors } from '@grafana/e2e-selectors';
import { SceneComponentProps } from '@grafana/scenes';
import { CustomScrollbar, useStyles2 } from '@grafana/ui';
import { Page } from 'app/core/components/Page/Page';
+import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound';
import { getNavModel } from 'app/core/selectors/navModel';
import DashboardEmpty from 'app/features/dashboard/dashgrid/DashboardEmpty';
import { useSelector } from 'app/types';
@@ -35,14 +36,26 @@ export function DashboardSceneRenderer({ model }: SceneComponentProps;
+ const emptyState = (
+
+ );
const withPanels = (
-
+
);
+ const notFound = meta.dashboardNotFound &&
;
+
+ let body = [withPanels];
+
+ if (notFound) {
+ body = [notFound];
+ } else if (isEmpty) {
+ body = [emptyState, withPanels];
+ }
+
return (
{editPanel && }
@@ -55,7 +68,7 @@ export function DashboardSceneRenderer({ model }: SceneComponentProps
- {scopes && }
+ {scopes && !meta.dashboardNotFound && }
{controls && hasControls && (
-
- <>{isEmpty && emptyState}>
- {withPanels}
-
+
{body}
)}
diff --git a/public/app/features/dashboard-scene/scene/NavToolbarActions.test.tsx b/public/app/features/dashboard-scene/scene/NavToolbarActions.test.tsx
index 797a80fe51d..ce2bfb8fa66 100644
--- a/public/app/features/dashboard-scene/scene/NavToolbarActions.test.tsx
+++ b/public/app/features/dashboard-scene/scene/NavToolbarActions.test.tsx
@@ -8,6 +8,7 @@ import { selectors } from '@grafana/e2e-selectors';
import { config, locationService } from '@grafana/runtime';
import { SceneGridLayout, SceneQueryRunner, SceneTimeRange, UrlSyncContextProvider, VizPanel } from '@grafana/scenes';
import { playlistSrv } from 'app/features/playlist/PlaylistSrv';
+import { DashboardMeta } from 'app/types';
import { buildPanelEditScene } from '../panel-edit/PanelEditor';
@@ -163,9 +164,27 @@ describe('NavToolbarActions', () => {
expect(newShareButton).toBeInTheDocument();
});
});
+
+ describe('Snapshot', () => {
+ it('should show link button when is a snapshot', () => {
+ setup({
+ isSnapshot: true,
+ });
+
+ expect(screen.queryByTestId('button-snapshot')).toBeInTheDocument();
+ });
+ it('should not show link button when is not found dashboard', () => {
+ setup({
+ isSnapshot: true,
+ dashboardNotFound: true,
+ });
+
+ expect(screen.queryByTestId('button-snapshot')).not.toBeInTheDocument();
+ });
+ });
});
-function setup() {
+function setup(meta?: DashboardMeta) {
const dashboard = new DashboardScene({
$timeRange: new SceneTimeRange({ from: 'now-6h', to: 'now' }),
meta: {
@@ -177,6 +196,7 @@ function setup() {
canStar: true,
canAdmin: true,
canDelete: true,
+ ...meta,
},
title: 'hello',
uid: 'dash-1',
diff --git a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx
index 18a6a336ccf..47a714cc1dc 100644
--- a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx
+++ b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx
@@ -139,7 +139,7 @@ export function ToolbarActions({ dashboard }: Props) {
toolbarActions.push({
group: 'icon-actions',
- condition: meta.isSnapshot && !isEditing,
+ condition: meta.isSnapshot && !meta.dashboardNotFound && !isEditing,
render: () => (
{
- return this._dashboardLoadFailed('Not found', true);
+ const dash = this._dashboardLoadFailed('Not found', true);
+ dash.dashboard.uid = uid;
+ return dash;
});
} else {
throw new Error('Dashboard uid or slug required');