AlertRuleList.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import React from 'react';
  2. import { hot } from 'react-hot-loader';
  3. import classNames from 'classnames';
  4. import { inject, observer } from 'mobx-react';
  5. import PageHeader from 'app/core/components/PageHeader/PageHeader';
  6. import { IAlertRule } from 'app/stores/AlertListStore/AlertListStore';
  7. import appEvents from 'app/core/app_events';
  8. import IContainerProps from 'app/containers/IContainerProps';
  9. import Highlighter from 'react-highlight-words';
  10. @inject('view', 'nav', 'alertList')
  11. @observer
  12. export class AlertRuleList extends React.Component<IContainerProps, any> {
  13. stateFilters = [
  14. { text: 'All', value: 'all' },
  15. { text: 'OK', value: 'ok' },
  16. { text: 'Not OK', value: 'not_ok' },
  17. { text: 'Alerting', value: 'alerting' },
  18. { text: 'No Data', value: 'no_data' },
  19. { text: 'Paused', value: 'paused' },
  20. ];
  21. constructor(props) {
  22. super(props);
  23. this.props.nav.load('alerting', 'alert-list');
  24. this.fetchRules();
  25. }
  26. onStateFilterChanged = evt => {
  27. this.props.view.updateQuery({ state: evt.target.value });
  28. this.fetchRules();
  29. };
  30. fetchRules() {
  31. this.props.alertList.loadRules({
  32. state: this.props.view.query.get('state') || 'all',
  33. });
  34. }
  35. onOpenHowTo = () => {
  36. appEvents.emit('show-modal', {
  37. src: 'public/app/features/alerting/partials/alert_howto.html',
  38. modalClass: 'confirm-modal',
  39. model: {},
  40. });
  41. };
  42. onSearchQueryChange = evt => {
  43. this.props.alertList.setSearchQuery(evt.target.value);
  44. };
  45. render() {
  46. const { nav, alertList } = this.props;
  47. return (
  48. <div>
  49. <PageHeader model={nav as any} />
  50. <div className="page-container page-body">
  51. <div className="page-action-bar">
  52. <div className="gf-form gf-form--grow">
  53. <label className="gf-form--has-input-icon gf-form--grow">
  54. <input
  55. type="text"
  56. className="gf-form-input"
  57. placeholder="Search alerts"
  58. value={alertList.search}
  59. onChange={this.onSearchQueryChange}
  60. />
  61. <i className="gf-form-input-icon fa fa-search" />
  62. </label>
  63. </div>
  64. <div className="gf-form">
  65. <label className="gf-form-label">States</label>
  66. <div className="gf-form-select-wrapper width-13">
  67. <select className="gf-form-input" onChange={this.onStateFilterChanged} value={alertList.stateFilter}>
  68. {this.stateFilters.map(AlertStateFilterOption)}
  69. </select>
  70. </div>
  71. </div>
  72. <div className="page-action-bar__spacer" />
  73. <a className="btn btn-secondary" onClick={this.onOpenHowTo}>
  74. <i className="fa fa-info-circle" /> How to add an alert
  75. </a>
  76. </div>
  77. <section>
  78. <ol className="alert-rule-list">
  79. {alertList.filteredRules.map(rule => (
  80. <AlertRuleItem rule={rule} key={rule.id} search={alertList.search} />
  81. ))}
  82. </ol>
  83. </section>
  84. </div>
  85. </div>
  86. );
  87. }
  88. }
  89. function AlertStateFilterOption({ text, value }) {
  90. return (
  91. <option key={value} value={value}>
  92. {text}
  93. </option>
  94. );
  95. }
  96. export interface AlertRuleItemProps {
  97. rule: IAlertRule;
  98. search: string;
  99. }
  100. @observer
  101. export class AlertRuleItem extends React.Component<AlertRuleItemProps, any> {
  102. toggleState = () => {
  103. this.props.rule.togglePaused();
  104. };
  105. renderText(text: string) {
  106. return (
  107. <Highlighter
  108. highlightClassName="highlight-search-match"
  109. textToHighlight={text}
  110. searchWords={[this.props.search]}
  111. />
  112. );
  113. }
  114. render() {
  115. const { rule } = this.props;
  116. let stateClass = classNames({
  117. fa: true,
  118. 'fa-play': rule.isPaused,
  119. 'fa-pause': !rule.isPaused,
  120. });
  121. let ruleUrl = `${rule.url}?panelId=${rule.panelId}&fullscreen=true&edit=true&tab=alert`;
  122. return (
  123. <li className="alert-rule-item">
  124. <span className={`alert-rule-item__icon ${rule.stateClass}`}>
  125. <i className={rule.stateIcon} />
  126. </span>
  127. <div className="alert-rule-item__body">
  128. <div className="alert-rule-item__header">
  129. <div className="alert-rule-item__name">
  130. <a href={ruleUrl}>{this.renderText(rule.name)}</a>
  131. </div>
  132. <div className="alert-rule-item__text">
  133. <span className={`${rule.stateClass}`}>{this.renderText(rule.stateText)}</span>
  134. <span className="alert-rule-item__time"> for {rule.stateAge}</span>
  135. </div>
  136. </div>
  137. {rule.info && <div className="small muted alert-rule-item__info">{this.renderText(rule.info)}</div>}
  138. </div>
  139. <div className="alert-rule-item__actions">
  140. <button
  141. className="btn btn-small btn-inverse alert-list__btn width-2"
  142. title="Pausing an alert rule prevents it from executing"
  143. onClick={this.toggleState}
  144. >
  145. <i className={stateClass} />
  146. </button>
  147. <a className="btn btn-small btn-inverse alert-list__btn width-2" href={ruleUrl} title="Edit alert rule">
  148. <i className="icon-gf icon-gf-settings" />
  149. </a>
  150. </div>
  151. </li>
  152. );
  153. }
  154. }
  155. export default hot(module)(AlertRuleList);