Commit e642fce4 by Peter Holmberg

created component for http settings

parent c5946ebd
import React, { SFC } from 'react';
interface Props {}
const InfoPopover: SFC<Props> = props => {
return <div />;
};
export default InfoPopover;
import React, { PureComponent } from 'react';
interface Props {
access: any;
basicAuth: any;
showAccessOption: any;
tlsAuth: any;
tlsAuthWithCACert: any;
tlsCACert: any;
tlsClientCert: any;
tlsClientKey: any;
url: any;
}
interface State {
basicAuthUser: string;
basicAuthPassword: string;
showAccessHelp: boolean;
}
export default class DataSourceHttpSettings extends PureComponent<Props, State> {
state = {
basicAuthUser: '',
basicAuthPassword: '',
showAccessHelp: false,
};
onToggleAccessHelp = () => {};
render() {
const {
access,
basicAuth,
showAccessOption,
tlsAuth,
tlsAuthWithCACert,
tlsCACert,
tlsClientCert,
tlsClientKey,
url,
} = this.props;
const { showAccessHelp, basicAuthUser, basicAuthPassword } = this.state;
// const accessOptions = [{key: 'proxy', value: 'Server (Default)'}, { key: 'direct', value: 'Browser'}];
return (
<div className="gf-form-group">
<h3 className="page-heading">HTTP</h3>
<div className="gf-form-group">
<div className="gf-form-inline">
<div className="gf-form max-width-30">
<span className="gf-form-label width-10">URL</span>
<input className="gf-form-input" type="text" value={url} placeholder="https://localhost:9090" />
</div>
</div>
{showAccessOption && (
<div className="gf-form-inline">
<div className="gf-form max-width-30">
<span className="gf-form-label width-10">Access</span>
<div className="gf-form-select-wrapper max-width-24" />
</div>
<div className="gf-form">
<label className="gf-form-label query-keyword pointer" onClick={this.onToggleAccessHelp}>
Help&nbsp;
{showAccessHelp && <i className="fa fa-caret-down" />}
{!showAccessHelp && <i className="fa fa-caret-right">&nbsp;</i>}
</label>
</div>
</div>
)}
{showAccessHelp && (
<div className="grafana-info-box m-t-2">
<p>
Access mode controls how requests to the data source will be handled.
<strong>
<i>Server</i>
</strong>{' '}
should be the preferred way if nothing else stated.
</p>
<div className="alert-title">Server access mode (Default):</div>
<p>
All requests will be made from the browser to Grafana backend/server which in turn will forward the
requests to the data source and by that circumvent possible Cross-Origin Resource Sharing (CORS)
requirements. The URL needs to be accessible from the grafana backend/server if you select this access
mode.
</p>
<div className="alert-title">Browser access mode:</div>
<p>
All requests will be made from the browser directly to the data source and may be subject to
Cross-Origin Resource Sharing (CORS) requirements. The URL needs to be accessible from the browser if
you select this access mode.
</p>
</div>
)}
{access === 'proxy' && (
<div className="gf-form-inline">
<div className="gf-form">
<span className="gf-form-label width-10">Whitelisted Cookies</span>
</div>
</div>
)}
<h3 className="page-heading">Auth</h3>
<div className="gf-form-group">
<div className="gf-form-inline" />
<div className="gf-form-inline" />
<div className="gf-form-inline" />
</div>
{basicAuth && (
<div className="gf-form-group">
<h6>Basic Auth Details</h6>
<div className="gf-form">
<span className="gf-form-label width-10">User</span>
<input className="gf-form-input max-width-21" type="text" value={basicAuthUser} placeholder="User" />
</div>
<div className="gf-form">
<span className="gf-form-label width-10">Password</span>
<input
className="gf-form-input max-width-21"
type="password"
value={basicAuthPassword}
placeholder="Password"
/>
</div>
</div>
)}
{(tlsAuth || tlsAuthWithCACert) &&
access === 'proxy' && (
<div className="gf-form-group">
<div className="gf-form">
<h6>TLS Auth Details</h6>
</div>
{tlsAuthWithCACert && (
<div>
<div className="gf-form-inline">
<div className="gf-form gf-form--v-stretch">
<label className="gf-form-label width-7">CA Cert</label>
</div>
{!tlsCACert && (
<div className="gf-form gf-form--grow">
<textarea
rows={7}
className="gf-form-input gf-form-textarea"
value={tlsCACert}
placeholder="Begins with -----BEGIN CERTIFICATE-----"
/>
</div>
)}
{tlsCACert && (
<div className="gf-form">
<input type="text" className="gf-form-input max-width-12" value="configured" />
<a className="btn btn-secondary gf-form-btn" href="#" onClick={() => {}}>
reset
</a>
</div>
)}
</div>
</div>
)}
{tlsAuth && (
<div>
<div className="gf-form-inline">
<div className="gf-form gf-form--v-stretch">
<label className="gf-form-label width-7">Client Cert</label>
</div>
{!tlsClientCert && (
<div className="gf-form gf-form--grow">
<textarea
rows={7}
className="gf-form-input gf-form-textarea"
value={tlsClientCert}
placeholder="Begins with -----BEGIN CERTIFICATE-----"
required
/>
</div>
)}
{tlsClientCert && (
<div className="gf-form">
<input type="text" className="gf-form-input max-width-12" value="configured" />
<a className="btn btn-secondary gf-form-btn" href="#" onClick={() => {}}>
reset
</a>
</div>
)}
</div>
<div className="gf-form-inline">
<div className="gf-form gf-form--v-stretch">
<label className="gf-form-label width-7">Client Key</label>
</div>
{tlsClientKey && (
<div className="gf-form gf-form--grow">
<textarea
rows={7}
className="gf-form-input gf-form-textarea"
value={tlsClientKey}
placeholder="Begins with -----BEGIN RSA PRIVATE KEY-----"
/>
</div>
)}
{tlsClientKey && (
<div className="gf-form">
<input type="text" className="gf-form-input max-width-12" value="configured" />
<a className="btn btn-secondary gf-form-btn" href="#" onClick={() => {}}>
reset
</a>
</div>
)}
</div>
</div>
)}
</div>
)}
</div>
</div>
);
}
}
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import { DataSource, Plugin } from 'app/types';
import DataSourceHttpSettings from './DataSourceHttpSettings';
export interface Props {
dataSource: DataSource;
......@@ -8,6 +9,7 @@ export interface Props {
}
interface State {
name: string;
showNamePopover: boolean;
}
enum DataSourceStates {
......@@ -16,13 +18,10 @@ enum DataSourceStates {
}
export class DataSourceSettings extends PureComponent<Props, State> {
constructor(props) {
super(props);
this.state = {
name: props.dataSource.name,
};
}
state = {
name: this.props.dataSource.name,
showNamePopover: false,
};
onNameChange = event => {
this.setState({
......@@ -39,6 +38,12 @@ export class DataSourceSettings extends PureComponent<Props, State> {
console.log(event);
};
onTogglePopover = () => {
this.setState(prevState => ({
showNamePopover: !prevState.showNamePopover,
}));
};
isReadyOnly() {
return this.props.dataSource.readOnly === true;
}
......@@ -70,11 +75,22 @@ export class DataSourceSettings extends PureComponent<Props, State> {
}
render() {
const { name } = this.state;
const { name, showNamePopover } = this.state;
const props = {
access: {},
basicAuth: {},
showAccessOption: {},
tlsAuth: {},
tlsAuthWithCACert: {},
tlsCACert: {},
tlsClientCert: {},
tlsClientKey: {},
url: {},
};
return (
<div>
<h3 className="page-sub-heading">Settings</h3>
<form onSubmit={this.onSubmit}>
<div className="gf-form-group">
<div className="gf-form-inline">
......@@ -84,10 +100,31 @@ export class DataSourceSettings extends PureComponent<Props, State> {
className="gf-form-input max-width-23"
type="text"
value={name}
placeholder="name"
placeholder="Name"
onChange={this.onNameChange}
required
/>
<div onClick={this.onTogglePopover}>
<i className="fa fa-info-circle" />
</div>
{showNamePopover && (
<div
style={{
position: 'absolute',
left: '450px',
top: '-20px',
padding: '10px',
backgroundColor: 'black',
zIndex: 2,
width: '300px',
border: '1px solid gray',
borderRadius: '3px',
}}
>
The name is used when you select the data source in panels. The <em>Default</em> data source is
preselected in new panels.
</div>
)}
</div>
</div>
</div>
......@@ -110,6 +147,7 @@ export class DataSourceSettings extends PureComponent<Props, State> {
</a>
</div>
</form>
<DataSourceHttpSettings {...props} />
</div>
);
}
......
import React from 'react';
import { shallow } from 'enzyme';
import { EditDataSourcePage, Props } from './EditDataSourcePage';
import { DataSource, NavModel } from '../../types';
const setup = (propOverrides?: object) => {
const props: Props = {
navModel: {} as NavModel,
dataSource: {} as DataSource,
dataSourceId: 1,
pageName: '',
loadDataSource: jest.fn(),
};
Object.assign(props, propOverrides);
const wrapper = shallow(<EditDataSourcePage {...props} />);
const instance = wrapper.instance() as EditDataSourcePage;
return {
wrapper,
instance,
};
};
describe('Render', () => {
it('should render component', () => {
const { wrapper } = setup();
expect(wrapper).toMatchSnapshot();
});
it('should render permissions page', () => {
const { wrapper } = setup({
pageName: 'permissions',
});
expect(wrapper).toMatchSnapshot();
});
});
describe('Functions', () => {
describe('is page valid', () => {
it('should be a valid page', () => {
const { instance } = setup();
expect(instance.isValidPage('permissions')).toBeTruthy();
});
it('should not be a valid page', () => {
const { instance } = setup();
expect(instance.isValidPage('asdf')).toBeFalsy();
});
});
describe('get current page', () => {
it('should return permissions', () => {
const { instance } = setup({
pageName: 'permissions',
});
expect(instance.getCurrentPage()).toEqual('permissions');
});
it('should return settings if bogus route', () => {
const { instance } = setup({
pageName: 'asdf',
});
expect(instance.getCurrentPage()).toEqual('settings');
});
});
});
......@@ -3,6 +3,7 @@ import { hot } from 'react-hot-loader';
import { connect } from 'react-redux';
import PageHeader from '../../core/components/PageHeader/PageHeader';
import DataSourcePermissions from './DataSourcePermissions';
import DataSourceSettings from './DataSourceSettings';
import { DataSource, NavModel } from 'app/types';
import { loadDataSource } from './state/actions';
import { getNavModel } from '../../core/selectors/navModel';
......@@ -24,6 +25,8 @@ enum PageTypes {
Dashboards = 'dashboards',
}
const fallBackPage = PageTypes.Settings;
export class EditDataSourcePage extends PureComponent<Props> {
componentDidMount() {
this.fetchDataSource();
......@@ -39,12 +42,13 @@ export class EditDataSourcePage extends PureComponent<Props> {
getCurrentPage() {
const currentPage = this.props.pageName;
return this.isValidPage(currentPage) ? currentPage : PageTypes.Permissions;
return this.isValidPage(currentPage) ? currentPage : fallBackPage;
}
renderPage() {
switch (this.getCurrentPage()) {
case PageTypes.Settings:
return <DataSourceSettings />;
case PageTypes.Permissions:
return <DataSourcePermissions />;
}
......@@ -65,7 +69,7 @@ export class EditDataSourcePage extends PureComponent<Props> {
}
function mapStateToProps(state) {
const pageName = getRouteParamsPage(state.location) || PageTypes.Permissions;
const pageName = getRouteParamsPage(state.location) || fallBackPage;
const dataSourceId = getRouteParamsId(state.location);
const dataSourceLoadingNav = getDataSourceLoadingNav(pageName);
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Render should render component 1`] = `
<div>
<PageHeader
model={Object {}}
/>
<div
className="page-container page-body"
>
<Connect(DataSourceSettings) />
</div>
</div>
`;
exports[`Render should render permissions page 1`] = `
<div>
<PageHeader
model={Object {}}
/>
<div
className="page-container page-body"
>
<Connect(DataSourcePermissions) />
</div>
</div>
`;
......@@ -73,11 +73,6 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
component: () => DataSourcesListPage,
},
})
.when('/datasources/edit/:id', {
templateUrl: 'public/app/features/plugins/partials/ds_edit.html',
controller: 'DataSourceEditCtrl',
controllerAs: 'ctrl',
})
.when('/datasources/edit/:id/dashboards', {
templateUrl: 'public/app/features/plugins/partials/ds_dashboards.html',
controller: 'DataSourceDashboardsCtrl',
......
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