NewDataSourcePage.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import React, { PureComponent } from 'react';
  2. import { connect } from 'react-redux';
  3. import { hot } from 'react-hot-loader';
  4. import Page from 'app/core/components/Page/Page';
  5. import { StoreState } from 'app/types';
  6. import { addDataSource, loadDataSourceTypes, setDataSourceTypeSearchQuery } from './state/actions';
  7. import { getNavModel } from 'app/core/selectors/navModel';
  8. import { getDataSourceTypes } from './state/selectors';
  9. import { FilterInput } from 'app/core/components/FilterInput/FilterInput';
  10. import { NavModel, DataSourcePluginMeta } from '@grafana/ui';
  11. export interface Props {
  12. navModel: NavModel;
  13. dataSourceTypes: DataSourcePluginMeta[];
  14. isLoading: boolean;
  15. addDataSource: typeof addDataSource;
  16. loadDataSourceTypes: typeof loadDataSourceTypes;
  17. dataSourceTypeSearchQuery: string;
  18. setDataSourceTypeSearchQuery: typeof setDataSourceTypeSearchQuery;
  19. }
  20. class NewDataSourcePage extends PureComponent<Props> {
  21. componentDidMount() {
  22. this.props.loadDataSourceTypes();
  23. }
  24. onDataSourceTypeClicked = (plugin: DataSourcePluginMeta) => {
  25. this.props.addDataSource(plugin);
  26. };
  27. onSearchQueryChange = (value: string) => {
  28. this.props.setDataSourceTypeSearchQuery(value);
  29. };
  30. render() {
  31. const { navModel, dataSourceTypes, dataSourceTypeSearchQuery, isLoading } = this.props;
  32. return (
  33. <Page navModel={navModel}>
  34. <Page.Contents isLoading={isLoading}>
  35. <h2 className="add-data-source-header">Choose data source type</h2>
  36. <div className="add-data-source-search">
  37. <FilterInput
  38. labelClassName="gf-form--has-input-icon"
  39. inputClassName="gf-form-input width-20"
  40. value={dataSourceTypeSearchQuery}
  41. onChange={this.onSearchQueryChange}
  42. placeholder="Filter by name or type"
  43. />
  44. </div>
  45. <div className="add-data-source-grid">
  46. {dataSourceTypes.map((plugin, index) => {
  47. return (
  48. <div
  49. onClick={() => this.onDataSourceTypeClicked(plugin)}
  50. className="add-data-source-grid-item"
  51. key={`${plugin.id}-${index}`}
  52. >
  53. <img className="add-data-source-grid-item-logo" src={plugin.info.logos.small} />
  54. <span className="add-data-source-grid-item-text">{plugin.name}</span>
  55. </div>
  56. );
  57. })}
  58. </div>
  59. </Page.Contents>
  60. </Page>
  61. );
  62. }
  63. }
  64. function mapStateToProps(state: StoreState) {
  65. return {
  66. navModel: getNavModel(state.navIndex, 'datasources'),
  67. dataSourceTypes: getDataSourceTypes(state.dataSources),
  68. dataSourceTypeSearchQuery: state.dataSources.dataSourceTypeSearchQuery,
  69. isLoading: state.dataSources.isLoadingDataSources,
  70. };
  71. }
  72. const mapDispatchToProps = {
  73. addDataSource,
  74. loadDataSourceTypes,
  75. setDataSourceTypeSearchQuery,
  76. };
  77. export default hot(module)(
  78. connect(
  79. mapStateToProps,
  80. mapDispatchToProps
  81. )(NewDataSourcePage)
  82. );