mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
parent
e2ed42c2a3
commit
f71bfd88c5
@ -75,6 +75,7 @@ export const AddPanelWidgetUnconnected = ({ panel, dashboard }: Props) => {
|
|||||||
const newPanel: Partial<PanelModel> = {
|
const newPanel: Partial<PanelModel> = {
|
||||||
type: 'timeseries',
|
type: 'timeseries',
|
||||||
title: 'Panel Title',
|
title: 'Panel Title',
|
||||||
|
datasource: panel.datasource,
|
||||||
gridPos: { x: gridPos.x, y: gridPos.y, w: gridPos.w, h: gridPos.h },
|
gridPos: { x: gridPos.x, y: gridPos.y, w: gridPos.w, h: gridPos.h },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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 "{datasourceUid}" not found.</div>
|
||||||
|
</Page.Contents>
|
||||||
|
</Page>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
@ -38,7 +38,7 @@ describe('<DataSourcesList>', () => {
|
|||||||
|
|
||||||
expect(await screen.findAllByRole('listitem')).toHaveLength(3);
|
expect(await screen.findAllByRole('listitem')).toHaveLength(3);
|
||||||
expect(await screen.findAllByRole('heading')).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);
|
expect(await screen.findAllByRole('link', { name: 'Explore' })).toHaveLength(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -100,8 +100,13 @@ export function DataSourcesListView({
|
|||||||
]}
|
]}
|
||||||
</Card.Meta>
|
</Card.Meta>
|
||||||
<Card.Tags>
|
<Card.Tags>
|
||||||
<LinkButton icon="apps" fill="outline" variant="secondary" href={config.appSubUrl + '/dashboard/new'}>
|
<LinkButton
|
||||||
Build a Dashboard
|
icon="apps"
|
||||||
|
fill="outline"
|
||||||
|
variant="secondary"
|
||||||
|
href={`dashboard/new-with-ds/${dataSource.uid}`}
|
||||||
|
>
|
||||||
|
Build a dashboard
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
{hasExploreRights && (
|
{hasExploreRights && (
|
||||||
<LinkButton
|
<LinkButton
|
||||||
|
@ -71,7 +71,7 @@ describe('Render', () => {
|
|||||||
getDataSourcesMock.mockResolvedValue(getMockDataSources(3));
|
getDataSourcesMock.mockResolvedValue(getMockDataSources(3));
|
||||||
setup({ isSortAscending: true });
|
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);
|
expect(screen.queryAllByRole('link', { name: 'Explore' })).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ describe('Render', () => {
|
|||||||
getDataSourcesMock.mockResolvedValue(getMockDataSources(3));
|
getDataSourcesMock.mockResolvedValue(getMockDataSources(3));
|
||||||
setup({ isSortAscending: true });
|
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);
|
expect(screen.queryAllByRole('link', { name: 'Explore' })).toHaveLength(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -74,14 +74,6 @@ export function getAppRoutes(): RouteDescriptor[] {
|
|||||||
() => import(/* webpackChunkName: "DashboardPage" */ '../features/dashboard/containers/DashboardPage')
|
() => 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',
|
path: '/dashboard/new',
|
||||||
roles: () => contextSrv.evaluatePermission(() => ['Editor', 'Admin'], [AccessControlAction.DashboardsCreate]),
|
roles: () => contextSrv.evaluatePermission(() => ['Editor', 'Admin'], [AccessControlAction.DashboardsCreate]),
|
||||||
@ -91,6 +83,21 @@ export function getAppRoutes(): RouteDescriptor[] {
|
|||||||
() => import(/* webpackChunkName: "DashboardPage" */ '../features/dashboard/containers/NewDashboardPage')
|
() => 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',
|
path: '/d-solo/:uid/:slug',
|
||||||
pageClass: 'dashboard-solo',
|
pageClass: 'dashboard-solo',
|
||||||
|
Loading…
Reference in New Issue
Block a user