feat(ui): modal window with filters help

This commit is contained in:
Łukasz Mierzwa
2018-07-14 22:37:20 +02:00
parent 2b213ada8d
commit c3fbb1a6e8
5 changed files with 339 additions and 15 deletions

View File

@@ -6391,5 +6391,8 @@ a.text-dark:hover, a.text-dark:focus {
.bg-primary-transparent {
background-color: rgba(69, 90, 100, 0.95); }
.bg-primary-transparent-80 {
background-color: rgba(59, 66, 71, 0.8); }
.cursor-pointer {
cursor: pointer; }

View File

@@ -24,6 +24,10 @@ $dark: #3b4247;
.bg-primary-transparent {
background-color: rgba($primary, 0.95);
}
// version for modals
.bg-primary-transparent-80 {
background-color: rgba($dark, 0.8);
}
.cursor-pointer {
cursor: pointer;

View File

@@ -0,0 +1,247 @@
import React from "react";
import PropTypes from "prop-types";
const FilterOperatorHelp = ({ operator, description, children }) => (
<React.Fragment>
<dt>
<kbd>{operator}</kbd> {description}
</dt>
<dd className="mb-3">
<div>
Example: <code>key{operator}value</code>
</div>
<div>{children}</div>
</dd>
</React.Fragment>
);
FilterOperatorHelp.propTypes = {
operator: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
children: PropTypes.array
};
const QueryHelp = ({ title, operators, children }) => (
<React.Fragment>
<dt>{title}</dt>
<dd className="mb-5">
<div>
Supported operators:{" "}
{operators.map(op => (
<kbd key={op} className="mr-1">
{op}
</kbd>
))}
</div>
<div>Examples:</div>
<ul>{children}</ul>
</dd>
</React.Fragment>
);
QueryHelp.propTypes = {
title: PropTypes.string.isRequired,
operators: PropTypes.arrayOf(PropTypes.string).isRequired,
children: PropTypes.array
};
const FilterExample = ({ example, children }) => (
<li>
<div>
<span className="badge badge-info">{example}</span>
</div>
<div>{children}</div>
</li>
);
FilterExample.propTypes = {
example: PropTypes.string.isRequired,
children: PropTypes.array
};
const Help = () => (
<div>
<h4 className="text-center">Filter operators</h4>
<dl>
<FilterOperatorHelp operator="=" description="Exact match">
True if compared alert attribute value is equal to <code>value</code>.
</FilterOperatorHelp>
<FilterOperatorHelp operator="!=" description="Negative match">
True if compared alert attribute is missing or have a value that is not
equal to <code>value</code>.
</FilterOperatorHelp>
<FilterOperatorHelp operator="=~" description="Regular expression match">
True if compared alert attribute value matches <code>value</code> regex.
</FilterOperatorHelp>
<FilterOperatorHelp
operator="!~"
description="Negative regular expression match"
>
False if compared alert attribute value matches <code>value</code>{" "}
regex.
</FilterOperatorHelp>
<FilterOperatorHelp operator="&gt;" description="Greater than match">
True if compared alert attribute value is greater than{" "}
<code>value</code>.
</FilterOperatorHelp>
<FilterOperatorHelp operator="&lt;" description="Less than match">
True if compared alert attribue value is less than <code>value</code>.
</FilterOperatorHelp>
</dl>
<div className="mt-5">
<h4 className="text-center">Filtering using alert labels</h4>
<dl>
<QueryHelp
title="Match alerts based on any label"
operators={["=", "!=", "=~", "!~", ">", "<"]}
>
<FilterExample example="alertname=UnableToPing">
Match alerts with label <code>alertname</code> equal to{" "}
<code>UnableToPing</code>.
</FilterExample>
<FilterExample example="hostname=localhost">
Match alerts with label <code>hostname</code> equal to{" "}
<code>localhost</code>.
</FilterExample>
<FilterExample example="service!=apache3">
Match alerts with label <code>service</code> missing or not equal to{" "}
<code>apache3</code>.
</FilterExample>
<FilterExample example="service=~apache">
Match alerts with label <code>service</code> matching regular
expression <code>/.*apache.*/</code>.
</FilterExample>
<FilterExample example="service=~apache[1-3]">
Match alerts with label <code>service</code> matching regular
expression <code>/.*apache[1-3].*/</code>.
</FilterExample>
<FilterExample example="priority>4">
Match alerts with label <code>priority</code> value{" "}
<code>&gt;</code> than <code>4</code>. Value will be casted to
integer if possible, string comparision will be used as fallback.
</FilterExample>
</QueryHelp>
</dl>
</div>
<div className="mt-5">
<h4 className="text-center">Filtering alerts using special filters</h4>
<dl>
<QueryHelp
title="Match alerts based on the Alertmanager instance name they were
collected from"
operators={["=", "!=", "=~", "!~"]}
>
<FilterExample example="@alertmanager=prod">
Match alerts collected from Alertmanager instance named{" "}
<code>prod</code>.
</FilterExample>
<FilterExample example="@alertmanager!=dev">
Match alerts collected from Alertmanager instances except for the
one named <code>dev</code>.
</FilterExample>
<FilterExample example="@alertmanager=~prod">
Match alerts collected from Alertmanager instances with names
matching regular expression <code>/.*prod.*/</code>.
</FilterExample>
</QueryHelp>
<QueryHelp
title="Match alerts based on the receiver name"
operators={["=", "!=", "=~", "!~"]}
>
<FilterExample example="@receiver=default">
Match alerts sent to the default receiver.
</FilterExample>
<FilterExample example="@receiver!=hipchat">
Match alerts not sent to the hipchat receiver.
</FilterExample>
<FilterExample example="@receiver=~email">
Match alerts sent to any receiver with name matching regular
expression <code>/.*email.*/</code>.
</FilterExample>
</QueryHelp>
<QueryHelp
title="Match alerts based on the state"
operators={["=", "!="]}
>
<FilterExample example="@state=active">
Match only active alerts.
</FilterExample>
<FilterExample example="@state!=active">
Match alerts that are not active, only suppressed and unprocessed
will be matched.
</FilterExample>
<FilterExample example="@state=suppressed">
Match only suppressed alerts.
</FilterExample>
<FilterExample example="@state=unprocessed">
Match only unprocessed alerts.
</FilterExample>
</QueryHelp>
<QueryHelp
title="Match alerts based on the author of silence"
operators={["=", "!=", "=~", "!~"]}
>
<FilterExample example="@silence_author=me@example.com">
Match alerts silenced by <code>me@example.com</code>.
</FilterExample>
<FilterExample example="@silence_author!=me@example.com">
Match alerts silenced by everyone except{" "}
<code>foo@example.com</code>.
</FilterExample>
<FilterExample example="@silence_author=~@example.com">
Match alerts silenced by author matching regular expression{" "}
<code>/.*@example.com.*/</code>.
</FilterExample>
</QueryHelp>
<QueryHelp
title="Match alerts based on the jira linked in the silence"
operators={["=", "!=", "=~", "!~"]}
>
<div className="text-warning">
This is supported only if JIRA regexp are enabled and able to match
JIRA ids in the silence comment body.
</div>
<FilterExample example="@silence_jira=PROJECT-123">
Match silenced alerts where detected JIRA issue id is equal to{" "}
<code>PROJECT-123</code>.
</FilterExample>
<FilterExample example="@silence_jira!=PROJECT-123">
Match silenced alerts where detected JIRA issue id is different than{" "}
<code>PROJECT-123</code>.
</FilterExample>
<FilterExample example="@silence_jira=~PROJECT">
Match silenced alerts where detected JIRA issue id matches regular
expression <code>/.*PROJECT.*/</code>.
</FilterExample>
</QueryHelp>
<QueryHelp title="Limit number of displayed alerts" operators={["="]}>
<div className="text-warning">Value must be a number &gt;= 1.</div>
<FilterExample example="@limit=10">
Limit number of displayed alerts to 10.
</FilterExample>
</QueryHelp>
<QueryHelp
title="Match alerts based on creation timestamp"
operators={[">", "<"]}
>
<FilterExample example="@age&gt;15m">
Match alerts older than 15 minutes.
</FilterExample>
<FilterExample example="@age&gt;1h">
Match alerts older than 1 hour.
</FilterExample>
<FilterExample example="@age&lt;10h30m">
Match alerts more recent than 10 hours and 30 minutes.
</FilterExample>
</QueryHelp>
</dl>
</div>
</div>
);
export { Help };

View File

@@ -0,0 +1,83 @@
import React, { Component } from "react";
import { observer } from "mobx-react";
import { observable, action } from "mobx";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCog } from "@fortawesome/free-solid-svg-icons/faCog";
import { Help } from "./Help";
const MainModal = observer(
class MainModal extends Component {
toggle = observable(
{
show: false,
toggle() {
this.show = !this.show;
},
hide() {
this.show = false;
}
},
{ toggle: action.bound, hide: action.bound }
);
componentDidUpdate() {
document.body.classList.toggle("modal-open", this.toggle.show);
}
componentWillUnmount() {
document.body.classList.remove("modal-open");
}
render() {
return (
<React.Fragment>
<ul className="navbar-nav">
<li className="nav-item dropdown">
<a
className="nav-link mx-1 cursor-pointer"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="true"
onClick={this.toggle.toggle}
>
<FontAwesomeIcon icon={faCog} />
</a>
</li>
</ul>
{this.toggle.show ? (
<div
className="modal d-block bg-primary-transparent-80"
tabIndex="-1"
role="dialog"
>
<div className="modal-dialog modal-lg" role="document">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title">Help</h5>
<button
type="button"
className="close"
data-dismiss="modal"
aria-label="Close"
onClick={this.toggle.hide}
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div className="modal-body">
<Help />
</div>
</div>
</div>
</div>
) : null}
</React.Fragment>
);
}
}
);
export { MainModal };

View File

@@ -5,12 +5,10 @@ import { observer } from "mobx-react";
import ReactResizeDetector from "react-resize-detector";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCog } from "@fortawesome/free-solid-svg-icons/faCog";
import { AlertStore } from "Stores/AlertStore";
import { FetchIndicator } from "./FetchIndicator";
import { FilterInput } from "./FilterInput";
import { MainModal } from "Components/MainModal";
import "./index.css";
@@ -35,18 +33,7 @@ const NavBar = observer(
<FetchIndicator status={alertStore.status.value.toString()} />
</span>
<FilterInput alertStore={alertStore} />
<ul className="navbar-nav">
<li className="nav-item dropdown">
<a
className="nav-link mx-1"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="true"
>
<FontAwesomeIcon icon={faCog} />
</a>
</li>
</ul>
<MainModal />
</nav>
</div>
);