2019-12-09 00:14:25 -08:00
|
|
|
import React, { FC, PureComponent } from 'react';
|
2021-07-23 10:33:26 +01:00
|
|
|
import { connect, ConnectedProps } from 'react-redux';
|
2020-01-06 16:56:34 +01:00
|
|
|
import { DataSourcePluginMeta, NavModel } from '@grafana/data';
|
2021-09-29 09:35:41 +02:00
|
|
|
import { Button, LinkButton, List, PluginSignatureBadge, FilterInput } from '@grafana/ui';
|
2020-04-27 09:09:05 +02:00
|
|
|
import { selectors } from '@grafana/e2e-selectors';
|
2019-12-09 00:14:25 -08:00
|
|
|
|
2019-01-28 16:25:03 +01:00
|
|
|
import Page from 'app/core/components/Page/Page';
|
2021-07-23 10:33:26 +01:00
|
|
|
import { StoreState } from 'app/types';
|
2020-01-13 08:03:22 +01:00
|
|
|
import { addDataSource, loadDataSourcePlugins } from './state/actions';
|
2020-01-06 16:56:34 +01:00
|
|
|
import { getDataSourcePlugins } from './state/selectors';
|
2020-01-13 08:03:22 +01:00
|
|
|
import { setDataSourceTypeSearchQuery } from './state/reducers';
|
2020-04-23 10:12:06 +02:00
|
|
|
import { Card } from 'app/core/components/Card/Card';
|
2020-10-27 13:08:08 +01:00
|
|
|
import { PluginsErrorsInfo } from '../plugins/PluginsErrorsInfo';
|
2018-10-02 16:18:42 +02:00
|
|
|
|
2021-07-23 10:33:26 +01:00
|
|
|
function mapStateToProps(state: StoreState) {
|
|
|
|
|
return {
|
|
|
|
|
navModel: getNavModel(),
|
|
|
|
|
plugins: getDataSourcePlugins(state.dataSources),
|
|
|
|
|
searchQuery: state.dataSources.dataSourceTypeSearchQuery,
|
|
|
|
|
categories: state.dataSources.categories,
|
|
|
|
|
isLoading: state.dataSources.isLoadingDataSources,
|
|
|
|
|
};
|
2018-10-02 16:18:42 +02:00
|
|
|
}
|
|
|
|
|
|
2021-07-23 10:33:26 +01:00
|
|
|
const mapDispatchToProps = {
|
|
|
|
|
addDataSource,
|
|
|
|
|
loadDataSourcePlugins,
|
|
|
|
|
setDataSourceTypeSearchQuery,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const connector = connect(mapStateToProps, mapDispatchToProps);
|
|
|
|
|
|
|
|
|
|
type Props = ConnectedProps<typeof connector>;
|
|
|
|
|
|
2018-10-03 16:04:30 +02:00
|
|
|
class NewDataSourcePage extends PureComponent<Props> {
|
2018-10-03 09:56:15 +02:00
|
|
|
componentDidMount() {
|
2020-01-06 16:56:34 +01:00
|
|
|
this.props.loadDataSourcePlugins();
|
2018-10-03 09:56:15 +02:00
|
|
|
}
|
|
|
|
|
|
2019-04-29 09:14:39 -07:00
|
|
|
onDataSourceTypeClicked = (plugin: DataSourcePluginMeta) => {
|
2019-01-28 16:25:03 +01:00
|
|
|
this.props.addDataSource(plugin);
|
2018-10-02 16:18:42 +02:00
|
|
|
};
|
|
|
|
|
|
2019-02-12 08:03:43 +01:00
|
|
|
onSearchQueryChange = (value: string) => {
|
|
|
|
|
this.props.setDataSourceTypeSearchQuery(value);
|
2018-10-04 11:42:17 +02:00
|
|
|
};
|
|
|
|
|
|
2020-01-06 16:56:34 +01:00
|
|
|
renderPlugins(plugins: DataSourcePluginMeta[]) {
|
|
|
|
|
if (!plugins || !plugins.length) {
|
2019-05-09 11:45:39 +02:00
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<List
|
2020-01-06 16:56:34 +01:00
|
|
|
items={plugins}
|
2021-01-20 07:59:48 +01:00
|
|
|
getItemKey={(item) => item.id.toString()}
|
|
|
|
|
renderItem={(item) => (
|
2019-05-09 11:45:39 +02:00
|
|
|
<DataSourceTypeCard
|
|
|
|
|
plugin={item}
|
|
|
|
|
onClick={() => this.onDataSourceTypeClicked(item)}
|
|
|
|
|
onLearnMoreClick={this.onLearnMoreClick}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onLearnMoreClick = (evt: React.SyntheticEvent<HTMLElement>) => {
|
|
|
|
|
evt.stopPropagation();
|
|
|
|
|
};
|
|
|
|
|
|
2020-01-06 16:56:34 +01:00
|
|
|
renderCategories() {
|
|
|
|
|
const { categories } = this.props;
|
2019-05-29 09:37:29 +02:00
|
|
|
|
2019-05-09 11:45:39 +02:00
|
|
|
return (
|
|
|
|
|
<>
|
2021-01-20 07:59:48 +01:00
|
|
|
{categories.map((category) => (
|
2019-05-09 11:45:39 +02:00
|
|
|
<div className="add-data-source-category" key={category.id}>
|
|
|
|
|
<div className="add-data-source-category__header">{category.title}</div>
|
2020-01-06 16:56:34 +01:00
|
|
|
{this.renderPlugins(category.plugins)}
|
2019-05-09 11:45:39 +02:00
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
<div className="add-data-source-more">
|
2020-04-01 15:55:23 +02:00
|
|
|
<LinkButton
|
|
|
|
|
variant="secondary"
|
2020-01-06 16:56:34 +01:00
|
|
|
href="https://grafana.com/plugins?type=datasource&utm_source=grafana_add_ds"
|
2019-05-09 11:45:39 +02:00
|
|
|
target="_blank"
|
2019-09-03 09:29:02 +01:00
|
|
|
rel="noopener"
|
2019-05-09 11:45:39 +02:00
|
|
|
>
|
|
|
|
|
Find more data source plugins on grafana.com
|
2020-04-01 15:55:23 +02:00
|
|
|
</LinkButton>
|
2019-05-09 11:45:39 +02:00
|
|
|
</div>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-02 16:18:42 +02:00
|
|
|
render() {
|
2020-01-06 16:56:34 +01:00
|
|
|
const { navModel, isLoading, searchQuery, plugins } = this.props;
|
2019-05-09 11:45:39 +02:00
|
|
|
|
2018-10-02 16:18:42 +02:00
|
|
|
return (
|
2019-01-28 16:25:03 +01:00
|
|
|
<Page navModel={navModel}>
|
|
|
|
|
<Page.Contents isLoading={isLoading}>
|
2019-05-09 11:45:39 +02:00
|
|
|
<div className="page-action-bar">
|
2020-04-01 15:55:23 +02:00
|
|
|
<FilterInput value={searchQuery} onChange={this.onSearchQueryChange} placeholder="Filter by name or type" />
|
2019-05-09 11:45:39 +02:00
|
|
|
<div className="page-action-bar__spacer" />
|
2021-04-27 15:36:48 +02:00
|
|
|
<LinkButton href="datasources" fill="outline" variant="secondary" icon="arrow-left">
|
|
|
|
|
Cancel
|
|
|
|
|
</LinkButton>
|
2019-02-12 12:49:40 +01:00
|
|
|
</div>
|
2021-05-31 21:54:53 +02:00
|
|
|
{!searchQuery && <PluginsErrorsInfo />}
|
2019-05-09 11:45:39 +02:00
|
|
|
<div>
|
2020-01-06 16:56:34 +01:00
|
|
|
{searchQuery && this.renderPlugins(plugins)}
|
|
|
|
|
{!searchQuery && this.renderCategories()}
|
2018-10-03 16:04:30 +02:00
|
|
|
</div>
|
2019-01-28 16:25:03 +01:00
|
|
|
</Page.Contents>
|
|
|
|
|
</Page>
|
2018-10-02 16:18:42 +02:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-09 11:45:39 +02:00
|
|
|
interface DataSourceTypeCardProps {
|
|
|
|
|
plugin: DataSourcePluginMeta;
|
|
|
|
|
onClick: () => void;
|
|
|
|
|
onLearnMoreClick: (evt: React.SyntheticEvent<HTMLElement>) => void;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-20 07:59:48 +01:00
|
|
|
const DataSourceTypeCard: FC<DataSourceTypeCardProps> = (props) => {
|
2019-05-29 09:37:29 +02:00
|
|
|
const { plugin, onLearnMoreClick } = props;
|
2020-01-06 16:56:34 +01:00
|
|
|
const isPhantom = plugin.module === 'phantom';
|
2020-11-05 12:55:40 +02:00
|
|
|
const onClick = !isPhantom && !plugin.unlicensed ? props.onClick : () => {};
|
2019-05-09 11:45:39 +02:00
|
|
|
// find first plugin info link
|
2020-11-05 12:55:40 +02:00
|
|
|
const learnMoreLink = plugin.info?.links?.length > 0 ? plugin.info.links[0] : null;
|
2019-05-09 11:45:39 +02:00
|
|
|
|
|
|
|
|
return (
|
2020-04-23 10:12:06 +02:00
|
|
|
<Card
|
|
|
|
|
title={plugin.name}
|
|
|
|
|
description={plugin.info.description}
|
2020-04-27 09:09:05 +02:00
|
|
|
ariaLabel={selectors.pages.AddDataSource.dataSourcePlugins(plugin.name)}
|
2020-04-23 10:12:06 +02:00
|
|
|
logoUrl={plugin.info.logos.small}
|
|
|
|
|
actions={
|
|
|
|
|
<>
|
|
|
|
|
{learnMoreLink && (
|
|
|
|
|
<LinkButton
|
|
|
|
|
variant="secondary"
|
|
|
|
|
href={`${learnMoreLink.url}?utm_source=grafana_add_ds`}
|
|
|
|
|
target="_blank"
|
|
|
|
|
rel="noopener"
|
|
|
|
|
onClick={onLearnMoreClick}
|
|
|
|
|
icon="external-link-alt"
|
|
|
|
|
>
|
|
|
|
|
{learnMoreLink.name}
|
|
|
|
|
</LinkButton>
|
|
|
|
|
)}
|
2020-11-05 12:55:40 +02:00
|
|
|
{!isPhantom && <Button disabled={plugin.unlicensed}>Select</Button>}
|
2020-04-23 10:12:06 +02:00
|
|
|
</>
|
|
|
|
|
}
|
2021-01-18 11:51:27 +01:00
|
|
|
labels={!isPhantom && <PluginSignatureBadge status={plugin.signature} />}
|
2020-05-14 14:25:52 +02:00
|
|
|
className={isPhantom ? 'add-data-source-item--phantom' : ''}
|
2020-04-23 21:39:08 +02:00
|
|
|
onClick={onClick}
|
2020-04-27 09:09:05 +02:00
|
|
|
aria-label={selectors.pages.AddDataSource.dataSourcePlugins(plugin.name)}
|
2020-04-23 21:39:08 +02:00
|
|
|
/>
|
2019-05-09 11:45:39 +02:00
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export function getNavModel(): NavModel {
|
|
|
|
|
const main = {
|
2020-04-29 11:05:58 +02:00
|
|
|
icon: 'database',
|
2019-05-09 11:45:39 +02:00
|
|
|
id: 'datasource-new',
|
2019-05-09 14:21:02 +02:00
|
|
|
text: 'Add data source',
|
2019-05-09 11:45:39 +02:00
|
|
|
href: 'datasources/new',
|
|
|
|
|
subTitle: 'Choose a data source type',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
main: main,
|
|
|
|
|
node: main,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-31 12:55:05 +02:00
|
|
|
export default connector(NewDataSourcePage);
|