Added testing state in reducer

This commit is contained in:
Peter Holmberg
2018-11-07 15:38:53 +01:00
parent e25b2d0ab6
commit b7d494551c
7 changed files with 122 additions and 15 deletions

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { shallow } from 'enzyme';
import { DataSourceSettings, Props } from './DataSourceSettings';
import { DataSource, NavModel } from '../../../types';
import { DataSource, DataSourceTest, NavModel } from '../../../types';
import { getMockDataSource } from '../__mocks__/dataSourcesMocks';
import { getMockPlugin } from '../../plugins/__mocks__/pluginMocks';
@@ -15,6 +15,7 @@ const setup = (propOverrides?: object) => {
loadDataSource: jest.fn(),
setDataSourceName: jest.fn(),
updateDataSource: jest.fn(),
testing: {} as DataSourceTest,
};
Object.assign(props, propOverrides);

View File

@@ -1,7 +1,7 @@
import React, { PureComponent } from 'react';
import { hot } from 'react-hot-loader';
import { connect } from 'react-redux';
import { DataSource, NavModel, Plugin } from 'app/types/';
import { DataSource, DataSourceTest, NavModel, Plugin } from 'app/types/';
import PageHeader from '../../../core/components/PageHeader/PageHeader';
import PageLoader from '../../../core/components/PageLoader/PageLoader';
import PluginSettings from './PluginSettings';
@@ -18,6 +18,7 @@ export interface Props {
dataSource: DataSource;
dataSourceMeta: Plugin;
pageId: number;
testing: DataSourceTest;
deleteDataSource: typeof deleteDataSource;
loadDataSource: typeof loadDataSource;
setDataSourceName: typeof setDataSourceName;
@@ -111,7 +112,7 @@ export class DataSourceSettings extends PureComponent<Props, State> {
}
render() {
const { dataSource, dataSourceMeta, navModel } = this.props;
const { dataSource, dataSourceMeta, navModel, testing } = this.props;
return (
<div>
@@ -137,6 +138,30 @@ export class DataSourceSettings extends PureComponent<Props, State> {
onModelChange={this.onModelChange}
/>
)}
<div className="gf-form-group section">
{testing.inProgress && (
<h5>
Testing.... <i className="fa fa-spiner fa-spin" />
</h5>
)}
{!testing.inProgress &&
testing.status && (
<div className={`alert-${testing.status} alert`}>
<div className="alert-icon">
{testing.status === 'error' ? (
<i className="fa fa-exclamation-triangle" />
) : (
<i className="fa fa-check" />
)}
</div>
<div className="alert-body">
<div className="alert-title">{testing.message}</div>
</div>
</div>
)}
</div>
<ButtonRow
onSubmit={event => this.onSubmit(event)}
isReadOnly={this.isReadOnly()}
@@ -160,6 +185,7 @@ function mapStateToProps(state) {
dataSource: getDataSource(state.dataSources, pageId),
dataSourceMeta: getDataSourceMeta(state.dataSources, dataSource.type),
pageId: pageId,
testing: state.dataSources.testing,
};
}

View File

@@ -79,6 +79,9 @@ exports[`Render should render alpha info text 1`] = `
}
onModelChange={[Function]}
/>
<div
className="gf-form-group section"
/>
<ButtonRow
isReadOnly={false}
onDelete={[Function]}
@@ -169,6 +172,9 @@ exports[`Render should render beta info text 1`] = `
}
onModelChange={[Function]}
/>
<div
className="gf-form-group section"
/>
<ButtonRow
isReadOnly={false}
onDelete={[Function]}
@@ -254,6 +260,9 @@ exports[`Render should render component 1`] = `
}
onModelChange={[Function]}
/>
<div
className="gf-form-group section"
/>
<ButtonRow
isReadOnly={false}
onDelete={[Function]}
@@ -344,6 +353,9 @@ exports[`Render should render is ready only message 1`] = `
}
onModelChange={[Function]}
/>
<div
className="gf-form-group section"
/>
<ButtonRow
isReadOnly={true}
onDelete={[Function]}

View File

