From a0bb5a29a2b174c50d77387d24151a79238982cb Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 16 Jun 2017 15:08:55 -0700 Subject: [PATCH 01/10] Modify function selector to optionally work as a single select --- .../data_explorer/components/FieldListItem.js | 38 +--------- ui/src/shared/components/FunctionSelector.js | 74 ++++++++++++------- .../style/components/function-selector.scss | 4 +- 3 files changed, 54 insertions(+), 62 deletions(-) diff --git a/ui/src/data_explorer/components/FieldListItem.js b/ui/src/data_explorer/components/FieldListItem.js index 418a07b953..a91673de08 100644 --- a/ui/src/data_explorer/components/FieldListItem.js +++ b/ui/src/data_explorer/components/FieldListItem.js @@ -3,9 +3,6 @@ import classnames from 'classnames' import _ from 'lodash' import FunctionSelector from 'shared/components/FunctionSelector' -import Dropdown from 'shared/components/Dropdown' - -import {INFLUXQL_FUNCTIONS} from '../constants' const {string, shape, func, arrayOf, bool} = PropTypes const FieldListItem = React.createClass({ @@ -41,7 +38,7 @@ const FieldListItem = React.createClass({ handleApplyFunctions(selectedFuncs) { this.props.onApplyFuncsToField({ field: this.props.fieldFunc.field, - funcs: this.props.isKapacitorRule ? [selectedFuncs.text] : selectedFuncs, + funcs: selectedFuncs, }) this.setState({isOpen: false}) }, @@ -50,38 +47,6 @@ const FieldListItem = React.createClass({ const {isKapacitorRule, fieldFunc, isSelected} = this.props const {isOpen} = this.state const {field: fieldText} = fieldFunc - const items = INFLUXQL_FUNCTIONS.map(text => { - return {text} - }) - - if (isKapacitorRule) { - return ( -
- -
- {fieldText} - - {isSelected - ? - : null} -
- ) - } let fieldFuncsLabel if (!fieldFunc.funcs.length) { @@ -121,6 +86,7 @@ const FieldListItem = React.createClass({ ? : null}
diff --git a/ui/src/shared/components/FunctionSelector.js b/ui/src/shared/components/FunctionSelector.js index 8cc7d73acb..de7e813a2b 100644 --- a/ui/src/shared/components/FunctionSelector.js +++ b/ui/src/shared/components/FunctionSelector.js @@ -12,6 +12,7 @@ class FunctionSelector extends Component { } this.onSelect = ::this.onSelect + this.onSingleSelect = ::this.onSingleSelect this.handleApplyFunctions = ::this.handleApplyFunctions } @@ -36,6 +37,11 @@ class FunctionSelector extends Component { this.setState({localSelectedItems: nextItems}) } + onSingleSelect(item) { + this.props.onApply([item]) + this.setState({localSelectedItems: [item]}) + } + isSelected(item) { return !!this.state.localSelectedItems.find(text => text === item) } @@ -48,47 +54,65 @@ class FunctionSelector extends Component { render() { const {localSelectedItems} = this.state + const {singleSelect} = this.props return (
-
- - {localSelectedItems.length > 0 - ? `${localSelectedItems.length} Selected` - : 'Select functions below'} - -
- Apply -
-
-
- {INFLUXQL_FUNCTIONS.map((f, i) => { - return ( + {singleSelect + ? null + :
+ + {localSelectedItems.length > 0 + ? `${localSelectedItems.length} Selected` + : 'Select functions below'} +
- {f} + Apply
- ) - })} +
} +
+ {singleSelect + ? INFLUXQL_FUNCTIONS.map((f, i) => { + return ( +
+ {f} +
+ ) + }) + : INFLUXQL_FUNCTIONS.map((f, i) => { + return ( +
+ {f} +
+ ) + })}
) } } -const {arrayOf, func, string} = PropTypes +const {arrayOf, bool, func, string} = PropTypes FunctionSelector.propTypes = { onApply: func.isRequired, selectedItems: arrayOf(string.isRequired).isRequired, + singleSelect: bool, } export default FunctionSelector diff --git a/ui/src/style/components/function-selector.scss b/ui/src/style/components/function-selector.scss index a903b00ba0..c0ba4b1a69 100644 --- a/ui/src/style/components/function-selector.scss +++ b/ui/src/style/components/function-selector.scss @@ -33,10 +33,12 @@ $function-selector--text-active: $g20-white; display: flex; flex-wrap: wrap; padding: $function-selector--gutter; - padding-top: 0; border-radius: 0 0 $radius $radius; background-color: $function-selector--bg; } +.function-selector--header + .function-selector--grid { + padding-top: 0; +} .function-selector--item { @include no-user-select(); border-radius: $radius; From e7ba879a9ccc067f3b79a9d818c35e2d833bb5be Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 16 Jun 2017 15:18:31 -0700 Subject: [PATCH 02/10] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 242fa3b144..6424ae98a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ 1. [#1512](https://github.com/influxdata/chronograf/pull/1512): Prevent legend from flowing over window bottom bound 1. [#1600](https://github.com/influxdata/chronograf/pull/1600): Prevent Kapacitor configurations from having the same name 1. [#1600](https://github.com/influxdata/chronograf/pull/1600): Limit Kapacitor configuration names to 33 characters to fix display bug +1. [#1622](https://github.com/influxdata/chronograf/pull/1622): Use function selector grid in Kapacitor rule builder query maker instead of dropdown ### Features 1. [#1512](https://github.com/influxdata/chronograf/pull/1512): Synchronize vertical crosshair at same time across all graphs in a dashboard From 9381265dc77a883e2bdc1accd1dae1cc5ee0daf5 Mon Sep 17 00:00:00 2001 From: Hunter Trujillo Date: Mon, 19 Jun 2017 16:31:53 -0600 Subject: [PATCH 03/10] Adjust synchronizer to omit zoom and range synchronization, for performance reasons. --- ui/src/dashboards/containers/DashboardPage.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/src/dashboards/containers/DashboardPage.js b/ui/src/dashboards/containers/DashboardPage.js index b253862c8a..d6531b62aa 100644 --- a/ui/src/dashboards/containers/DashboardPage.js +++ b/ui/src/dashboards/containers/DashboardPage.js @@ -213,7 +213,11 @@ class DashboardPage extends Component { synchronizer(dygraph) { const dygraphs = [...this.state.dygraphs, dygraph] if (dygraphs.length > 1) { - Dygraph.synchronize(dygraphs) + Dygraph.synchronize(dygraphs, { + selection: true, + zoom: false, + range: false, + }) } this.setState({dygraphs}) } From 9a4d7bdc18d98132f3efa89a3e50be804845993c Mon Sep 17 00:00:00 2001 From: Hunter Trujillo Date: Mon, 19 Jun 2017 16:32:01 -0600 Subject: [PATCH 04/10] Prettier. --- ui/src/dashboards/containers/DashboardPage.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ui/src/dashboards/containers/DashboardPage.js b/ui/src/dashboards/containers/DashboardPage.js index d6531b62aa..b73f3b1c6f 100644 --- a/ui/src/dashboards/containers/DashboardPage.js +++ b/ui/src/dashboards/containers/DashboardPage.js @@ -270,8 +270,10 @@ class DashboardPage extends Component { values: [], } - const templatesIncludingDashTime = (dashboard && - dashboard.templates.concat(dashboardTime).concat(interval)) || [] + const templatesIncludingDashTime = + (dashboard && + dashboard.templates.concat(dashboardTime).concat(interval)) || + [] const {selectedCell, isEditMode, isTemplating} = this.state From 5838c72e08c3c1bba18d99ed476e1823779445ab Mon Sep 17 00:00:00 2001 From: Hunter Trujillo Date: Mon, 19 Jun 2017 16:58:00 -0600 Subject: [PATCH 05/10] Optimize first run of synchronizer initialization. --- ui/src/dashboards/containers/DashboardPage.js | 4 +++- ui/src/hosts/containers/HostPage.js | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/ui/src/dashboards/containers/DashboardPage.js b/ui/src/dashboards/containers/DashboardPage.js index b73f3b1c6f..2b70228ffe 100644 --- a/ui/src/dashboards/containers/DashboardPage.js +++ b/ui/src/dashboards/containers/DashboardPage.js @@ -212,7 +212,9 @@ class DashboardPage extends Component { synchronizer(dygraph) { const dygraphs = [...this.state.dygraphs, dygraph] - if (dygraphs.length > 1) { + const {dashboards, params} = this.props + const dashboard = dashboards.find(d => d.id === +params.dashboardID) + if (dashboard && dygraphs.length === dashboard.cells.length) { Dygraph.synchronize(dygraphs, { selection: true, zoom: false, diff --git a/ui/src/hosts/containers/HostPage.js b/ui/src/hosts/containers/HostPage.js index 888ce10b64..3d474bd94d 100644 --- a/ui/src/hosts/containers/HostPage.js +++ b/ui/src/hosts/containers/HostPage.js @@ -5,6 +5,8 @@ import {bindActionCreators} from 'redux' import _ from 'lodash' import classnames from 'classnames' +import Dygraph from 'src/external/dygraph' + import LayoutRenderer from 'shared/components/LayoutRenderer' import DashboardHeader from 'src/dashboards/components/DashboardHeader' import FancyScrollbar from 'shared/components/FancyScrollbar' @@ -51,6 +53,7 @@ export const HostPage = React.createClass({ layouts: [], hosts: [], timeRange: timeRanges.find(tr => tr.lower === 'now() - 1h'), + dygraphs: [], } }, @@ -100,6 +103,22 @@ export const HostPage = React.createClass({ this.setState({timeRange}) }, + synchronizer(dygraph) { + const dygraphs = [...this.state.dygraphs, dygraph] + const numGraphs = this.state.layouts.reduce((acc, {cells}) => { + return acc + cells.length + }, 0) + + if (dygraphs.length === numGraphs) { + Dygraph.synchronize(dygraphs, { + selection: true, + zoom: false, + range: false, + }) + } + this.setState({dygraphs}) + }, + renderLayouts(layouts) { const {timeRange} = this.state const {source, autoRefresh} = this.props @@ -156,6 +175,7 @@ export const HostPage = React.createClass({ source={source} host={this.props.params.hostID} shouldNotBeEditable={true} + synchronizer={this.synchronizer} /> ) }, From a7261faa9bf2f2a80cf646e795ef62d669a51160 Mon Sep 17 00:00:00 2001 From: Hunter Trujillo Date: Mon, 19 Jun 2017 17:12:17 -0600 Subject: [PATCH 06/10] CHANGELOG. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d54a62f9a..658d3b8238 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ 1. [#1599](https://github.com/influxdata/chronograf/pull/1599): Bar graph option added to dashboard 1. [#1600](https://github.com/influxdata/chronograf/pull/1600): Redesign source management table to be more intuitive 1. [#1600](https://github.com/influxdata/chronograf/pull/1600): Redesign Line + Single Stat cells to appear more like a sparkline, and improve legibility +1. [#1639](https://github.com/influxdata/chronograf/pull/1639): Improve graph synchronization performance ## v1.3.2.1 [2017-06-06] From 927e252885d7e6a73ef5ba24f392cb1329dc0caf Mon Sep 17 00:00:00 2001 From: Alex P Date: Mon, 19 Jun 2017 16:17:05 -0700 Subject: [PATCH 07/10] Consolidate map methods Moved the ternary operator into the onClick --- ui/src/shared/components/FunctionSelector.js | 43 ++++++++------------ 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/ui/src/shared/components/FunctionSelector.js b/ui/src/shared/components/FunctionSelector.js index de7e813a2b..7f0d9b4bec 100644 --- a/ui/src/shared/components/FunctionSelector.js +++ b/ui/src/shared/components/FunctionSelector.js @@ -74,33 +74,22 @@ class FunctionSelector extends Component {
}
- {singleSelect - ? INFLUXQL_FUNCTIONS.map((f, i) => { - return ( -
- {f} -
- ) - }) - : INFLUXQL_FUNCTIONS.map((f, i) => { - return ( -
- {f} -
- ) - })} + {INFLUXQL_FUNCTIONS.map((f, i) => { + return ( +
+ {f} +
+ ) + })}
) From b4c4ad4774c0723931ec0c32d9d6471a5787ec4e Mon Sep 17 00:00:00 2001 From: Alex P Date: Mon, 19 Jun 2017 16:25:51 -0700 Subject: [PATCH 08/10] Add ability to deselect a function was previously impossible to do through the UI --- ui/src/shared/components/FunctionSelector.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ui/src/shared/components/FunctionSelector.js b/ui/src/shared/components/FunctionSelector.js index 7f0d9b4bec..75be5eb5ae 100644 --- a/ui/src/shared/components/FunctionSelector.js +++ b/ui/src/shared/components/FunctionSelector.js @@ -38,8 +38,13 @@ class FunctionSelector extends Component { } onSingleSelect(item) { - this.props.onApply([item]) - this.setState({localSelectedItems: [item]}) + if (item === this.state.localSelectedItems[0]) { + this.props.onApply([]) + this.setState({localSelectedItems: []}) + } else { + this.props.onApply([item]) + this.setState({localSelectedItems: [item]}) + } } isSelected(item) { From 7037167a441880edbabaa045f9b21c443f4e69bb Mon Sep 17 00:00:00 2001 From: Jared Scheib Date: Tue, 20 Jun 2017 11:59:31 -0700 Subject: [PATCH 09/10] Do not prefix external news feed link with basepath --- ui/src/status/apis/index.js | 17 ++++++++++------- ui/src/utils/ajax.js | 29 +++++++++++++++-------------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/ui/src/status/apis/index.js b/ui/src/status/apis/index.js index 984f9b08da..595e658c03 100644 --- a/ui/src/status/apis/index.js +++ b/ui/src/status/apis/index.js @@ -1,10 +1,13 @@ import AJAX from 'utils/ajax' export const fetchJSONFeed = url => - AJAX({ - method: 'GET', - url, - // For explanation of why this header makes this work: - // https://stackoverflow.com/questions/22968406/how-to-skip-the-options-preflight-request-in-angularjs - headers: {'Content-Type': 'text/plain; charset=UTF-8'}, - }) + AJAX( + { + method: 'GET', + url, + // For explanation of why this header makes this work: + // https://stackoverflow.com/questions/22968406/how-to-skip-the-options-preflight-request-in-angularjs + headers: {'Content-Type': 'text/plain; charset=UTF-8'}, + }, + true // don't prefix route of external link with basepath + ) diff --git a/ui/src/utils/ajax.js b/ui/src/utils/ajax.js index 409e6dc280..99c44ab761 100644 --- a/ui/src/utils/ajax.js +++ b/ui/src/utils/ajax.js @@ -2,6 +2,13 @@ import axios from 'axios' let links +// do not prefix route with basepath, ex. for external links +const addBasepath = (url, excludeBasepath) => { + const basepath = window.basepath || '' + + return excludeBasepath ? url : `${basepath}${url}` +} + const generateResponseWithLinks = (response, {auth, logout, external}) => ({ ...response, auth: {links: auth}, @@ -9,24 +16,18 @@ const generateResponseWithLinks = (response, {auth, logout, external}) => ({ external, }) -const AJAX = async ({ - url, - resource, - id, - method = 'GET', - data = {}, - params = {}, - headers = {}, -}) => { +const AJAX = async ( + {url, resource, id, method = 'GET', data = {}, params = {}, headers = {}}, + excludeBasepath +) => { try { - const basepath = window.basepath || '' let response - url = `${basepath}${url}` + url = addBasepath(url, excludeBasepath) if (!links) { const linksRes = (response = await axios({ - url: `${basepath}/chronograf/v1`, + url: addBasepath('/chronograf/v1', excludeBasepath), method: 'GET', })) links = linksRes.data @@ -34,8 +35,8 @@ const AJAX = async ({ if (resource) { url = id - ? `${basepath}${links[resource]}/${id}` - : `${basepath}${links[resource]}` + ? addBasepath(`${links[resource]}/${id}`, excludeBasepath) + : addBasepath(`${links[resource]}`, excludeBasepath) } response = await axios({ From 2df7a7d6ada3d4cd6fdf2ae44972aec524953279 Mon Sep 17 00:00:00 2001 From: Jared Scheib Date: Tue, 20 Jun 2017 12:12:14 -0700 Subject: [PATCH 10/10] Update changelog --- CHANGELOG.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a955578ab0..83447c8f97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,6 @@ -## v1.3.4.0 [unreleased] - +## v1.3.3.1 [2017-06-20] ### Bug Fixes -### Features -### UI Improvements +1. [#1642](https://github.com/influxdata/chronograf/pull/1642): Do not prefix basepath to external link for news feed ## v1.3.3.0 [2017-06-19]