mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
search data source types
This commit is contained in:
@@ -3,9 +3,10 @@ import { connect } from 'react-redux';
|
|||||||
import { hot } from 'react-hot-loader';
|
import { hot } from 'react-hot-loader';
|
||||||
import PageHeader from 'app/core/components/PageHeader/PageHeader';
|
import PageHeader from 'app/core/components/PageHeader/PageHeader';
|
||||||
import { NavModel, Plugin } from 'app/types';
|
import { NavModel, Plugin } from 'app/types';
|
||||||
import { addDataSource, loadDataSourceTypes } from './state/actions';
|
import { addDataSource, loadDataSourceTypes, setDataSourceTypeSearchQuery } from './state/actions';
|
||||||
import { updateLocation } from '../../core/actions';
|
import { updateLocation } from '../../core/actions';
|
||||||
import { getNavModel } from 'app/core/selectors/navModel';
|
import { getNavModel } from 'app/core/selectors/navModel';
|
||||||
|
import { getDataSourceTypes } from './state/selectors';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
navModel: NavModel;
|
navModel: NavModel;
|
||||||
@@ -13,6 +14,8 @@ export interface Props {
|
|||||||
addDataSource: typeof addDataSource;
|
addDataSource: typeof addDataSource;
|
||||||
loadDataSourceTypes: typeof loadDataSourceTypes;
|
loadDataSourceTypes: typeof loadDataSourceTypes;
|
||||||
updateLocation: typeof updateLocation;
|
updateLocation: typeof updateLocation;
|
||||||
|
dataSourceTypeSearchQuery: string;
|
||||||
|
setDataSourceTypeSearchQuery: typeof setDataSourceTypeSearchQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
class NewDataSourcePage extends PureComponent<Props> {
|
class NewDataSourcePage extends PureComponent<Props> {
|
||||||
@@ -24,14 +27,30 @@ class NewDataSourcePage extends PureComponent<Props> {
|
|||||||
this.props.addDataSource(type.name, type.value);
|
this.props.addDataSource(type.name, type.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onSearchQueryChange = event => {
|
||||||
|
this.props.setDataSourceTypeSearchQuery(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { navModel, dataSourceTypes } = this.props;
|
const { navModel, dataSourceTypes, dataSourceTypeSearchQuery } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<PageHeader model={navModel} />
|
<PageHeader model={navModel} />
|
||||||
<div className="page-container page-body">
|
<div className="page-container page-body">
|
||||||
<h3 className="add-data-source-header">Choose data source type</h3>
|
<h3 className="add-data-source-header">Choose data source type</h3>
|
||||||
|
<div className="add-data-source-search">
|
||||||
|
<label className="gf-form--has-input-icon">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="gf-form-input width-20"
|
||||||
|
value={dataSourceTypeSearchQuery}
|
||||||
|
onChange={this.onSearchQueryChange}
|
||||||
|
placeholder="Filter by name or type"
|
||||||
|
/>
|
||||||
|
<i className="gf-form-input-icon fa fa-search" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<div className="add-data-source-grid">
|
<div className="add-data-source-grid">
|
||||||
{dataSourceTypes.map((type, index) => {
|
{dataSourceTypes.map((type, index) => {
|
||||||
return (
|
return (
|
||||||
@@ -55,7 +74,7 @@ class NewDataSourcePage extends PureComponent<Props> {
|
|||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
navModel: getNavModel(state.navIndex, 'datasources'),
|
navModel: getNavModel(state.navIndex, 'datasources'),
|
||||||
dataSourceTypes: state.dataSources.dataSourceTypes,
|
dataSourceTypes: getDataSourceTypes(state.dataSources),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +82,7 @@ const mapDispatchToProps = {
|
|||||||
addDataSource,
|
addDataSource,
|
||||||
loadDataSourceTypes,
|
loadDataSourceTypes,
|
||||||
updateLocation,
|
updateLocation,
|
||||||
|
setDataSourceTypeSearchQuery,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(NewDataSourcePage));
|
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(NewDataSourcePage));
|
||||||
|
@@ -10,6 +10,7 @@ export enum ActionTypes {
|
|||||||
LoadDataSourceTypes = 'LOAD_DATA_SOURCE_TYPES',
|
LoadDataSourceTypes = 'LOAD_DATA_SOURCE_TYPES',
|
||||||
SetDataSourcesSearchQuery = 'SET_DATA_SOURCES_SEARCH_QUERY',
|
SetDataSourcesSearchQuery = 'SET_DATA_SOURCES_SEARCH_QUERY',
|
||||||
SetDataSourcesLayoutMode = 'SET_DATA_SOURCES_LAYOUT_MODE',
|
SetDataSourcesLayoutMode = 'SET_DATA_SOURCES_LAYOUT_MODE',
|
||||||
|
SetDataSourceTypeSearchQuery = 'SET_DATA_SOURCE_TYPE_SEARCH_QUERY',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LoadDataSourcesAction {
|
export interface LoadDataSourcesAction {
|
||||||
@@ -32,6 +33,11 @@ export interface LoadDataSourceTypesAction {
|
|||||||
payload: Plugin[];
|
payload: Plugin[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SetDataSourceTypeSearchQueryAction {
|
||||||
|
type: ActionTypes.SetDataSourceTypeSearchQuery;
|
||||||
|
payload: string;
|
||||||
|
}
|
||||||
|
|
||||||
const dataSourcesLoaded = (dataSources: DataSource[]): LoadDataSourcesAction => ({
|
const dataSourcesLoaded = (dataSources: DataSource[]): LoadDataSourcesAction => ({
|
||||||
type: ActionTypes.LoadDataSources,
|
type: ActionTypes.LoadDataSources,
|
||||||
payload: dataSources,
|
payload: dataSources,
|
||||||
@@ -52,12 +58,18 @@ export const setDataSourcesLayoutMode = (layoutMode: LayoutMode): SetDataSources
|
|||||||
payload: layoutMode,
|
payload: layoutMode,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const setDataSourceTypeSearchQuery = (query: string): SetDataSourceTypeSearchQueryAction => ({
|
||||||
|
type: ActionTypes.SetDataSourceTypeSearchQuery,
|
||||||
|
payload: query,
|
||||||
|
});
|
||||||
|
|
||||||
export type Action =
|
export type Action =
|
||||||
| LoadDataSourcesAction
|
| LoadDataSourcesAction
|
||||||
| SetDataSourcesSearchQueryAction
|
| SetDataSourcesSearchQueryAction
|
||||||
| SetDataSourcesLayoutModeAction
|
| SetDataSourcesLayoutModeAction
|
||||||
| UpdateLocationAction
|
| UpdateLocationAction
|
||||||
| LoadDataSourceTypesAction;
|
| LoadDataSourceTypesAction
|
||||||
|
| SetDataSourceTypeSearchQueryAction;
|
||||||
|
|
||||||
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, Action>;
|
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, Action>;
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@ const initialState: DataSourcesState = {
|
|||||||
searchQuery: '',
|
searchQuery: '',
|
||||||
dataSourcesCount: 0,
|
dataSourcesCount: 0,
|
||||||
dataSourceTypes: [] as Plugin[],
|
dataSourceTypes: [] as Plugin[],
|
||||||
|
dataSourceTypeSearchQuery: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const dataSourcesReducer = (state = initialState, action: Action): DataSourcesState => {
|
export const dataSourcesReducer = (state = initialState, action: Action): DataSourcesState => {
|
||||||
@@ -23,6 +24,9 @@ export const dataSourcesReducer = (state = initialState, action: Action): DataSo
|
|||||||
|
|
||||||
case ActionTypes.LoadDataSourceTypes:
|
case ActionTypes.LoadDataSourceTypes:
|
||||||
return { ...state, dataSourceTypes: action.payload };
|
return { ...state, dataSourceTypes: action.payload };
|
||||||
|
|
||||||
|
case ActionTypes.SetDataSourceTypeSearchQuery:
|
||||||
|
return { ...state, dataSourceTypeSearchQuery: action.payload };
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
|
@@ -6,6 +6,14 @@ export const getDataSources = state => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getDataSourceTypes = state => {
|
||||||
|
const regex = new RegExp(state.dataSourceTypeSearchQuery, 'i');
|
||||||
|
|
||||||
|
return state.dataSourceTypes.filter(type => {
|
||||||
|
return regex.test(type.name);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const getDataSourcesSearchQuery = state => state.searchQuery;
|
export const getDataSourcesSearchQuery = state => state.searchQuery;
|
||||||
export const getDataSourcesLayoutMode = state => state.layoutMode;
|
export const getDataSourcesLayoutMode = state => state.layoutMode;
|
||||||
export const getDataSourcesCount = state => state.dataSourcesCount;
|
export const getDataSourcesCount = state => state.dataSourcesCount;
|
||||||
|
@@ -21,6 +21,7 @@ export interface DataSource {
|
|||||||
export interface DataSourcesState {
|
export interface DataSourcesState {
|
||||||
dataSources: DataSource[];
|
dataSources: DataSource[];
|
||||||
searchQuery: string;
|
searchQuery: string;
|
||||||
|
dataSourceTypeSearchQuery: string;
|
||||||
layoutMode: LayoutMode;
|
layoutMode: LayoutMode;
|
||||||
dataSourcesCount: number;
|
dataSourcesCount: number;
|
||||||
dataSourceTypes: Plugin[];
|
dataSourceTypes: Plugin[];
|
||||||
|
@@ -1,13 +1,27 @@
|
|||||||
.add-data-source-header {
|
.add-data-source-header {
|
||||||
margin-bottom: 20px;
|
margin-bottom: $panel-margin * 2;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.add-data-source-search {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: $panel-margin * 6;
|
||||||
|
}
|
||||||
|
|
||||||
.add-data-source-grid {
|
.add-data-source-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
grid-row-gap: 10px;
|
grid-row-gap: 10px;
|
||||||
grid-column-gap: 10px;
|
grid-column-gap: 10px;
|
||||||
|
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(lg) {
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-data-source-grid-item {
|
.add-data-source-grid-item {
|
||||||
|
Reference in New Issue
Block a user