grafana/public/app/features/datasources/settings/DataSourceSettingsPage.tsx

256 lines
7.3 KiB
TypeScript
Raw Normal View History

// Libraries
2018-10-30 10:40:08 -05:00
import React, { PureComponent } from 'react';
import { hot } from 'react-hot-loader';
import { connect } from 'react-redux';
// Components
import PageHeader from 'app/core/components/PageHeader/PageHeader';
import PageLoader from 'app/core/components/PageLoader/PageLoader';
2018-10-31 07:23:05 -05:00
import PluginSettings from './PluginSettings';
import BasicSettings from './BasicSettings';
import ButtonRow from './ButtonRow';
// Services & Utils
import appEvents from 'app/core/app_events';
import { getBackendSrv } from 'app/core/services/backend_srv';
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
// Actions & selectors
2018-10-31 07:23:05 -05:00
import { getDataSource, getDataSourceMeta } from '../state/selectors';
2018-12-05 04:47:02 -06:00
import { deleteDataSource, loadDataSource, setDataSourceName, setIsDefault, updateDataSource } from '../state/actions';
import { getNavModel } from 'app/core/selectors/navModel';
import { getRouteParamsId } from 'app/core/selectors/location';
// Types
import { NavModel, Plugin } from 'app/types/';
import { DataSourceSettings } from '@grafana/ui/src/types/';
2018-11-08 02:34:14 -06:00
import { getDataSourceLoadingNav } from '../state/navModel';
export interface Props {
2018-10-24 09:17:25 -05:00
navModel: NavModel;
dataSource: DataSourceSettings;
dataSourceMeta: Plugin;
2018-10-24 09:17:25 -05:00
pageId: number;
2018-10-31 08:28:16 -05:00
deleteDataSource: typeof deleteDataSource;
2018-10-24 09:17:25 -05:00
loadDataSource: typeof loadDataSource;
2018-10-30 10:40:08 -05:00
setDataSourceName: typeof setDataSourceName;
2018-10-31 08:28:16 -05:00
updateDataSource: typeof updateDataSource;
2018-12-05 04:47:02 -06:00
setIsDefault: typeof setIsDefault;
}
interface State {
dataSource: DataSourceSettings;
isTesting?: boolean;
testingMessage?: string;
testingStatus?: string;
}
enum DataSourceStates {
Alpha = 'alpha',
Beta = 'beta',
}
export class DataSourceSettingsPage extends PureComponent<Props, State> {
constructor(props) {
super(props);
this.state = {
dataSource: {} as DataSourceSettings,
};
}
2018-11-01 05:19:40 -05:00
2018-10-24 09:17:25 -05:00
async componentDidMount() {
const { loadDataSource, pageId } = this.props;
await loadDataSource(pageId);
2018-10-16 02:59:03 -05:00
}
onSubmit = async event => {
event.preventDefault();
2018-10-31 08:28:16 -05:00
await this.props.updateDataSource({ ...this.state.dataSource, name: this.props.dataSource.name });
this.testDataSource();
2018-10-31 08:28:16 -05:00
};
onDelete = () => {
appEvents.emit('confirm-modal', {
title: 'Delete',
text: 'Are you sure you want to delete this data source?',
yesText: 'Delete',
icon: 'fa-trash',
onConfirm: () => {
this.confirmDelete();
},
});
};
2018-10-31 08:28:16 -05:00
confirmDelete = () => {
this.props.deleteDataSource();
};
2018-11-01 05:19:40 -05:00
onModelChange = dataSource => {
this.setState({
dataSource: dataSource,
});
};
2018-10-31 07:23:05 -05:00
isReadOnly() {
return this.props.dataSource.readOnly === true;
}
shouldRenderInfoBox() {
const { state } = this.props.dataSourceMeta;
return state === DataSourceStates.Alpha || state === DataSourceStates.Beta;
}
getInfoText() {
const { dataSourceMeta } = this.props;
switch (dataSourceMeta.state) {
case DataSourceStates.Alpha:
return (
'This plugin is marked as being in alpha state, which means it is in early development phase and updates' +
' will include breaking changes.'
);
case DataSourceStates.Beta:
return (
'This plugin is marked as being in a beta development state. This means it is in currently in active' +
' development and could be missing important features.'
);
}
return null;
}
2018-10-31 07:29:02 -05:00
renderIsReadOnlyMessage() {
return (
<div className="grafana-info-box span8">
This datasource was added by config and cannot be modified using the UI. Please contact your server admin to
update this datasource.
</div>
);
}
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() {
2018-12-05 04:47:02 -06:00
const { dataSource, dataSourceMeta, navModel, setDataSourceName, setIsDefault } = this.props;
const { testingMessage, testingStatus } = this.state;
2018-10-24 09:17:25 -05:00
return (
<div>
2018-10-30 10:40:08 -05:00
<PageHeader model={navModel} />
2018-10-31 07:29:02 -05:00
{Object.keys(dataSource).length === 0 ? (
2018-10-30 10:40:08 -05:00
<PageLoader pageName="Data source settings" />
) : (
<div className="page-container page-body">
<div>
<form onSubmit={this.onSubmit}>
2018-12-13 14:24:41 -06:00
{this.isReadOnly() && this.renderIsReadOnlyMessage()}
{this.shouldRenderInfoBox() && <div className="grafana-info-box">{this.getInfoText()}</div>}
2018-10-31 07:23:05 -05:00
<BasicSettings
2018-12-05 04:47:02 -06:00
dataSourceName={dataSource.name}
isDefault={dataSource.isDefault}
onDefaultChange={state => setIsDefault(state)}
onNameChange={name => setDataSourceName(name)}
2018-10-31 07:23:05 -05:00
/>
2018-10-30 10:40:08 -05:00
2018-11-01 05:19:40 -05:00
{dataSourceMeta.module && (
<PluginSettings
dataSource={dataSource}
dataSourceMeta={dataSourceMeta}
onModelChange={this.onModelChange}
/>
)}
2018-11-07 08:38:53 -06:00
<div className="gf-form-group section">
{testingMessage && (
<div className={`alert-${testingStatus} alert`}>
<div className="alert-icon">
{testingStatus === 'error' ? (
<i className="fa fa-exclamation-triangle" />
) : (
<i className="fa fa-check" />
)}
</div>
<div className="alert-body">
<div className="alert-title">{testingMessage}</div>
2018-11-07 08:38:53 -06:00
</div>
</div>
)}
2018-11-07 08:38:53 -06:00
</div>
2018-10-31 07:23:05 -05:00
<ButtonRow
onSubmit={event => this.onSubmit(event)}
isReadOnly={this.isReadOnly()}
2018-10-31 08:28:16 -05:00
onDelete={this.onDelete}
2018-10-31 07:23:05 -05:00
/>
2018-10-30 10:40:08 -05:00
</form>
</div>
</div>
2018-10-30 10:40:08 -05:00
)}
</div>
);
}
}
function mapStateToProps(state) {
2018-10-24 09:17:25 -05:00
const pageId = getRouteParamsId(state.location);
2018-10-31 07:23:05 -05:00
const dataSource = getDataSource(state.dataSources, pageId);
2018-10-24 09:17:25 -05:00
return {
2018-11-08 02:34:14 -06:00
navModel: getNavModel(state.navIndex, `datasource-settings-${pageId}`, getDataSourceLoadingNav('settings')),
2018-10-30 10:40:08 -05:00
dataSource: getDataSource(state.dataSources, pageId),
2018-10-31 07:23:05 -05:00
dataSourceMeta: getDataSourceMeta(state.dataSources, dataSource.type),
2018-10-24 09:17:25 -05:00
pageId: pageId,
};
}
2018-10-24 09:17:25 -05:00
const mapDispatchToProps = {
2018-10-31 08:28:16 -05:00
deleteDataSource,
2018-10-24 09:17:25 -05:00
loadDataSource,
2018-10-30 10:40:08 -05:00
setDataSourceName,
2018-10-31 08:28:16 -05:00
updateDataSource,
2018-12-05 04:47:02 -06:00
setIsDefault,
2018-10-24 09:17:25 -05:00
};
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(DataSourceSettingsPage));