import React, { PureComponent } from 'react'; import { cx, css } from 'emotion'; import { ZBX_ACK_ACTION_ADD_MESSAGE, ZBX_ACK_ACTION_ACK, ZBX_ACK_ACTION_CHANGE_SEVERITY, ZBX_ACK_ACTION_CLOSE } from '../../datasource-zabbix/constants'; import { Button, VerticalGroup, Spinner, Modal, Input, Forms, stylesFactory, withTheme, Themeable } from '@grafana/ui'; import { FAIcon } from '../../components'; import * as grafanaUi from '@grafana/ui'; import { GrafanaTheme } from '@grafana/data'; const Checkbox: any = Forms?.Checkbox || (grafanaUi as any).Checkbox; const RadioButtonGroup: any = Forms?.RadioButtonGroup || (grafanaUi as any).RadioButtonGroup; const KEYBOARD_ENTER_KEY = 13; const KEYBOARD_ESCAPE_KEY = 27; interface Props extends Themeable { canAck?: boolean; canClose?: boolean; severity?: number; withBackdrop?: boolean; onSubmit: (data?: AckProblemData) => Promise | any; onDismiss?: () => void; } interface State { value: string; error: boolean; errorMessage: string; ackError: string; acknowledge: boolean; closeProblem: boolean; changeSeverity: boolean; selectedSeverity: number; loading: boolean; } export interface AckProblemData { message: string; closeProblem?: boolean; action?: number; severity?: number; } const severityOptions = [ {value: 0, label: 'Not classified'}, {value: 1, label: 'Information'}, {value: 2, label: 'Warning'}, {value: 3, label: 'Average'}, {value: 4, label: 'High'}, {value: 5, label: 'Disaster'} ]; export class AckModalUnthemed extends PureComponent { static defaultProps: Partial = { withBackdrop: true, }; constructor(props) { super(props); this.state = { value: '', error: false, errorMessage: '', ackError: '', acknowledge: false, closeProblem: false, changeSeverity: false, selectedSeverity: props.severity || 0, loading: false, }; } handleChange = (event: React.ChangeEvent) => { this.setState({ value: event.target.value, error: false }); } handleKeyUp = (event: React.KeyboardEvent) => { if (event.which === KEYBOARD_ENTER_KEY || event.key === 'Enter') { this.submit(); } else if (event.which === KEYBOARD_ESCAPE_KEY || event.key === 'Escape') { this.dismiss(); } } handleBackdropClick = () => { this.dismiss(); } onAcknowledgeToggle = () => { this.setState({ acknowledge: !this.state.acknowledge, error: false }); } onChangeSeverityToggle = () => { this.setState({ changeSeverity: !this.state.changeSeverity, error: false }); } onCloseProblemToggle = () => { this.setState({ closeProblem: !this.state.closeProblem, error: false }); } onChangeSelectedSeverity = v => { this.setState({ selectedSeverity: v }); }; dismiss = () => { this.setState({ value: '', error: false, errorMessage: '', ackError: '', loading: false }); this.props.onDismiss(); } submit = () => { const { acknowledge, changeSeverity, closeProblem } = this.state; const actionSelected = acknowledge || changeSeverity || closeProblem; if (!this.state.value && !actionSelected) { return this.setState({ error: true, errorMessage: 'Enter message text or select an action' }); } this.setState({ ackError: '', loading: true }); const ackData: AckProblemData = { message: this.state.value, }; let action = ZBX_ACK_ACTION_ADD_MESSAGE; if (this.state.acknowledge) { action += ZBX_ACK_ACTION_ACK; } if (this.state.changeSeverity) { action += ZBX_ACK_ACTION_CHANGE_SEVERITY; ackData.severity = this.state.selectedSeverity; } if (this.state.closeProblem) { action += ZBX_ACK_ACTION_CLOSE; } ackData.action = action; this.props.onSubmit(ackData).then(() => { this.dismiss(); }).catch(err => { this.setState({ ackError: err.message || err.data, loading: false, }); }); } renderActions() { const { canClose } = this.props; const actions = [ , , this.state.changeSeverity && , canClose && , ]; // doesn't handle empty elements properly, so don't return it return actions.filter(e => e); } render() { const { theme } = this.props; const styles = getStyles(theme); const modalClass = cx(styles.modal); const modalTitleClass = cx(styles.modalHeaderTitle); const inputGroupClass = cx('gf-form', styles.inputGroup); const inputClass = cx(this.state.error && styles.input); const inputHintClass = cx('gf-form-hint-text', styles.inputHint); const inputErrorClass = cx('gf-form-hint-text', styles.inputError); return ( {this.state.loading ? : } Acknowledge Problem } >
{this.renderActions()}
{this.state.ackError &&
{this.state.ackError}
}
); } } const getStyles = stylesFactory((theme: GrafanaTheme) => { return { modal: css` width: 500px; `, modalHeaderTitle: css` font-size: ${theme.typography.heading.h3}; padding-top: ${theme.spacing.sm}; margin: 0 ${theme.spacing.md}; display: flex; `, inputGroup: css` margin-bottom: 16px; `, input: css` border-color: ${theme.colors.red}; border-radius: 2px; outline-offset: 2px; box-shadow: 0 0 0 2px ${theme.colors.pageBg}, 0 0 0px 4px ${theme.colors.red}; `, inputHint: css` display: inherit; float: right; color: ${theme.colors.textWeak}; `, inputError: css` float: left; color: ${theme.colors.red}; `, ackError: css` color: ${theme.colors.red}; `, }; }); export const AckModal = withTheme(AckModalUnthemed);