mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
PluginsCatalog: post installation, adding an "add datasource"-button. (#40155)
* added post installation steps. * changes according to feedback. * removing return union null type. * added tests. * changing the wording of the button to 'create a..' * updated tests to check for the updated copy. * changing the back to be a regular back button. * updated snapshot
This commit is contained in:
@@ -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<Props> = ({ isReadOnly, onDelete, onSubmit, onTest, exploreU
|
||||
|
||||
return (
|
||||
<div className="gf-form-button-row">
|
||||
<LinkButton variant="secondary" fill="solid" href={`${config.appSubUrl}/datasources`}>
|
||||
<Button variant="secondary" fill="solid" type="button" onClick={() => history.back()}>
|
||||
Back
|
||||
</LinkButton>
|
||||
</Button>
|
||||
<LinkButton variant="secondary" fill="solid" href={exploreUrl} disabled={!canExploreDataSources}>
|
||||
Explore
|
||||
</LinkButton>
|
||||
|
@@ -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<Props> {
|
||||
Delete
|
||||
</Button>
|
||||
)}
|
||||
<LinkButton variant="secondary" href="datasources" fill="outline">
|
||||
<Button variant="secondary" fill="outline" type="button" onClick={() => history.back()}>
|
||||
Back
|
||||
</LinkButton>
|
||||
</Button>
|
||||
</div>
|
||||
</Page.Contents>
|
||||
</Page>
|
||||
|
@@ -4,13 +4,14 @@ exports[`Render should render component 1`] = `
|
||||
<div
|
||||
className="gf-form-button-row"
|
||||
>
|
||||
<LinkButton
|
||||
<Button
|
||||
fill="solid"
|
||||
href="/datasources"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
variant="secondary"
|
||||
>
|
||||
Back
|
||||
</LinkButton>
|
||||
</Button>
|
||||
<LinkButton
|
||||
disabled={false}
|
||||
fill="solid"
|
||||
@@ -42,13 +43,14 @@ exports[`Render should render with buttons enabled 1`] = `
|
||||
<div
|
||||
className="gf-form-button-row"
|
||||
>
|
||||
<LinkButton
|
||||
<Button
|
||||
fill="solid"
|
||||
href="/datasources"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
variant="secondary"
|
||||
>
|
||||
Back
|
||||
</LinkButton>
|
||||
</Button>
|
||||
<LinkButton
|
||||
disabled={false}
|
||||
fill="solid"
|
||||
|
@@ -0,0 +1,28 @@
|
||||
import { DataSourcePluginMeta } from '@grafana/data';
|
||||
import { Button } from '@grafana/ui';
|
||||
import { addDataSource } from 'app/features/datasources/state/actions';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { CatalogPlugin } from '../../types';
|
||||
|
||||
type Props = {
|
||||
plugin: CatalogPlugin;
|
||||
};
|
||||
|
||||
export function GetStartedWithDataSource({ plugin }: Props): React.ReactElement {
|
||||
const dispatch = useDispatch();
|
||||
const onAddDataSource = useCallback(() => {
|
||||
const meta = {
|
||||
name: plugin.name,
|
||||
id: plugin.id,
|
||||
} as DataSourcePluginMeta;
|
||||
|
||||
dispatch(addDataSource(meta));
|
||||
}, [dispatch, plugin]);
|
||||
|
||||
return (
|
||||
<Button variant="primary" onClick={onAddDataSource}>
|
||||
Create a {plugin.name} data source
|
||||
</Button>
|
||||
);
|
||||
}
|
@@ -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 <GetStartedWithDataSource plugin={plugin} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1 @@
|
||||
export { GetStartedWithPlugin } from './GetStartedWithPlugin';
|
@@ -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
|
||||
|
||||
<p>{plugin.description}</p>
|
||||
|
||||
<InstallControls plugin={plugin} />
|
||||
<HorizontalGroup height="auto">
|
||||
<InstallControls plugin={plugin} />
|
||||
<GetStartedWithPlugin plugin={plugin} />
|
||||
</HorizontalGroup>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@@ -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();
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user