diff --git a/ui/mocks/dummy.ts b/ui/mocks/dummy.ts new file mode 100644 index 0000000000..ffab516810 --- /dev/null +++ b/ui/mocks/dummy.ts @@ -0,0 +1,10 @@ +export const kapacitor = { + id: '1', + name: 'Test Kapacitor', + url: 'http://localhost:9092', + active: true, + links: { + self: '/chronograf/v1/sources/47/kapacitors/1', + proxy: '/chronograf/v1/sources/47/kapacitors/1/proxy', + }, +} diff --git a/ui/mocks/shared/apis/index.js b/ui/mocks/shared/apis/index.js new file mode 100644 index 0000000000..d70eaa530c --- /dev/null +++ b/ui/mocks/shared/apis/index.js @@ -0,0 +1,6 @@ +import {kapacitor} from 'mocks/dummy' + +export const getKapacitor = jest.fn(() => Promise.resolve(kapacitor)) +export const createKapacitor = jest.fn(() => Promise.resolve({data: kapacitor})) +export const updateKapacitor = jest.fn(() => Promise.resolve({data: kapacitor})) +export const pingKapacitor = jest.fn(() => Promise.resolve()) diff --git a/ui/package.json b/ui/package.json index 84cff2f309..dbcd295592 100644 --- a/ui/package.json +++ b/ui/package.json @@ -121,13 +121,13 @@ "react": "^15.0.2", "react-addons-shallow-compare": "^15.0.2", "react-codemirror": "^1.0.0", - "react-component-resizable": "^1.1.0-rc1", "react-custom-scrollbars": "^4.1.1", "react-dimensions": "^1.2.0", "react-dom": "^15.0.2", - "react-grid-layout": "^0.13.9", + "react-grid-layout": "^0.16.6", "react-onclickoutside": "^5.2.0", "react-redux": "^4.4.0", + "react-resizable": "^1.7.5", "react-router": "^3.0.2", "react-router-redux": "^4.0.8", "react-tooltip": "^3.2.1", diff --git a/ui/src/App.js b/ui/src/App.js index 1662a7e5e3..e74c929a6a 100644 --- a/ui/src/App.js +++ b/ui/src/App.js @@ -1,4 +1,5 @@ -import React, {PropTypes} from 'react' +import React from 'react' +import PropTypes from 'prop-types' import {connect} from 'react-redux' import {bindActionCreators} from 'redux' diff --git a/ui/src/CheckSources.js b/ui/src/CheckSources.js index 9872576ba5..ae5c70f796 100644 --- a/ui/src/CheckSources.js +++ b/ui/src/CheckSources.js @@ -1,4 +1,5 @@ -import React, {Component, PropTypes} from 'react' +import React, {Component} from 'react' +import PropTypes from 'prop-types' import {withRouter} from 'react-router' import {connect} from 'react-redux' import {bindActionCreators} from 'redux' diff --git a/ui/src/admin/components/AdminTabs.js b/ui/src/admin/components/AdminTabs.js index 4067a4e43d..8087a1b559 100644 --- a/ui/src/admin/components/AdminTabs.js +++ b/ui/src/admin/components/AdminTabs.js @@ -1,4 +1,5 @@ -import React, {PropTypes} from 'react' +import React from 'react' +import PropTypes from 'prop-types' import {Tab, Tabs, TabPanel, TabPanels, TabList} from 'shared/components/Tabs' import UsersTable from 'src/admin/components/UsersTable' import RolesTable from 'src/admin/components/RolesTable' diff --git a/ui/src/admin/components/ChangePassRow.js b/ui/src/admin/components/ChangePassRow.js index d0d1ee3845..444a88da43 100644 --- a/ui/src/admin/components/ChangePassRow.js +++ b/ui/src/admin/components/ChangePassRow.js @@ -1,4 +1,5 @@ -import React, {Component, PropTypes} from 'react' +import React, {Component} from 'react' +import PropTypes from 'prop-types' import OnClickOutside from 'shared/components/OnClickOutside' import ConfirmButtons from 'shared/components/ConfirmButtons' diff --git a/ui/src/admin/components/DatabaseManager.js b/ui/src/admin/components/DatabaseManager.js index fa4f58f2d2..08f343d159 100644 --- a/ui/src/admin/components/DatabaseManager.js +++ b/ui/src/admin/components/DatabaseManager.js @@ -1,4 +1,5 @@ -import React, {PropTypes} from 'react' +import React from 'react' +import PropTypes from 'prop-types' import DatabaseTable from 'src/admin/components/DatabaseTable' diff --git a/ui/src/admin/components/DatabaseRow.js b/ui/src/admin/components/DatabaseRow.js index 60a216138c..172c112a24 100644 --- a/ui/src/admin/components/DatabaseRow.js +++ b/ui/src/admin/components/DatabaseRow.js @@ -1,4 +1,5 @@ -import React, {PropTypes, Component} from 'react' +import React, {Component} from 'react' +import PropTypes from 'prop-types' import onClickOutside from 'react-onclickoutside' import {formatRPDuration} from 'utils/formatting' diff --git a/ui/src/admin/components/DatabaseTable.js b/ui/src/admin/components/DatabaseTable.js index 9766d63742..084d5a9dad 100644 --- a/ui/src/admin/components/DatabaseTable.js +++ b/ui/src/admin/components/DatabaseTable.js @@ -1,4 +1,5 @@ -import React, {PropTypes} from 'react' +import React from 'react' +import PropTypes from 'prop-types' import _ from 'lodash' import classnames from 'classnames' diff --git a/ui/src/admin/components/DatabaseTableHeader.js b/ui/src/admin/components/DatabaseTableHeader.js index 8afd449459..7f6b481d10 100644 --- a/ui/src/admin/components/DatabaseTableHeader.js +++ b/ui/src/admin/components/DatabaseTableHeader.js @@ -1,4 +1,6 @@ -import React, {PropTypes} from 'react' +import React from 'react' +import PropTypes from 'prop-types' + import ConfirmButtons from 'shared/components/ConfirmButtons' const DatabaseTableHeader = ({ diff --git a/ui/src/admin/components/EmptyRow.js b/ui/src/admin/components/EmptyRow.js index e26587e1f6..b8ffe09d48 100644 --- a/ui/src/admin/components/EmptyRow.js +++ b/ui/src/admin/components/EmptyRow.js @@ -1,4 +1,5 @@ -import React, {PropTypes} from 'react' +import React from 'react' +import PropTypes from 'prop-types' const EmptyRow = ({tableName}) =>
diff --git a/ui/src/kapacitor/components/HandlerInput.js b/ui/src/kapacitor/components/HandlerInput.js
index 35f6d6e960..1b63c2925d 100644
--- a/ui/src/kapacitor/components/HandlerInput.js
+++ b/ui/src/kapacitor/components/HandlerInput.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
const HandlerInput = ({
diff --git a/ui/src/kapacitor/components/HandlerOptions.js b/ui/src/kapacitor/components/HandlerOptions.js
index 5b2c6fdaea..67e39b1a00 100644
--- a/ui/src/kapacitor/components/HandlerOptions.js
+++ b/ui/src/kapacitor/components/HandlerOptions.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {
PostHandler,
TcpHandler,
diff --git a/ui/src/kapacitor/components/HandlerTabs.js b/ui/src/kapacitor/components/HandlerTabs.js
index 980c9a5afc..5e4f62292e 100644
--- a/ui/src/kapacitor/components/HandlerTabs.js
+++ b/ui/src/kapacitor/components/HandlerTabs.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
import uuid from 'uuid'
diff --git a/ui/src/kapacitor/components/KapacitorForm.js b/ui/src/kapacitor/components/KapacitorForm.js
deleted file mode 100644
index 4ec77efb79..0000000000
--- a/ui/src/kapacitor/components/KapacitorForm.js
+++ /dev/null
@@ -1,169 +0,0 @@
-import React, {Component, PropTypes} from 'react'
-
-import AlertTabs from 'src/kapacitor/components/AlertTabs'
-import FancyScrollbar from 'shared/components/FancyScrollbar'
-
-class KapacitorForm extends Component {
- render() {
- const {
- onInputChange,
- onChangeUrl,
- onReset,
- kapacitor,
- onSubmit,
- exists,
- } = this.props
- const {url, name, username, password} = kapacitor
- return (
-
-
-
-
- {`${exists
- ? 'Configure'
- : 'Add a New'} Kapacitor Connection`}
-
-
-
-
-
-
-
-
-
- Connection Details
-
-
-
-
-
-
-
- {this.renderAlertOutputs()}
-
-
-
-
-
- )
- }
-
- // TODO: move these to another page. they dont belong on this page
- renderAlertOutputs() {
- const {exists, kapacitor, addFlashMessage, source, hash} = this.props
-
- if (exists) {
- return (
-
- )
- }
-
- return (
-
-
- Configure Alert Endpoints
-
-
-
-
- Connect to an active Kapacitor instance to configure alerting
- endpoints
-
-
-
-
- )
- }
-}
-
-const {func, shape, string, bool} = PropTypes
-
-KapacitorForm.propTypes = {
- onSubmit: func.isRequired,
- onInputChange: func.isRequired,
- onChangeUrl: func.isRequired,
- onReset: func.isRequired,
- kapacitor: shape({
- url: string.isRequired,
- name: string.isRequired,
- username: string,
- password: string,
- }).isRequired,
- source: shape({}).isRequired,
- addFlashMessage: func.isRequired,
- exists: bool.isRequired,
- hash: string.isRequired,
-}
-
-export default KapacitorForm
diff --git a/ui/src/kapacitor/components/KapacitorForm.tsx b/ui/src/kapacitor/components/KapacitorForm.tsx
new file mode 100644
index 0000000000..38eaf1e62b
--- /dev/null
+++ b/ui/src/kapacitor/components/KapacitorForm.tsx
@@ -0,0 +1,124 @@
+import React, {SFC, ChangeEvent, MouseEvent} from 'react'
+
+import AlertOutputs from 'src/kapacitor/components/AlertOutputs'
+import FancyScrollbar from 'src/shared/components/FancyScrollbar'
+import Input from 'src/kapacitor/components/KapacitorFormInput'
+
+import {Kapacitor, Source} from 'src/types'
+
+type FlashMessage = {type: string; text: string}
+
+interface Props {
+ kapacitor: Kapacitor
+ exists: boolean
+ onReset: (e: MouseEvent) => void
+ onSubmit: (e: ChangeEvent) => void
+ onInputChange: (e: ChangeEvent) => void
+ onChangeUrl: (e: ChangeEvent) => void
+ addFlashMessage: (message: FlashMessage) => void
+ source: Source
+ hash: string
+}
+
+const KapacitorForm: SFC = ({
+ onChangeUrl,
+ onReset,
+ kapacitor,
+ kapacitor: {url, name, username, password},
+ onSubmit,
+ exists,
+ onInputChange,
+ addFlashMessage,
+ source,
+ hash,
+}) =>
+
+
+
+
+ {`${exists
+ ? 'Configure'
+ : 'Add a New'} Kapacitor Connection`}
+
+
+
+
+
+
+
+
+
+ Connection Details
+
+
+
+
+
+
+
+ {
+
+ }
+
+
+
+
+
+
+export default KapacitorForm
diff --git a/ui/src/kapacitor/components/KapacitorFormInput.tsx b/ui/src/kapacitor/components/KapacitorFormInput.tsx
new file mode 100644
index 0000000000..be3afb499a
--- /dev/null
+++ b/ui/src/kapacitor/components/KapacitorFormInput.tsx
@@ -0,0 +1,43 @@
+import React, {SFC, ChangeEvent} from 'react'
+
+interface Props {
+ name: string
+ label: string
+ value: string
+ placeholder: string
+ onChange: (e: ChangeEvent) => void
+ maxLength?: number
+ inputType?: string
+}
+
+const KapacitorFormInput: SFC = ({
+ name,
+ label,
+ value,
+ placeholder,
+ onChange,
+ maxLength,
+ inputType,
+}) =>
+
+
+
+
+
+KapacitorFormInput.defaultProps = {
+ inputType: '',
+}
+
+export default KapacitorFormInput
diff --git a/ui/src/kapacitor/components/KapacitorRule.js b/ui/src/kapacitor/components/KapacitorRule.js
index b61d8f9e13..f7fde915f9 100644
--- a/ui/src/kapacitor/components/KapacitorRule.js
+++ b/ui/src/kapacitor/components/KapacitorRule.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import NameSection from 'src/kapacitor/components/NameSection'
import ValuesSection from 'src/kapacitor/components/ValuesSection'
diff --git a/ui/src/kapacitor/components/KapacitorRules.js b/ui/src/kapacitor/components/KapacitorRules.js
index 6067284868..2909b3a0e0 100644
--- a/ui/src/kapacitor/components/KapacitorRules.js
+++ b/ui/src/kapacitor/components/KapacitorRules.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import {Link} from 'react-router'
import NoKapacitorError from 'shared/components/NoKapacitorError'
diff --git a/ui/src/kapacitor/components/KapacitorRulesTable.js b/ui/src/kapacitor/components/KapacitorRulesTable.js
index df01161448..d894600457 100644
--- a/ui/src/kapacitor/components/KapacitorRulesTable.js
+++ b/ui/src/kapacitor/components/KapacitorRulesTable.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import {Link} from 'react-router'
import _ from 'lodash'
diff --git a/ui/src/kapacitor/components/LogItemHTTP.js b/ui/src/kapacitor/components/LogItemHTTP.js
index 0d8b7a7758..450ce76897 100644
--- a/ui/src/kapacitor/components/LogItemHTTP.js
+++ b/ui/src/kapacitor/components/LogItemHTTP.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
const LogItemHTTP = ({logItem}) =>
diff --git a/ui/src/kapacitor/components/LogItemHTTPError.js b/ui/src/kapacitor/components/LogItemHTTPError.js
index c2f1d74078..0be95e49d6 100644
--- a/ui/src/kapacitor/components/LogItemHTTPError.js
+++ b/ui/src/kapacitor/components/LogItemHTTPError.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
const LogItemHTTPError = ({logItem}) =>
diff --git a/ui/src/kapacitor/components/LogItemInfluxDBDebug.js b/ui/src/kapacitor/components/LogItemInfluxDBDebug.js
index bbbd292df1..4d3734b5bd 100644
--- a/ui/src/kapacitor/components/LogItemInfluxDBDebug.js
+++ b/ui/src/kapacitor/components/LogItemInfluxDBDebug.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
const LogItemInfluxDBDebug = ({logItem}) =>
diff --git a/ui/src/kapacitor/components/LogItemKapacitorDebug.js b/ui/src/kapacitor/components/LogItemKapacitorDebug.js
index 3f694dd4eb..50f0867f15 100644
--- a/ui/src/kapacitor/components/LogItemKapacitorDebug.js
+++ b/ui/src/kapacitor/components/LogItemKapacitorDebug.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
const LogItemKapacitorDebug = ({logItem}) =>
diff --git a/ui/src/kapacitor/components/LogItemKapacitorError.js b/ui/src/kapacitor/components/LogItemKapacitorError.js
index 83fa42b81f..0429bf6d33 100644
--- a/ui/src/kapacitor/components/LogItemKapacitorError.js
+++ b/ui/src/kapacitor/components/LogItemKapacitorError.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
const LogItemKapacitorError = ({logItem}) =>
diff --git a/ui/src/kapacitor/components/LogItemKapacitorPoint.js b/ui/src/kapacitor/components/LogItemKapacitorPoint.js
index 898f656bb4..f8289af109 100644
--- a/ui/src/kapacitor/components/LogItemKapacitorPoint.js
+++ b/ui/src/kapacitor/components/LogItemKapacitorPoint.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
const renderKeysAndValues = (object, name) => {
if (!object) {
diff --git a/ui/src/kapacitor/components/LogItemSession.js b/ui/src/kapacitor/components/LogItemSession.js
index c5c1cb2860..623f9f155a 100644
--- a/ui/src/kapacitor/components/LogItemSession.js
+++ b/ui/src/kapacitor/components/LogItemSession.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
const LogItemSession = ({logItem}) =>
diff --git a/ui/src/kapacitor/components/LogsTable.js b/ui/src/kapacitor/components/LogsTable.js
index 41fee0de53..b4ecdce048 100644
--- a/ui/src/kapacitor/components/LogsTable.js
+++ b/ui/src/kapacitor/components/LogsTable.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import LogsTableRow from 'src/kapacitor/components/LogsTableRow'
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
diff --git a/ui/src/kapacitor/components/LogsTableRow.js b/ui/src/kapacitor/components/LogsTableRow.js
index 83c12bcec0..91c14d4644 100644
--- a/ui/src/kapacitor/components/LogsTableRow.js
+++ b/ui/src/kapacitor/components/LogsTableRow.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import LogItemSession from 'src/kapacitor/components/LogItemSession'
import LogItemHTTP from 'src/kapacitor/components/LogItemHTTP'
diff --git a/ui/src/kapacitor/components/LogsToggle.js b/ui/src/kapacitor/components/LogsToggle.js
index 9820b621b4..af6a2e41ae 100644
--- a/ui/src/kapacitor/components/LogsToggle.js
+++ b/ui/src/kapacitor/components/LogsToggle.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
const LogsToggle = ({areLogsVisible, onToggleLogsVisibility}) =>
diff --git a/ui/src/kapacitor/components/NameSection.js b/ui/src/kapacitor/components/NameSection.js
index 5abbc95adb..025b18c27e 100644
--- a/ui/src/kapacitor/components/NameSection.js
+++ b/ui/src/kapacitor/components/NameSection.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {DEFAULT_RULE_ID} from 'src/kapacitor/constants'
class NameSection extends Component {
diff --git a/ui/src/kapacitor/components/Relative.js b/ui/src/kapacitor/components/Relative.js
index 91709940a5..0ce0935dfe 100644
--- a/ui/src/kapacitor/components/Relative.js
+++ b/ui/src/kapacitor/components/Relative.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import {CHANGES, RELATIVE_OPERATORS, SHIFTS} from 'src/kapacitor/constants'
import Dropdown from 'shared/components/Dropdown'
diff --git a/ui/src/kapacitor/components/RuleDetailsText.js b/ui/src/kapacitor/components/RuleDetailsText.js
index 82d2abf295..ba9a451ef5 100644
--- a/ui/src/kapacitor/components/RuleDetailsText.js
+++ b/ui/src/kapacitor/components/RuleDetailsText.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
class RuleDetailsText extends Component {
constructor(props) {
diff --git a/ui/src/kapacitor/components/RuleGraph.js b/ui/src/kapacitor/components/RuleGraph.js
index b80ea80aa4..a181243aea 100644
--- a/ui/src/kapacitor/components/RuleGraph.js
+++ b/ui/src/kapacitor/components/RuleGraph.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import buildInfluxQLQuery from 'utils/influxql'
import AutoRefresh from 'shared/components/AutoRefresh'
import LineGraph from 'shared/components/LineGraph'
diff --git a/ui/src/kapacitor/components/RuleHandlers.js b/ui/src/kapacitor/components/RuleHandlers.js
index 21ec7864f1..ffe1d3456d 100644
--- a/ui/src/kapacitor/components/RuleHandlers.js
+++ b/ui/src/kapacitor/components/RuleHandlers.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
import HandlerOptions from 'src/kapacitor/components/HandlerOptions'
diff --git a/ui/src/kapacitor/components/RuleHeader.js b/ui/src/kapacitor/components/RuleHeader.js
index bb8246214a..19f95e31a7 100644
--- a/ui/src/kapacitor/components/RuleHeader.js
+++ b/ui/src/kapacitor/components/RuleHeader.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import RuleHeaderSave from 'src/kapacitor/components/RuleHeaderSave'
class RuleHeader extends Component {
diff --git a/ui/src/kapacitor/components/RuleHeaderSave.js b/ui/src/kapacitor/components/RuleHeaderSave.js
index 8a6143d7f3..953dcd808f 100644
--- a/ui/src/kapacitor/components/RuleHeaderSave.js
+++ b/ui/src/kapacitor/components/RuleHeaderSave.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import ReactTooltip from 'react-tooltip'
import SourceIndicator from 'shared/components/SourceIndicator'
diff --git a/ui/src/kapacitor/components/RuleMessage.js b/ui/src/kapacitor/components/RuleMessage.js
index ce9ecc42bc..d5da4f575e 100644
--- a/ui/src/kapacitor/components/RuleMessage.js
+++ b/ui/src/kapacitor/components/RuleMessage.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import RuleMessageText from 'src/kapacitor/components/RuleMessageText'
import RuleMessageTemplates from 'src/kapacitor/components/RuleMessageTemplates'
diff --git a/ui/src/kapacitor/components/RuleMessageTemplates.js b/ui/src/kapacitor/components/RuleMessageTemplates.js
index 82807ed16b..3b0fd01d27 100644
--- a/ui/src/kapacitor/components/RuleMessageTemplates.js
+++ b/ui/src/kapacitor/components/RuleMessageTemplates.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
import ReactTooltip from 'react-tooltip'
diff --git a/ui/src/kapacitor/components/RuleMessageText.js b/ui/src/kapacitor/components/RuleMessageText.js
index 526dc4f43c..8fcb0373a7 100644
--- a/ui/src/kapacitor/components/RuleMessageText.js
+++ b/ui/src/kapacitor/components/RuleMessageText.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
const RuleMessageText = ({rule, updateMessage}) =>
diff --git a/ui/src/kapacitor/components/TICKscriptOverlay.js b/ui/src/kapacitor/components/TICKscriptOverlay.js
index 87762ae8d1..1dda8bab8c 100644
--- a/ui/src/kapacitor/components/TICKscriptOverlay.js
+++ b/ui/src/kapacitor/components/TICKscriptOverlay.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import OverlayTechnologies from 'shared/components/OverlayTechnologies'
const TICKscriptOverlay = ({tickscript, onClose}) =>
diff --git a/ui/src/kapacitor/components/TasksTable.js b/ui/src/kapacitor/components/TasksTable.js
index bf48eb8871..ea49157366 100644
--- a/ui/src/kapacitor/components/TasksTable.js
+++ b/ui/src/kapacitor/components/TasksTable.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import {Link} from 'react-router'
import _ from 'lodash'
diff --git a/ui/src/kapacitor/components/Threshold.js b/ui/src/kapacitor/components/Threshold.js
index b43cfbb89c..3154d99add 100644
--- a/ui/src/kapacitor/components/Threshold.js
+++ b/ui/src/kapacitor/components/Threshold.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import {THRESHOLD_OPERATORS} from 'src/kapacitor/constants'
import Dropdown from 'shared/components/Dropdown'
import _ from 'lodash'
diff --git a/ui/src/kapacitor/components/Tickscript.js b/ui/src/kapacitor/components/Tickscript.js
index 65320d0561..8e9d80b894 100644
--- a/ui/src/kapacitor/components/Tickscript.js
+++ b/ui/src/kapacitor/components/Tickscript.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import TickscriptHeader from 'src/kapacitor/components/TickscriptHeader'
import TickscriptEditor from 'src/kapacitor/components/TickscriptEditor'
diff --git a/ui/src/kapacitor/components/TickscriptEditor.js b/ui/src/kapacitor/components/TickscriptEditor.js
index 1ca8ab717a..571feeba9b 100644
--- a/ui/src/kapacitor/components/TickscriptEditor.js
+++ b/ui/src/kapacitor/components/TickscriptEditor.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import CodeMirror from '@skidding/react-codemirror'
import 'src/external/codemirror'
diff --git a/ui/src/kapacitor/components/TickscriptEditorConsole.js b/ui/src/kapacitor/components/TickscriptEditorConsole.js
index 9940bf92ce..1b9f102dba 100644
--- a/ui/src/kapacitor/components/TickscriptEditorConsole.js
+++ b/ui/src/kapacitor/components/TickscriptEditorConsole.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
const TickscriptEditorConsole = ({consoleMessage, unsavedChanges}) => {
let consoleOutput = 'TICKscript is valid'
diff --git a/ui/src/kapacitor/components/TickscriptEditorControls.js b/ui/src/kapacitor/components/TickscriptEditorControls.js
index aff0961044..2b045090b2 100644
--- a/ui/src/kapacitor/components/TickscriptEditorControls.js
+++ b/ui/src/kapacitor/components/TickscriptEditorControls.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import TickscriptType from 'src/kapacitor/components/TickscriptType'
import MultiSelectDBDropdown from 'shared/components/MultiSelectDBDropdown'
import TickscriptID, {
diff --git a/ui/src/kapacitor/components/TickscriptHeader.js b/ui/src/kapacitor/components/TickscriptHeader.js
index babe033d8c..59b7379523 100644
--- a/ui/src/kapacitor/components/TickscriptHeader.js
+++ b/ui/src/kapacitor/components/TickscriptHeader.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import SourceIndicator from 'shared/components/SourceIndicator'
import LogsToggle from 'src/kapacitor/components/LogsToggle'
diff --git a/ui/src/kapacitor/components/TickscriptID.js b/ui/src/kapacitor/components/TickscriptID.js
index 8121e70505..5d3123c6df 100644
--- a/ui/src/kapacitor/components/TickscriptID.js
+++ b/ui/src/kapacitor/components/TickscriptID.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
class TickscriptID extends Component {
constructor(props) {
diff --git a/ui/src/kapacitor/components/TickscriptType.js b/ui/src/kapacitor/components/TickscriptType.js
index e28a454bc2..3523f1c01f 100644
--- a/ui/src/kapacitor/components/TickscriptType.js
+++ b/ui/src/kapacitor/components/TickscriptType.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
const STREAM = 'stream'
const BATCH = 'batch'
diff --git a/ui/src/kapacitor/components/ValuesSection.js b/ui/src/kapacitor/components/ValuesSection.js
index 551510e95f..903cab6dfc 100644
--- a/ui/src/kapacitor/components/ValuesSection.js
+++ b/ui/src/kapacitor/components/ValuesSection.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
diff --git a/ui/src/kapacitor/components/config/AlertaConfig.js b/ui/src/kapacitor/components/config/AlertaConfig.js
index a55707a6fe..837bd1ca2e 100644
--- a/ui/src/kapacitor/components/config/AlertaConfig.js
+++ b/ui/src/kapacitor/components/config/AlertaConfig.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import RedactedInput from './RedactedInput'
diff --git a/ui/src/kapacitor/components/config/HipChatConfig.js b/ui/src/kapacitor/components/config/HipChatConfig.js
index 0abb95806f..355fa96147 100644
--- a/ui/src/kapacitor/components/config/HipChatConfig.js
+++ b/ui/src/kapacitor/components/config/HipChatConfig.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import QuestionMarkTooltip from 'shared/components/QuestionMarkTooltip'
import {HIPCHAT_TOKEN_TIP} from 'src/kapacitor/copy'
diff --git a/ui/src/kapacitor/components/config/OpsGenieConfig.js b/ui/src/kapacitor/components/config/OpsGenieConfig.js
index 81d9b2ebb4..41427bfe1c 100644
--- a/ui/src/kapacitor/components/config/OpsGenieConfig.js
+++ b/ui/src/kapacitor/components/config/OpsGenieConfig.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import RedactedInput from './RedactedInput'
import TagInput from 'shared/components/TagInput'
diff --git a/ui/src/kapacitor/components/config/PagerDutyConfig.js b/ui/src/kapacitor/components/config/PagerDutyConfig.js
index ece95e13ea..74c6863cdf 100644
--- a/ui/src/kapacitor/components/config/PagerDutyConfig.js
+++ b/ui/src/kapacitor/components/config/PagerDutyConfig.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import RedactedInput from './RedactedInput'
class PagerDutyConfig extends Component {
diff --git a/ui/src/kapacitor/components/config/PushoverConfig.js b/ui/src/kapacitor/components/config/PushoverConfig.js
index bb8b7bf7dd..e0d2593e76 100644
--- a/ui/src/kapacitor/components/config/PushoverConfig.js
+++ b/ui/src/kapacitor/components/config/PushoverConfig.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import QuestionMarkTooltip from 'shared/components/QuestionMarkTooltip'
import RedactedInput from './RedactedInput'
diff --git a/ui/src/kapacitor/components/config/RedactedInput.js b/ui/src/kapacitor/components/config/RedactedInput.js
index 8296be50da..a7d2ba2c5c 100644
--- a/ui/src/kapacitor/components/config/RedactedInput.js
+++ b/ui/src/kapacitor/components/config/RedactedInput.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
class RedactedInput extends Component {
constructor(props) {
diff --git a/ui/src/kapacitor/components/config/SMTPConfig.js b/ui/src/kapacitor/components/config/SMTPConfig.js
index 4b3a57272d..b635adc35a 100644
--- a/ui/src/kapacitor/components/config/SMTPConfig.js
+++ b/ui/src/kapacitor/components/config/SMTPConfig.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
class SMTPConfig extends Component {
constructor(props) {
diff --git a/ui/src/kapacitor/components/config/SensuConfig.js b/ui/src/kapacitor/components/config/SensuConfig.js
index 6bf01c2f7e..59ba63f63e 100644
--- a/ui/src/kapacitor/components/config/SensuConfig.js
+++ b/ui/src/kapacitor/components/config/SensuConfig.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
class SensuConfig extends Component {
constructor(props) {
diff --git a/ui/src/kapacitor/components/config/SlackConfig.js b/ui/src/kapacitor/components/config/SlackConfig.js
index 7dcfb1a701..1acba68ee0 100644
--- a/ui/src/kapacitor/components/config/SlackConfig.js
+++ b/ui/src/kapacitor/components/config/SlackConfig.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import RedactedInput from './RedactedInput'
diff --git a/ui/src/kapacitor/components/config/TalkConfig.js b/ui/src/kapacitor/components/config/TalkConfig.js
index 94c9206088..10599c92fe 100644
--- a/ui/src/kapacitor/components/config/TalkConfig.js
+++ b/ui/src/kapacitor/components/config/TalkConfig.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import RedactedInput from './RedactedInput'
diff --git a/ui/src/kapacitor/components/config/TelegramConfig.js b/ui/src/kapacitor/components/config/TelegramConfig.js
index 3cf40b73e7..03fcf727fe 100644
--- a/ui/src/kapacitor/components/config/TelegramConfig.js
+++ b/ui/src/kapacitor/components/config/TelegramConfig.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import QuestionMarkTooltip from 'shared/components/QuestionMarkTooltip'
import {TELEGRAM_CHAT_ID_TIP, TELEGRAM_TOKEN_TIP} from 'src/kapacitor/copy'
diff --git a/ui/src/kapacitor/components/config/VictorOpsConfig.js b/ui/src/kapacitor/components/config/VictorOpsConfig.js
index 62c241ca48..e70159d888 100644
--- a/ui/src/kapacitor/components/config/VictorOpsConfig.js
+++ b/ui/src/kapacitor/components/config/VictorOpsConfig.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import RedactedInput from './RedactedInput'
diff --git a/ui/src/kapacitor/components/handlers/AlertaHandler.js b/ui/src/kapacitor/components/handlers/AlertaHandler.js
index 38d4b5ad22..692942ba61 100644
--- a/ui/src/kapacitor/components/handlers/AlertaHandler.js
+++ b/ui/src/kapacitor/components/handlers/AlertaHandler.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
diff --git a/ui/src/kapacitor/components/handlers/EmailHandler.js b/ui/src/kapacitor/components/handlers/EmailHandler.js
index ddd2175a3a..953c7340ac 100644
--- a/ui/src/kapacitor/components/handlers/EmailHandler.js
+++ b/ui/src/kapacitor/components/handlers/EmailHandler.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
import RuleDetailsText from 'src/kapacitor/components/RuleDetailsText'
diff --git a/ui/src/kapacitor/components/handlers/ExecHandler.js b/ui/src/kapacitor/components/handlers/ExecHandler.js
index c2f92e2535..136083909f 100644
--- a/ui/src/kapacitor/components/handlers/ExecHandler.js
+++ b/ui/src/kapacitor/components/handlers/ExecHandler.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
const ExecHandler = ({selectedHandler, handleModifyHandler}) =>
diff --git a/ui/src/kapacitor/components/handlers/HipchatHandler.js b/ui/src/kapacitor/components/handlers/HipchatHandler.js
index bca39be612..bca5098859 100644
--- a/ui/src/kapacitor/components/handlers/HipchatHandler.js
+++ b/ui/src/kapacitor/components/handlers/HipchatHandler.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
diff --git a/ui/src/kapacitor/components/handlers/LogHandler.js b/ui/src/kapacitor/components/handlers/LogHandler.js
index 586c4770c5..2eabf11165 100644
--- a/ui/src/kapacitor/components/handlers/LogHandler.js
+++ b/ui/src/kapacitor/components/handlers/LogHandler.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
const LogHandler = ({selectedHandler, handleModifyHandler}) =>
diff --git a/ui/src/kapacitor/components/handlers/OpsgenieHandler.js b/ui/src/kapacitor/components/handlers/OpsgenieHandler.js
index 783c20ec3d..e7ee1fe253 100644
--- a/ui/src/kapacitor/components/handlers/OpsgenieHandler.js
+++ b/ui/src/kapacitor/components/handlers/OpsgenieHandler.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
diff --git a/ui/src/kapacitor/components/handlers/PagerdutyHandler.js b/ui/src/kapacitor/components/handlers/PagerdutyHandler.js
index 400654e2eb..1f0700143e 100644
--- a/ui/src/kapacitor/components/handlers/PagerdutyHandler.js
+++ b/ui/src/kapacitor/components/handlers/PagerdutyHandler.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
diff --git a/ui/src/kapacitor/components/handlers/PostHandler.js b/ui/src/kapacitor/components/handlers/PostHandler.js
index 42df3eb8d4..e5b4879004 100644
--- a/ui/src/kapacitor/components/handlers/PostHandler.js
+++ b/ui/src/kapacitor/components/handlers/PostHandler.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
const PostHandler = ({selectedHandler, handleModifyHandler}) =>
diff --git a/ui/src/kapacitor/components/handlers/PushoverHandler.js b/ui/src/kapacitor/components/handlers/PushoverHandler.js
index 5b2f12c7f9..e9a97aa346 100644
--- a/ui/src/kapacitor/components/handlers/PushoverHandler.js
+++ b/ui/src/kapacitor/components/handlers/PushoverHandler.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
diff --git a/ui/src/kapacitor/components/handlers/SensuHandler.js b/ui/src/kapacitor/components/handlers/SensuHandler.js
index 00d530469d..acb746312b 100644
--- a/ui/src/kapacitor/components/handlers/SensuHandler.js
+++ b/ui/src/kapacitor/components/handlers/SensuHandler.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
diff --git a/ui/src/kapacitor/components/handlers/SlackHandler.js b/ui/src/kapacitor/components/handlers/SlackHandler.js
index 2a2ebd1acf..74f1192583 100644
--- a/ui/src/kapacitor/components/handlers/SlackHandler.js
+++ b/ui/src/kapacitor/components/handlers/SlackHandler.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
diff --git a/ui/src/kapacitor/components/handlers/TalkHandler.js b/ui/src/kapacitor/components/handlers/TalkHandler.js
index 5b24b8b864..e842efa6da 100644
--- a/ui/src/kapacitor/components/handlers/TalkHandler.js
+++ b/ui/src/kapacitor/components/handlers/TalkHandler.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
diff --git a/ui/src/kapacitor/components/handlers/TcpHandler.js b/ui/src/kapacitor/components/handlers/TcpHandler.js
index 9e8aeadef6..739023a5b8 100644
--- a/ui/src/kapacitor/components/handlers/TcpHandler.js
+++ b/ui/src/kapacitor/components/handlers/TcpHandler.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
const TcpHandler = ({selectedHandler, handleModifyHandler}) =>
diff --git a/ui/src/kapacitor/components/handlers/TelegramHandler.js b/ui/src/kapacitor/components/handlers/TelegramHandler.js
index fcc2cfe428..d46d640d77 100644
--- a/ui/src/kapacitor/components/handlers/TelegramHandler.js
+++ b/ui/src/kapacitor/components/handlers/TelegramHandler.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerCheckbox from 'src/kapacitor/components/HandlerCheckbox'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
diff --git a/ui/src/kapacitor/components/handlers/VictoropsHandler.js b/ui/src/kapacitor/components/handlers/VictoropsHandler.js
index 9aa00bbcb9..dd90655ff2 100644
--- a/ui/src/kapacitor/components/handlers/VictoropsHandler.js
+++ b/ui/src/kapacitor/components/handlers/VictoropsHandler.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
diff --git a/ui/src/kapacitor/containers/KapacitorPage.js b/ui/src/kapacitor/containers/KapacitorPage.js
deleted file mode 100644
index 79fd256783..0000000000
--- a/ui/src/kapacitor/containers/KapacitorPage.js
+++ /dev/null
@@ -1,180 +0,0 @@
-import React, {Component, PropTypes} from 'react'
-import {withRouter} from 'react-router'
-
-import {
- getKapacitor,
- createKapacitor,
- updateKapacitor,
- pingKapacitor,
-} from 'shared/apis'
-import KapacitorForm from '../components/KapacitorForm'
-
-const defaultName = 'My Kapacitor'
-const kapacitorPort = '9092'
-
-class KapacitorPage extends Component {
- constructor(props) {
- super(props)
- this.state = {
- kapacitor: {
- url: this._parseKapacitorURL(),
- name: defaultName,
- username: '',
- password: '',
- },
- exists: false,
- }
- }
-
- componentDidMount() {
- const {source, params: {id}} = this.props
- if (!id) {
- return
- }
-
- getKapacitor(source, id).then(kapacitor => {
- this.setState({kapacitor})
- this.checkKapacitorConnection(kapacitor)
- })
- }
-
- checkKapacitorConnection = async kapacitor => {
- try {
- await pingKapacitor(kapacitor)
- this.setState({exists: true})
- } catch (error) {
- this.setState({exists: false})
- this.props.addFlashMessage({
- type: 'error',
- text: 'Could not connect to Kapacitor. Check settings.',
- })
- }
- }
-
- handleInputChange = e => {
- const {value, name} = e.target
-
- this.setState(prevState => {
- const update = {[name]: value}
- return {kapacitor: {...prevState.kapacitor, ...update}}
- })
- }
-
- handleChangeUrl = e => {
- this.setState({kapacitor: {...this.state.kapacitor, url: e.target.value}})
- }
-
- handleSubmit = e => {
- e.preventDefault()
- const {
- addFlashMessage,
- source,
- source: {kapacitors = []},
- params,
- router,
- } = this.props
- const {kapacitor} = this.state
- kapacitor.name = kapacitor.name.trim()
- const isNameTaken = kapacitors.some(k => k.name === kapacitor.name)
- const isNew = !params.id
-
- if (isNew && isNameTaken) {
- addFlashMessage({
- type: 'error',
- text: `There is already a Kapacitor configuration named "${kapacitor.name}"`,
- })
- return
- }
-
- if (params.id) {
- updateKapacitor(kapacitor)
- .then(({data}) => {
- this.setState({kapacitor: data})
- this.checkKapacitorConnection(data)
- addFlashMessage({type: 'success', text: 'Kapacitor Updated!'})
- })
- .catch(() => {
- addFlashMessage({
- type: 'error',
- text: 'There was a problem updating the Kapacitor record',
- })
- })
- } else {
- createKapacitor(source, kapacitor)
- .then(({data}) => {
- // need up update kapacitor with info from server to AlertOutputs
- this.setState({kapacitor: data})
- this.checkKapacitorConnection(data)
- router.push(`/sources/${source.id}/kapacitors/${data.id}/edit`)
- addFlashMessage({
- type: 'success',
- text: 'Kapacitor Created! Configuring endpoints is optional.',
- })
- })
- .catch(() => {
- addFlashMessage({
- type: 'error',
- text: 'There was a problem creating the Kapacitor record',
- })
- })
- }
- }
-
- handleResetToDefaults = e => {
- e.preventDefault()
- const defaultState = {
- url: this._parseKapacitorURL(),
- name: defaultName,
- username: '',
- password: '',
- }
-
- this.setState({kapacitor: {...defaultState}})
- }
-
- _parseKapacitorURL = () => {
- const parser = document.createElement('a')
- parser.href = this.props.source.url
-
- return `${parser.protocol}//${parser.hostname}:${kapacitorPort}`
- }
-
- render() {
- const {source, addFlashMessage, location, params} = this.props
- const hash = (location && location.hash) || (params && params.hash) || ''
- const {kapacitor, exists} = this.state
- return (
-
- )
- }
-}
-
-const {array, func, shape, string} = PropTypes
-
-KapacitorPage.propTypes = {
- addFlashMessage: func,
- params: shape({
- id: string,
- }).isRequired,
- router: shape({
- push: func.isRequired,
- }).isRequired,
- source: shape({
- id: string.isRequired,
- url: string.isRequired,
- kapacitors: array,
- }),
- location: shape({pathname: string, hash: string}).isRequired,
-}
-
-export default withRouter(KapacitorPage)
diff --git a/ui/src/kapacitor/containers/KapacitorPage.tsx b/ui/src/kapacitor/containers/KapacitorPage.tsx
new file mode 100644
index 0000000000..eabfa17f16
--- /dev/null
+++ b/ui/src/kapacitor/containers/KapacitorPage.tsx
@@ -0,0 +1,211 @@
+import React, {PureComponent, ChangeEvent} from 'react'
+import {withRouter} from 'react-router'
+
+import {Source} from 'src/types'
+
+import {
+ getKapacitor,
+ createKapacitor,
+ updateKapacitor,
+ pingKapacitor,
+} from 'src/shared/apis'
+
+import KapacitorForm from '../components/KapacitorForm'
+
+export const defaultName = 'My Kapacitor'
+export const kapacitorPort = '9092'
+
+type FlashMessage = {type: string; text: string}
+
+interface Kapacitor {
+ url: string
+ name: string
+ username: string
+ password: string
+ active: boolean
+ links: {
+ self: string
+ }
+}
+
+interface Props {
+ source: Source
+ addFlashMessage: (message: FlashMessage) => void
+ kapacitor: Kapacitor
+ router: {push: (url: string) => void}
+ location: {pathname: string; hash: string}
+ params: {id: string; hash: string}
+}
+
+interface State {
+ kapacitor: Kapacitor
+ exists: boolean
+}
+
+export class KapacitorPage extends PureComponent {
+ constructor(props) {
+ super(props)
+ this.state = {
+ kapacitor: {
+ url: this.parseKapacitorURL(),
+ name: defaultName,
+ username: '',
+ password: '',
+ active: false,
+ links: {
+ self: '',
+ },
+ },
+ exists: false,
+ }
+
+ this.handleSubmit = this.handleSubmit.bind(this)
+ }
+
+ async componentDidMount() {
+ const {source, params: {id}, addFlashMessage} = this.props
+ if (!id) {
+ return
+ }
+
+ try {
+ const kapacitor = await getKapacitor(source, id)
+ this.setState({kapacitor})
+ await this.checkKapacitorConnection(kapacitor)
+ } catch (err) {
+ console.error('Could not get kapacitor: ', err)
+ addFlashMessage({
+ type: 'error',
+ text: 'Could not connect to Kapacitor',
+ })
+ }
+ }
+
+ handleInputChange = (e: ChangeEvent) => {
+ const {value, name} = e.target
+
+ this.setState(prevState => {
+ const update = {[name]: value}
+ return {kapacitor: {...prevState.kapacitor, ...update}}
+ })
+ }
+
+ handleChangeUrl = e => {
+ this.setState({kapacitor: {...this.state.kapacitor, url: e.target.value}})
+ }
+
+ handleSubmit = async e => {
+ e.preventDefault()
+ const {
+ addFlashMessage,
+ source,
+ source: {kapacitors = []},
+ params,
+ router,
+ } = this.props
+
+ const {kapacitor} = this.state
+ kapacitor.name = kapacitor.name.trim()
+ const isNameTaken = kapacitors.some(k => k.name === kapacitor.name)
+ const isNew = !params.id
+
+ if (isNew && isNameTaken) {
+ addFlashMessage({
+ type: 'error',
+ text: `There is already a Kapacitor configuration named "${kapacitor.name}"`,
+ })
+ return
+ }
+
+ if (params.id) {
+ try {
+ const {data} = await updateKapacitor(kapacitor)
+ this.setState({kapacitor: data})
+ this.checkKapacitorConnection(data)
+ addFlashMessage({type: 'success', text: 'Kapacitor Updated!'})
+ } catch (error) {
+ console.error(error)
+ addFlashMessage({
+ type: 'error',
+ text: 'There was a problem updating the Kapacitor record',
+ })
+ }
+ } else {
+ try {
+ const {data} = await createKapacitor(source, kapacitor)
+ // need up update kapacitor with info from server to AlertOutputs
+ this.setState({kapacitor: data})
+ this.checkKapacitorConnection(data)
+ router.push(`/sources/${source.id}/kapacitors/${data.id}/edit`)
+ addFlashMessage({
+ type: 'success',
+ text: 'Kapacitor Created! Configuring endpoints is optional.',
+ })
+ } catch (error) {
+ console.error(error)
+ addFlashMessage({
+ type: 'error',
+ text: 'There was a problem creating the Kapacitor record',
+ })
+ }
+ }
+ }
+
+ handleResetToDefaults = e => {
+ e.preventDefault()
+ const defaultState = {
+ url: this.parseKapacitorURL(),
+ name: defaultName,
+ username: '',
+ password: '',
+ active: false,
+ links: {
+ self: '',
+ },
+ }
+
+ this.setState({kapacitor: {...defaultState}})
+ }
+
+ private checkKapacitorConnection = async (kapacitor: Kapacitor) => {
+ try {
+ await pingKapacitor(kapacitor)
+ this.setState({exists: true})
+ } catch (error) {
+ this.setState({exists: false})
+ this.props.addFlashMessage({
+ type: 'error',
+ text: 'Could not connect to Kapacitor. Check settings.',
+ })
+ }
+ }
+
+ private parseKapacitorURL = () => {
+ const parser = document.createElement('a')
+ parser.href = this.props.source.url
+
+ return `${parser.protocol}//${parser.hostname}:${kapacitorPort}`
+ }
+
+ render() {
+ const {source, addFlashMessage, location, params} = this.props
+ const hash = (location && location.hash) || (params && params.hash) || ''
+ const {kapacitor, exists} = this.state
+
+ return (
+
+ )
+ }
+}
+
+export default withRouter(KapacitorPage)
diff --git a/ui/src/kapacitor/containers/KapacitorRulePage.js b/ui/src/kapacitor/containers/KapacitorRulePage.js
index 5a0abcd562..daf9728505 100644
--- a/ui/src/kapacitor/containers/KapacitorRulePage.js
+++ b/ui/src/kapacitor/containers/KapacitorRulePage.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import * as kapacitorRuleActionCreators from 'src/kapacitor/actions/view'
diff --git a/ui/src/kapacitor/containers/KapacitorRulesPage.js b/ui/src/kapacitor/containers/KapacitorRulesPage.js
index 68931be1bd..65fa946fad 100644
--- a/ui/src/kapacitor/containers/KapacitorRulesPage.js
+++ b/ui/src/kapacitor/containers/KapacitorRulesPage.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
import {getActiveKapacitor} from 'shared/apis'
diff --git a/ui/src/kapacitor/containers/KapacitorTasksPage.js b/ui/src/kapacitor/containers/KapacitorTasksPage.js
index dc8d6c348e..5ae7aed4c2 100644
--- a/ui/src/kapacitor/containers/KapacitorTasksPage.js
+++ b/ui/src/kapacitor/containers/KapacitorTasksPage.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
export const KapacitorTasksPage = React.createClass({
propTypes: {
diff --git a/ui/src/kapacitor/containers/TickscriptPage.js b/ui/src/kapacitor/containers/TickscriptPage.js
index 2a4f821d3a..92bad77cca 100644
--- a/ui/src/kapacitor/containers/TickscriptPage.js
+++ b/ui/src/kapacitor/containers/TickscriptPage.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
import uuid from 'uuid'
diff --git a/ui/src/shared/components/Annotation.js b/ui/src/shared/components/Annotation.js
index bb972f613b..56fd17e65e 100644
--- a/ui/src/shared/components/Annotation.js
+++ b/ui/src/shared/components/Annotation.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import AnnotationPoint from 'shared/components/AnnotationPoint'
import AnnotationSpan from 'shared/components/AnnotationSpan'
diff --git a/ui/src/shared/components/AnnotationInput.js b/ui/src/shared/components/AnnotationInput.js
index 1c559bf0c7..64ec098dc7 100644
--- a/ui/src/shared/components/AnnotationInput.js
+++ b/ui/src/shared/components/AnnotationInput.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import onClickOutside from 'react-onclickoutside'
class AnnotationInput extends Component {
diff --git a/ui/src/shared/components/AnnotationPoint.js b/ui/src/shared/components/AnnotationPoint.js
index 8407387153..84a7fdbe35 100644
--- a/ui/src/shared/components/AnnotationPoint.js
+++ b/ui/src/shared/components/AnnotationPoint.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {
diff --git a/ui/src/shared/components/AnnotationSpan.js b/ui/src/shared/components/AnnotationSpan.js
index 1bf2001670..84a8e89c35 100644
--- a/ui/src/shared/components/AnnotationSpan.js
+++ b/ui/src/shared/components/AnnotationSpan.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {
diff --git a/ui/src/shared/components/AnnotationTooltip.js b/ui/src/shared/components/AnnotationTooltip.js
index b0d5b8f833..08a77f0341 100644
--- a/ui/src/shared/components/AnnotationTooltip.js
+++ b/ui/src/shared/components/AnnotationTooltip.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import moment from 'moment'
import classnames from 'classnames'
diff --git a/ui/src/shared/components/AnnotationWindow.js b/ui/src/shared/components/AnnotationWindow.js
index 909745cf46..5837cae2db 100644
--- a/ui/src/shared/components/AnnotationWindow.js
+++ b/ui/src/shared/components/AnnotationWindow.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import {
DYGRAPH_CONTAINER_H_MARGIN,
diff --git a/ui/src/shared/components/Annotations.js b/ui/src/shared/components/Annotations.js
index d0c0a9ff0a..558f7697f2 100644
--- a/ui/src/shared/components/Annotations.js
+++ b/ui/src/shared/components/Annotations.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
diff --git a/ui/src/shared/components/AutoRefresh.js b/ui/src/shared/components/AutoRefresh.js
index 5cf7e286a0..43c49f63e7 100644
--- a/ui/src/shared/components/AutoRefresh.js
+++ b/ui/src/shared/components/AutoRefresh.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
import {fetchTimeSeriesAsync} from 'shared/actions/timeSeries'
diff --git a/ui/src/shared/components/AutoRefreshDropdown.js b/ui/src/shared/components/AutoRefreshDropdown.js
index 9310aeb678..d31430e006 100644
--- a/ui/src/shared/components/AutoRefreshDropdown.js
+++ b/ui/src/shared/components/AutoRefreshDropdown.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
import OnClickOutside from 'shared/components/OnClickOutside'
diff --git a/ui/src/shared/components/ClickOutsideInput.js b/ui/src/shared/components/ClickOutsideInput.js
index 8d4155a76a..47b573c59c 100644
--- a/ui/src/shared/components/ClickOutsideInput.js
+++ b/ui/src/shared/components/ClickOutsideInput.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import onClickOutside from 'shared/components/OnClickOutside'
diff --git a/ui/src/shared/components/ColorDropdown.js b/ui/src/shared/components/ColorDropdown.js
index 8d8275e603..515a492bde 100644
--- a/ui/src/shared/components/ColorDropdown.js
+++ b/ui/src/shared/components/ColorDropdown.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
import OnClickOutside from 'shared/components/OnClickOutside'
diff --git a/ui/src/shared/components/CustomTimeIndicator.js b/ui/src/shared/components/CustomTimeIndicator.js
index 16fd558364..a74e619407 100644
--- a/ui/src/shared/components/CustomTimeIndicator.js
+++ b/ui/src/shared/components/CustomTimeIndicator.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
const CustomTimeIndicator = ({queries}) => {
diff --git a/ui/src/shared/components/CustomTimeRange.js b/ui/src/shared/components/CustomTimeRange.js
index d497217286..c0486ddda2 100644
--- a/ui/src/shared/components/CustomTimeRange.js
+++ b/ui/src/shared/components/CustomTimeRange.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import rome from 'rome'
import moment from 'moment'
diff --git a/ui/src/shared/components/CustomTimeRangeDropdown.js b/ui/src/shared/components/CustomTimeRangeDropdown.js
index e7e998776d..cb35a4e039 100644
--- a/ui/src/shared/components/CustomTimeRangeDropdown.js
+++ b/ui/src/shared/components/CustomTimeRangeDropdown.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import moment from 'moment'
import classnames from 'classnames'
import OnClickOutside from 'react-onclickoutside'
diff --git a/ui/src/shared/components/CustomTimeRangeOverlay.js b/ui/src/shared/components/CustomTimeRangeOverlay.js
index 04e941c702..b7c395a9ce 100644
--- a/ui/src/shared/components/CustomTimeRangeOverlay.js
+++ b/ui/src/shared/components/CustomTimeRangeOverlay.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import OnClickOutside from 'react-onclickoutside'
import CustomTimeRange from 'shared/components/CustomTimeRange'
diff --git a/ui/src/shared/components/DeleteConfirmButtons.js b/ui/src/shared/components/DeleteConfirmButtons.js
index 1f85e29917..11f80f8d17 100644
--- a/ui/src/shared/components/DeleteConfirmButtons.js
+++ b/ui/src/shared/components/DeleteConfirmButtons.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
import OnClickOutside from 'shared/components/OnClickOutside'
diff --git a/ui/src/shared/components/Dygraph.js b/ui/src/shared/components/Dygraph.js
index 5d58c3fde1..eff78785ba 100644
--- a/ui/src/shared/components/Dygraph.js
+++ b/ui/src/shared/components/Dygraph.js
@@ -1,5 +1,6 @@
/* eslint-disable no-magic-numbers */
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import shallowCompare from 'react-addons-shallow-compare'
import _ from 'lodash'
diff --git a/ui/src/shared/components/DygraphLegend.js b/ui/src/shared/components/DygraphLegend.js
index 433a6b0fe1..d490747cdb 100644
--- a/ui/src/shared/components/DygraphLegend.js
+++ b/ui/src/shared/components/DygraphLegend.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
import classnames from 'classnames'
import uuid from 'uuid'
diff --git a/ui/src/shared/components/EmptyQuery.js b/ui/src/shared/components/EmptyQuery.js
index e42cca09d9..9511c6480e 100644
--- a/ui/src/shared/components/EmptyQuery.js
+++ b/ui/src/shared/components/EmptyQuery.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
const EmptyQueryState = ({onAddQuery}) =>
diff --git a/ui/src/shared/components/FieldList.js b/ui/src/shared/components/FieldList.js
index dd2db74860..6aa4ffcab3 100644
--- a/ui/src/shared/components/FieldList.js
+++ b/ui/src/shared/components/FieldList.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
import QueryOptions from 'shared/components/QueryOptions'
diff --git a/ui/src/shared/components/FillQuery.js b/ui/src/shared/components/FillQuery.js
index b126752486..7b42a2c007 100644
--- a/ui/src/shared/components/FillQuery.js
+++ b/ui/src/shared/components/FillQuery.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import Dropdown from 'shared/components/Dropdown'
import {NULL_STRING, NUMBER} from 'shared/constants/queryFillOptions'
diff --git a/ui/src/shared/components/FunctionSelector.js b/ui/src/shared/components/FunctionSelector.js
index 9a977784df..0ee308baa4 100644
--- a/ui/src/shared/components/FunctionSelector.js
+++ b/ui/src/shared/components/FunctionSelector.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
import _ from 'lodash'
import {INFLUXQL_FUNCTIONS} from 'src/data_explorer/constants'
diff --git a/ui/src/shared/components/Gauge.js b/ui/src/shared/components/Gauge.js
index aa18fd8eda..704fa37fb0 100644
--- a/ui/src/shared/components/Gauge.js
+++ b/ui/src/shared/components/Gauge.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
import {GAUGE_SPECS} from 'shared/constants/gaugeSpecs'
diff --git a/ui/src/shared/components/GaugeChart.js b/ui/src/shared/components/GaugeChart.js
index 9362af8747..d280df2072 100644
--- a/ui/src/shared/components/GaugeChart.js
+++ b/ui/src/shared/components/GaugeChart.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, PureComponent} from 'react'
+import React, {PureComponent} from 'react'
+import PropTypes from 'prop-types'
import lastValues from 'shared/parsing/lastValues'
import Gauge from 'shared/components/Gauge'
diff --git a/ui/src/shared/components/InfiniteScroll.js b/ui/src/shared/components/InfiniteScroll.js
index 9854ef1afa..1be5787aca 100644
--- a/ui/src/shared/components/InfiniteScroll.js
+++ b/ui/src/shared/components/InfiniteScroll.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
import {Scrollbars} from 'react-custom-scrollbars'
import _ from 'lodash'
diff --git a/ui/src/shared/components/InputClickToEdit.js b/ui/src/shared/components/InputClickToEdit.js
new file mode 100644
index 0000000000..6d6daa1699
--- /dev/null
+++ b/ui/src/shared/components/InputClickToEdit.js
@@ -0,0 +1,108 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+
+class InputClickToEdit extends Component {
+ constructor(props) {
+ super(props)
+
+ this.state = {
+ isEditing: null,
+ value: this.props.value,
+ }
+ }
+
+ handleCancel = () => {
+ this.setState({
+ isEditing: false,
+ value: this.props.value,
+ })
+ }
+
+ handleInputClick = () => {
+ this.setState({isEditing: true})
+ }
+
+ handleInputBlur = e => {
+ const {onUpdate, value} = this.props
+
+ if (value !== e.target.value) {
+ onUpdate(e.target.value)
+ }
+
+ this.setState({isEditing: false, value: e.target.value})
+ }
+
+ handleKeyDown = e => {
+ if (e.key === 'Enter') {
+ this.handleInputBlur(e)
+ }
+ if (e.key === 'Escape') {
+ this.handleCancel()
+ }
+ }
+
+ handleFocus = e => {
+ e.target.select()
+ }
+
+ render() {
+ const {isEditing, value} = this.state
+ const {
+ wrapperClass: wrapper,
+ disabled,
+ tabIndex,
+ placeholder,
+ appearAsNormalInput,
+ } = this.props
+
+ const wrapperClass = `${wrapper}${appearAsNormalInput
+ ? ' input-cte__normal'
+ : ''}`
+ const defaultStyle = value ? 'input-cte' : 'input-cte__empty'
+
+ return disabled
+ ?
+
+ {value}
+
+
+ :
+ {isEditing
+ ? (this.inputRef = r)}
+ tabIndex={tabIndex}
+ spellCheck={false}
+ />
+ :
+ {value || placeholder}
+ {appearAsNormalInput || }
+ }
+
+ }
+}
+
+const {func, bool, number, string} = PropTypes
+
+InputClickToEdit.propTypes = {
+ wrapperClass: string.isRequired,
+ value: string,
+ onUpdate: func.isRequired,
+ disabled: bool,
+ tabIndex: number,
+ placeholder: string,
+ appearAsNormalInput: bool,
+}
+
+export default InputClickToEdit
diff --git a/ui/src/shared/components/Layout.js b/ui/src/shared/components/Layout.js
index 96548e422e..71b9e88c77 100644
--- a/ui/src/shared/components/Layout.js
+++ b/ui/src/shared/components/Layout.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import WidgetCell from 'shared/components/WidgetCell'
import LayoutCell from 'shared/components/LayoutCell'
import RefreshingGraph from 'shared/components/RefreshingGraph'
diff --git a/ui/src/shared/components/LayoutCell.js b/ui/src/shared/components/LayoutCell.js
index 91360f6c43..e0fd20caaa 100644
--- a/ui/src/shared/components/LayoutCell.js
+++ b/ui/src/shared/components/LayoutCell.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'
diff --git a/ui/src/shared/components/LayoutCellHeader.js b/ui/src/shared/components/LayoutCellHeader.js
index cf7aa147dc..64878f1ec3 100644
--- a/ui/src/shared/components/LayoutCellHeader.js
+++ b/ui/src/shared/components/LayoutCellHeader.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import {NEW_DEFAULT_DASHBOARD_CELL} from 'src/dashboards/constants/index'
const LayoutCellHeader = ({isEditable, cellName}) => {
diff --git a/ui/src/shared/components/LayoutCellMenu.js b/ui/src/shared/components/LayoutCellMenu.js
index 267d6217aa..e8080b66fc 100644
--- a/ui/src/shared/components/LayoutCellMenu.js
+++ b/ui/src/shared/components/LayoutCellMenu.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
diff --git a/ui/src/shared/components/LayoutRenderer.js b/ui/src/shared/components/LayoutRenderer.js
index 0b8f975753..f853071e41 100644
--- a/ui/src/shared/components/LayoutRenderer.js
+++ b/ui/src/shared/components/LayoutRenderer.js
@@ -1,8 +1,7 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import ReactGridLayout, {WidthProvider} from 'react-grid-layout'
-import Resizeable from 'react-component-resizable'
-
-import _ from 'lodash'
+import {ResizableBox} from 'react-resizable'
import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'
@@ -55,12 +54,8 @@ class LayoutRenderer extends Component {
: DASHBOARD_LAYOUT_ROW_HEIGHT
}
- handleCellResize = (__, oldCoords, resizeCoords) => {
- if (_.isEqual(oldCoords, resizeCoords)) {
- return
- }
-
- this.setState({resizeCoords})
+ handleCellResize = () => {
+ this.resizeCoords = this.setState({resizeCoords: new Date()})
}
render() {
@@ -86,7 +81,11 @@ class LayoutRenderer extends Component {
const isDashboard = !!this.props.onPositionChange
return (
-
+
-
+
)
}
}
diff --git a/ui/src/shared/components/LineGraph.js b/ui/src/shared/components/LineGraph.js
index 4cc8b00789..7c73e8ae76 100644
--- a/ui/src/shared/components/LineGraph.js
+++ b/ui/src/shared/components/LineGraph.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import Dygraph from 'shared/components/Dygraph'
import shallowCompare from 'react-addons-shallow-compare'
diff --git a/ui/src/shared/components/LoadingDots.js b/ui/src/shared/components/LoadingDots.js
index 51a5543c6b..e5f1c8cda8 100644
--- a/ui/src/shared/components/LoadingDots.js
+++ b/ui/src/shared/components/LoadingDots.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
const LoadingDots = ({className}) =>
diff --git a/ui/src/shared/components/MenuTooltipButton.js b/ui/src/shared/components/MenuTooltipButton.js
index 13b691167b..58b8b9fc89 100644
--- a/ui/src/shared/components/MenuTooltipButton.js
+++ b/ui/src/shared/components/MenuTooltipButton.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import OnClickOutside from 'react-onclickoutside'
import classnames from 'classnames'
diff --git a/ui/src/shared/components/MiniGraph.js b/ui/src/shared/components/MiniGraph.js
index a79ccb6abd..79ce1f23fd 100644
--- a/ui/src/shared/components/MiniGraph.js
+++ b/ui/src/shared/components/MiniGraph.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import Dygraph from './Dygraph'
import shallowCompare from 'react-addons-shallow-compare'
diff --git a/ui/src/shared/components/MultiSelectDBDropdown.js b/ui/src/shared/components/MultiSelectDBDropdown.js
index 050789a33e..4ba5ed535b 100644
--- a/ui/src/shared/components/MultiSelectDBDropdown.js
+++ b/ui/src/shared/components/MultiSelectDBDropdown.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {showDatabases, showRetentionPolicies} from 'shared/apis/metaQuery'
import showDatabasesParser from 'shared/parsing/showDatabases'
diff --git a/ui/src/shared/components/MultiSelectDropdown.js b/ui/src/shared/components/MultiSelectDropdown.js
index 5abbd159b3..dd1aa64bfd 100644
--- a/ui/src/shared/components/MultiSelectDropdown.js
+++ b/ui/src/shared/components/MultiSelectDropdown.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
import _ from 'lodash'
diff --git a/ui/src/shared/components/NewAnnotation.js b/ui/src/shared/components/NewAnnotation.js
index a53a5343c2..c1c591fac2 100644
--- a/ui/src/shared/components/NewAnnotation.js
+++ b/ui/src/shared/components/NewAnnotation.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
import {connect} from 'react-redux'
import uuid from 'uuid'
diff --git a/ui/src/shared/components/NoKapacitorError.js b/ui/src/shared/components/NoKapacitorError.js
index 05cf2af522..1712f0286a 100644
--- a/ui/src/shared/components/NoKapacitorError.js
+++ b/ui/src/shared/components/NoKapacitorError.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import {Link} from 'react-router'
import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'
diff --git a/ui/src/shared/components/Notifications.js b/ui/src/shared/components/Notifications.js
index d45d840c88..43e4ab2231 100644
--- a/ui/src/shared/components/Notifications.js
+++ b/ui/src/shared/components/Notifications.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
import {withRouter} from 'react-router'
import {connect} from 'react-redux'
diff --git a/ui/src/shared/components/OptIn.js b/ui/src/shared/components/OptIn.js
index 541cf9be80..265c081351 100644
--- a/ui/src/shared/components/OptIn.js
+++ b/ui/src/shared/components/OptIn.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
import uuid from 'uuid'
diff --git a/ui/src/shared/components/OverlayTechnologies.js b/ui/src/shared/components/OverlayTechnologies.js
index 8f3e6089bc..96d0651006 100644
--- a/ui/src/shared/components/OverlayTechnologies.js
+++ b/ui/src/shared/components/OverlayTechnologies.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import {OVERLAY_TECHNOLOGY} from 'shared/constants/classNames'
diff --git a/ui/src/shared/components/PanelBody.js b/ui/src/shared/components/PanelBody.js
index caa0ed44ec..307ebafdac 100644
--- a/ui/src/shared/components/PanelBody.js
+++ b/ui/src/shared/components/PanelBody.js
@@ -1,6 +1,7 @@
import React from 'react'
+import PropTypes from 'prop-types'
-const {node} = React.PropTypes
+const {node} = PropTypes
const PanelBody = React.createClass({
propTypes: {
children: node.isRequired,
diff --git a/ui/src/shared/components/PanelHeading.js b/ui/src/shared/components/PanelHeading.js
index c46aa2e49d..e5200e39dc 100644
--- a/ui/src/shared/components/PanelHeading.js
+++ b/ui/src/shared/components/PanelHeading.js
@@ -1,6 +1,7 @@
import React from 'react'
+import PropTypes from 'prop-types'
-const {node} = React.PropTypes
+const {node} = PropTypes
const PanelHeading = React.createClass({
propTypes: {
children: node.isRequired,
diff --git a/ui/src/shared/components/QueryOptions.js b/ui/src/shared/components/QueryOptions.js
index d02ee02408..a922ddad31 100644
--- a/ui/src/shared/components/QueryOptions.js
+++ b/ui/src/shared/components/QueryOptions.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import GroupByTimeDropdown from 'src/data_explorer/components/GroupByTimeDropdown'
import TimeShiftDropdown from 'src/shared/components/TimeShiftDropdown'
import FillQuery from 'shared/components/FillQuery'
diff --git a/ui/src/shared/components/QueryStatus.js b/ui/src/shared/components/QueryStatus.js
index 9fa329a38c..1eaadb93b9 100644
--- a/ui/src/shared/components/QueryStatus.js
+++ b/ui/src/shared/components/QueryStatus.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import LoadingDots from 'shared/components/LoadingDots'
import classnames from 'classnames'
diff --git a/ui/src/shared/components/QueryTabList.js b/ui/src/shared/components/QueryTabList.js
index 49d7225764..b7078ba6bf 100644
--- a/ui/src/shared/components/QueryTabList.js
+++ b/ui/src/shared/components/QueryTabList.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import QueryMakerTab from 'src/data_explorer/components/QueryMakerTab'
import buildInfluxQLQuery from 'utils/influxql'
diff --git a/ui/src/shared/components/QuestionMarkTooltip.js b/ui/src/shared/components/QuestionMarkTooltip.js
index bad9352ab9..5c14253783 100644
--- a/ui/src/shared/components/QuestionMarkTooltip.js
+++ b/ui/src/shared/components/QuestionMarkTooltip.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import ReactTooltip from 'react-tooltip'
const QuestionMarkTooltip = ({tipID, tipContent}) =>
diff --git a/ui/src/shared/components/RefreshingGraph.js b/ui/src/shared/components/RefreshingGraph.js
index 588efdb7d4..7a1544c404 100644
--- a/ui/src/shared/components/RefreshingGraph.js
+++ b/ui/src/shared/components/RefreshingGraph.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import {emptyGraphCopy} from 'src/shared/copy/cell'
diff --git a/ui/src/shared/components/ResizeContainer.js b/ui/src/shared/components/ResizeContainer.js
index 95076f2013..f4ebfc0673 100644
--- a/ui/src/shared/components/ResizeContainer.js
+++ b/ui/src/shared/components/ResizeContainer.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
import ResizeHandle from 'shared/components/ResizeHandle'
diff --git a/ui/src/shared/components/ResizeHandle.js b/ui/src/shared/components/ResizeHandle.js
index 86585f17b6..cb57728942 100644
--- a/ui/src/shared/components/ResizeHandle.js
+++ b/ui/src/shared/components/ResizeHandle.js
@@ -1,7 +1,8 @@
import React from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
-const {func, bool, string} = React.PropTypes
+const {func, bool, string} = PropTypes
const ResizeHandle = React.createClass({
propTypes: {
onHandleStartDrag: func.isRequired,
diff --git a/ui/src/shared/components/RoleIndicator.js b/ui/src/shared/components/RoleIndicator.js
index 5854a0ba05..ce99e3bc55 100644
--- a/ui/src/shared/components/RoleIndicator.js
+++ b/ui/src/shared/components/RoleIndicator.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import uuid from 'uuid'
import {connect} from 'react-redux'
diff --git a/ui/src/shared/components/SchemaExplorer.js b/ui/src/shared/components/SchemaExplorer.js
index e3326b2310..d48369a736 100644
--- a/ui/src/shared/components/SchemaExplorer.js
+++ b/ui/src/shared/components/SchemaExplorer.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import DatabaseList from 'src/shared/components/DatabaseList'
import MeasurementList from 'src/shared/components/MeasurementList'
diff --git a/ui/src/shared/components/SingleStat.js b/ui/src/shared/components/SingleStat.js
index 9161466f86..a560ddf462 100644
--- a/ui/src/shared/components/SingleStat.js
+++ b/ui/src/shared/components/SingleStat.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, PureComponent} from 'react'
+import React, {PureComponent} from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
import lastValues from 'shared/parsing/lastValues'
diff --git a/ui/src/shared/components/SlideToggle.js b/ui/src/shared/components/SlideToggle.js
index 3597e9ab14..7e478b1d81 100644
--- a/ui/src/shared/components/SlideToggle.js
+++ b/ui/src/shared/components/SlideToggle.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
class SlideToggle extends Component {
constructor(props) {
diff --git a/ui/src/shared/components/SourceIndicator.js b/ui/src/shared/components/SourceIndicator.js
index e6d1892193..b7e7200800 100644
--- a/ui/src/shared/components/SourceIndicator.js
+++ b/ui/src/shared/components/SourceIndicator.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
import uuid from 'uuid'
diff --git a/ui/src/shared/components/SplashPage.js b/ui/src/shared/components/SplashPage.js
index 237dc2d1be..955cb253ce 100644
--- a/ui/src/shared/components/SplashPage.js
+++ b/ui/src/shared/components/SplashPage.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
const SplashPage = ({children}) =>
diff --git a/ui/src/shared/components/StaticLegend.js b/ui/src/shared/components/StaticLegend.js
index 5b49cc71e2..a268fb42cd 100644
--- a/ui/src/shared/components/StaticLegend.js
+++ b/ui/src/shared/components/StaticLegend.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
import uuid from 'uuid'
import {removeMeasurement} from 'shared/graphs/helpers'
diff --git a/ui/src/shared/components/TableGraph.js b/ui/src/shared/components/TableGraph.js
index 5d90cbc20c..0d9124f276 100644
--- a/ui/src/shared/components/TableGraph.js
+++ b/ui/src/shared/components/TableGraph.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
import classnames from 'classnames'
import {timeSeriesToTable} from 'src/utils/timeSeriesToDygraph'
diff --git a/ui/src/shared/components/Tabs.js b/ui/src/shared/components/Tabs.js
deleted file mode 100644
index afb84ff2d6..0000000000
--- a/ui/src/shared/components/Tabs.js
+++ /dev/null
@@ -1,176 +0,0 @@
-import React, {PropTypes} from 'react'
-import classnames from 'classnames'
-
-const {node, func, bool, number, string} = PropTypes
-export const Tab = React.createClass({
- propTypes: {
- children: node.isRequired,
- onClick: func,
- isDisabled: bool,
- isActive: bool,
- isKapacitorTab: bool,
- isConfigured: bool,
- },
-
- render() {
- if (this.props.isKapacitorTab) {
- return (
- -
- {this.props.children}
-
- )
- }
- return (
-
- {this.props.children}
-
- )
- },
-})
-
-export const TabList = React.createClass({
- propTypes: {
- children: node.isRequired,
- activeIndex: number,
- onActivate: func,
- isKapacitorTabs: string,
- customClass: string,
- },
-
- getDefaultProps() {
- return {
- isKapacitorTabs: '',
- }
- },
-
- render() {
- const children = React.Children.map(this.props.children, (child, index) => {
- return React.cloneElement(child, {
- isActive: index === this.props.activeIndex,
- onClick: () => this.props.onActivate(index),
- })
- })
-
- if (this.props.isKapacitorTabs === 'true') {
- return (
-
- Choose One:
-
- {children}
-
-
- )
- }
-
- if (this.props.customClass) {
- return (
-
-
- {children}
-
-
- )
- }
-
- return (
-
- {children}
-
- )
- },
-})
-
-export const TabPanels = React.createClass({
- propTypes: {
- children: node.isRequired,
- activeIndex: number,
- customClass: string,
- },
-
- // if only 1 child, children array index lookup will fail
- render() {
- return (
-
- {this.props.children[this.props.activeIndex]}
-
- )
- },
-})
-
-export const TabPanel = React.createClass({
- propTypes: {
- children: node.isRequired,
- },
-
- render() {
- return (
-
- {this.props.children}
-
- )
- },
-})
-
-export const Tabs = React.createClass({
- propTypes: {
- children: node.isRequired,
- onSelect: func,
- tabContentsClass: string,
- tabsClass: string,
- initialIndex: number,
- },
-
- getDefaultProps() {
- return {
- onSelect() {},
- tabContentsClass: '',
- }
- },
-
- getInitialState() {
- // initialIndex allows the user to enable a Tab and TabPanel
- // other than 0 on initial render.
- return {
- activeIndex: this.props.initialIndex || 0,
- }
- },
-
- handleActivateTab(activeIndex) {
- this.setState({activeIndex})
- this.props.onSelect(activeIndex)
- },
-
- render() {
- const children = React.Children.map(this.props.children, child => {
- if (child && child.type === TabPanels) {
- return React.cloneElement(child, {
- activeIndex: this.state.activeIndex,
- })
- }
-
- if (child && child.type === TabList) {
- return React.cloneElement(child, {
- activeIndex: this.state.activeIndex,
- onActivate: this.handleActivateTab,
- })
- }
-
- return child
- })
-
- return (
-
- {children}
-
- )
- },
-})
diff --git a/ui/src/shared/components/Tabs.tsx b/ui/src/shared/components/Tabs.tsx
new file mode 100644
index 0000000000..56408e9c31
--- /dev/null
+++ b/ui/src/shared/components/Tabs.tsx
@@ -0,0 +1,186 @@
+import React, {SFC, ReactElement, PureComponent} from 'react'
+import classnames from 'classnames'
+
+interface TabProps {
+ children: JSX.Element[] | JSX.Element
+ onClick: () => void
+ isDisabled: boolean
+ isActive: boolean
+ isKapacitorTab: boolean
+ isConfigured: boolean
+}
+
+export const Tab: SFC = ({
+ children,
+ onClick,
+ isDisabled,
+ isActive,
+ isKapacitorTab,
+ isConfigured,
+}) => {
+ if (isKapacitorTab) {
+ return (
+ -
+ {children}
+
+ )
+ }
+
+ return (
+
+ {children}
+
+ )
+}
+
+interface TabListProps {
+ children: JSX.Element[] | JSX.Element
+ activeIndex: number
+ onActivate: (index: number) => void
+ isKapacitorTabs: string
+ customClass: string
+}
+
+export const TabList: SFC = ({
+ children,
+ activeIndex,
+ onActivate,
+ isKapacitorTabs,
+ customClass,
+}) => {
+ const kids = React.Children.map(
+ children,
+ (child: ReactElement, index) => {
+ return React.cloneElement(child, {
+ isActive: index === activeIndex,
+ onClick: () => onActivate(index),
+ })
+ }
+ )
+
+ if (isKapacitorTabs === 'true') {
+ return (
+
+ Choose One:
+
+ {kids}
+
+
+ )
+ }
+
+ if (customClass) {
+ return (
+
+
+ {kids}
+
+
+ )
+ }
+
+ return (
+
+ {kids}
+
+ )
+}
+
+TabList.defaultProps = {
+ isKapacitorTabs: '',
+}
+
+interface TabPanelsProps {
+ children: JSX.Element[] | JSX.Element
+ activeIndex: number
+ customClass: string
+}
+
+export const TabPanels: SFC = ({
+ children,
+ activeIndex,
+ customClass,
+}) =>
+ // if only 1 child, children array index lookup will fail
+
+ {children[activeIndex]}
+
+
+interface TabPanelProps {
+ children: JSX.Element[] | JSX.Element
+}
+
+export const TabPanel: SFC = ({children}) =>
+
+ {children}
+
+
+interface TabsProps {
+ children: JSX.Element[] | JSX.Element
+ onSelect: (activeIndex: number) => void
+ tabContentsClass: string
+ tabsClass: string
+ initialIndex: number
+}
+
+interface TabsState {
+ activeIndex: number
+}
+
+export class Tabs extends PureComponent {
+ constructor(props) {
+ super(props)
+
+ // initialIndex allows the user to enable a Tab and TabPanel
+ // other than 0 on initial render.
+ this.state = {
+ activeIndex: this.props.initialIndex || 0,
+ }
+ }
+
+ public static defaultProps: Partial = {
+ onSelect: () => {},
+ tabContentsClass: '',
+ }
+
+ handleActivateTab = activeIndex => {
+ this.setState({activeIndex})
+ this.props.onSelect(activeIndex)
+ }
+
+ render() {
+ const {children, tabContentsClass} = this.props
+
+ const kids = React.Children.map(children, (child: ReactElement) => {
+ if (child && child.type === TabPanels) {
+ return React.cloneElement(child, {
+ activeIndex: this.state.activeIndex,
+ })
+ }
+
+ if (child && child.type === TabList) {
+ return React.cloneElement(child, {
+ activeIndex: this.state.activeIndex,
+ onActivate: this.handleActivateTab,
+ })
+ }
+
+ return child
+ })
+
+ return (
+
+ {kids}
+
+ )
+ }
+}
diff --git a/ui/src/shared/components/TagInput.js b/ui/src/shared/components/TagInput.js
index 6fd7d6f039..a246daf085 100644
--- a/ui/src/shared/components/TagInput.js
+++ b/ui/src/shared/components/TagInput.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
import Tags from 'shared/components/Tags'
diff --git a/ui/src/shared/components/Tags.js b/ui/src/shared/components/Tags.js
index 7a0897ed43..b7b4bc47a5 100644
--- a/ui/src/shared/components/Tags.js
+++ b/ui/src/shared/components/Tags.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import TagsAddButton from 'src/shared/components/TagsAddButton'
import ConfirmButton from 'src/shared/components/ConfirmButton'
diff --git a/ui/src/shared/components/TagsAddButton.js b/ui/src/shared/components/TagsAddButton.js
index 7f59b74969..8a3a74de16 100644
--- a/ui/src/shared/components/TagsAddButton.js
+++ b/ui/src/shared/components/TagsAddButton.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import OnClickOutside from 'shared/components/OnClickOutside'
import uuid from 'uuid'
diff --git a/ui/src/shared/components/TemplateDrawer.js b/ui/src/shared/components/TemplateDrawer.js
index db58f4cfed..80e360c788 100644
--- a/ui/src/shared/components/TemplateDrawer.js
+++ b/ui/src/shared/components/TemplateDrawer.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import OnClickOutside from 'react-onclickoutside'
import classnames from 'classnames'
diff --git a/ui/src/shared/components/TimeRangeDropdown.js b/ui/src/shared/components/TimeRangeDropdown.js
index 1626574836..50559e9175 100644
--- a/ui/src/shared/components/TimeRangeDropdown.js
+++ b/ui/src/shared/components/TimeRangeDropdown.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
import moment from 'moment'
diff --git a/ui/src/shared/components/TimeShiftDropdown.js b/ui/src/shared/components/TimeShiftDropdown.js
index 066be7fd19..20a3b2dbf5 100644
--- a/ui/src/shared/components/TimeShiftDropdown.js
+++ b/ui/src/shared/components/TimeShiftDropdown.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import Dropdown from 'shared/components/Dropdown'
import {TIME_SHIFTS} from 'shared/constants/timeShift'
diff --git a/ui/src/shared/components/Tooltip.js b/ui/src/shared/components/Tooltip.js
index 8022cd273a..eb93ffa7db 100644
--- a/ui/src/shared/components/Tooltip.js
+++ b/ui/src/shared/components/Tooltip.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import ReactTooltip from 'react-tooltip'
const Tooltip = ({tip, children}) =>
diff --git a/ui/src/shared/components/WidgetCell.js b/ui/src/shared/components/WidgetCell.js
index 098b686851..c2930f6a62 100644
--- a/ui/src/shared/components/WidgetCell.js
+++ b/ui/src/shared/components/WidgetCell.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import AlertsApp from 'src/alerts/containers/AlertsApp'
import NewsFeed from 'src/status/components/NewsFeed'
diff --git a/ui/src/shared/components/YesNoButtons.js b/ui/src/shared/components/YesNoButtons.js
index b9cae1c2ba..b74bf21821 100644
--- a/ui/src/shared/components/YesNoButtons.js
+++ b/ui/src/shared/components/YesNoButtons.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
const YesNoButtons = ({onConfirm, onCancel, buttonSize}) =>
diff --git a/ui/src/shared/schemas.js b/ui/src/shared/schemas.js
index b012e1a2d8..35df59a72b 100644
--- a/ui/src/shared/schemas.js
+++ b/ui/src/shared/schemas.js
@@ -1,4 +1,4 @@
-import {PropTypes} from 'react'
+import PropTypes from 'prop-types'
const {shape, string} = PropTypes
diff --git a/ui/src/side_nav/components/NavItems.js b/ui/src/side_nav/components/NavItems.js
index c0761582a7..f9f3e23533 100644
--- a/ui/src/side_nav/components/NavItems.js
+++ b/ui/src/side_nav/components/NavItems.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import {Link} from 'react-router'
import classnames from 'classnames'
diff --git a/ui/src/side_nav/components/UserNavBlock.js b/ui/src/side_nav/components/UserNavBlock.js
index 4883dcf96e..cda37afc99 100644
--- a/ui/src/side_nav/components/UserNavBlock.js
+++ b/ui/src/side_nav/components/UserNavBlock.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
import {withRouter} from 'react-router'
diff --git a/ui/src/side_nav/containers/SideNav.js b/ui/src/side_nav/containers/SideNav.js
index 633f543fa5..55ca9cca17 100644
--- a/ui/src/side_nav/containers/SideNav.js
+++ b/ui/src/side_nav/containers/SideNav.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import {withRouter, Link} from 'react-router'
import {connect} from 'react-redux'
diff --git a/ui/src/side_nav/modals/RenameCluster.js b/ui/src/side_nav/modals/RenameCluster.js
index 20f16ace29..d4bc36b524 100644
--- a/ui/src/side_nav/modals/RenameCluster.js
+++ b/ui/src/side_nav/modals/RenameCluster.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
const {func} = PropTypes
const RenameCluster = React.createClass({
diff --git a/ui/src/sources/components/InfluxTable.js b/ui/src/sources/components/InfluxTable.js
index 98eb9f3a85..fef5936b1b 100644
--- a/ui/src/sources/components/InfluxTable.js
+++ b/ui/src/sources/components/InfluxTable.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import {Link, withRouter} from 'react-router'
import {connect} from 'react-redux'
diff --git a/ui/src/sources/components/SourceForm.js b/ui/src/sources/components/SourceForm.js
index 6275928da8..9c97ef5a10 100644
--- a/ui/src/sources/components/SourceForm.js
+++ b/ui/src/sources/components/SourceForm.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import classnames from 'classnames'
import {connect} from 'react-redux'
import _ from 'lodash'
diff --git a/ui/src/sources/containers/ManageSources.js b/ui/src/sources/containers/ManageSources.js
index 24b2b915bf..cca6b5ff6a 100644
--- a/ui/src/sources/containers/ManageSources.js
+++ b/ui/src/sources/containers/ManageSources.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
diff --git a/ui/src/sources/containers/SourcePage.js b/ui/src/sources/containers/SourcePage.js
index 1dc7b1cfae..812004952c 100644
--- a/ui/src/sources/containers/SourcePage.js
+++ b/ui/src/sources/containers/SourcePage.js
@@ -1,4 +1,5 @@
-import React, {PropTypes, Component} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {withRouter} from 'react-router'
import _ from 'lodash'
import {getSource} from 'shared/apis'
diff --git a/ui/src/status/components/JSONFeedReader.js b/ui/src/status/components/JSONFeedReader.js
index ca7274610b..7ed520fa65 100644
--- a/ui/src/status/components/JSONFeedReader.js
+++ b/ui/src/status/components/JSONFeedReader.js
@@ -1,4 +1,5 @@
-import React, {PropTypes} from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
import moment from 'moment'
diff --git a/ui/src/status/components/NewsFeed.js b/ui/src/status/components/NewsFeed.js
index d643ac3708..11bb92098a 100644
--- a/ui/src/status/components/NewsFeed.js
+++ b/ui/src/status/components/NewsFeed.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
diff --git a/ui/src/status/containers/StatusPage.js b/ui/src/status/containers/StatusPage.js
index 50974161de..179d589f8a 100644
--- a/ui/src/status/containers/StatusPage.js
+++ b/ui/src/status/containers/StatusPage.js
@@ -1,4 +1,5 @@
-import React, {Component, PropTypes} from 'react'
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import SourceIndicator from 'shared/components/SourceIndicator'
diff --git a/ui/src/types/index.tsx b/ui/src/types/index.tsx
index 804c6ced8a..a1013345f1 100644
--- a/ui/src/types/index.tsx
+++ b/ui/src/types/index.tsx
@@ -1,4 +1,4 @@
import {Query} from './query'
-import {Source} from './sources'
+import {Source, Kapacitor} from './sources'
-export {Query, Source}
+export {Query, Source, Kapacitor}
diff --git a/ui/test/kapacitor/containers/KapacitorPage.test.tsx b/ui/test/kapacitor/containers/KapacitorPage.test.tsx
new file mode 100644
index 0000000000..9cd879ee9f
--- /dev/null
+++ b/ui/test/kapacitor/containers/KapacitorPage.test.tsx
@@ -0,0 +1,206 @@
+import React from 'react'
+import {
+ KapacitorPage,
+ defaultName,
+ kapacitorPort,
+} from 'src/kapacitor/containers/KapacitorPage'
+import KapacitorForm from 'src/kapacitor/components/KapacitorForm'
+import KapacitorFormInput from 'src/kapacitor/components/KapacitorFormInput'
+import {mount} from 'enzyme'
+import {getKapacitor, createKapacitor, updateKapacitor} from 'src/shared/apis'
+
+import {source, kapacitor} from 'test/resources'
+import * as mocks from 'mocks/dummy'
+
+jest.mock('src/shared/apis', () => require('mocks/shared/apis'))
+
+const setup = (override = {}) => {
+ const props = {
+ source: source,
+ addFlashMessage: () => {},
+ kapacitor,
+ router: {
+ push: () => {},
+ replace: () => {},
+ },
+ location: {pathname: '', hash: ''},
+ params: {id: '', hash: ''},
+ ...override,
+ }
+
+ const wrapper = mount( )
+
+ return {
+ wrapper,
+ props,
+ }
+}
+
+describe('Kapacitor.Containers.KapacitorPage', () => {
+ afterEach(() => {
+ jest.clearAllMocks()
+ })
+
+ describe('rendering', () => {
+ it('renders the KapacitorPage', () => {
+ const {wrapper} = setup()
+ expect(wrapper.exists()).toBe(true)
+ })
+
+ it('renders the KapacitorForm', async () => {
+ const {wrapper} = setup()
+ const form = wrapper.find(KapacitorForm)
+
+ expect(form.exists()).toBe(true)
+ })
+ })
+
+ describe('user interactions ', () => {
+ describe('entering the url', () => {
+ it('renders the text that is inputted', () => {
+ const {wrapper} = setup()
+ const value = '/new/url'
+ const event = {target: {value}}
+
+ let inputElement = wrapper.find('#kapaUrl')
+
+ inputElement.simulate('change', event)
+ wrapper.update()
+
+ inputElement = wrapper.find('#kapaUrl')
+
+ expect(inputElement.prop('value')).toBe(value)
+ })
+ })
+
+ describe('entering the kapacitor name', () => {
+ it('renders the text that is inputted', () => {
+ const {wrapper} = setup()
+ const value = 'My New Kapacitor'
+ const event = {target: {value, name: 'name'}}
+
+ let input = wrapper.find('#name')
+
+ input.simulate('change', event)
+ wrapper.update()
+
+ input = wrapper.find('#name')
+
+ expect(input.prop('value')).toBe(value)
+ })
+ })
+
+ describe('entering the username', () => {
+ it('renders the text that is inputted', () => {
+ const {wrapper} = setup()
+ const value = 'user1'
+ const event = {target: {value, name: 'username'}}
+
+ let input = wrapper.find('#username')
+
+ input.simulate('change', event)
+ wrapper.update()
+
+ input = wrapper.find('#username')
+
+ expect(input.prop('value')).toBe(value)
+ })
+ })
+
+ describe('entering the password', () => {
+ it('renders the text that is inputted', () => {
+ const {wrapper} = setup()
+ const value = 'password'
+ const event = {target: {value, name: 'password'}}
+
+ let input = wrapper.find('#password')
+
+ input.simulate('change', event)
+ wrapper.update()
+
+ input = wrapper.find('#password')
+
+ expect(input.prop('value')).toBe(value)
+ })
+ })
+
+ describe('submitting the form', () => {
+ it('creates a new Kapacitor if there is no kapacitor', async () => {
+ const {wrapper} = setup()
+ const submit = wrapper.find({'data-test': 'submit-button'})
+
+ submit.simulate('submit')
+
+ expect(createKapacitor).toHaveBeenCalled()
+ expect(updateKapacitor).not.toHaveBeenCalled()
+ })
+
+ it('updates an existing Kapacitor if there is a kapacitor', () => {
+ const props = {params: {id: '1', hash: ''}}
+ const {wrapper} = setup(props)
+ const submit = wrapper.find({'data-test': 'submit-button'})
+
+ submit.simulate('submit')
+
+ expect(updateKapacitor).toHaveBeenCalled()
+ expect(createKapacitor).not.toHaveBeenCalled()
+ })
+ })
+
+ describe('clicking the `reset` button', () => {
+ it('resets all inputs to their defaults', () => {
+ const {wrapper} = setup()
+
+ const url = wrapper.find('#kapaUrl')
+ const name = wrapper.find('#name')
+ const username = wrapper.find('#username')
+ const password = wrapper.find('#password')
+
+ const value = 'reset me'
+
+ // change all values to some non-default value
+ url.simulate('change', {target: {value}})
+ name.simulate('change', {target: {value, name: 'name'}})
+ username.simulate('change', {target: {value, name: 'username'}})
+ password.simulate('change', {target: {value, name: 'password'}})
+
+ const inputs = wrapper.find(KapacitorFormInput)
+ inputs.map(n => expect(n.find('input').prop('value')).toBe(value))
+
+ // reset
+ const reset = wrapper.find({'data-test': 'reset-button'})
+ reset.simulate('click')
+
+ expect(url.prop('value')).toBe(`https://localhost:${kapacitorPort}`)
+ expect(name.prop('value')).toBe(defaultName)
+ expect(username.prop('value')).toBe('')
+ expect(password.prop('value')).toBe('')
+ })
+ })
+ })
+
+ describe('instance methods', () => {
+ describe('componentDidMount', () => {
+ describe('if it is a new kapacitor', () => {
+ it('does not get the kapacitor', async () => {
+ const {wrapper} = setup()
+
+ await wrapper.instance().componentDidMount()
+
+ expect(getKapacitor).not.toHaveBeenCalled()
+ })
+ })
+
+ describe('if it is an existing kapacitor', () => {
+ it('gets the kapacitor info and sets the appropriate state', async () => {
+ const params = {id: '1', hash: ''}
+ const {wrapper} = setup({params})
+
+ await wrapper.instance().componentDidMount()
+
+ expect(wrapper.state().kapacitor).toEqual(mocks.kapacitor)
+ })
+ })
+ })
+ })
+})
diff --git a/ui/test/resources.ts b/ui/test/resources.ts
index 392766a6ee..caee2f9c51 100644
--- a/ui/test/resources.ts
+++ b/ui/test/resources.ts
@@ -47,3 +47,15 @@ export const query = {
status: null,
shifts: [],
}
+
+export const kapacitor = {
+ url: '/foo/bar/baz',
+ name: 'kapa',
+ username: 'influx',
+ password: '',
+ active: false,
+ links: {
+ self: '/kapa/1',
+ proxy: '/proxy/kapacitor/1',
+ },
+}
diff --git a/ui/yarn.lock b/ui/yarn.lock
index 5a7a789ae5..80fc640763 100644
--- a/ui/yarn.lock
+++ b/ui/yarn.lock
@@ -1704,7 +1704,7 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
-classnames@^2.2.3, classnames@^2.2.5:
+classnames@2.x, classnames@^2.2.3, classnames@^2.2.5:
version "2.2.5"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d"
@@ -6874,10 +6874,6 @@ react-codemirror@^1.0.0:
lodash.isequal "^4.5.0"
prop-types "^15.5.4"
-react-component-resizable@^1.1.0-rc1:
- version "1.1.0-rc1"
- resolved "https://registry.yarnpkg.com/react-component-resizable/-/react-component-resizable-1.1.0-rc1.tgz#167b635dfde48da512b0000cbd224c6bc539f2b3"
-
react-custom-scrollbars@^4.1.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/react-custom-scrollbars/-/react-custom-scrollbars-4.2.1.tgz#830fd9502927e97e8a78c2086813899b2a8b66db"
@@ -6901,19 +6897,28 @@ react-dom@^15.0.2:
object-assign "^4.1.0"
prop-types "^15.5.10"
-react-draggable@^2.1.1, "react-draggable@^2.2.6 || ^3.0.3":
+react-draggable@3.x:
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-3.0.5.tgz#c031e0ed4313531f9409d6cd84c8ebcec0ddfe2d"
+ dependencies:
+ classnames "^2.2.5"
+ prop-types "^15.6.0"
+
+"react-draggable@^2.2.6 || ^3.0.3":
version "2.2.6"
resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-2.2.6.tgz#3a806e10f2da6babfea4136be6510e89b0d76901"
dependencies:
classnames "^2.2.5"
-react-grid-layout@^0.13.9:
- version "0.13.9"
- resolved "https://registry.yarnpkg.com/react-grid-layout/-/react-grid-layout-0.13.9.tgz#5ba29cdc0e6422362f46d9a49047ebb24e0e293e"
+react-grid-layout@^0.16.6:
+ version "0.16.6"
+ resolved "https://registry.yarnpkg.com/react-grid-layout/-/react-grid-layout-0.16.6.tgz#9b2407a2b946c2260ebaf66f13b556e1da4efeb2"
dependencies:
+ classnames "2.x"
lodash.isequal "^4.0.0"
- react-draggable "^2.1.1"
- react-resizable "^1.4.0"
+ prop-types "15.x"
+ react-draggable "3.x"
+ react-resizable "1.x"
react-onclickoutside@^5.2.0:
version "5.11.1"
@@ -6932,7 +6937,7 @@ react-redux@^4.4.0:
loose-envify "^1.1.0"
prop-types "^15.5.4"
-react-resizable@^1.4.0:
+react-resizable@1.x, react-resizable@^1.7.5:
version "1.7.5"
resolved "https://registry.yarnpkg.com/react-resizable/-/react-resizable-1.7.5.tgz#83eb75bb3684da6989bbbf4f826e1470f0af902e"
dependencies: