diff --git a/public/app/features/datasources/settings/DataSourceSettings.test.tsx b/public/app/features/datasources/settings/DataSourceSettings.test.tsx index 222587d9249..73c05fdd518 100644 --- a/public/app/features/datasources/settings/DataSourceSettings.test.tsx +++ b/public/app/features/datasources/settings/DataSourceSettings.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { DataSourceSettings, Props } from './DataSourceSettings'; -import { DataSource, DataSourceTest, NavModel } from '../../../types'; +import { DataSource, NavModel } from '../../../types'; import { getMockDataSource } from '../__mocks__/dataSourcesMocks'; import { getMockPlugin } from '../../plugins/__mocks__/pluginMocks'; @@ -15,8 +15,6 @@ const setup = (propOverrides?: object) => { loadDataSource: jest.fn(), setDataSourceName: jest.fn(), updateDataSource: jest.fn(), - testing: {} as DataSourceTest, - clearTesting: jest.fn(), }; Object.assign(props, propOverrides); diff --git a/public/app/features/datasources/settings/DataSourceSettings.tsx b/public/app/features/datasources/settings/DataSourceSettings.tsx index e9a1b49c02a..e816c0231f0 100644 --- a/public/app/features/datasources/settings/DataSourceSettings.tsx +++ b/public/app/features/datasources/settings/DataSourceSettings.tsx @@ -1,33 +1,40 @@ import React, { PureComponent } from 'react'; import { hot } from 'react-hot-loader'; import { connect } from 'react-redux'; -import { DataSource, DataSourceTest, NavModel, Plugin } from 'app/types/'; -import PageHeader from '../../../core/components/PageHeader/PageHeader'; -import PageLoader from '../../../core/components/PageLoader/PageLoader'; + +import PageHeader from 'app/core/components/PageHeader/PageHeader'; +import PageLoader from 'app/core/components/PageLoader/PageLoader'; import PluginSettings from './PluginSettings'; import BasicSettings from './BasicSettings'; import ButtonRow from './ButtonRow'; -import appEvents from '../../../core/app_events'; -import { clearTesting, deleteDataSource, loadDataSource, setDataSourceName, updateDataSource } from '../state/actions'; -import { getNavModel } from '../../../core/selectors/navModel'; -import { getRouteParamsId } from '../../../core/selectors/location'; + +import appEvents from 'app/core/app_events'; +import { getBackendSrv } from 'app/core/services/backend_srv'; +import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; + import { getDataSource, getDataSourceMeta } from '../state/selectors'; +import { deleteDataSource, loadDataSource, setDataSourceName, updateDataSource } from '../state/actions'; +import { getNavModel } from 'app/core/selectors/navModel'; +import { getRouteParamsId } from 'app/core/selectors/location'; + +import { DataSource, NavModel, Plugin } from 'app/types/'; export interface Props { navModel: NavModel; dataSource: DataSource; dataSourceMeta: Plugin; pageId: number; - testing: DataSourceTest; deleteDataSource: typeof deleteDataSource; loadDataSource: typeof loadDataSource; setDataSourceName: typeof setDataSourceName; updateDataSource: typeof updateDataSource; - clearTesting: typeof clearTesting; } + interface State { dataSource: DataSource; - hasClosedTest: boolean; + isTesting?: boolean; + testingMessage?: string; + testingStatus?: string; } enum DataSourceStates { @@ -36,10 +43,13 @@ enum DataSourceStates { } export class DataSourceSettings extends PureComponent { - state = { - dataSource: {} as DataSource, - hasClosedTest: false, - }; + constructor(props) { + super(props); + + this.state = { + dataSource: {} as DataSource, + }; + } async componentDidMount() { const { loadDataSource, pageId } = this.props; @@ -47,27 +57,12 @@ export class DataSourceSettings extends PureComponent { await loadDataSource(pageId); } - componentDidUpdate(prevProps) { - const { clearTesting } = this.props; - - if (!this.state.hasClosedTest && prevProps.testing.status === 'success') { - this.setState({ hasClosedTest: true }); - - setTimeout(() => { - clearTesting(); - this.setState({ hasClosedTest: false }); - }, 3000); - } - } - - componentWillUnmount() { - this.props.clearTesting(); - } - - onSubmit = event => { + onSubmit = async event => { event.preventDefault(); - this.props.updateDataSource({ ...this.state.dataSource, name: this.props.dataSource.name }); + await this.props.updateDataSource({ ...this.state.dataSource, name: this.props.dataSource.name }); + + this.testDataSource(); }; onDelete = () => { @@ -131,8 +126,45 @@ export class DataSourceSettings extends PureComponent { ); } + async testDataSource() { + const dsApi = await getDatasourceSrv().get(this.state.dataSource.name); + + if (!dsApi.testDatasource) { + return; + } + + this.setState({ isTesting: true, testingMessage: 'Testing...', testingStatus: 'info' }); + + getBackendSrv().withNoBackendCache(async () => { + try { + const result = await dsApi.testDatasource(); + + this.setState({ + isTesting: false, + testingStatus: result.status, + testingMessage: result.message, + }); + } catch (err) { + let message = ''; + + if (err.statusText) { + message = 'HTTP Error ' + err.statusText; + } else { + message = err.message; + } + + this.setState({ + isTesting: false, + testingStatus: 'error', + testingMessage: message, + }); + } + }); + } + render() { - const { dataSource, dataSourceMeta, navModel, testing } = this.props; + const { dataSource, dataSourceMeta, navModel } = this.props; + const { testingMessage, testingStatus } = this.state; return (
@@ -160,26 +192,20 @@ export class DataSourceSettings extends PureComponent { )}
- {testing.inProgress && ( -
- Testing.... -
- )} - {!testing.inProgress && - testing.status && ( -
-
- {testing.status === 'error' ? ( - - ) : ( - - )} -
-
-
{testing.message}
-
+ {testingMessage && ( +
+
+ {testingStatus === 'error' ? ( + + ) : ( + + )} +
+
+
{testingMessage}
- )} +
+ )}
({ type: ActionTypes.LoadDataSources, payload: dataSources, @@ -123,28 +99,6 @@ export const setDataSourceName = (name: string) => ({ payload: name, }); -export const clearTesting = (): ClearTestingAction => ({ - type: ActionTypes.ClearTesting, -}); - -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 @@ -155,11 +109,7 @@ export type Action = | LoadDataSourceAction | UpdateNavIndexAction | LoadDataSourceMetaAction - | SetDataSourceNameAction - | SetDataSourceTestingProgessAction - | SetDataSourceTestingSuccessAction - | SetDataSourceTestingFailAction - | ClearTestingAction; + | SetDataSourceNameAction; type ThunkResult = ThunkAction; @@ -211,15 +161,9 @@ export function loadDataSourceTypes(): ThunkResult { export function updateDataSource(dataSource: DataSource): ThunkResult { return async dispatch => { - await getBackendSrv() - .put(`/api/datasources/${dataSource.id}`, dataSource) - .then(response => { - updateFrontendSettings().then(() => { - testDataSource(dispatch, response.name); - }); - }); - - dispatch(loadDataSource(dataSource.id)); + await getBackendSrv().put(`/api/datasources/${dataSource.id}`, dataSource); + await updateFrontendSettings(); + return dispatch(loadDataSource(dataSource.id)); }; } @@ -270,40 +214,6 @@ function updateFrontendSettings() { }); } -function testDataSource(dispatch, name) { - dispatch(setDataSourceTestingProgress(true)); - getDatasourceSrv() - .get(name) - .then(dataSource => { - if (!dataSource.testDatasource) { - return; - } - - // make test call in no backend cache context - getBackendSrv() - .withNoBackendCache(() => { - return dataSource - .testDatasource() - .then(result => { - dispatch(setDataSourceTestingSuccess(result.status, result.message)); - }) - .catch(err => { - let message = ''; - - if (err.statusText) { - message = 'HTTP Error ' + err.statusText; - } else { - message = err.message; - } - dispatch(setDataSourceTestingFail(message)); - }); - }) - .finally(() => { - dispatch(setDataSourceTestingProgress(false)); - }); - }); -} - function nameHasSuffix(name) { return name.endsWith('-', name.length - 1); } diff --git a/public/app/features/datasources/state/reducers.ts b/public/app/features/datasources/state/reducers.ts index 2fc6500e522..33feae6770a 100644 --- a/public/app/features/datasources/state/reducers.ts +++ b/public/app/features/datasources/state/reducers.ts @@ -12,7 +12,6 @@ const initialState: DataSourcesState = { dataSourceTypeSearchQuery: '', hasFetched: false, dataSourceMeta: {} as Plugin, - testing: { inProgress: false, status: '', message: '' }, }; export const dataSourcesReducer = (state = initialState, action: Action): DataSourcesState => { @@ -40,28 +39,6 @@ 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 }, - }; - - case ActionTypes.ClearTesting: - return { ...state, testing: { inProgress: false, status: '', message: '' } }; } return state; diff --git a/public/app/plugins/datasource/cloudwatch/datasource.ts b/public/app/plugins/datasource/cloudwatch/datasource.ts index 3eb8eff2d09..d9fb3450524 100644 --- a/public/app/plugins/datasource/cloudwatch/datasource.ts +++ b/public/app/plugins/datasource/cloudwatch/datasource.ts @@ -362,14 +362,9 @@ export default class CloudWatchDatasource { const metricName = 'EstimatedCharges'; const dimensions = {}; - return this.getDimensionValues(region, namespace, metricName, 'ServiceName', dimensions).then( - () => { - return { status: 'success', message: 'Data source is working' }; - }, - err => { - return { status: 'error', message: err.message }; - } - ); + return this.getDimensionValues(region, namespace, metricName, 'ServiceName', dimensions).then(() => { + return { status: 'success', message: 'Data source is working' }; + }); } awsRequest(url, data) { diff --git a/public/app/types/datasources.ts b/public/app/types/datasources.ts index ef6077ffc20..970ef4f11c8 100644 --- a/public/app/types/datasources.ts +++ b/public/app/types/datasources.ts @@ -25,12 +25,6 @@ export interface DataSource { testDatasource?: () => Promise; } -export interface DataSourceTest { - inProgress: boolean; - message: string; - status: string; -} - export interface DataSourcesState { dataSources: DataSource[]; searchQuery: string; @@ -41,5 +35,4 @@ export interface DataSourcesState { dataSource: DataSource; dataSourceMeta: Plugin; hasFetched: boolean; - testing: DataSourceTest; } diff --git a/public/app/types/index.ts b/public/app/types/index.ts index 013c132a94f..fc176fed7e2 100644 --- a/public/app/types/index.ts +++ b/public/app/types/index.ts @@ -7,7 +7,7 @@ import { DashboardState } from './dashboard'; import { DashboardAcl, OrgRole, PermissionLevel } from './acl'; import { ApiKey, ApiKeysState, NewApiKey } from './apiKeys'; import { Invitee, OrgUser, User, UsersState, UserState } from './user'; -import { DataSource, DataSourceTest, DataSourcesState } from './datasources'; +import { DataSource, DataSourcesState } from './datasources'; import { TimeRange, LoadingState, @@ -88,7 +88,6 @@ export { AppNotificationTimeout, DashboardSearchHit, UserState, - DataSourceTest, }; export interface StoreState {