Create EndpointTabs SFC and fix actions and reducers for adding and removing new endpoints
parent
3487055fd0
commit
3d859a095f
|
@ -163,16 +163,22 @@ export function updateAlerts(ruleID, alerts) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateAlertNodes(ruleID, alertNodeName, alertNodesText) {
|
export function updateAlertNodes(ruleID, alerts) {
|
||||||
return {
|
return {
|
||||||
type: 'UPDATE_RULE_ALERT_NODES',
|
type: 'UPDATE_RULE_ALERT_NODES',
|
||||||
payload: {
|
payload: {ruleID, alerts},
|
||||||
ruleID,
|
|
||||||
alertNodeName,
|
|
||||||
alertNodesText,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// export function updateAlertNodes(ruleID, alertNodeName, alertNodesText) {
|
||||||
|
// return {
|
||||||
|
// type: 'UPDATE_RULE_ALERT_NODES',
|
||||||
|
// payload: {
|
||||||
|
// ruleID,
|
||||||
|
// alertNodeName,
|
||||||
|
// alertNodesText,
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
export function updateRuleName(ruleID, name) {
|
export function updateRuleName(ruleID, name) {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
import React, {PropTypes} from 'react'
|
||||||
|
import _ from 'lodash'
|
||||||
|
import classnames from 'classnames'
|
||||||
|
import uuid from 'node-uuid'
|
||||||
|
import {RULE_ALERT_OPTIONS} from 'src/kapacitor/constants'
|
||||||
|
|
||||||
|
const EndpointTabs = ({
|
||||||
|
endpointsOnThisAlert,
|
||||||
|
selectedEndpoint,
|
||||||
|
handleChooseAlert,
|
||||||
|
handleRemoveEndpoint,
|
||||||
|
}) => {
|
||||||
|
return endpointsOnThisAlert.length
|
||||||
|
? <ul className="nav nav-tablist nav-tablist-sm nav-tablist-malachite">
|
||||||
|
{endpointsOnThisAlert
|
||||||
|
.filter(alert => _.get(RULE_ALERT_OPTIONS, alert.type, false))
|
||||||
|
.map(alert =>
|
||||||
|
<li
|
||||||
|
key={uuid.v4()}
|
||||||
|
className={classnames({
|
||||||
|
active:
|
||||||
|
alert.alias === (selectedEndpoint && selectedEndpoint.alias),
|
||||||
|
})}
|
||||||
|
onClick={handleChooseAlert(alert)}
|
||||||
|
>
|
||||||
|
{alert.alias}
|
||||||
|
<div
|
||||||
|
className="nav-tab--delete"
|
||||||
|
onClick={handleRemoveEndpoint(alert)}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
|
||||||
|
const {shape, func, array} = PropTypes
|
||||||
|
|
||||||
|
EndpointTabs.propTypes = {
|
||||||
|
endpointsOnThisAlert: array,
|
||||||
|
selectedEndpoint: shape({}),
|
||||||
|
handleChooseAlert: func.isRequired,
|
||||||
|
handleRemoveEndpoint: func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EndpointTabs
|
|
@ -1,14 +1,13 @@
|
||||||
import React, {Component, PropTypes} from 'react'
|
import React, {Component, PropTypes} from 'react'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import classnames from 'classnames'
|
|
||||||
import uuid from 'node-uuid'
|
|
||||||
|
|
||||||
import RuleMessageOptions from 'src/kapacitor/components/RuleMessageOptions'
|
import RuleMessageOptions from 'src/kapacitor/components/RuleMessageOptions'
|
||||||
import RuleMessageText from 'src/kapacitor/components/RuleMessageText'
|
import RuleMessageText from 'src/kapacitor/components/RuleMessageText'
|
||||||
import RuleMessageTemplates from 'src/kapacitor/components/RuleMessageTemplates'
|
import RuleMessageTemplates from 'src/kapacitor/components/RuleMessageTemplates'
|
||||||
|
import EndpointTabs from 'src/kapacitor/components/EndpointTabs'
|
||||||
import Dropdown from 'shared/components/Dropdown'
|
import Dropdown from 'shared/components/Dropdown'
|
||||||
|
|
||||||
import {DEFAULT_ALERTS, RULE_ALERT_OPTIONS} from 'src/kapacitor/constants'
|
import {DEFAULT_ALERTS} from 'src/kapacitor/constants'
|
||||||
|
|
||||||
const alertNodesToEndpoints = rule => {
|
const alertNodesToEndpoints = rule => {
|
||||||
const endpointsOfKind = {}
|
const endpointsOfKind = {}
|
||||||
|
@ -17,9 +16,12 @@ const alertNodesToEndpoints = rule => {
|
||||||
const count = _.get(endpointsOfKind, ep.name, 0) + 1
|
const count = _.get(endpointsOfKind, ep.name, 0) + 1
|
||||||
endpointsOfKind[ep.name] = count
|
endpointsOfKind[ep.name] = count
|
||||||
endpointsOnThisAlert.push({
|
endpointsOnThisAlert.push({
|
||||||
text: ep.name + count,
|
alias: ep.name + count,
|
||||||
kind: ep.name,
|
type: ep.name,
|
||||||
|
text: ep.name,
|
||||||
ruleID: rule.id,
|
ruleID: rule.id,
|
||||||
|
args: ep.args,
|
||||||
|
properties: ep.properties,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
const selectedEndpoint = endpointsOnThisAlert.length
|
const selectedEndpoint = endpointsOnThisAlert.length
|
||||||
|
@ -50,61 +52,74 @@ class RuleMessage extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChooseAlert = item => () => {
|
handleChooseAlert = item => () => {
|
||||||
const {actions} = this.props
|
|
||||||
actions.updateAlerts(item.ruleID, [item.text])
|
|
||||||
actions.updateAlertNodes(item.ruleID, item.text, '')
|
|
||||||
this.setState({selectedEndpoint: item})
|
this.setState({selectedEndpoint: item})
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAddEndpoint = selectedItem => {
|
handleAddEndpoint = selectedItem => {
|
||||||
const {endpointsOnThisAlert, endpointsOfKind} = this.state
|
const {endpointsOnThisAlert, endpointsOfKind} = this.state
|
||||||
const newItemNumbering = _.get(endpointsOfKind, selectedItem.text, 0) + 1
|
const newItemNumbering = _.get(endpointsOfKind, selectedItem.alias, 0) + 1
|
||||||
const newItemName = selectedItem.text + newItemNumbering
|
const newItemName = selectedItem.alias + newItemNumbering
|
||||||
const newEndpoint = {
|
const newEndpoint = {
|
||||||
text: newItemName,
|
alias: newItemName,
|
||||||
kind: selectedItem.text,
|
type: selectedItem.alias,
|
||||||
ruleID: selectedItem.ruleID,
|
ruleID: selectedItem.ruleID,
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState(
|
||||||
endpointsOnThisAlert: [...endpointsOnThisAlert, newEndpoint],
|
{
|
||||||
endpointsOfKind: {
|
endpointsOnThisAlert: [...endpointsOnThisAlert, newEndpoint],
|
||||||
...endpointsOfKind,
|
endpointsOfKind: {
|
||||||
[selectedItem.text]: newItemNumbering,
|
...endpointsOfKind,
|
||||||
|
[selectedItem.alias]: newItemNumbering,
|
||||||
|
},
|
||||||
|
selectedEndpoint: newEndpoint,
|
||||||
},
|
},
|
||||||
selectedEndpoint: newEndpoint,
|
this.handleUpdateAllAlerts
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRemoveEndpoint = alert => e => {
|
handleRemoveEndpoint = alert => e => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const {endpointsOnThisAlert, selectedEndpoint} = this.state
|
const {endpointsOnThisAlert, selectedEndpoint} = this.state
|
||||||
const removedIndex = _.findIndex(endpointsOnThisAlert, ['text', alert.text])
|
const removedIndex = _.findIndex(endpointsOnThisAlert, [
|
||||||
const remainingEndpoints = _.reject(endpointsOnThisAlert, [
|
'alias',
|
||||||
'text',
|
alert.alias,
|
||||||
alert.text,
|
|
||||||
])
|
])
|
||||||
if (selectedEndpoint.text === alert.text) {
|
const remainingEndpoints = _.reject(endpointsOnThisAlert, [
|
||||||
|
'alias',
|
||||||
|
alert.alias,
|
||||||
|
])
|
||||||
|
if (selectedEndpoint.alias === alert.alias) {
|
||||||
const selectedIndex = removedIndex > 0 ? removedIndex - 1 : 0
|
const selectedIndex = removedIndex > 0 ? removedIndex - 1 : 0
|
||||||
const newSelected = remainingEndpoints.length
|
const newSelected = remainingEndpoints.length
|
||||||
? remainingEndpoints[selectedIndex]
|
? remainingEndpoints[selectedIndex]
|
||||||
: null
|
: null
|
||||||
this.setState({selectedEndpoint: newSelected})
|
this.setState({selectedEndpoint: newSelected})
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState(
|
||||||
endpointsOnThisAlert: remainingEndpoints,
|
{
|
||||||
})
|
endpointsOnThisAlert: remainingEndpoints,
|
||||||
|
},
|
||||||
|
this.handleUpdateAllAlerts
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleUpdateAllAlerts = () => {
|
||||||
|
const {rule, actions} = this.props
|
||||||
|
const {endpointsOnThisAlert} = this.state
|
||||||
|
actions.updateAlertNodes(rule.id, endpointsOnThisAlert)
|
||||||
|
actions.updateAlerts(rule.id, endpointsOnThisAlert)
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {rule, actions, enabledAlerts} = this.props
|
const {rule, actions, enabledAlerts} = this.props
|
||||||
const {endpointsOnThisAlert, selectedEndpoint} = this.state
|
const {endpointsOnThisAlert, selectedEndpoint} = this.state
|
||||||
const defaultAlertEndpoints = DEFAULT_ALERTS.map(text => {
|
const defaultAlertEndpoints = DEFAULT_ALERTS.map(alias => {
|
||||||
return {text, kind: text, ruleID: rule.id}
|
return {alias, text: alias, type: alias, ruleID: rule.id}
|
||||||
})
|
})
|
||||||
const alerts = [
|
const alerts = [
|
||||||
...defaultAlertEndpoints,
|
...defaultAlertEndpoints,
|
||||||
...enabledAlerts.map(text => {
|
...enabledAlerts.map(alias => {
|
||||||
return {text, kind: text, ruleID: rule.id}
|
return {text: alias, type: alias, ruleID: rule.id}
|
||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
return (
|
return (
|
||||||
|
@ -113,31 +128,12 @@ class RuleMessage extends Component {
|
||||||
<div className="rule-section--body">
|
<div className="rule-section--body">
|
||||||
<div className="rule-section--row rule-section--row-first rule-section--border-bottom">
|
<div className="rule-section--row rule-section--row-first rule-section--border-bottom">
|
||||||
<p>Send this Alert to:</p>
|
<p>Send this Alert to:</p>
|
||||||
{endpointsOnThisAlert.length
|
<EndpointTabs
|
||||||
? <ul className="nav nav-tablist nav-tablist-sm nav-tablist-malachite">
|
endpointsOnThisAlert={endpointsOnThisAlert}
|
||||||
{endpointsOnThisAlert
|
selectedEndpoint={selectedEndpoint}
|
||||||
.filter(alert =>
|
handleChooseAlert={this.handleChooseAlert}
|
||||||
_.get(RULE_ALERT_OPTIONS, alert.kind, false)
|
handleRemoveEndpoint={this.handleRemoveEndpoint}
|
||||||
)
|
/>
|
||||||
.map(alert =>
|
|
||||||
<li
|
|
||||||
key={uuid.v4()}
|
|
||||||
className={classnames({
|
|
||||||
active:
|
|
||||||
alert.text ===
|
|
||||||
(selectedEndpoint && selectedEndpoint.text),
|
|
||||||
})}
|
|
||||||
onClick={this.handleChooseAlert(alert)}
|
|
||||||
>
|
|
||||||
{alert.text}
|
|
||||||
<div
|
|
||||||
className="nav-tab--delete"
|
|
||||||
onClick={this.handleRemoveEndpoint(alert)}
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
</ul>
|
|
||||||
: null}
|
|
||||||
<Dropdown
|
<Dropdown
|
||||||
items={alerts}
|
items={alerts}
|
||||||
menuClass="dropdown-malachite"
|
menuClass="dropdown-malachite"
|
||||||
|
@ -151,9 +147,12 @@ class RuleMessage extends Component {
|
||||||
<RuleMessageOptions
|
<RuleMessageOptions
|
||||||
rule={rule}
|
rule={rule}
|
||||||
alertNode={selectedEndpoint}
|
alertNode={selectedEndpoint}
|
||||||
|
selectedEndpoint={selectedEndpoint}
|
||||||
updateAlertNodes={actions.updateAlertNodes}
|
updateAlertNodes={actions.updateAlertNodes}
|
||||||
updateDetails={actions.updateDetails}
|
updateDetails={actions.updateDetails}
|
||||||
updateAlertProperty={actions.updateAlertProperty}
|
updateAlertProperty={actions.updateAlertProperty}
|
||||||
|
handleEditAlert={this.handleEditAlert}
|
||||||
|
handleUpdateArg={this.handleUpdateArg}
|
||||||
/>
|
/>
|
||||||
<RuleMessageText
|
<RuleMessageText
|
||||||
rule={rule}
|
rule={rule}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
import React, {Component, PropTypes} from 'react'
|
import React, {Component, PropTypes} from 'react'
|
||||||
|
|
||||||
import {
|
import {RULE_ALERT_OPTIONS} from 'src/kapacitor/constants'
|
||||||
RULE_ALERT_OPTIONS,
|
|
||||||
ALERT_NODES_ACCESSORS,
|
|
||||||
} from 'src/kapacitor/constants'
|
|
||||||
|
|
||||||
class RuleMessageOptions extends Component {
|
class RuleMessageOptions extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -31,8 +28,8 @@ class RuleMessageOptions extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleUpdateAlertNodes = e => {
|
handleUpdateAlertNodes = e => {
|
||||||
const {updateAlertNodes, alertNode, rule} = this.props
|
const {handleUpdateArg, selectedEndpoint} = this.props
|
||||||
updateAlertNodes(rule.id, alertNode, e.target.value)
|
handleUpdateArg(selectedEndpoint, e.target.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleUpdateAlertProperty = propertyName => e => {
|
handleUpdateAlertProperty = propertyName => e => {
|
||||||
|
@ -44,8 +41,10 @@ class RuleMessageOptions extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {rule, alertNode} = this.props
|
const {rule, selectedEndpoint, handleEditAlert} = this.props
|
||||||
const {args, details, properties} = RULE_ALERT_OPTIONS[alertNode.kind]
|
const {args, details, properties} = RULE_ALERT_OPTIONS[
|
||||||
|
selectedEndpoint.type
|
||||||
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -61,7 +60,7 @@ class RuleMessageOptions extends Component {
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={args.placeholder}
|
placeholder={args.placeholder}
|
||||||
onChange={this.handleUpdateAlertNodes}
|
onChange={this.handleUpdateAlertNodes}
|
||||||
value={ALERT_NODES_ACCESSORS[alertNode.kind](rule)}
|
value={selectedEndpoint.args}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
spellCheck="false"
|
spellCheck="false"
|
||||||
/>
|
/>
|
||||||
|
@ -116,7 +115,7 @@ const {func, shape} = PropTypes
|
||||||
|
|
||||||
RuleMessageOptions.propTypes = {
|
RuleMessageOptions.propTypes = {
|
||||||
rule: shape({}).isRequired,
|
rule: shape({}).isRequired,
|
||||||
alertNode: shape({}),
|
selectedEndpoint: shape({}),
|
||||||
updateAlertNodes: func.isRequired,
|
updateAlertNodes: func.isRequired,
|
||||||
updateDetails: func.isRequired,
|
updateDetails: func.isRequired,
|
||||||
updateAlertProperty: func.isRequired,
|
updateAlertProperty: func.isRequired,
|
||||||
|
|
|
@ -76,65 +76,57 @@ export default function rules(state = {}, action) {
|
||||||
|
|
||||||
case 'UPDATE_RULE_ALERTS': {
|
case 'UPDATE_RULE_ALERTS': {
|
||||||
const {ruleID, alerts} = action.payload
|
const {ruleID, alerts} = action.payload
|
||||||
|
const culledalerts = alerts.map(a => a.type)
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
[ruleID]: Object.assign({}, state[ruleID], {
|
[ruleID]: Object.assign({}, state[ruleID], {
|
||||||
alerts,
|
alerts: culledalerts,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'UPDATE_RULE_ALERT_NODES': {
|
case 'UPDATE_RULE_ALERT_NODES': {
|
||||||
const {ruleID, alertNodeName, alertNodesText} = action.payload
|
const {ruleID, alerts} = action.payload
|
||||||
|
const alertNodesByType = alerts.map(alert => {
|
||||||
let alertNodesByType
|
const {type, alias} = alert
|
||||||
|
switch (type) {
|
||||||
switch (alertNodeName) {
|
case 'http':
|
||||||
case 'http':
|
case 'tcp':
|
||||||
case 'tcp':
|
case 'log':
|
||||||
case 'log':
|
return {
|
||||||
alertNodesByType = [
|
name: type,
|
||||||
{
|
args: [alias],
|
||||||
name: alertNodeName,
|
|
||||||
args: [alertNodesText],
|
|
||||||
properties: [],
|
properties: [],
|
||||||
},
|
}
|
||||||
]
|
case 'exec':
|
||||||
break
|
case 'smtp':
|
||||||
case 'exec':
|
return [
|
||||||
case 'smtp':
|
{
|
||||||
alertNodesByType = [
|
name: type,
|
||||||
{
|
args: alias.split(' '),
|
||||||
name: alertNodeName,
|
properties: [],
|
||||||
args: alertNodesText.split(' '),
|
},
|
||||||
properties: [],
|
]
|
||||||
},
|
case 'alerta':
|
||||||
]
|
return {
|
||||||
break
|
name: type,
|
||||||
case 'alerta':
|
|
||||||
alertNodesByType = [
|
|
||||||
{
|
|
||||||
name: alertNodeName,
|
|
||||||
args: [],
|
args: [],
|
||||||
properties: parseAlerta(alertNodesText),
|
properties: parseAlerta(alias),
|
||||||
},
|
}
|
||||||
]
|
case 'hipchat':
|
||||||
break
|
case 'opsgenie':
|
||||||
case 'hipchat':
|
case 'pagerduty':
|
||||||
case 'opsgenie':
|
case 'slack':
|
||||||
case 'pagerduty':
|
case 'telegram':
|
||||||
case 'slack':
|
case 'victorops':
|
||||||
case 'telegram':
|
case 'pushover':
|
||||||
case 'victorops':
|
default:
|
||||||
case 'pushover':
|
return {
|
||||||
default:
|
name: type,
|
||||||
alertNodesByType = [
|
|
||||||
{
|
|
||||||
name: alertNodeName,
|
|
||||||
args: [],
|
args: [],
|
||||||
properties: [],
|
properties: [],
|
||||||
},
|
}
|
||||||
]
|
}
|
||||||
}
|
})
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
[ruleID]: Object.assign({}, state[ruleID], {
|
[ruleID]: Object.assign({}, state[ruleID], {
|
||||||
alertNodes: alertNodesByType,
|
alertNodes: alertNodesByType,
|
||||||
|
|
Loading…
Reference in New Issue