diff --git a/CHANGELOG.md b/CHANGELOG.md
index 71d3b0ffc4..bd0ee92418 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,12 +2,17 @@
### Bug Fixes
1. [#1337](https://github.com/influxdata/chronograf/pull/1337): Fix no apps for hosts false negative
+ 1. [#1340](https://github.com/influxdata/chronograf/pull/1340): Fix no active query in DE and Cell editing
+ 1. [#1338](https://github.com/influxdata/chronograf/pull/1338): Require url and name when adding a new source
+ 1. [#1348](https://github.com/influxdata/chronograf/pull/1348): Fix broken 'Add Kapacitor' Link
### Features
### UI Improvements
1. [#1335](https://github.com/influxdata/chronograf/pull/1335): Improve UX for sanitized kapacitor settings
1. [#1342](https://github.com/influxdata/chronograf/pull/1342): No more sort-as-you-type in DB admin
+ 1. [#1344](https://github.com/influxdata/chronograf/pull/1344): Remove K8 dashboard
+ 1. [#1340](https://github.com/influxdata/chronograf/pull/1340): Automatically switch to table view if meta query
## v1.2.0-beta9 [2017-04-21]
@@ -17,6 +22,8 @@
1. [#1269](https://github.com/influxdata/chronograf/issues/1269): Add more functionality to the explorer's query generation process
1. [#1318](https://github.com/influxdata/chronograf/issues/1318): Fix JWT refresh for auth-durations of zero and less than five minutes
1. [#1332](https://github.com/influxdata/chronograf/pull/1332): Remove table toggle from dashboard visualization
+ 1. [#1335](https://github.com/influxdata/chronograf/pull/1335): Improve UX for sanitized kapacitor settings
+
### Features
1. [#1232](https://github.com/influxdata/chronograf/pull/1232): Fuse the query builder and raw query editor
diff --git a/ui/src/dashboards/components/DashboardHeader.js b/ui/src/dashboards/components/DashboardHeader.js
index 0ce37f6411..4ab53fab64 100644
--- a/ui/src/dashboards/components/DashboardHeader.js
+++ b/ui/src/dashboards/components/DashboardHeader.js
@@ -32,11 +32,8 @@ const DashboardHeader = ({
-
- }
- {headerText &&
- Kubernetes Dashboard
- }
+ }
+ {headerText}
diff --git a/ui/src/dashboards/containers/DashboardsPage.js b/ui/src/dashboards/containers/DashboardsPage.js
index 4b2ba2f830..99f6b5fd23 100644
--- a/ui/src/dashboards/containers/DashboardsPage.js
+++ b/ui/src/dashboards/containers/DashboardsPage.js
@@ -11,12 +11,7 @@ import {getDashboardsAsync, deleteDashboardAsync} from 'src/dashboards/actions'
import {NEW_DASHBOARD} from 'src/dashboards/constants'
-const {
- arrayOf,
- func,
- string,
- shape,
-} = PropTypes
+const {arrayOf, func, string, shape} = PropTypes
const DashboardsPage = React.createClass({
propTypes: {
@@ -57,10 +52,10 @@ const DashboardsPage = React.createClass({
let tableHeader
if (dashboards === null) {
tableHeader = 'Loading Dashboards...'
- } else if (dashboards.length === 0) {
+ } else if (dashboards.length === 1) {
tableHeader = '1 Dashboard'
} else {
- tableHeader = `${dashboards.length + 1} Dashboards`
+ tableHeader = `${dashboards.length} Dashboards`
}
return (
@@ -84,43 +79,52 @@ const DashboardsPage = React.createClass({
{tableHeader}
- Create Dashboard
+
+ Create Dashboard
+
-
-
-
- Name
-
-
-
-
- {
- dashboards && dashboards.length ?
- dashboards.map((dashboard) => {
- return (
-
-
-
- {dashboard.name}
-
-
-
-
- )
- }) :
- null
- }
-
-
-
- {'Kubernetes'}
-
-
-
-
-
-
+ {dashboards && dashboards.length
+ ?
+
+
+ Name
+
+
+
+
+ {dashboards.map(dashboard => (
+
+
+
+ {dashboard.name}
+
+
+
+
+ ))}
+
+
+ :
+
+ Looks like you dont have any dashboards
+
+
+ Create Dashboard
+
+ }
@@ -137,9 +141,11 @@ const mapStateToProps = ({dashboardUI: {dashboards, dashboard}}) => ({
dashboard,
})
-const mapDispatchToProps = (dispatch) => ({
+const mapDispatchToProps = dispatch => ({
handleGetDashboards: bindActionCreators(getDashboardsAsync, dispatch),
handleDeleteDashboard: bindActionCreators(deleteDashboardAsync, dispatch),
})
-export default connect(mapStateToProps, mapDispatchToProps)(withRouter(DashboardsPage))
+export default connect(mapStateToProps, mapDispatchToProps)(
+ withRouter(DashboardsPage)
+)
diff --git a/ui/src/data_explorer/components/Visualization.js b/ui/src/data_explorer/components/Visualization.js
index 40c3d2789e..410ca2fc98 100644
--- a/ui/src/data_explorer/components/Visualization.js
+++ b/ui/src/data_explorer/components/Visualization.js
@@ -4,8 +4,10 @@ import classNames from 'classnames'
import VisHeader from 'src/data_explorer/components/VisHeader'
import VisView from 'src/data_explorer/components/VisView'
import {GRAPH, TABLE} from 'src/shared/constants'
+import _ from 'lodash'
const {arrayOf, func, number, shape, string} = PropTypes
+const META_QUERY_REGEX = /^show/i
const Visualization = React.createClass({
propTypes: {
@@ -33,18 +35,12 @@ const Visualization = React.createClass({
},
getInitialState() {
- const {queryConfigs, activeQueryIndex} = this.props
- if (!queryConfigs.length || activeQueryIndex === null) {
- return {
- view: GRAPH,
- }
- }
+ const {activeQueryIndex, queryConfigs} = this.props
+ const activeQueryText = this.getQueryText(queryConfigs, activeQueryIndex)
- return {
- view: typeof queryConfigs[activeQueryIndex].rawText === 'string'
- ? TABLE
- : GRAPH,
- }
+ return activeQueryText.match(META_QUERY_REGEX)
+ ? {view: TABLE}
+ : {view: GRAPH}
},
getDefaultProps() {
@@ -54,19 +50,22 @@ const Visualization = React.createClass({
},
componentWillReceiveProps(nextProps) {
- const {queryConfigs, activeQueryIndex} = nextProps
- if (
- !queryConfigs.length ||
- activeQueryIndex === null ||
- activeQueryIndex === this.props.activeQueryIndex
- ) {
+ const {activeQueryIndex, queryConfigs} = nextProps
+ const nextQueryText = this.getQueryText(queryConfigs, activeQueryIndex)
+ const queryText = this.getQueryText(
+ this.props.queryConfigs,
+ this.props.activeQueryIndex
+ )
+
+ if (queryText === nextQueryText) {
return
}
- const activeQuery = queryConfigs[activeQueryIndex]
- if (activeQuery && typeof activeQuery.rawText === 'string') {
+ if (nextQueryText.match(META_QUERY_REGEX)) {
return this.setState({view: TABLE})
}
+
+ this.setState({view: GRAPH})
},
handleToggleView(view) {
@@ -125,6 +124,11 @@ const Visualization = React.createClass({
)
},
+
+ getQueryText(queryConfigs, index) {
+ // rawText can be null
+ return _.get(queryConfigs, [`${index}`, 'rawText'], '') || ''
+ },
})
export default Visualization
diff --git a/ui/src/data_explorer/containers/DataExplorer.js b/ui/src/data_explorer/containers/DataExplorer.js
index 7d8d81e427..33f60d720b 100644
--- a/ui/src/data_explorer/containers/DataExplorer.js
+++ b/ui/src/data_explorer/containers/DataExplorer.js
@@ -57,7 +57,7 @@ const DataExplorer = React.createClass({
getInitialState() {
return {
- activeQueryIndex: null,
+ activeQueryIndex: 0,
}
},
diff --git a/ui/src/index.js b/ui/src/index.js
index 119223a980..c93fd0880a 100644
--- a/ui/src/index.js
+++ b/ui/src/index.js
@@ -9,7 +9,6 @@ import App from 'src/App'
import AlertsApp from 'src/alerts'
import CheckSources from 'src/CheckSources'
import {HostsPage, HostPage} from 'src/hosts'
-import {KubernetesPage} from 'src/kubernetes'
import {Login, UserIsAuthenticated, UserIsNotAuthenticated} from 'src/auth'
import {KapacitorPage, KapacitorRulePage, KapacitorRulesPage, KapacitorTasksPage} from 'src/kapacitor'
import DataExplorer from 'src/data_explorer'
@@ -108,7 +107,6 @@ const Root = React.createClass({
-
diff --git a/ui/src/kubernetes/components/KubernetesDashboard.js b/ui/src/kubernetes/components/KubernetesDashboard.js
deleted file mode 100644
index dac4b6ada3..0000000000
--- a/ui/src/kubernetes/components/KubernetesDashboard.js
+++ /dev/null
@@ -1,107 +0,0 @@
-import React, {PropTypes} from 'react'
-import classnames from 'classnames'
-
-import LayoutRenderer from 'shared/components/LayoutRenderer'
-import DashboardHeader from 'src/dashboards/components/DashboardHeader'
-import timeRanges from 'hson!../../shared/data/timeRanges.hson'
-
-const {
- arrayOf,
- bool,
- func,
- number,
- shape,
- string,
-} = PropTypes
-
-export const KubernetesDashboard = React.createClass({
- propTypes: {
- source: shape({
- links: shape({
- proxy: string.isRequired,
- }).isRequired,
- telegraf: string.isRequired,
- }),
- layouts: arrayOf(shape().isRequired).isRequired,
- autoRefresh: number.isRequired,
- handleChooseAutoRefresh: func.isRequired,
- inPresentationMode: bool.isRequired,
- handleClickPresentationButton: func,
- },
-
- getInitialState() {
- const fifteenMinutesIndex = 1
- return {
- timeRange: timeRanges[fifteenMinutesIndex],
- }
- },
-
- renderLayouts(layouts) {
- const {timeRange} = this.state
- const {source, autoRefresh} = this.props
-
- let layoutCells = []
- layouts.forEach((layout) => {
- layoutCells = layoutCells.concat(layout.cells)
- })
-
- layoutCells.forEach((cell, i) => {
- cell.queries.forEach((q) => {
- q.text = q.query
- q.database = source.telegraf
- })
- cell.x = (i * 4 % 12) // eslint-disable-line no-magic-numbers
- cell.y = 0
- })
-
- return (
-
- )
- },
-
- handleChooseTimeRange({lower}) {
- const timeRange = timeRanges.find((range) => range.lower === lower)
- this.setState({timeRange})
- },
-
- render() {
- const {layouts, autoRefresh, handleChooseAutoRefresh, inPresentationMode, handleClickPresentationButton, source} = this.props
- const {timeRange} = this.state
- const emptyState = (
-
-
-
No Kubernetes configuration found
-
- )
-
- return (
-
-
-
-
- {layouts.length ? this.renderLayouts(layouts) : emptyState}
-
-
-
- )
- },
-})
-
-export default KubernetesDashboard
diff --git a/ui/src/kubernetes/containers/KubernetesPage.js b/ui/src/kubernetes/containers/KubernetesPage.js
deleted file mode 100644
index de342fa2d3..0000000000
--- a/ui/src/kubernetes/containers/KubernetesPage.js
+++ /dev/null
@@ -1,72 +0,0 @@
-import React, {PropTypes} from 'react'
-import {connect} from 'react-redux'
-import {bindActionCreators} from 'redux'
-
-import {fetchLayouts} from 'shared/apis'
-import KubernetesDashboard from 'src/kubernetes/components/KubernetesDashboard'
-
-import {setAutoRefresh} from 'shared/actions/app'
-import {presentationButtonDispatcher} from 'shared/dispatchers'
-
-const {
- bool,
- func,
- number,
- shape,
- string,
-} = PropTypes
-
-export const KubernetesPage = React.createClass({
- propTypes: {
- source: shape({
- links: shape({
- proxy: string.isRequired,
- }).isRequired,
- }),
- autoRefresh: number.isRequired,
- handleChooseAutoRefresh: func.isRequired,
- inPresentationMode: bool.isRequired,
- handleClickPresentationButton: func,
- },
-
- getInitialState() {
- return {
- layouts: [],
- }
- },
-
- componentDidMount() {
- fetchLayouts().then(({data: {layouts}}) => {
- const kubernetesLayouts = layouts.filter((l) => l.app === 'kubernetes')
- this.setState({layouts: kubernetesLayouts})
- })
- },
-
- render() {
- const {layouts} = this.state
- const {source, autoRefresh, handleChooseAutoRefresh, inPresentationMode, handleClickPresentationButton} = this.props
-
- return (
-
- )
- },
-})
-
-const mapStateToProps = ({app: {ephemeral: {inPresentationMode}, persisted: {autoRefresh}}}) => ({
- inPresentationMode,
- autoRefresh,
-})
-
-const mapDispatchToProps = (dispatch) => ({
- handleChooseAutoRefresh: bindActionCreators(setAutoRefresh, dispatch),
- handleClickPresentationButton: presentationButtonDispatcher(dispatch),
-})
-
-export default connect(mapStateToProps, mapDispatchToProps)(KubernetesPage)
diff --git a/ui/src/kubernetes/index.js b/ui/src/kubernetes/index.js
deleted file mode 100644
index 891c2af4d0..0000000000
--- a/ui/src/kubernetes/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import KubernetesPage from './containers/KubernetesPage'
-export {KubernetesPage}
diff --git a/ui/src/shared/components/LayoutRenderer.js b/ui/src/shared/components/LayoutRenderer.js
index 62d76482a4..1721c3a18b 100644
--- a/ui/src/shared/components/LayoutRenderer.js
+++ b/ui/src/shared/components/LayoutRenderer.js
@@ -94,7 +94,7 @@ export const LayoutRenderer = React.createClass({
return cells.map((cell) => {
const qs = cell.queries.map((query) => {
- // TODO: Canned dashboards (and possibly Kubernetes dashboard) use an old query schema,
+ // TODO: Canned dashboards use an old query schema,
// which does not have enough information for the new `buildInfluxQLQuery` function
// to operate on. We will use `buildQueryForOldQuerySchema` until we conform
// on a stable query representation.
diff --git a/ui/src/shared/components/NoKapacitorError.js b/ui/src/shared/components/NoKapacitorError.js
index fda9ce61f8..530a90bead 100644
--- a/ui/src/shared/components/NoKapacitorError.js
+++ b/ui/src/shared/components/NoKapacitorError.js
@@ -9,7 +9,7 @@ const NoKapacitorError = React.createClass({
},
render() {
- const path = `/sources/${this.props.source.id}/kapacitor-config`
+ const path = `/sources/${this.props.source.id}/kapacitors/new`
return (
The current source does not have an associated Kapacitor instance, please configure one.
diff --git a/ui/src/sources/components/SourceForm.js b/ui/src/sources/components/SourceForm.js
index 4dd228a7f2..a5813f3213 100644
--- a/ui/src/sources/components/SourceForm.js
+++ b/ui/src/sources/components/SourceForm.js
@@ -3,11 +3,7 @@ import classNames from 'classnames'
import {insecureSkipVerifyText} from 'src/shared/copy/tooltipText'
import _ from 'lodash'
-const {
- bool,
- func,
- shape,
-} = PropTypes
+const {bool, func, shape} = PropTypes
export const SourceForm = React.createClass({
propTypes: {
@@ -28,7 +24,9 @@ export const SourceForm = React.createClass({
password: this.sourcePassword.value,
'default': this.sourceDefault.checked,
telegraf: this.sourceTelegraf.value,
- insecureSkipVerify: this.sourceInsecureSkipVerify ? this.sourceInsecureSkipVerify.checked : false,
+ insecureSkipVerify: this.sourceInsecureSkipVerify
+ ? this.sourceInsecureSkipVerify.checked
+ : false,
metaUrl: this.metaUrl && this.metaUrl.value.trim(),
}
@@ -56,50 +54,126 @@ export const SourceForm = React.createClass({
return (