DataSourceList: Build a dashboard button to open new dashboard in panel edit with data source already set (#60532)

* New dashboard with preset data source

* Updates

* use replace instead

* Tests: fix failing tests

* Chore: add UID to the error message

Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com>
This commit is contained in:
Torkel Ödegaard 2023-01-06 15:21:40 +01:00 committed by GitHub
parent e2ed42c2a3
commit f71bfd88c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 71 additions and 13 deletions

View File

@ -75,6 +75,7 @@ export const AddPanelWidgetUnconnected = ({ panel, dashboard }: Props) => {
const newPanel: Partial<PanelModel> = {
type: 'timeseries',
title: 'Panel Title',
datasource: panel.datasource,
gridPos: { x: gridPos.x, y: gridPos.y, w: gridPos.w, h: gridPos.h },
};

View File

@ -0,0 +1,45 @@
import React, { useEffect, useState } from 'react';
import { getDataSourceSrv, locationService } from '@grafana/runtime';
import { Page } from 'app/core/components/Page/Page';
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
import { getNewDashboardModelData, setDashboardToFetchFromLocalStorage } from '../state/initDashboard';
export default function NewDashboardWithDS(props: GrafanaRouteComponentProps<{ datasourceUid: string }>) {
const [error, setError] = useState<string | null>(null);
const { datasourceUid } = props.match.params;
useEffect(() => {
const ds = getDataSourceSrv().getInstanceSettings(datasourceUid);
if (!ds) {
setError('Data source not found');
return;
}
const newDashboard = getNewDashboardModelData();
const { dashboard } = newDashboard;
dashboard.panels[0] = {
...dashboard.panels[0],
datasource: {
uid: ds.uid,
type: ds.type,
},
};
setDashboardToFetchFromLocalStorage(newDashboard);
locationService.replace('/dashboard/new');
}, [datasourceUid]);
if (error) {
return (
<Page navId="dashboards">
<Page.Contents>
<div>Data source with UID &quot;{datasourceUid}&quot; not found.</div>
</Page.Contents>
</Page>
);
}
return null;
}

View File

@ -38,7 +38,7 @@ describe('<DataSourcesList>', () => {
expect(await screen.findAllByRole('listitem')).toHaveLength(3);
expect(await screen.findAllByRole('heading')).toHaveLength(3);
expect(await screen.findAllByRole('link', { name: 'Build a Dashboard' })).toHaveLength(3);
expect(await screen.findAllByRole('link', { name: /Build a dashboard/i })).toHaveLength(3);
expect(await screen.findAllByRole('link', { name: 'Explore' })).toHaveLength(3);
});

View File

@ -100,8 +100,13 @@ export function DataSourcesListView({
]}
</Card.Meta>
<Card.Tags>
<LinkButton icon="apps" fill="outline" variant="secondary" href={config.appSubUrl + '/dashboard/new'}>
Build a Dashboard
<LinkButton
icon="apps"
fill="outline"
variant="secondary"
href={`dashboard/new-with-ds/${dataSource.uid}`}
>
Build a dashboard
</LinkButton>
{hasExploreRights && (
<LinkButton

View File

@ -71,7 +71,7 @@ describe('Render', () => {
getDataSourcesMock.mockResolvedValue(getMockDataSources(3));
setup({ isSortAscending: true });
expect(await screen.findAllByRole('link', { name: 'Build a Dashboard' })).toHaveLength(3);
expect(await screen.findAllByRole('link', { name: /Build a dashboard/i })).toHaveLength(3);
expect(screen.queryAllByRole('link', { name: 'Explore' })).toHaveLength(0);
});
@ -88,7 +88,7 @@ describe('Render', () => {
getDataSourcesMock.mockResolvedValue(getMockDataSources(3));
setup({ isSortAscending: true });
expect(await screen.findAllByRole('link', { name: 'Build a Dashboard' })).toHaveLength(3);
expect(await screen.findAllByRole('link', { name: /Build a dashboard/i })).toHaveLength(3);
expect(screen.queryAllByRole('link', { name: 'Explore' })).toHaveLength(3);
});

View File

@ -74,14 +74,6 @@ export function getAppRoutes(): RouteDescriptor[] {
() => import(/* webpackChunkName: "DashboardPage" */ '../features/dashboard/containers/DashboardPage')
),
},
{
path: '/dashboard/:type/:slug',
pageClass: 'page-dashboard',
routeName: DashboardRoutes.Normal,
component: SafeDynamicImport(
() => import(/* webpackChunkName: "DashboardPage" */ '../features/dashboard/containers/DashboardPage')
),
},
{
path: '/dashboard/new',
roles: () => contextSrv.evaluatePermission(() => ['Editor', 'Admin'], [AccessControlAction.DashboardsCreate]),
@ -91,6 +83,21 @@ export function getAppRoutes(): RouteDescriptor[] {
() => import(/* webpackChunkName: "DashboardPage" */ '../features/dashboard/containers/NewDashboardPage')
),
},
{
path: '/dashboard/new-with-ds/:datasourceUid',
roles: () => contextSrv.evaluatePermission(() => ['Editor', 'Admin'], [AccessControlAction.DashboardsCreate]),
component: SafeDynamicImport(
() => import(/* webpackChunkName: "DashboardPage" */ '../features/dashboard/containers/NewDashboardWithDS')
),
},
{
path: '/dashboard/:type/:slug',
pageClass: 'page-dashboard',
routeName: DashboardRoutes.Normal,
component: SafeDynamicImport(
() => import(/* webpackChunkName: "DashboardPage" */ '../features/dashboard/containers/DashboardPage')
),
},
{
path: '/d-solo/:uid/:slug',
pageClass: 'dashboard-solo',