@@ -18,6 +18,9 @@ export enum ActionTypes {
SetDataSourcesLayoutMode = 'SET_DATA_SOURCES_LAYOUT_MODE',
SetDataSourceTypeSearchQuery = 'SET_DATA_SOURCE_TYPE_SEARCH_QUERY',
SetDataSourceName = 'SET_DATA_SOURCE_NAME',
SetDataSourceTestingProgess = 'SET_TESTING_PROGRESS',
SetDataSourceTestingSuccess = 'SET_DATA_SOURCE_TESTING_SUCCESS',
SetDataSourceTestingFail = 'SET_DATA_SOURCE_TESTING_FAIL',
}
interface LoadDataSourcesAction {
@@ -60,6 +63,21 @@ interface SetDataSourceNameAction {
payload: string;
}
interface SetDataSourceTestingProgessAction {
type: ActionTypes.SetDataSourceTestingProgess;
payload: boolean;
}
interface SetDataSourceTestingSuccessAction {
type: ActionTypes.SetDataSourceTestingSuccess;
payload: { status: string; message: string };
}
interface SetDataSourceTestingFailAction {
type: ActionTypes.SetDataSourceTestingFail;
payload: string;
}
const dataSourcesLoaded = (dataSources: DataSource[]): LoadDataSourcesAction => ({
type: ActionTypes.LoadDataSources,
payload: dataSources,
@@ -100,6 +118,24 @@ export const setDataSourceName = (name: string) => ({
payload: name,
});
const setDataSourceTestingProgress = (state: boolean): SetDataSourceTestingProgessAction => ({
type: ActionTypes.SetDataSourceTestingProgess,
payload: state,
});
const setDataSourceTestingSuccess = (status: string, message: string): SetDataSourceTestingSuccessAction => ({
type: ActionTypes.SetDataSourceTestingSuccess,
payload: {
status: status,
message: message,
},
});
const setDataSourceTestingFail = (message: string): SetDataSourceTestingFailAction => ({
type: ActionTypes.SetDataSourceTestingFail,
payload: message,
});
export type Action =
| LoadDataSourcesAction
| SetDataSourcesSearchQueryAction
@@ -110,7 +146,10 @@ export type Action =
| LoadDataSourceAction
| UpdateNavIndexAction
| LoadDataSourceMetaAction
| SetDataSourceNameAction;
| SetDataSourceNameAction
| SetDataSourceTestingProgessAction
| SetDataSourceTestingSuccessAction
| SetDataSourceTestingFailAction;
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, Action>;
@@ -166,7 +205,7 @@ export function updateDataSource(dataSource: DataSource): ThunkResult<void> {
.put(`/api/datasources/${dataSource.id}`, dataSource)
.then(response => {
updateFrontendSettings().then(() => {
testDataSource(response.name);
testDataSource(dispatch, response.name);
});
});
@@ -221,7 +260,8 @@ function updateFrontendSettings() {
});
}
function testDataSource(name) {
function testDataSource(dispatch, name) {
dispatch(setDataSourceTestingProgress(true));
getDatasourceSrv()
.get(name)
.then(dataSource => {
@@ -229,27 +269,27 @@ function testDataSource(name) {
return;
}
const testing = { done: false, status: 'error', message: '' };
// make test call in no backend cache context
getBackendSrv()
.withNoBackendCache(() => {
return dataSource
.testDatasource()
.then(result => {
testing.message = result.message;
testing.status = result.status;
dispatch(setDataSourceTestingSuccess(result.status, result.message));
})
.catch(err => {
let message = '';
if (err.statusText) {
testing.message = 'HTTP Error ' + err.statusText;
message = 'HTTP Error ' + err.statusText;
} else {
testing.message = err.message;
message = err.message;
}
dispatch(setDataSourceTestingFail(message));
});
})
.finally(() => {
testing.done = true;
dispatch(setDataSourceTestingProgress(false));
});
});
}

View File

@@ -1,4 +1,4 @@
import { DataSource, DataSourcesState, Plugin } from 'app/types';
import { DataSource, DataSourcesState, DataSourceTest, Plugin } from 'app/types';
import { Action, ActionTypes } from './actions';
import { LayoutModes } from '../../../core/components/LayoutSelector/LayoutSelector';
@@ -12,6 +12,7 @@ const initialState: DataSourcesState = {
dataSourceTypeSearchQuery: '',
hasFetched: false,
dataSourceMeta: {} as Plugin,
testing: {} as DataSourceTest,
};
export const dataSourcesReducer = (state = initialState, action: Action): DataSourcesState => {
@@ -39,6 +40,25 @@ export const dataSourcesReducer = (state = initialState, action: Action): DataSo
case ActionTypes.SetDataSourceName:
return { ...state, dataSource: { ...state.dataSource, name: action.payload } };
case ActionTypes.SetDataSourceTestingProgess:
return { ...state, testing: { ...state.testing, inProgress: action.payload } };
case ActionTypes.SetDataSourceTestingSuccess:
return {
...state,
testing: {
status: action.payload.status,
message: action.payload.message,
inProgress: false,
},
};
case ActionTypes.SetDataSourceTestingFail:
return {
...state,
testing: { status: 'error', message: action.payload, inProgress: false },
};
}
return state;