Commit eadf3240 by Shavonn Brown Committed by Torkel Ödegaard

InfluxDB: convert config editor to react (#20282)

* convert config editor to react

* tests and some cleanup

* test

* snaps

* updating per comments

* remove anonymous funcs, remove config from state

* remove unecessaries
parent de9ea829
import React from 'react';
import { shallow } from 'enzyme';
import ConfigEditor, { Props } from './ConfigEditor';
const setup = (propOverrides?: object) => {
const props: Props = {
options: {
id: 21,
orgId: 1,
name: 'InfluxDB-3',
type: 'influxdb',
typeLogoUrl: '',
access: 'proxy',
url: '',
password: '',
user: '',
database: '',
basicAuth: false,
basicAuthUser: '',
basicAuthPassword: '',
withCredentials: false,
isDefault: false,
jsonData: {
httpMode: 'POST',
timeInterval: '4',
},
secureJsonFields: {},
version: 1,
readOnly: false,
},
onOptionsChange: jest.fn(),
};
Object.assign(props, propOverrides);
return shallow(<ConfigEditor {...props} />);
};
describe('Render', () => {
it('should render component', () => {
const wrapper = setup();
expect(wrapper).toMatchSnapshot();
});
it('should disable basic auth password input', () => {
const wrapper = setup({
secureJsonFields: {
basicAuthPassword: true,
},
});
expect(wrapper).toMatchSnapshot();
});
it('should hide white listed cookies input when browser access chosen', () => {
const wrapper = setup({
access: 'direct',
});
expect(wrapper).toMatchSnapshot();
});
it('should hide basic auth fields when switch off', () => {
const wrapper = setup({
basicAuth: false,
});
expect(wrapper).toMatchSnapshot();
});
});
import React, { PureComponent, ChangeEvent } from 'react';
import { DataSourcePluginOptionsEditorProps, SelectableValue } from '@grafana/data';
import { DataSourceHttpSettings, FormLabel, Input, SecretFormField, Select } from '@grafana/ui';
import { InfluxOptions, InfluxSecureJsonData } from '../types';
const httpModes = [{ label: 'GET', value: 'GET' }, { label: 'POST', value: 'POST' }] as SelectableValue[];
export type Props = DataSourcePluginOptionsEditorProps<InfluxOptions>;
export class ConfigEditor extends PureComponent<Props> {
onDatabaseChange = (event: ChangeEvent<HTMLInputElement>) => {
const { onOptionsChange, options } = this.props;
onOptionsChange({
...options,
database: event.target.value,
});
};
onUserChange = (event: ChangeEvent<HTMLInputElement>) => {
const { onOptionsChange, options } = this.props;
onOptionsChange({
...options,
user: event.target.value,
});
};
onPasswordChange = (event: ChangeEvent<HTMLInputElement>) => {
const { onOptionsChange, options } = this.props;
onOptionsChange({
...options,
secureJsonData: {
...options.secureJsonData,
password: event.target.value,
},
});
};
onTimeIntervalChange = (event: ChangeEvent<HTMLInputElement>) => {
const { onOptionsChange, options } = this.props;
onOptionsChange({
...options,
jsonData: {
...options.jsonData,
timeInterval: event.target.value,
},
});
};
onResetPassword = () => {
const { onOptionsChange, options } = this.props;
onOptionsChange({
...options,
secureJsonFields: {
...options.secureJsonFields,
password: false,
},
secureJsonData: {
...options.secureJsonData,
password: '',
},
});
};
onHttpModeSelect = (httpMode: SelectableValue) => {
const { onOptionsChange, options } = this.props;
onOptionsChange({
...options,
jsonData: {
...options.jsonData,
httpMode: httpMode.value,
},
});
};
render() {
const { options, onOptionsChange } = this.props;
const { secureJsonFields } = options;
const secureJsonData = (options.secureJsonData || {}) as InfluxSecureJsonData;
return (
<>
<DataSourceHttpSettings
showAccessOptions={true}
dataSourceConfig={options}
defaultUrl="http://localhost:8086"
onChange={onOptionsChange}
/>
<h3 className="page-heading">InfluxDB Details</h3>
<div className="gf-form-group">
<div className="gf-form-inline">
<div className="gf-form">
<FormLabel className="width-10">Database</FormLabel>
<div className="width-20">
<Input className="width-20" value={options.database || ''} onChange={this.onDatabaseChange} />
</div>
</div>
</div>
<div className="gf-form-inline">
<div className="gf-form">
<FormLabel className="width-10">User</FormLabel>
<div className="width-10">
<Input className="width-20" value={options.user || ''} onChange={this.onUserChange} />
</div>
</div>
</div>
<div className="gf-form-inline">
<div className="gf-form">
<SecretFormField
isConfigured={(secureJsonFields && secureJsonFields.password) as boolean}
value={secureJsonData.password || ''}
label="Password"
labelWidth={10}
inputWidth={20}
onReset={this.onResetPassword}
onChange={this.onPasswordChange}
/>
</div>
</div>
<div className="gf-form-inline">
<div className="gf-form">
<FormLabel
className="width-10"
tooltip="You can use either GET or POST HTTP method to query your InfluxDB database. The POST
method allows you to perform heavy requests (with a lots of WHERE clause) while the GET method
will restrict you and return an error if the query is too large."
>
HTTP Method
</FormLabel>
<Select
className="width-10"
value={httpModes.find(httpMode => httpMode.value === options.jsonData.httpMode)}
options={httpModes}
defaultValue={options.jsonData.httpMode}
onChange={this.onHttpModeSelect}
/>
</div>
</div>
</div>
<div className="gf-form-group">
<div className="grafana-info-box">
<h5>Database Access</h5>
<p>
Setting the database for this datasource does not deny access to other databases. The InfluxDB query
syntax allows switching the database in the query. For example:
<code>SHOW MEASUREMENTS ON _internal</code> or <code>SELECT * FROM "_internal".."database" LIMIT 10</code>
<br />
<br />
To support data isolation and security, make sure appropriate permissions are configured in InfluxDB.
</p>
</div>
</div>
<div className="gf-form-group">
<div className="gf-form-inline">
<div className="gf-form">
<FormLabel
className="width-10"
tooltip="A lower limit for the auto group by time interval. Recommended to be set to write frequency,
for example 1m if your data is written every minute."
>
Min time interval
</FormLabel>
<div className="width-10">
<Input
className="width-10"
placeholder="10s"
value={options.jsonData.timeInterval || ''}
onChange={this.onTimeIntervalChange}
/>
</div>
</div>
</div>
</div>
</>
);
}
}
export default ConfigEditor;
......@@ -2,35 +2,15 @@ import InfluxDatasource from './datasource';
import { InfluxQueryCtrl } from './query_ctrl';
import { InfluxLogsQueryField } from './components/InfluxLogsQueryField';
import InfluxStartPage from './components/InfluxStartPage';
import {
createChangeHandler,
createResetHandler,
PasswordFieldEnum,
} from '../../../features/datasources/utils/passwordHandlers';
import { DataSourcePlugin } from '@grafana/data';
class InfluxConfigCtrl {
static templateUrl = 'partials/config.html';
current: any;
onPasswordReset: ReturnType<typeof createResetHandler>;
onPasswordChange: ReturnType<typeof createChangeHandler>;
constructor() {
this.onPasswordReset = createResetHandler(this, PasswordFieldEnum.Password);
this.onPasswordChange = createChangeHandler(this, PasswordFieldEnum.Password);
this.current.jsonData.httpMode = this.current.jsonData.httpMode || 'GET';
}
httpMode = [{ name: 'GET', value: 'GET' }, { name: 'POST', value: 'POST' }];
}
import ConfigEditor from './components/ConfigEditor';
class InfluxAnnotationsQueryCtrl {
static templateUrl = 'partials/annotations.editor.html';
}
export const plugin = new DataSourcePlugin(InfluxDatasource)
.setConfigCtrl(InfluxConfigCtrl)
.setConfigEditor(ConfigEditor)
.setQueryCtrl(InfluxQueryCtrl)
.setAnnotationQueryCtrl(InfluxAnnotationsQueryCtrl)
.setExploreLogsQueryField(InfluxLogsQueryField)
......
<datasource-http-settings current="ctrl.current" suggest-url="http://localhost:8086">
</datasource-http-settings>
<h3 class="page-heading">InfluxDB Details</h3>
<div class="gf-form-group">
<div class="gf-form-inline">
<div class="gf-form max-width-30">
<span class="gf-form-label width-10">Database</span>
<input type="text" class="gf-form-input" ng-model='ctrl.current.database' placeholder="" required></input>
</div>
</div>
<div class="gf-form-inline">
<div class="gf-form max-width-15">
<span class="gf-form-label width-10">User</span>
<input type="text" class="gf-form-input" ng-model='ctrl.current.user' placeholder=""></input>
</div>
<div class="gf-form">
<secret-form-field
isConfigured="ctrl.current.password || ctrl.current.secureJsonFields.password"
value="ctrl.current.secureJsonData.password || ''"
on-reset="ctrl.onPasswordReset"
on-change="ctrl.onPasswordChange"
inputWidth="9"
/>
</div>
</div>
<div class="gf-form">
<label class="gf-form-label width-8">HTTP Method</label>
<div class="gf-form-select-wrapper width-8 gf-form-select-wrapper--has-help-icon">
<select class="gf-form-input" ng-model="ctrl.current.jsonData.httpMode" ng-options="f.value as f.name for f in ctrl.httpMode"></select>
<info-popover mode="right-absolute">
You can use either <code>GET</code> or <code>POST</code> HTTP method to query your InfluxDB database. The <code>POST</code>
method allows you to perform heavy requests (with a lots of <code>WHERE</code> clause) while the <code>GET</code> method
will restrict you and return an error if the query is too large.
</info-popover>
</div>
</div>
</div>
<div class="gf-form-group">
<div class="grafana-info-box">
<h5>Database Access</h5>
<p>
Setting the database for this datasource does not deny access to other databases. The InfluxDB query syntax allows
switching the database in the query. For example:
<code>SHOW MEASUREMENTS ON _internal</code> or <code>SELECT * FROM "_internal".."database" LIMIT 10</code>
<br/><br/>
To support data isolation and security, make sure appropriate permissions are configured in InfluxDB.
</p>
</div>
</div>
<div class="gf-form-group">
<div class="gf-form-inline">
<div class="gf-form">
<span class="gf-form-label">Min time interval</span>
<input type="text" class="gf-form-input width-6 gf-form-input--has-help-icon" ng-model="ctrl.current.jsonData.timeInterval" spellcheck='false' placeholder="10s"></input>
<info-popover mode="right-absolute">
A lower limit for the auto group by time interval. Recommended to be set to write frequency,
for example <code>1m</code> if your data is written every minute.
</info-popover>
</div>
</div>
</div>
......@@ -5,6 +5,10 @@ export interface InfluxOptions extends DataSourceJsonData {
httpMode: string;
}
export interface InfluxSecureJsonData {
password?: string;
}
export interface InfluxQueryPart {
type: string;
params?: string[];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment