diff --git a/CHANGELOG.md b/CHANGELOG.md index d23d96a8a..b176ab2f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,14 +5,19 @@ 1. [#2093](https://github.com/influxdata/chronograf/pull/2093): Fix when exporting `SHOW DATABASES` CSV has bad data 1. [#2098](https://github.com/influxdata/chronograf/pull/2098): Fix not-equal-to highlighting in Kapacitor Rule Builder 1. [#2130](https://github.com/influxdata/chronograf/pull/2130): Fix undescriptive error messages for database and retention policy creation +1. [#2135](https://github.com/influxdata/chronograf/pull/2135): Fix drag and drop cancel button + ### Features 1. [#2083](https://github.com/influxdata/chronograf/pull/2083): Every dashboard can now have its own time range 1. [#2045](https://github.com/influxdata/chronograf/pull/2045): Add CSV download option in dashboard cells +1. [#2133](https://github.com/influxdata/chronograf/pull/2133): Implicitly prepend source urls with http:// +1. [#2127](https://github.com/influxdata/chronograf/pull/2127): Add support for graph zooming and point display on the millisecond-level ### UI Improvements 1. [#2111](https://github.com/influxdata/chronograf/pull/2111): Increase size of Cell Editor query tabs to reveal more of their query strings -1. [#2119](https://github.com/influxdata/chronograf/pull/2119): Add support for graph zooming and point display on the millisecond-level +1. [#2120](https://github.com/influxdata/chronograf/pull/2120): Improve appearance of Admin Page tabs on smaller screens +1. [#2119](https://github.com/influxdata/chronograf/pull/2119): Add cancel button to Tickscript editor ## v1.3.9.0 [2017-10-06] ### Bug Fixes diff --git a/ui/src/data_explorer/components/WriteDataForm.js b/ui/src/data_explorer/components/WriteDataForm.js index 2ae70db83..1221c6f05 100644 --- a/ui/src/data_explorer/components/WriteDataForm.js +++ b/ui/src/data_explorer/components/WriteDataForm.js @@ -79,6 +79,10 @@ class WriteDataForm extends Component { file = e.target.files[0] } + if (!file) { + return + } + e.preventDefault() e.stopPropagation() @@ -94,6 +98,7 @@ class WriteDataForm extends Component { handleCancelFile = () => { this.setState({uploadContent: ''}) + this.fileInput.value = '' } handleDragOver = e => { diff --git a/ui/src/sources/components/SourceForm.js b/ui/src/sources/components/SourceForm.js index bebb85569..21e340f33 100644 --- a/ui/src/sources/components/SourceForm.js +++ b/ui/src/sources/components/SourceForm.js @@ -1,159 +1,139 @@ -import React, {PropTypes, Component} from 'react' +import React, {PropTypes} from 'react' import classnames from 'classnames' import {insecureSkipVerifyText} from 'shared/copy/tooltipText' import _ from 'lodash' -class SourceForm extends Component { - constructor(props) { - super(props) - } +const SourceForm = ({ + source, + editMode, + onSubmit, + onInputChange, + onBlurSourceURL, +}) => + <div className="panel-body"> + <h4 className="text-center">Connection Details</h4> + <br /> - handleBlurSourceURL = () => { - const url = this.props.source.url.trim() - - if (!url) { - return - } - - const newSource = { - ...this.props.source, - url, - } - - this.props.onBlurSourceURL(newSource) - } - - render() { - const {source, editMode, onSubmit, onInputChange} = this.props - - return ( - <div className="panel-body"> - <h4 className="text-center">Connection Details</h4> - <br /> - - <form onSubmit={onSubmit}> - <div className="form-group col-xs-12 col-sm-6"> - <label htmlFor="connect-string">Connection String</label> + <form onSubmit={onSubmit}> + <div className="form-group col-xs-12 col-sm-6"> + <label htmlFor="connect-string">Connection String</label> + <input + type="text" + name="url" + className="form-control" + id="connect-string" + placeholder="Address of InfluxDB" + onChange={onInputChange} + value={source.url} + onBlur={onBlurSourceURL} + required={true} + /> + </div> + <div className="form-group col-xs-12 col-sm-6"> + <label htmlFor="name">Name</label> + <input + type="text" + name="name" + className="form-control" + id="name" + placeholder="Name this source" + onChange={onInputChange} + value={source.name} + required={true} + /> + </div> + <div className="form-group col-xs-12 col-sm-6"> + <label htmlFor="username">Username</label> + <input + type="text" + name="username" + className="form-control" + id="username" + onChange={onInputChange} + value={source.username} + /> + </div> + <div className="form-group col-xs-12 col-sm-6"> + <label htmlFor="password">Password</label> + <input + type="password" + name="password" + className="form-control" + id="password" + onChange={onInputChange} + value={source.password} + /> + </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="url" + name="metaUrl" className="form-control" - id="connect-string" - placeholder="Address of InfluxDB" + id="meta-url" + placeholder="http://localhost:8091" onChange={onInputChange} - value={source.url} - onBlur={this.handleBlurSourceURL} - required={true} + value={source.metaUrl} /> </div> - <div className="form-group col-xs-12 col-sm-6"> - <label htmlFor="name">Name</label> - <input - type="text" - name="name" - className="form-control" - id="name" - placeholder="Name this source" - onChange={onInputChange} - value={source.name} - required={true} - /> - </div> - <div className="form-group col-xs-12 col-sm-6"> - <label htmlFor="username">Username</label> - <input - type="text" - name="username" - className="form-control" - id="username" - onChange={onInputChange} - value={source.username} - /> - </div> - <div className="form-group col-xs-12 col-sm-6"> - <label htmlFor="password">Password</label> - <input - type="password" - name="password" - className="form-control" - id="password" - onChange={onInputChange} - value={source.password} - /> - </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" - className="form-control" - id="meta-url" - placeholder="http://localhost:8091" - onChange={onInputChange} - value={source.metaUrl} - /> - </div> - : null} - <div className="form-group col-xs-12"> - <label htmlFor="telegraf">Telegraf database</label> - <input - type="text" - name="telegraf" - className="form-control" - id="telegraf" - onChange={onInputChange} - value={source.telegraf} - /> - </div> - <div className="form-group col-xs-12"> + : null} + <div className="form-group col-xs-12"> + <label htmlFor="telegraf">Telegraf database</label> + <input + type="text" + name="telegraf" + className="form-control" + id="telegraf" + onChange={onInputChange} + value={source.telegraf} + /> + </div> + <div className="form-group col-xs-12"> + <div className="form-control-static"> + <input + type="checkbox" + id="defaultSourceCheckbox" + name="default" + checked={source.default} + onChange={onInputChange} + /> + <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="defaultSourceCheckbox" - name="default" - checked={source.default} + id="insecureSkipVerifyCheckbox" + name="insecureSkipVerify" + checked={source.insecureSkipVerify} onChange={onInputChange} /> - <label htmlFor="defaultSourceCheckbox"> - Make this the default source - </label> + <label htmlFor="insecureSkipVerifyCheckbox">Unsafe SSL</label> </div> + <label className="form-helper"> + {insecureSkipVerifyText} + </label> </div> - {_.get(source, 'url', '').startsWith('https') - ? <div className="form-group col-xs-12"> - <div className="form-control-static"> - <input - type="checkbox" - id="insecureSkipVerifyCheckbox" - name="insecureSkipVerify" - checked={source.insecureSkipVerify} - onChange={onInputChange} - /> - <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 text-center"> - <button - className={classnames('btn btn-block', { - 'btn-primary': editMode, - 'btn-success': !editMode, - })} - type="submit" - > - {editMode ? 'Save Changes' : 'Add Source'} - </button> - <br /> - </div> - </form> + : null} + <div className="form-group form-group-submit col-xs-12 col-sm-6 col-sm-offset-3 text-center"> + <button + className={classnames('btn btn-block', { + 'btn-primary': editMode, + 'btn-success': !editMode, + })} + type="submit" + > + {editMode ? 'Save Changes' : 'Add Source'} + </button> + <br /> </div> - ) - } -} + </form> + </div> const {bool, func, shape, string} = PropTypes diff --git a/ui/src/sources/containers/SourcePage.js b/ui/src/sources/containers/SourcePage.js index 4997c6a48..d3eb5b6cb 100644 --- a/ui/src/sources/containers/SourcePage.js +++ b/ui/src/sources/containers/SourcePage.js @@ -67,23 +67,56 @@ class SourcePage extends Component { }) } - handleBlurSourceURL = newSource => { - if (this.state.editMode) { + handleBlurSourceURL = () => { + const {source, editMode} = this.state + if (editMode) { + this.setState(this._normalizeSource) return } - if (!newSource.url) { + if (!source.url) { return } + this.setState(this._normalizeSource, this._createSourceOnBlur) + } + + handleSubmit = e => { + e.preventDefault() + const {isCreated, editMode} = this.state + const isNewSource = !editMode + + if (!isCreated && isNewSource) { + return this.setState(this._normalizeSource, this._createSource) + } + + this.setState(this._normalizeSource, this._updateSource) + } + + handleError = (bannerText, err) => { + const {notify} = this.props + const error = this._parseError(err) + console.error('Error: ', error) + notify('error', `${bannerText}: ${error}`) + } + + _normalizeSource({source}) { + const url = source.url.trim() + if (source.url.startsWith('http')) { + return {source: {...source, url}} + } + return {source: {...source, url: `http://${url}`}} + } + + _createSourceOnBlur = () => { + const {source} = this.state // if there is a type on source it has already been created - if (newSource.type) { + if (source.type) { return } - - createSource(newSource) + createSource(source) .then(({data: sourceFromServer}) => { - this.props.addSourceAction(sourceFromServer) + addSourceAction(sourceFromServer) this.setState({ source: {...DEFAULT_SOURCE, ...sourceFromServer}, isCreated: true, @@ -91,31 +124,29 @@ class SourcePage extends Component { }) .catch(err => { // dont want to flash this until they submit - const error = this.parseError(err) + const error = this._parseError(err) console.error('Error on source creation: ', error) }) } - handleSubmit = e => { - e.preventDefault() + _createSource = () => { + const {source} = this.state + createSource(source) + .then(({data: sourceFromServer}) => { + addSourceAction(sourceFromServer) + this._redirect(sourceFromServer) + }) + .catch(error => { + this.handleError('Unable to create source', error) + }) + } + + _updateSource = () => { + const {source} = this.state const {notify} = this.props - const {isCreated, source, editMode} = this.state - const isNewSource = !editMode - - if (!isCreated && isNewSource) { - return createSource(source) - .then(({data: sourceFromServer}) => { - this.props.addSourceAction(sourceFromServer) - this._redirect(sourceFromServer) - }) - .catch(error => { - this.handleError('Unable to create source', error) - }) - } - updateSource(source) .then(({data: sourceFromServer}) => { - this.props.updateSourceAction(sourceFromServer) + updateSourceAction(sourceFromServer) this._redirect(sourceFromServer) notify('success', `New source ${source.name} added`) }) @@ -124,13 +155,6 @@ class SourcePage extends Component { }) } - handleError = (bannerText, err) => { - const {notify} = this.props - const error = this.parseError(err) - console.error('Error: ', error) - notify('error', `${bannerText}: ${error}`) - } - _redirect = source => { const {isInitialSource} = this.state const {params, router} = this.props @@ -157,7 +181,7 @@ class SourcePage extends Component { return router.push(fixedPath) } - parseError = error => { + _parseError = error => { return _.get(error, ['data', 'message'], error) } diff --git a/ui/src/style/pages/admin.scss b/ui/src/style/pages/admin.scss index fc66cc6f3..715dba70e 100644 --- a/ui/src/style/pages/admin.scss +++ b/ui/src/style/pages/admin.scss @@ -1,30 +1,21 @@ /* Styles for Admin Pages - ---------------------------------------------- + ---------------------------------------------------------------------------- */ - - - /* Admin Tabs - ---------------------------------------------- + ---------------------------------------------------------------------------- */ -.admin-tabs { - padding-right: 0; - & + div {padding-left: 0;} -} .admin-tabs .btn-group { margin: 0; width: 100%; display: flex; - flex-direction: column; align-items: stretch; .tab { font-weight: 500 !important; - border-radius: $radius 0 0 $radius !important; - margin-bottom: 2px !important; + border-radius: $radius $radius 0 0 !important; transition: background-color 0.25s ease, color 0.25s ease !important; @@ -32,7 +23,7 @@ text-align: left; height: 60px !important; line-height: 60px !important; - padding: 0 0 0 16px !important; + padding: 0 30px !important; font-size: 17px; background-color: transparent !important; color: $g11-sidewalk !important; @@ -62,9 +53,29 @@ .panel-heading + .panel-body {padding-top: 0;} } +/* + Responsive Layout for Admin Tabs on Small Screens + ---------------------------------------------------------------------------- +*/ + +@media screen and (min-width: 992px) { + .admin-tabs { + padding-right: 0px; + + .btn-group { + flex-direction: column; + } + .btn-group .tab { + border-radius: $radius 0 0 $radius !important; + padding: 0 0 0 16px !important; + } + & + div {padding-left: 0px;} + } +} + /* Admin Table - ---------------------------------------------- + ---------------------------------------------------------------------------- */ .admin-table .dropdown-toggle { background-color: transparent; @@ -125,7 +136,7 @@ pre.admin-table--query { /* Database Manager - ---------------------------------------------- + ---------------------------------------------------------------------------- */ .db-manager { margin-bottom: 8px; diff --git a/ui/src/style/pages/dashboards.scss b/ui/src/style/pages/dashboards.scss index f0b07700c..aae882209 100644 --- a/ui/src/style/pages/dashboards.scss +++ b/ui/src/style/pages/dashboards.scss @@ -168,7 +168,7 @@ $dash-graph-options-arrow: 8px; position: relative; height: $dash-graph-heading; line-height: $dash-graph-heading; - width: calc(100% - 53px); + width: calc(100% - 78px); padding-left: 10px; transition: color 0.25s ease, background-color 0.25s ease, border-color 0.25s ease;