WIP Refactor RuleMessage to support arbitrary properties

pull/10616/head
Jared Scheib 2017-07-18 17:20:05 -07:00
parent 5d7e9ded17
commit 0950833ec0
3 changed files with 139 additions and 112 deletions

View File

@ -5,7 +5,7 @@ import RuleMessageOptions from 'src/kapacitor/components/RuleMessageOptions'
import RuleMessageText from 'src/kapacitor/components/RuleMessageText'
import RuleMessageTemplates from 'src/kapacitor/components/RuleMessageTemplates'
import {DEFAULT_ALERTS} from 'src/kapacitor/constants'
import {DEFAULT_ALERTS, RULE_ALERT_OPTIONS} from 'src/kapacitor/constants'
class RuleMessage extends Component {
constructor(props) {
@ -54,17 +54,22 @@ class RuleMessage extends Component {
<div className="rule-section--row rule-section--row-first rule-section--border-bottom">
<p>Send this Alert to:</p>
<ul className="nav nav-tablist nav-tablist-sm nav-tablist-malachite">
{alerts.map(alert =>
<li
key={alert.text}
className={classnames({
active: alert.text === selectedAlert,
})}
onClick={() => this.handleChooseAlert(alert)}
>
{alert.text}
</li>
)}
{alerts
// only display alert endpoints that have had their argument details configured
.filter(alert =>
Object.keys(RULE_ALERT_OPTIONS).includes(alert.text)
)
.map(alert =>
<li
key={alert.text}
className={classnames({
active: alert.text === selectedAlert,
})}
onClick={() => this.handleChooseAlert(alert)}
>
{alert.text}
</li>
)}
</ul>
</div>
<RuleMessageOptions

View File

@ -1,27 +1,72 @@
import React, {Component, PropTypes} from 'react'
import {
DEFAULT_ALERT_PLACEHOLDERS,
DEFAULT_ALERT_LABELS,
RULE_ALERT_OPTIONS,
ALERT_NODES_ACCESSORS,
} from 'src/kapacitor/constants'
const RuleMessageOptions = ({rule, alert, updateAlertNodes, updateDetails}) => {
const isDetailsTypeDefault =
Object.keys(DEFAULT_ALERT_PLACEHOLDERS).find(a => a === alert) &&
Object.keys(DEFAULT_ALERT_LABELS).find(a => a === alert)
class RuleMessageOptions extends Component {
constructor(props) {
super(props)
}
return isDetailsTypeDefault
? <DefaultOptions
rule={rule}
alert={alert}
updateAlertNodes={updateAlertNodes}
/>
: <NonDefaultOptions
rule={rule}
alert={alert}
updateDetails={updateDetails}
/>
render() {
const {rule, alert, updateAlertNodes, updateDetails} = this.props
const {args, details, properties} = RULE_ALERT_OPTIONS[alert]
return (
<div>
{args
? <div className="rule-section--row rule-section--border-bottom">
<p>{args.label}</p>
<input
id="alert-input"
className="form-control input-sm form-malachite"
style={{flex: '1 0 0'}}
type="text"
placeholder={args.placeholder}
onChange={e => updateAlertNodes(rule.id, alert, e.target.value)}
value={ALERT_NODES_ACCESSORS[alert](rule)}
autoComplete="off"
spellCheck="false"
/>
</div>
: null}
{details
? <div className="rule-section--border-bottom">
<textarea
className="form-control form-malachite monotype rule-builder--message"
placeholder={details.placeholder ? details.placeholder : ''}
ref={r => (this.details = r)}
onChange={() => updateDetails(rule.id, this.details.value)}
value={rule.details}
spellCheck={false}
/>
</div>
: null}
{properties
? properties.map(({key, label, placeholder}) =>
<div
key={key}
className="rule-section--row rule-section--border-bottom"
>
<p>{label}</p>
<input
className="form-control input-sm form-malachite"
style={{flex: '1 0 0'}}
type="text"
placeholder={placeholder}
// onChange={e => updateProperties(rule.id, e.target.value)}
value={ALERT_NODES_ACCESSORS[alert](rule)}
autoComplete="off"
spellCheck="false"
/>
</div>
)
: null}
</div>
)
}
}
const {func, shape, string} = PropTypes
@ -33,70 +78,4 @@ RuleMessageOptions.propTypes = {
updateDetails: func.isRequired,
}
class DefaultOptions extends Component {
constructor(props) {
super(props)
}
render() {
const {rule, alert, updateAlertNodes} = this.props
return (
<div className="rule-section--row rule-section--border-bottom">
<p>{DEFAULT_ALERT_LABELS[alert]}</p>
<input
id="alert-input"
className="form-control input-sm form-malachite"
style={{flex: '1 0 0'}}
type="text"
placeholder={DEFAULT_ALERT_PLACEHOLDERS[alert]}
onChange={e => updateAlertNodes(rule.id, alert, e.target.value)}
value={ALERT_NODES_ACCESSORS[alert](rule)}
autoComplete="off"
spellCheck="false"
/>
</div>
)
}
}
DefaultOptions.propTypes = {
rule: shape({}).isRequired,
alert: string,
updateAlertNodes: func.isRequired,
}
class NonDefaultOptions extends Component {
constructor(props) {
super(props)
}
render() {
const {rule, alert, updateDetails} = this.props
switch (alert) {
case 'smtp':
return (
<div className="rule-section--border-bottom">
<textarea
className="form-control form-malachite monotype rule-builder--message"
placeholder="Email body text goes here"
ref={r => (this.details = r)}
onChange={() => updateDetails(rule.id, this.details.value)}
value={rule.details}
spellCheck={false}
/>
</div>
)
default:
return null
}
}
}
NonDefaultOptions.propTypes = {
rule: shape({}).isRequired,
alert: string,
updateDetails: func.isRequired,
}
export default RuleMessageOptions

View File

@ -83,23 +83,65 @@ export const RULE_MESSAGE_TEMPLATES = {
export const DEFAULT_ALERTS = ['http', 'tcp', 'exec', 'log']
export const DEFAULT_ALERT_LABELS = {
http: 'URL:',
tcp: 'Address:',
exec: 'Add Command (Arguments separated by Spaces):',
log: 'File:',
smtp: 'Email Addresses (Separated by Spaces):',
slack: 'Send alerts to Slack channel:',
alerta: 'Paste Alerta TICKscript:',
}
export const DEFAULT_ALERT_PLACEHOLDERS = {
http: 'Ex: http://example.com/api/alert',
tcp: 'Ex: exampleendpoint.com:5678',
exec: 'Ex: woogie boogie',
log: 'Ex: /tmp/alerts.log',
smtp: 'Ex: benedict@domain.com delaney@domain.com susan@domain.com',
slack: '#alerts',
alerta: 'alerta()',
export const RULE_ALERT_OPTIONS = {
http: {
args: {
label: 'URL:',
placeholder: 'Ex: http://example.com/api/alert',
},
},
tcp: {
args: {
label: 'Address:',
placeholder: 'Ex: exampleendpoint.com:5678',
},
},
exec: {
args: {
label: 'Add Command (Arguments separated by Spaces):',
placeholder: 'Ex: woogie boogie',
},
},
log: {
args: {
label: 'File:',
placeholder: 'Ex: /tmp/alerts.log',
},
},
smtp: {
args: {
label: 'Email Addresses (Separated by Spaces):',
placeholder:
'Ex: benedict@domain.com delaney@domain.com susan@domain.com',
},
details: {placeholder: 'Email body text goes here'},
},
slack: {
args: {
label: 'Send alerts to Slack channel:',
placeholder: '#alerts',
},
},
alerta: {
args: {
label: 'Paste Alerta TICKscript:',
placeholder: 'alerta()',
},
},
pushover: {
args: {
label: 'Devices (Separated by Commas, Optional):',
placeholder: 'phone33,submarine,pineapple_tower',
},
properties: [
{key: 'UserKey', label: 'User Key', placeholder: 'my_user_key'},
{key: 'Device', label: 'Device', placeholder: 'my_device'},
{key: 'Title', label: 'Title', placeholder: 'message_title'},
{key: 'URL', label: 'URL', placeholder: 'http://reference.url'},
{key: 'URLTitle', label: 'URL Title', placeholder: 'My URL Title'},
{key: 'Sound', label: 'Sound', placeholder: 'pineapple_falling'},
],
},
}
export const ALERT_NODES_ACCESSORS = {
@ -119,4 +161,5 @@ export const ALERT_NODES_ACCESSORS = {
['alerta()']
)
.join('.'),
pushover: rule => _.get(rule, 'alertNodes[0].args'),
}