diff --git a/ui/src/CheckDataNodes.js b/ui/src/CheckDataNodes.js index 86e79ed7a..beb9e7ac9 100644 --- a/ui/src/CheckDataNodes.js +++ b/ui/src/CheckDataNodes.js @@ -1,6 +1,6 @@ import React, {PropTypes} from 'react'; import {withRouter} from 'react-router'; -import {getSources} from 'src/shared/apis'; +import {getSources} from 'shared/apis'; const {bool, number, string, node, func, shape} = PropTypes; diff --git a/ui/src/index.js b/ui/src/index.js index 161e915a2..37e437161 100644 --- a/ui/src/index.js +++ b/ui/src/index.js @@ -13,7 +13,7 @@ import RetentionPoliciesPage from 'src/retention_policies'; import DataExplorer from 'src/chronograf'; import DatabaseManager from 'src/database_manager'; import SignUp from 'src/sign_up'; -import {CreateSource, ManageSources} from 'src/sources'; +import {CreateSource, SourceForm, ManageSources} from 'src/sources'; import {ClusterAccountsPage, ClusterAccountPage} from 'src/cluster_accounts'; import {RolesPageContainer, RolePageContainer} from 'src/access_control'; import NotFound from 'src/shared/components/NotFound'; @@ -100,6 +100,8 @@ const Root = React.createClass({ + + diff --git a/ui/src/shared/apis/index.js b/ui/src/shared/apis/index.js index 2c131e334..5ac010b78 100644 --- a/ui/src/shared/apis/index.js +++ b/ui/src/shared/apis/index.js @@ -6,17 +6,25 @@ export function getSources() { }); } -export function createSource({url, name, username, password, isDefault}) { +export function getSource(sourceID) { + return AJAX({ + url: `/chronograf/v1/sources/${sourceID}`, + }); +} + +export function createSource(attributes) { return AJAX({ url: '/chronograf/v1/sources', method: 'POST', - data: { - url, - name, - username, - password, - 'default': isDefault, - }, + data: attributes, + }); +} + +export function updateSource(newSource) { + return AJAX({ + url: newSource.links.self, + method: 'PATCH', + data: newSource, }); } diff --git a/ui/src/sources/containers/ManageSources.js b/ui/src/sources/containers/ManageSources.js index 7b2cf4399..5d3dba33c 100644 --- a/ui/src/sources/containers/ManageSources.js +++ b/ui/src/sources/containers/ManageSources.js @@ -81,7 +81,7 @@ export const ManageSources = React.createClass({ } -
Add
+ Add diff --git a/ui/src/sources/containers/SourceForm.js b/ui/src/sources/containers/SourceForm.js new file mode 100644 index 000000000..ca27c21a6 --- /dev/null +++ b/ui/src/sources/containers/SourceForm.js @@ -0,0 +1,138 @@ +import React, {PropTypes} from 'react'; +import {withRouter} from 'react-router'; +import {getSource, createSource, updateSource} from 'shared/apis'; + +export const SourceForm = React.createClass({ + propTypes: { + params: PropTypes.shape({ + id: PropTypes.string, + }), + router: PropTypes.shape({ + push: PropTypes.func.isRequired, + }).isRequired, + location: PropTypes.shape({ + query: PropTypes.shape({ + redirectPath: PropTypes.string, + }).isRequired, + }).isRequired, + addFlashMessage: PropTypes.func.isRequired, + }, + + getInitialState() { + return { + source: {}, + editMode: this.props.params.id !== undefined, + }; + }, + + componentDidMount() { + if (!this.state.editMode) { + return; + } + getSource(this.props.params.id).then(({data: source}) => { + this.setState({source}); + }); + }, + + handleSubmit(e) { + e.preventDefault(); + const {router, params, addFlashMessage} = this.props; + const newSource = Object.assign({}, this.state.source, { + url: this.sourceURL.value, + name: this.sourceName.value, + username: this.sourceUsername.value, + password: this.sourcePassword.value, + 'default': this.sourceDefault.checked, + }); + if (this.state.editMode) { + updateSource(newSource).then(() => { + router.push(`/sources/${params.sourceID}/manage-sources`); + addFlashMessage({type: 'success', text: 'The source was successfully updated'}); + }); + } else { + createSource(newSource).then(() => { + router.push(`/sources/${params.sourceID}/manage-sources`); + addFlashMessage({type: 'success', text: 'The source was successfully created'}); + }); + } + }, + + onInputChange(e) { + const val = e.target.value; + const name = e.target.name; + this.setState((prevState) => { + const newSource = Object.assign({}, prevState.source, { + [name]: val, + }); + return Object.assign({}, prevState, {source: newSource}); + }); + }, + + render() { + const {source, editMode} = this.state; + + if (editMode && !source.id) { + return
; + } + + return ( +
+
+
+
+

+ Source Form +

+
+
+
+
+
+
+
+
+

{editMode ? "Update Existing Source" : "Connect to a New Source"}

+
+ +
+
+
+ + this.sourceURL = r} className="form-control" id="connect-string" placeholder="http://localhost:8086" onChange={this.onInputChange} value={source.url || ''}> +
+
+ + this.sourceName = r} className="form-control" id="name" placeholder="Influx 1" onChange={this.onInputChange} value={source.name || ''}> +
+
+ + this.sourceUsername = r} className="form-control" id="username" onChange={this.onInputChange} value={source.username || ''}> +
+
+ + this.sourcePassword = r} className="form-control" id="password" onChange={this.onInputChange} value={source.password || ''}> +
+
+
+ +
+
+
+ +
+ +
+
+
+
+
+
+
+
+ ); + }, +}); +export default withRouter(SourceForm); diff --git a/ui/src/sources/index.js b/ui/src/sources/index.js index 4f7c95a88..6c75485c8 100644 --- a/ui/src/sources/index.js +++ b/ui/src/sources/index.js @@ -1,3 +1,4 @@ import CreateSource from './containers/CreateSource'; +import SourceForm from './containers/SourceForm'; import ManageSources from './containers/ManageSources'; -export {CreateSource, ManageSources}; +export {CreateSource, SourceForm, ManageSources};