AlertRuleList.tsx 5.2 KB

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