Merge pull request #1205 from influxdata/initial-source-options
add missing options when creating initial sourcepull/10616/head
commit
67f9e4020f
|
@ -23,6 +23,7 @@
|
|||
1. [#1209](https://github.com/influxdata/chronograf/pull/1209): HipChat Kapacitor config now uses only the subdomain instead of asking for the entire HipChat URL.
|
||||
1. [#1219](https://github.com/influxdata/chronograf/pull/1219): Update query for default cell in new dashboard
|
||||
1. [#1206](https://github.com/influxdata/chronograf/issues/1206): Chronograf now proxies to kapacitors behind proxy using vhost correctly.
|
||||
1. [#1205](https://github.com/influxdata/chronograf/pull/1205): Allow initial source to be an enterprise source.
|
||||
|
||||
### Features
|
||||
1. [#1112](https://github.com/influxdata/chronograf/pull/1112): Add ability to delete a dashboard
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
import classnames from 'classnames'
|
||||
import SideNavContainer from 'src/side_nav'
|
||||
import Notifications from 'shared/components/Notifications'
|
||||
import {
|
||||
publishNotification as publishNotificationAction,
|
||||
dismissNotification as dismissNotificationAction,
|
||||
dismissAllNotifications as dismissAllNotificationsAction,
|
||||
} from 'src/shared/actions/notifications'
|
||||
|
||||
const {
|
||||
func,
|
||||
node,
|
||||
shape,
|
||||
string,
|
||||
func,
|
||||
} = PropTypes
|
||||
|
||||
const App = React.createClass({
|
||||
|
@ -24,99 +22,34 @@ const App = React.createClass({
|
|||
params: shape({
|
||||
sourceID: string.isRequired,
|
||||
}).isRequired,
|
||||
publishNotification: func.isRequired,
|
||||
dismissNotification: func.isRequired,
|
||||
dismissAllNotifications: func.isRequired,
|
||||
notifications: shape({
|
||||
success: string,
|
||||
error: string,
|
||||
warning: string,
|
||||
}),
|
||||
notify: func.isRequired,
|
||||
},
|
||||
|
||||
handleNotification({type, text}) {
|
||||
const validTypes = ['error', 'success', 'warning']
|
||||
if (!validTypes.includes(type) || text === undefined) {
|
||||
console.error("handleNotification must have a valid type and text") // eslint-disable-line no-console
|
||||
}
|
||||
this.props.publishNotification(type, text)
|
||||
},
|
||||
handleAddFlashMessage({type, text}) {
|
||||
const {notify} = this.props
|
||||
|
||||
handleDismissNotification(type) {
|
||||
this.props.dismissNotification(type)
|
||||
},
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.location.pathname !== this.props.location.pathname) {
|
||||
this.props.dismissAllNotifications()
|
||||
}
|
||||
notify(type, text)
|
||||
},
|
||||
|
||||
render() {
|
||||
const {params: {sourceID}} = this.props
|
||||
const {params: {sourceID}, location} = this.props
|
||||
|
||||
return (
|
||||
<div className="chronograf-root">
|
||||
<SideNavContainer
|
||||
sourceID={sourceID}
|
||||
addFlashMessage={this.handleNotification}
|
||||
addFlashMessage={this.handleAddFlashMessage}
|
||||
currentLocation={this.props.location.pathname}
|
||||
/>
|
||||
{this.renderNotifications()}
|
||||
<Notifications location={location} />
|
||||
{this.props.children && React.cloneElement(this.props.children, {
|
||||
addFlashMessage: this.handleNotification,
|
||||
addFlashMessage: this.handleAddFlashMessage,
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
|
||||
renderNotifications() {
|
||||
const {success, error, warning} = this.props.notifications
|
||||
if (!success && !error && !warning) {
|
||||
return null
|
||||
}
|
||||
return (
|
||||
<div className="flash-messages">
|
||||
{this.renderNotification('success', success)}
|
||||
{this.renderNotification('error', error)}
|
||||
{this.renderNotification('warning', warning)}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
|
||||
renderNotification(type, message) {
|
||||
if (!message) {
|
||||
return null
|
||||
}
|
||||
const cls = classnames('alert', {
|
||||
'alert-danger': type === 'error',
|
||||
'alert-success': type === 'success',
|
||||
'alert-warning': type === 'warning',
|
||||
})
|
||||
return (
|
||||
<div className={cls} role="alert">
|
||||
{message}{this.renderDismiss(type)}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
|
||||
renderDismiss(type) {
|
||||
return (
|
||||
<button className="close" data-dismiss="alert" aria-label="Close" onClick={() => this.handleDismissNotification(type)}>
|
||||
<span className="icon remove"></span>
|
||||
</button>
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
notifications: state.notifications,
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, {
|
||||
publishNotification: publishNotificationAction,
|
||||
dismissNotification: dismissNotificationAction,
|
||||
dismissAllNotifications: dismissAllNotificationsAction,
|
||||
export default connect(null, {
|
||||
notify: publishNotificationAction,
|
||||
})(App)
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
export function publishNotification(type, message) {
|
||||
// this validator is purely for development purposes. It might make sense to move this to a middleware.
|
||||
const validTypes = ['error', 'success', 'warning']
|
||||
if (!validTypes.includes(type) || message === undefined) {
|
||||
console.error("handleNotification must have a valid type and text") // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'NOTIFICATION_RECEIVED',
|
||||
payload: {
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import classnames from 'classnames'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
||||
import {
|
||||
publishNotification as publishNotificationAction,
|
||||
dismissNotification as dismissNotificationAction,
|
||||
dismissAllNotifications as dismissAllNotificationsAction,
|
||||
} from 'src/shared/actions/notifications'
|
||||
|
||||
class Notifications extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.renderNotification = ::this.renderNotification
|
||||
this.renderDismiss = ::this.renderDismiss
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.location.pathname !== this.props.location.pathname) {
|
||||
this.props.dismissAllNotifications()
|
||||
}
|
||||
}
|
||||
|
||||
renderNotification(type, message) {
|
||||
if (!message) {
|
||||
return null
|
||||
}
|
||||
const cls = classnames('alert', {
|
||||
'alert-danger': type === 'error',
|
||||
'alert-success': type === 'success',
|
||||
'alert-warning': type === 'warning',
|
||||
})
|
||||
return (
|
||||
<div className={cls} role="alert">
|
||||
{message}{this.renderDismiss(type)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderDismiss(type) {
|
||||
const {dismissNotification} = this.props
|
||||
|
||||
return (
|
||||
<button className="close" data-dismiss="alert" aria-label="Close" onClick={() => dismissNotification(type)}>
|
||||
<span className="icon remove"></span>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {success, error, warning} = this.props.notifications
|
||||
if (!success && !error && !warning) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flash-messages">
|
||||
{this.renderNotification('success', success)}
|
||||
{this.renderNotification('error', error)}
|
||||
{this.renderNotification('warning', warning)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const {
|
||||
func,
|
||||
shape,
|
||||
string,
|
||||
} = PropTypes
|
||||
|
||||
Notifications.propTypes = {
|
||||
location: shape({
|
||||
pathname: string,
|
||||
}),
|
||||
publishNotification: func.isRequired,
|
||||
dismissNotification: func.isRequired,
|
||||
dismissAllNotifications: func.isRequired,
|
||||
notifications: shape({
|
||||
success: string,
|
||||
error: string,
|
||||
warning: string,
|
||||
}),
|
||||
}
|
||||
|
||||
const mapStateToProps = ({notifications}) => ({
|
||||
notifications,
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
publishNotification: bindActionCreators(publishNotificationAction, dispatch),
|
||||
dismissNotification: bindActionCreators(dismissNotificationAction, dispatch),
|
||||
dismissAllNotifications: bindActionCreators(dismissAllNotificationsAction, dispatch),
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Notifications)
|
|
@ -11,9 +11,6 @@ const {
|
|||
|
||||
export const SourceForm = React.createClass({
|
||||
propTypes: {
|
||||
addFlashMessage: func.isRequired,
|
||||
addSourceAction: func,
|
||||
updateSourceAction: func,
|
||||
source: shape({}).isRequired,
|
||||
editMode: bool.isRequired,
|
||||
onInputChange: func.isRequired,
|
||||
|
@ -56,80 +53,55 @@ export const SourceForm = React.createClass({
|
|||
render() {
|
||||
const {source, editMode, onInputChange} = this.props
|
||||
|
||||
if (editMode && !source.id) {
|
||||
return <div className="page-spinner"></div>
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="page" id="source-form-page">
|
||||
<div className="page-header">
|
||||
<div className="page-header__container">
|
||||
<div className="page-header__left">
|
||||
<h1>
|
||||
{editMode ? "Edit Source" : "Add a New Source"}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="page-contents">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-md-8 col-md-offset-2">
|
||||
<div className="panel panel-minimal">
|
||||
<div className="panel-body">
|
||||
<h4 className="text-center">Connection Details</h4>
|
||||
<br/>
|
||||
<div className="panel-body">
|
||||
<h4 className="text-center">Connection Details</h4>
|
||||
<br/>
|
||||
|
||||
<form onSubmit={this.handleSubmitForm}>
|
||||
<div className="form-group col-xs-12 col-sm-6">
|
||||
<label htmlFor="connect-string"> Connection String</label>
|
||||
<input type="text" name="url" ref={(r) => this.sourceURL = r} className="form-control" id="connect-string" placeholder="http://localhost:8086" onChange={onInputChange} value={source.url || ''} onBlur={this.handleBlurSourceURL}></input>
|
||||
</div>
|
||||
<div className="form-group col-xs-12 col-sm-6">
|
||||
<label htmlFor="name">Name</label>
|
||||
<input type="text" name="name" ref={(r) => this.sourceName = r} className="form-control" id="name" placeholder="Influx 1" onChange={onInputChange} value={source.name || ''}></input>
|
||||
</div>
|
||||
<div className="form-group col-xs-12 col-sm-6">
|
||||
<label htmlFor="username">Username</label>
|
||||
<input type="text" name="username" ref={(r) => this.sourceUsername = r} className="form-control" id="username" onChange={onInputChange} value={source.username || ''}></input>
|
||||
</div>
|
||||
<div className="form-group col-xs-12 col-sm-6">
|
||||
<label htmlFor="password">Password</label>
|
||||
<input type="password" name="password" ref={(r) => this.sourcePassword = r} className="form-control" id="password" onChange={onInputChange} value={source.password || ''}></input>
|
||||
</div>
|
||||
{_.get(source, 'type', '').includes("enterprise") ?
|
||||
<div className="form-group col-xs-12">
|
||||
<label htmlFor="meta-url">Meta Service Connection URL</label>
|
||||
<input type="text" name="metaUrl" ref={(r) => this.metaUrl = r} className="form-control" id="meta-url" placeholder="http://localhost:8091" onChange={onInputChange} value={source.metaUrl || ''}></input>
|
||||
</div> : null}
|
||||
<div className="form-group col-xs-12">
|
||||
<label htmlFor="telegraf">Telegraf database</label>
|
||||
<input type="text" name="telegraf" ref={(r) => this.sourceTelegraf = r} className="form-control" id="telegraf" onChange={onInputChange} value={source.telegraf || 'telegraf'}></input>
|
||||
</div>
|
||||
<div className="form-group col-xs-12">
|
||||
<div className="form-control-static">
|
||||
<input type="checkbox" id="defaultSourceCheckbox" defaultChecked={source.default} ref={(r) => this.sourceDefault = r} />
|
||||
<label htmlFor="defaultSourceCheckbox">Make this the default source</label>
|
||||
</div>
|
||||
</div>
|
||||
{_.get(source, 'url', '').startsWith("https") ?
|
||||
<div className="form-group col-xs-12">
|
||||
<div className="form-control-static">
|
||||
<input type="checkbox" id="insecureSkipVerifyCheckbox" defaultChecked={source.insecureSkipVerify} ref={(r) => this.sourceInsecureSkipVerify = r} />
|
||||
<label htmlFor="insecureSkipVerifyCheckbox">Unsafe SSL</label>
|
||||
</div>
|
||||
<label className="form-helper">{insecureSkipVerifyText}</label>
|
||||
</div> : null}
|
||||
<div className="form-group form-group-submit col-xs-12 col-sm-6 col-sm-offset-3">
|
||||
<button className={classNames('btn btn-block', {'btn-primary': editMode, 'btn-success': !editMode})} type="submit">{editMode ? "Save Changes" : "Add Source"}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form onSubmit={this.handleSubmitForm}>
|
||||
<div className="form-group col-xs-12 col-sm-6">
|
||||
<label htmlFor="connect-string"> Connection String</label>
|
||||
<input type="text" name="url" ref={(r) => this.sourceURL = r} className="form-control" id="connect-string" placeholder="http://localhost:8086" onChange={onInputChange} value={source.url || ''} onBlur={this.handleBlurSourceURL}></input>
|
||||
</div>
|
||||
<div className="form-group col-xs-12 col-sm-6">
|
||||
<label htmlFor="name">Name</label>
|
||||
<input type="text" name="name" ref={(r) => this.sourceName = r} className="form-control" id="name" placeholder="Influx 1" onChange={onInputChange} value={source.name || ''}></input>
|
||||
</div>
|
||||
<div className="form-group col-xs-12 col-sm-6">
|
||||
<label htmlFor="username">Username</label>
|
||||
<input type="text" name="username" ref={(r) => this.sourceUsername = r} className="form-control" id="username" onChange={onInputChange} value={source.username || ''}></input>
|
||||
</div>
|
||||
<div className="form-group col-xs-12 col-sm-6">
|
||||
<label htmlFor="password">Password</label>
|
||||
<input type="password" name="password" ref={(r) => this.sourcePassword = r} className="form-control" id="password" onChange={onInputChange} value={source.password || ''}></input>
|
||||
</div>
|
||||
{_.get(source, 'type', '').includes("enterprise") ?
|
||||
<div className="form-group col-xs-12">
|
||||
<label htmlFor="meta-url">Meta Service Connection URL</label>
|
||||
<input type="text" name="metaUrl" ref={(r) => this.metaUrl = r} className="form-control" id="meta-url" placeholder="http://localhost:8091" onChange={onInputChange} value={source.metaUrl || ''}></input>
|
||||
</div> : null}
|
||||
<div className="form-group col-xs-12">
|
||||
<label htmlFor="telegraf">Telegraf database</label>
|
||||
<input type="text" name="telegraf" ref={(r) => this.sourceTelegraf = r} className="form-control" id="telegraf" onChange={onInputChange} value={source.telegraf || 'telegraf'}></input>
|
||||
</div>
|
||||
<div className="form-group col-xs-12">
|
||||
<div className="form-control-static">
|
||||
<input type="checkbox" id="defaultSourceCheckbox" defaultChecked={source.default} ref={(r) => this.sourceDefault = r} />
|
||||
<label htmlFor="defaultSourceCheckbox">Make this the default source</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{_.get(source, 'url', '').startsWith("https") ?
|
||||
<div className="form-group col-xs-12">
|
||||
<div className="form-control-static">
|
||||
<input type="checkbox" id="insecureSkipVerifyCheckbox" defaultChecked={source.insecureSkipVerify} ref={(r) => this.sourceInsecureSkipVerify = r} />
|
||||
<label htmlFor="insecureSkipVerifyCheckbox">Unsafe SSL</label>
|
||||
</div>
|
||||
<label className="form-helper">{insecureSkipVerifyText}</label>
|
||||
</div> : null}
|
||||
<div className="form-group form-group-submit col-xs-12 col-sm-6 col-sm-offset-3">
|
||||
<button className={classNames('btn btn-block', {'btn-primary': editMode, 'btn-success': !editMode})} type="submit">{editMode ? "Save Changes" : "Add Source"}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
|
|
|
@ -1,36 +1,45 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import {withRouter} from 'react-router'
|
||||
import {addSource as addSourceAction} from 'src/shared/actions/sources'
|
||||
import {createSource} from 'shared/apis'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
||||
import {
|
||||
createSource as createSourceAJAX,
|
||||
updateSource as updateSourceAJAX,
|
||||
} from 'shared/apis'
|
||||
import SourceForm from 'src/sources/components/SourceForm'
|
||||
import Notifications from 'shared/components/Notifications'
|
||||
import {
|
||||
addSource as addSourceAction,
|
||||
updateSource as updateSourceAction,
|
||||
} from 'src/shared/actions/sources'
|
||||
import {publishNotification} from 'src/shared/actions/notifications'
|
||||
|
||||
const {
|
||||
func,
|
||||
shape,
|
||||
string,
|
||||
} = PropTypes
|
||||
|
||||
export const CreateSource = React.createClass({
|
||||
propTypes: {
|
||||
router: PropTypes.shape({
|
||||
push: PropTypes.func.isRequired,
|
||||
router: shape({
|
||||
push: func.isRequired,
|
||||
}).isRequired,
|
||||
location: PropTypes.shape({
|
||||
query: PropTypes.shape({
|
||||
redirectPath: PropTypes.string,
|
||||
location: shape({
|
||||
query: shape({
|
||||
redirectPath: string,
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
addSourceAction: PropTypes.func,
|
||||
addSource: func,
|
||||
updateSource: func,
|
||||
notify: func,
|
||||
},
|
||||
|
||||
handleNewSource(e) {
|
||||
e.preventDefault()
|
||||
const source = {
|
||||
url: this.sourceURL.value.trim(),
|
||||
name: this.sourceName.value,
|
||||
username: this.sourceUser.value,
|
||||
password: this.sourcePassword.value,
|
||||
isDefault: true,
|
||||
telegraf: this.sourceTelegraf.value,
|
||||
getInitialState() {
|
||||
return {
|
||||
source: {},
|
||||
}
|
||||
createSource(source).then(({data: sourceFromServer}) => {
|
||||
this.props.addSourceAction(sourceFromServer)
|
||||
this.redirectToApp(sourceFromServer)
|
||||
})
|
||||
},
|
||||
|
||||
redirectToApp(source) {
|
||||
|
@ -43,47 +52,77 @@ export const CreateSource = React.createClass({
|
|||
return this.props.router.push(fixedPath)
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="select-source-page" id="select-source-page">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-md-8 col-md-offset-2">
|
||||
<div className="panel panel-minimal">
|
||||
<div className="panel-heading text-center">
|
||||
<h2 className="deluxe">Welcome to Chronograf</h2>
|
||||
</div>
|
||||
<div className="panel-body">
|
||||
<h4 className="text-center">Connect to a New Source</h4>
|
||||
<br/>
|
||||
handleInputChange(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})
|
||||
})
|
||||
},
|
||||
|
||||
<form onSubmit={this.handleNewSource}>
|
||||
<div>
|
||||
<div className="form-group col-xs-6 col-sm-4 col-sm-offset-2">
|
||||
<label htmlFor="connect-string">Connection String</label>
|
||||
<input ref={(r) => this.sourceURL = r} className="form-control" id="connect-string" defaultValue="http://localhost:8086"></input>
|
||||
</div>
|
||||
<div className="form-group col-xs-6 col-sm-4">
|
||||
<label htmlFor="name">Name</label>
|
||||
<input ref={(r) => this.sourceName = r} className="form-control" id="name" defaultValue="Influx 1"></input>
|
||||
</div>
|
||||
<div className="form-group col-xs-6 col-sm-4 col-sm-offset-2">
|
||||
<label htmlFor="username">Username</label>
|
||||
<input ref={(r) => this.sourceUser = r} className="form-control" id="username"></input>
|
||||
</div>
|
||||
<div className="form-group col-xs-6 col-sm-4">
|
||||
<label htmlFor="password">Password</label>
|
||||
<input ref={(r) => this.sourcePassword = r} className="form-control" id="password" type="password"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group col-xs-8 col-xs-offset-2">
|
||||
<label htmlFor="telegraf">Telegraf Database</label>
|
||||
<input ref={(r) => this.sourceTelegraf = r} className="form-control" id="telegraf" type="text" defaultValue="telegraf"></input>
|
||||
</div>
|
||||
<div className="form-group form-group-submit col-xs-12 text-center">
|
||||
<button className="btn btn-success" type="submit">Connect New Source</button>
|
||||
</div>
|
||||
</form>
|
||||
handleBlurSourceURL(newSource) {
|
||||
if (this.state.editMode) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!newSource.url) {
|
||||
return
|
||||
}
|
||||
|
||||
// if there is a type on source it has already been created
|
||||
if (newSource.type) {
|
||||
return
|
||||
}
|
||||
|
||||
createSourceAJAX(newSource).then(({data: sourceFromServer}) => {
|
||||
this.props.addSource(sourceFromServer)
|
||||
this.setState({source: sourceFromServer, error: null})
|
||||
}).catch(({data: error}) => {
|
||||
this.setState({error: error.message})
|
||||
})
|
||||
},
|
||||
|
||||
handleSubmit(newSource) {
|
||||
const {error} = this.state
|
||||
const {notify, updateSource} = this.props
|
||||
|
||||
if (error) {
|
||||
return notify('error', error)
|
||||
}
|
||||
|
||||
updateSourceAJAX(newSource).then(({data: sourceFromServer}) => {
|
||||
updateSource(sourceFromServer)
|
||||
this.redirectToApp(sourceFromServer)
|
||||
}).catch(() => {
|
||||
notify('error', 'There was a problem updating the source. Check the settings')
|
||||
})
|
||||
},
|
||||
|
||||
render() {
|
||||
const {location} = this.props
|
||||
const {source} = this.state
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Notifications location={location} />
|
||||
<div className="select-source-page">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-md-8 col-md-offset-2">
|
||||
<div className="panel panel-minimal">
|
||||
<div className="panel-heading text-center">
|
||||
<h2 className="deluxe">Welcome to Chronograf</h2>
|
||||
</div>
|
||||
<SourceForm
|
||||
source={source}
|
||||
editMode={false}
|
||||
onInputChange={this.handleInputChange}
|
||||
onSubmit={this.handleSubmit}
|
||||
onBlurSourceURL={this.handleBlurSourceURL}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -94,8 +133,12 @@ export const CreateSource = React.createClass({
|
|||
},
|
||||
})
|
||||
|
||||
function mapStateToProps(_) {
|
||||
return {}
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
addSource: bindActionCreators(addSourceAction, dispatch),
|
||||
updateSource: bindActionCreators(updateSourceAction, dispatch),
|
||||
notify: bindActionCreators(publishNotification, dispatch),
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, {addSourceAction})(withRouter(CreateSource))
|
||||
export default connect(null, mapDispatchToProps)(withRouter(CreateSource))
|
||||
|
|
|
@ -78,7 +78,7 @@ export const SourcePage = React.createClass({
|
|||
|
||||
createSource(newSource).then(({data: sourceFromServer}) => {
|
||||
this.props.addSourceAction(sourceFromServer)
|
||||
this.setState({source: sourceFromServer})
|
||||
this.setState({source: sourceFromServer, error: null})
|
||||
}).catch(({data: error}) => {
|
||||
// dont want to flash this until they submit
|
||||
this.setState({error: error.message})
|
||||
|
@ -105,22 +105,40 @@ export const SourcePage = React.createClass({
|
|||
|
||||
render() {
|
||||
const {source, editMode} = this.state
|
||||
const {addFlashMessage, router, location, params} = this.props
|
||||
|
||||
if (editMode && !source.id) {
|
||||
return <div className="page-spinner"></div>
|
||||
}
|
||||
|
||||
return (
|
||||
<SourceForm
|
||||
sourceID={params.sourceID}
|
||||
router={router}
|
||||
location={location}
|
||||
source={source}
|
||||
editMode={editMode}
|
||||
addFlashMessage={addFlashMessage}
|
||||
addSourceAction={addSourceAction}
|
||||
updateSourceAction={updateSourceAction}
|
||||
onInputChange={this.handleInputChange}
|
||||
onSubmit={this.handleSubmit}
|
||||
onBlurSourceURL={this.handleBlurSourceURL}
|
||||
/>
|
||||
<div className="page" id="source-form-page">
|
||||
<div className="page-header">
|
||||
<div className="page-header__container">
|
||||
<div className="page-header__left">
|
||||
<h1>
|
||||
{editMode ? "Edit Source" : "Add a New Source"}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="page-contents">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-md-8 col-md-offset-2">
|
||||
<div className="panel panel-minimal">
|
||||
<SourceForm
|
||||
source={source}
|
||||
editMode={editMode}
|
||||
onInputChange={this.handleInputChange}
|
||||
onSubmit={this.handleSubmit}
|
||||
onBlurSourceURL={this.handleBlurSourceURL}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
})
|
||||
|
|
|
@ -2,16 +2,6 @@
|
|||
Unsorted
|
||||
----------------------------------------------
|
||||
*/
|
||||
.select-source-page {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
@include custom-scrollbar($g2-kevlar, $c-pool);
|
||||
@include gradient-v($g2-kevlar, $g0-obsidian);
|
||||
}
|
||||
.text-right .btn {
|
||||
margin: 0 0 0 4px;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue