diff --git a/public/app/features/datasources/settings/ButtonRow.tsx b/public/app/features/datasources/settings/ButtonRow.tsx index 387e1cd8bda..cf5ee44fef0 100644 --- a/public/app/features/datasources/settings/ButtonRow.tsx +++ b/public/app/features/datasources/settings/ButtonRow.tsx @@ -1,7 +1,6 @@ import React, { FC } from 'react'; import { selectors } from '@grafana/e2e-selectors'; -import config from 'app/core/config'; import { Button, LinkButton } from '@grafana/ui'; import { AccessControlAction } from 'app/types/'; @@ -22,9 +21,9 @@ const ButtonRow: FC = ({ isReadOnly, onDelete, onSubmit, onTest, exploreU return (
- + Explore diff --git a/public/app/features/datasources/settings/DataSourceSettingsPage.tsx b/public/app/features/datasources/settings/DataSourceSettingsPage.tsx index 8626f8f512d..14aaed49903 100644 --- a/public/app/features/datasources/settings/DataSourceSettingsPage.tsx +++ b/public/app/features/datasources/settings/DataSourceSettingsPage.tsx @@ -22,7 +22,7 @@ import { getNavModel } from 'app/core/selectors/navModel'; // Types import { StoreState, AccessControlAction } from 'app/types/'; import { DataSourceSettings, urlUtil } from '@grafana/data'; -import { Alert, Button, LinkButton } from '@grafana/ui'; +import { Alert, Button } from '@grafana/ui'; import { getDataSourceLoadingNav, buildNavModel, getDataSourceNav } from '../state/navModel'; import { PluginStateInfo } from 'app/features/plugins/PluginStateInfo'; import { dataSourceLoaded, setDataSourceName, setIsDefault } from '../state/reducers'; @@ -190,9 +190,9 @@ export class DataSourceSettingsPage extends PureComponent { Delete )} - +
diff --git a/public/app/features/datasources/settings/__snapshots__/ButtonRow.test.tsx.snap b/public/app/features/datasources/settings/__snapshots__/ButtonRow.test.tsx.snap index 068e473453e..dad29a6f8e8 100644 --- a/public/app/features/datasources/settings/__snapshots__/ButtonRow.test.tsx.snap +++ b/public/app/features/datasources/settings/__snapshots__/ButtonRow.test.tsx.snap @@ -4,13 +4,14 @@ exports[`Render should render component 1`] = `
- Back - + - Back - + { + const meta = { + name: plugin.name, + id: plugin.id, + } as DataSourcePluginMeta; + + dispatch(addDataSource(meta)); + }, [dispatch, plugin]); + + return ( + + ); +} diff --git a/public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithPlugin.tsx b/public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithPlugin.tsx new file mode 100644 index 00000000000..8184299d98b --- /dev/null +++ b/public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithPlugin.tsx @@ -0,0 +1,21 @@ +import React, { ReactElement } from 'react'; +import { PluginType } from '@grafana/data'; +import { CatalogPlugin } from '../../types'; +import { GetStartedWithDataSource } from './GetStartedWithDataSource'; + +type Props = { + plugin: CatalogPlugin; +}; + +export function GetStartedWithPlugin({ plugin }: Props): ReactElement | null { + if (!plugin.isInstalled || plugin.isDisabled) { + return null; + } + + switch (plugin.type) { + case PluginType.datasource: + return ; + default: + return null; + } +} diff --git a/public/app/features/plugins/admin/components/GetStartedWithPlugin/index.ts b/public/app/features/plugins/admin/components/GetStartedWithPlugin/index.ts new file mode 100644 index 00000000000..d2f630c5d9e --- /dev/null +++ b/public/app/features/plugins/admin/components/GetStartedWithPlugin/index.ts @@ -0,0 +1 @@ +export { GetStartedWithPlugin } from './GetStartedWithPlugin'; diff --git a/public/app/features/plugins/admin/components/PluginDetailsHeader.tsx b/public/app/features/plugins/admin/components/PluginDetailsHeader.tsx index 072cbdf3ab8..fe9d4acf695 100644 --- a/public/app/features/plugins/admin/components/PluginDetailsHeader.tsx +++ b/public/app/features/plugins/admin/components/PluginDetailsHeader.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { css, cx } from '@emotion/css'; import { GrafanaTheme2 } from '@grafana/data'; -import { useStyles2, Icon } from '@grafana/ui'; +import { useStyles2, Icon, HorizontalGroup } from '@grafana/ui'; import { InstallControls } from './InstallControls'; import { PluginDetailsHeaderSignature } from './PluginDetailsHeaderSignature'; @@ -9,6 +9,7 @@ import { PluginDetailsHeaderDependencies } from './PluginDetailsHeaderDependenci import { PluginLogo } from './PluginLogo'; import { CatalogPlugin } from '../types'; import { PluginDisabledBadge } from './Badges'; +import { GetStartedWithPlugin } from './GetStartedWithPlugin'; type Props = { currentUrl: string; @@ -84,7 +85,10 @@ export function PluginDetailsHeader({ plugin, currentUrl, parentUrl }: Props): R

{plugin.description}

- + + + +
); diff --git a/public/app/features/plugins/admin/pages/PluginDetails.test.tsx b/public/app/features/plugins/admin/pages/PluginDetails.test.tsx index 784685a0b34..0279251d631 100644 --- a/public/app/features/plugins/admin/pages/PluginDetails.test.tsx +++ b/public/app/features/plugins/admin/pages/PluginDetails.test.tsx @@ -11,7 +11,7 @@ import { CatalogPlugin, PluginTabIds, RequestStatus, ReducerState } from '../typ import * as api from '../api'; import { fetchRemotePlugins } from '../state/actions'; import { mockPluginApis, getCatalogPluginMock, getPluginsStateMock } from '../__mocks__'; -import { PluginErrorCode, PluginSignatureStatus } from '@grafana/data'; +import { PluginErrorCode, PluginSignatureStatus, PluginType } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; jest.mock('@grafana/runtime', () => { @@ -119,7 +119,6 @@ describe('Plugin details page', () => { it('should display the number of downloads in the header', async () => { const downloads = 24324; const { queryByText } = renderPluginDetails({ id, downloads }); - await waitFor(() => expect(queryByText(new Intl.NumberFormat().format(downloads))).toBeInTheDocument()); }); @@ -380,4 +379,53 @@ describe('Plugin details page', () => { const message = 'The install controls have been disabled because the Grafana server cannot access grafana.com.'; expect(rendered.getByText(message)).toBeInTheDocument(); }); + + it('should display post installation step for installed data source plugins', async () => { + const name = 'Akumuli'; + const { queryByText } = renderPluginDetails({ + name, + isInstalled: true, + type: PluginType.datasource, + }); + + await waitFor(() => queryByText('Uninstall')); + expect(queryByText(`Create a ${name} data source`)).toBeInTheDocument(); + }); + + it('should not display post installation step for disabled data source plugins', async () => { + const name = 'Akumuli'; + const { queryByText } = renderPluginDetails({ + name, + isInstalled: true, + isDisabled: true, + type: PluginType.datasource, + }); + + await waitFor(() => queryByText('Uninstall')); + expect(queryByText(`Create a ${name} data source`)).toBeNull(); + }); + + it('should not display post installation step for panel plugins', async () => { + const name = 'Akumuli'; + const { queryByText } = renderPluginDetails({ + name, + isInstalled: true, + type: PluginType.panel, + }); + + await waitFor(() => queryByText('Uninstall')); + expect(queryByText(`Create a ${name} data source`)).toBeNull(); + }); + + it('should not display post installation step for app plugins', async () => { + const name = 'Akumuli'; + const { queryByText } = renderPluginDetails({ + name, + isInstalled: true, + type: PluginType.app, + }); + + await waitFor(() => queryByText('Uninstall')); + expect(queryByText(`Create a ${name} data source`)).toBeNull(); + }); });