mirror of
https://github.com/prymitive/karma
synced 2026-05-05 03:16:51 +00:00
feat(ui): modal window with filters help
This commit is contained in:
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
|
||||
247
ui/src/Components/MainModal/Help.js
Normal file
247
ui/src/Components/MainModal/Help.js
Normal 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=">" description="Greater than match">
|
||||
True if compared alert attribute value is greater than{" "}
|
||||
<code>value</code>.
|
||||
</FilterOperatorHelp>
|
||||
<FilterOperatorHelp operator="<" 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>></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 >= 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>15m">
|
||||
Match alerts older than 15 minutes.
|
||||
</FilterExample>
|
||||
<FilterExample example="@age>1h">
|
||||
Match alerts older than 1 hour.
|
||||
</FilterExample>
|
||||
<FilterExample example="@age<10h30m">
|
||||
Match alerts more recent than 10 hours and 30 minutes.
|
||||
</FilterExample>
|
||||
</QueryHelp>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export { Help };
|
||||
83
ui/src/Components/MainModal/index.js
Normal file
83
ui/src/Components/MainModal/index.js
Normal 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">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<Help />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export { MainModal };
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user