cluster:
diff --git a/ui/src/Components/Grid/AlertGrid/AlertGroup/Alert/index.js b/ui/src/Components/Grid/AlertGrid/AlertGroup/Alert/index.js
index 6ad014d3a..0c1d5b844 100644
--- a/ui/src/Components/Grid/AlertGrid/AlertGroup/Alert/index.js
+++ b/ui/src/Components/Grid/AlertGrid/AlertGroup/Alert/index.js
@@ -5,7 +5,7 @@ import { observer } from "mobx-react";
import { APIAlert, APIGroup } from "Models/API";
import { SilenceFormStore } from "Stores/SilenceFormStore";
-import { GetLabelColorClass } from "Common/Colors";
+import { BorderClassMap } from "Common/Colors";
import { StaticLabels } from "Common/Query";
import { FilteringLabel } from "Components/Labels/FilteringLabel";
import { RenderNonLinkAnnotation, RenderLinkAnnotation } from "../Annotation";
@@ -42,23 +42,21 @@ const Alert = observer(
"my-1",
"rounded-0",
"border-left-1 border-right-0 border-top-0 border-bottom-0",
- `border-${GetLabelColorClass(StaticLabels.State, alert.state)}`
+ BorderClassMap[alert.state] || "border-warning"
];
return (
- {alert.annotations
- .filter(a => a.isLink === false)
- .map(a => (
-
- ))}
+ {alert.annotations.filter(a => a.isLink === false).map(a => (
+
+ ))}
) : null}
- {alert.annotations
- .filter(a => a.isLink === true)
- .map(a => (
-
- ))}
+ {alert.annotations.filter(a => a.isLink === true).map(a => (
+
+ ))}
{alert.alertmanager.map(am =>
am.silencedBy.map(silenceID => (
{
afterEach(() => {
// reset Date() to current time
clear();
+ jest.restoreAllMocks();
});
const MockAfterUpdate = jest.fn();
@@ -93,4 +95,54 @@ describe("", () => {
expect(silence).toHaveLength(1);
expect(silence.html()).toMatch(/silence123456789/);
});
+
+ it("uses BorderClassMap.active when @state=active", () => {
+ const alert = MockedAlert();
+ alert.state = "active";
+ const group = MockAlertGroup({}, [alert], [], {});
+ const tree = MountedAlert(alert, group, false, false);
+ expect(
+ tree
+ .find(".components-grid-alertgrid-alertgroup-alert")
+ .hasClass(BorderClassMap.active)
+ ).toBe(true);
+ });
+
+ it("uses BorderClassMap.suppressed when @state=suppressed", () => {
+ const alert = MockedAlert();
+ alert.state = "suppressed";
+ const group = MockAlertGroup({}, [alert], [], {});
+ const tree = MountedAlert(alert, group, false, false);
+ expect(
+ tree
+ .find(".components-grid-alertgrid-alertgroup-alert")
+ .hasClass(BorderClassMap.suppressed)
+ ).toBe(true);
+ });
+
+ it("uses BorderClassMap.unprocessed when @state=unprocessed", () => {
+ const alert = MockedAlert();
+ alert.state = "unprocessed";
+ const group = MockAlertGroup({}, [alert], [], {});
+ const tree = MountedAlert(alert, group, false, false);
+ expect(
+ tree
+ .find(".components-grid-alertgrid-alertgroup-alert")
+ .hasClass(BorderClassMap.unprocessed)
+ ).toBe(true);
+ });
+
+ it("uses 'border-warning' with unknown @state", () => {
+ jest.spyOn(console, "error").mockImplementation(() => {});
+
+ const alert = MockedAlert();
+ alert.state = "foobar";
+ const group = MockAlertGroup({}, [alert], [], {});
+ const tree = MountedAlert(alert, group, false, false);
+ expect(
+ tree
+ .find(".components-grid-alertgrid-alertgroup-alert")
+ .hasClass("border-warning")
+ ).toBe(true);
+ });
});
diff --git a/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupFooter/__snapshots__/index.test.js.snap b/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupFooter/__snapshots__/index.test.js.snap
index c4827f677..f98bfd4f7 100644
--- a/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupFooter/__snapshots__/index.test.js.snap
+++ b/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupFooter/__snapshots__/index.test.js.snap
@@ -48,7 +48,7 @@ exports[` matches snapshot 1`] = `
aria-describedby=\\"tippy-tooltip-1\\"
data-original-title=\\"Click to only show alerts with this label\\"
>
-
+
label1:
@@ -63,7 +63,7 @@ exports[` matches snapshot 1`] = `
aria-describedby=\\"tippy-tooltip-2\\"
data-original-title=\\"Click to only show alerts with this label\\"
>
-
+
label2:
@@ -78,7 +78,7 @@ exports[` matches snapshot 1`] = `
aria-describedby=\\"tippy-tooltip-3\\"
data-original-title=\\"Click to only show alerts with this label\\"
>
-
+
@alertmanager:
@@ -93,7 +93,7 @@ exports[` matches snapshot 1`] = `
aria-describedby=\\"tippy-tooltip-4\\"
data-original-title=\\"Click to only show alerts with this label\\"
>
-
+
@receiver:
diff --git a/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/__snapshots__/index.test.js.snap b/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/__snapshots__/index.test.js.snap
index f453a02e8..9c03bc7e0 100644
--- a/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/__snapshots__/index.test.js.snap
+++ b/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/__snapshots__/index.test.js.snap
@@ -108,7 +108,7 @@ exports[` matches snapshot with expaned details 1`] = `
aria-describedby=\\"tippy-tooltip-6\\"
data-original-title=\\"Click to only show alerts with this label\\"
>
-
+
@alertmanager:
diff --git a/ui/src/Components/LabelSetList/__snapshots__/index.test.js.snap b/ui/src/Components/LabelSetList/__snapshots__/index.test.js.snap
index 7f0088f71..bce2c5f61 100644
--- a/ui/src/Components/LabelSetList/__snapshots__/index.test.js.snap
+++ b/ui/src/Components/LabelSetList/__snapshots__/index.test.js.snap
@@ -9,7 +9,7 @@ exports[` matches snapshot with populated list 1`] = `
-
-
+
foo:
@@ -19,7 +19,7 @@ exports[` matches snapshot with populated list 1`] = `
-
-
+
job:
@@ -29,7 +29,7 @@ exports[` matches snapshot with populated list 1`] = `
-
-
+
instance:
@@ -39,7 +39,7 @@ exports[` matches snapshot with populated list 1`] = `
-
-
+
cluster:
diff --git a/ui/src/Components/Labels/BaseLabel/index.js b/ui/src/Components/Labels/BaseLabel/index.js
index 258926b35..17fab5a63 100644
--- a/ui/src/Components/Labels/BaseLabel/index.js
+++ b/ui/src/Components/Labels/BaseLabel/index.js
@@ -2,8 +2,13 @@ import { Component } from "react";
import PropTypes from "prop-types";
import { AlertStore } from "Stores/AlertStore";
-import { GetLabelColorClass, StaticColorLabelClass } from "Common/Colors";
-import { QueryOperators, FormatQuery } from "Common/Query";
+import {
+ StaticColorLabelClass,
+ StateLabelClassMap,
+ DefaultLabelClass,
+ AlertNameLabelClass
+} from "Common/Colors";
+import { QueryOperators, FormatQuery, StaticLabels } from "Common/Query";
import "./index.scss";
@@ -17,49 +22,54 @@ class BaseLabel extends Component {
value: PropTypes.string.isRequired
};
- isStaticColorLabel(name) {
+ getClassAndStyle(name, value, extraClass = "") {
const { alertStore } = this.props;
- return alertStore.settings.values.staticColorLabels.includes(name);
- }
+ const data = {
+ style: {},
+ className: "",
+ baseClassNames: [
+ "components-label",
+ "badge",
+ "text-nowrap",
+ "text-truncate",
+ "mw-100"
+ ],
+ colorClassNames: []
+ };
- isBackgroundDark(name, value) {
- const { alertStore } = this.props;
+ if (name === StaticLabels.AlertName) {
+ data.colorClassNames.push(AlertNameLabelClass);
+ } else if (name === StaticLabels.State) {
+ data.colorClassNames.push(StateLabelClassMap[value] || DefaultLabelClass);
+ } else if (alertStore.settings.values.staticColorLabels.includes(name)) {
+ data.colorClassNames.push(StaticColorLabelClass);
+ } else {
+ const c = alertStore.data.getColorData(name, value);
+ if (c) {
+ // if there's color information use it
+ data.style["backgroundColor"] = `rgba(${[
+ c.background.red,
+ c.background.green,
+ c.background.blue,
+ c.background.alpha
+ ].join(", ")})`;
- const c = alertStore.data.getColorData(name, value);
- if (c) {
- return isBackgroundDark(c.brightness);
+ data.colorClassNames.push(
+ isBackgroundDark(c.brightness)
+ ? "components-label-dark"
+ : "components-label-bright"
+ );
+ } else {
+ // if not fall back to class
+ data.colorClassNames.push(DefaultLabelClass);
+ }
}
- return true;
- }
+ data.className = `${[...data.baseClassNames, ...data.colorClassNames].join(
+ " "
+ )} ${extraClass}`;
- getColorClass(name, value) {
- if (this.isStaticColorLabel(name)) {
- return StaticColorLabelClass;
- }
- return GetLabelColorClass(name, value);
- }
-
- getColorStyle(name, value) {
- const { alertStore } = this.props;
-
- let style = {};
-
- if (this.isStaticColorLabel(name)) {
- // static labels only get class, no unique colors
- return style;
- }
-
- const c = alertStore.data.getColorData(name, value);
- if (c) {
- style["backgroundColor"] = `rgba(${[
- c.background.red,
- c.background.green,
- c.background.blue,
- c.background.alpha
- ].join(", ")})`;
- }
- return style;
+ return data;
}
handleClick = event => {
diff --git a/ui/src/Components/Labels/BaseLabel/index.test.js b/ui/src/Components/Labels/BaseLabel/index.test.js
index c0e2292a4..a0db5f8db 100644
--- a/ui/src/Components/Labels/BaseLabel/index.test.js
+++ b/ui/src/Components/Labels/BaseLabel/index.test.js
@@ -3,7 +3,12 @@ import React from "react";
import { shallow } from "enzyme";
import { AlertStore } from "Stores/AlertStore";
-
+import {
+ StaticColorLabelClass,
+ DefaultLabelClass,
+ AlertNameLabelClass,
+ StateLabelClassMap
+} from "Common/Colors";
import { BaseLabel } from ".";
let alertStore;
@@ -12,56 +17,92 @@ beforeEach(() => {
alertStore = new AlertStore([]);
});
-const FakeBaseLabel = () => {
- // BaseLabel doesn't implement render since it's an abstract component
- // Add a dummy implementation for testing
+const FakeBaseLabel = (name = "foo", value = "bar") => {
class RenderableBaseLabel extends BaseLabel {
render() {
- return null;
+ const { name, value } = this.props;
+ let cs = this.getClassAndStyle(name, value);
+ return (
+
+ {name}:{" "}
+ {value}
+
+ );
}
}
return shallow(
-
+
);
};
describe("", () => {
- it("isStaticColorLabel() returns true for labels present in staticColorLabels", () => {
+ it("static label uses StaticColorLabelClass", () => {
alertStore.settings.values.staticColorLabels = ["foo", "job", "bar"];
- const instance = FakeBaseLabel().instance();
- expect(instance.isStaticColorLabel("job")).toBeTruthy();
+ const tree = FakeBaseLabel();
+ expect(tree.find(".components-label").hasClass(StaticColorLabelClass)).toBe(
+ true
+ );
});
- it("isStaticColorLabel() returns false for labels not present in staticColorLabels", () => {
- alertStore.settings.values.staticColorLabels = ["foo"];
- const instance = FakeBaseLabel().instance();
- expect(instance.isStaticColorLabel("job")).toBeFalsy();
+ it("non-static label doesn't use StaticColorLabelClass", () => {
+ alertStore.settings.values.staticColorLabels = [];
+ const tree = FakeBaseLabel();
+ expect(tree.find(".components-label").hasClass(StaticColorLabelClass)).toBe(
+ false
+ );
});
- it("getColorClass() on a label included in staticColorLabels should return 'info'", () => {
- alertStore.settings.values.staticColorLabels = ["job"];
- const instance = FakeBaseLabel().instance();
- expect(instance.getColorClass("job", "foo")).toBe("info");
+ it("label with no special color information should use DefaultLabelClass", () => {
+ const tree = FakeBaseLabel();
+ expect(tree.find(".components-label").hasClass(DefaultLabelClass)).toBe(
+ true
+ );
});
- it("getColorClass() on a label without any special color should return 'warning'", () => {
- const instance = FakeBaseLabel().instance();
- expect(instance.getColorClass("foo", "bar")).toBe("warning");
+ it("alertname label should use AlertNameLabelClass", () => {
+ const tree = FakeBaseLabel("alertname", "foo");
+ expect(tree.find(".components-label").hasClass(AlertNameLabelClass)).toBe(
+ true
+ );
});
- it("getColorClass() on 'alertname' label should return 'dark'", () => {
- const instance = FakeBaseLabel().instance();
- expect(instance.getColorClass("alertname", "foo")).toBe("dark");
+ it("@state=active label should use StateLabelClassMap.active class", () => {
+ const tree = FakeBaseLabel("@state", "active");
+ expect(
+ tree.find(".components-label").hasClass(StateLabelClassMap.active)
+ ).toBe(true);
});
- it("getColorStyle() on a label included in staticColorLabels should be empty", () => {
- alertStore.settings.values.staticColorLabels = ["job"];
- const instance = FakeBaseLabel().instance();
- expect(instance.getColorStyle("job", "bar")).toMatchObject({});
+ it("@state=suppressed label should use StateLabelClassMap.suppressed class", () => {
+ const tree = FakeBaseLabel("@state", "suppressed");
+ expect(
+ tree.find(".components-label").hasClass(StateLabelClassMap.suppressed)
+ ).toBe(true);
});
- it("getColorStyle() on a label without any color information should be empty", () => {
- const instance = FakeBaseLabel().instance();
- expect(instance.getColorStyle("foo", "bar")).toMatchObject({});
+ it("@state=unprocessed label should use StateLabelClassMap.unprocessed class", () => {
+ const tree = FakeBaseLabel("@state", "unprocessed");
+ expect(
+ tree.find(".components-label").hasClass(StateLabelClassMap.unprocessed)
+ ).toBe(true);
+ });
+
+ it("@state with unknown label should use DefaultLabelClass", () => {
+ const tree = FakeBaseLabel("@state", "foobar");
+ expect(tree.find(".components-label").hasClass(DefaultLabelClass)).toBe(
+ true
+ );
+ });
+
+ it("style prop on a label included in staticColorLabels should be empty", () => {
+ alertStore.settings.values.staticColorLabels = ["foo", "job", "bar"];
+ const tree = FakeBaseLabel();
+ expect(tree.find(".components-label").props().style).toEqual({});
+ });
+
+ it("style prop on a label without any color information should be empty", () => {
+ alertStore.settings.values.staticColorLabels = [];
+ const tree = FakeBaseLabel();
+ expect(tree.find(".components-label").props().style).toEqual({});
});
});
diff --git a/ui/src/Components/Labels/FilterInputLabel/index.js b/ui/src/Components/Labels/FilterInputLabel/index.js
index 9e69063f0..a7f1d0d07 100644
--- a/ui/src/Components/Labels/FilterInputLabel/index.js
+++ b/ui/src/Components/Labels/FilterInputLabel/index.js
@@ -10,7 +10,6 @@ import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclama
import { faSpinner } from "@fortawesome/free-solid-svg-icons/faSpinner";
import { AlertStore } from "Stores/AlertStore";
-import { DefaultLabelClass } from "Common/Colors";
import { QueryOperators } from "Common/Query";
import { TooltipWrapper } from "Components/TooltipWrapper";
import { BaseLabel } from "Components/Labels/BaseLabel";
@@ -46,43 +45,32 @@ const FilterInputLabel = observer(
render() {
const { filter, alertStore } = this.props;
- let classNames = [
- "components-label",
- "components-filteredinputlabel",
- "badge",
- "text-nowrap",
- "text-truncate",
- "mw-100"
- ];
- let badgeClass = "";
- let style = {};
- if (!filter.applied) {
- classNames.push("badge-secondary");
- } else if (filter.matcher === QueryOperators.Equal) {
- // only pass color class & style for equality matchers (foo=bar)
- // if we have foo!=bar filter then it should't get the color we use
- // for "foo: bar" labels
- classNames.push(
- `badge-${this.getColorClass(filter.name, filter.value)}`
- );
- style = this.getColorStyle(filter.name, filter.value);
-
- badgeClass = this.isBackgroundDark(filter.name, filter.value)
- ? "components-label-dark"
- : "components-label-bright";
- } else {
- classNames.push(`badge-${DefaultLabelClass}`);
- }
+ let cs = this.getClassAndStyle(
+ filter.matcher === QueryOperators.Equal ? filter.name : "",
+ filter.matcher === QueryOperators.Equal ? filter.value : "",
+ "components-filteredinputlabel"
+ );
return (
-
+
{filter.isValid ? (
filter.applied ? (
@@ -105,7 +93,7 @@ const FilterInputLabel = observer(
value={filter.raw}
propName="raw"
change={this.onChange}
- className={badgeClass}
+ className={cs.colorClassNames.join(" ")}
classEditing="py-0 border-0 bg-light"
/>
diff --git a/ui/src/Components/Labels/FilteringCounterBadge/index.js b/ui/src/Components/Labels/FilteringCounterBadge/index.js
index 8cff69161..3aded14ff 100644
--- a/ui/src/Components/Labels/FilteringCounterBadge/index.js
+++ b/ui/src/Components/Labels/FilteringCounterBadge/index.js
@@ -25,14 +25,17 @@ const FilteringCounterBadge = inject("alertStore")(
if (counter === 0) return null;
+ let cs = this.getClassAndStyle(
+ name,
+ value,
+ "badge-pill components-label-with-hover"
+ );
+
return (
this.handleClick(e)}
>
{counter}
diff --git a/ui/src/Components/Labels/FilteringLabel/__snapshots__/index.test.js.snap b/ui/src/Components/Labels/FilteringLabel/__snapshots__/index.test.js.snap
index 96dc9c86f..c48370312 100644
--- a/ui/src/Components/Labels/FilteringLabel/__snapshots__/index.test.js.snap
+++ b/ui/src/Components/Labels/FilteringLabel/__snapshots__/index.test.js.snap
@@ -8,7 +8,7 @@ exports[` matches snapshot 1`] = `
aria-describedby=\\"tippy-tooltip-1\\"
data-original-title=\\"Click to only show alerts with this label\\"
>
-
+
foo:
diff --git a/ui/src/Components/Labels/FilteringLabel/index.js b/ui/src/Components/Labels/FilteringLabel/index.js
index 1a0b74d1b..2d05a11a2 100644
--- a/ui/src/Components/Labels/FilteringLabel/index.js
+++ b/ui/src/Components/Labels/FilteringLabel/index.js
@@ -12,22 +12,17 @@ const FilteringLabel = inject("alertStore")(
render() {
const { name, value } = this.props;
- const classNames = [
- "components-label",
- "components-label-with-hover",
- "text-nowrap text-truncate mw-100",
- "badge",
- `badge-${this.getColorClass(name, value)}`,
- this.isBackgroundDark(name, value)
- ? "components-label-dark"
- : "components-label-bright"
- ];
+ let cs = this.getClassAndStyle(
+ name,
+ value,
+ "components-label-with-hover"
+ );
return (
this.handleClick(e)}
>
{name}:{" "}
diff --git a/ui/src/Components/Labels/HistoryLabel/index.js b/ui/src/Components/Labels/HistoryLabel/index.js
index 06ea272c3..991847591 100644
--- a/ui/src/Components/Labels/HistoryLabel/index.js
+++ b/ui/src/Components/Labels/HistoryLabel/index.js
@@ -3,7 +3,6 @@ import PropTypes from "prop-types";
import { observer } from "mobx-react";
-import { DefaultLabelClass } from "Common/Colors";
import { QueryOperators } from "Common/Query";
import { AlertStore } from "Stores/AlertStore";
import { BaseLabel } from "Components/Labels/BaseLabel";
@@ -22,28 +21,14 @@ const HistoryLabel = observer(
render() {
const { name, matcher, value } = this.props;
- let classNames = [
- "components-label",
- "components-label-history",
- "text-nowrap",
- "text-truncate",
- "badge",
- "mw-100",
- "components-label-value",
- this.isBackgroundDark(name, value)
- ? "components-label-dark"
- : "components-label-bright"
- ];
- let style = {};
- if (matcher === QueryOperators.Equal) {
- classNames.push(`badge-${this.getColorClass(name, value)}`);
- style = this.getColorStyle(name, value);
- } else {
- classNames.push(`badge-${DefaultLabelClass}`);
- }
+ let cs = this.getClassAndStyle(
+ matcher === QueryOperators.Equal ? name : "",
+ matcher === QueryOperators.Equal ? value : "",
+ "components-label-history components-label-value"
+ );
return (
-
+
{name ? `${name}${matcher}` : null}
{value}
diff --git a/ui/src/Components/Labels/StaticLabel/__snapshots__/index.test.js.snap b/ui/src/Components/Labels/StaticLabel/__snapshots__/index.test.js.snap
index 2e863edc1..fa79adad8 100644
--- a/ui/src/Components/Labels/StaticLabel/__snapshots__/index.test.js.snap
+++ b/ui/src/Components/Labels/StaticLabel/__snapshots__/index.test.js.snap
@@ -2,7 +2,7 @@
exports[` matches snapshot 1`] = `
"
-
+
foo:
diff --git a/ui/src/Components/Labels/StaticLabel/index.js b/ui/src/Components/Labels/StaticLabel/index.js
index 4f58a12ac..91f9a6bd4 100644
--- a/ui/src/Components/Labels/StaticLabel/index.js
+++ b/ui/src/Components/Labels/StaticLabel/index.js
@@ -11,21 +11,10 @@ const StaticLabel = inject("alertStore")(
render() {
const { name, value } = this.props;
- const classNames = [
- "components-label",
- "text-nowrap text-truncate mw-100",
- "badge",
- `badge-${this.getColorClass(name, value)}`,
- this.isBackgroundDark(name, value)
- ? "components-label-dark"
- : "components-label-bright"
- ];
+ let cs = this.getClassAndStyle(name, value);
return (
-
+
{name}:{" "}
{value}
diff --git a/ui/src/Components/SilenceModal/SilencePreview/__snapshots__/index.test.js.snap b/ui/src/Components/SilenceModal/SilencePreview/__snapshots__/index.test.js.snap
index 5b3c1c050..aec630a90 100644
--- a/ui/src/Components/SilenceModal/SilencePreview/__snapshots__/index.test.js.snap
+++ b/ui/src/Components/SilenceModal/SilencePreview/__snapshots__/index.test.js.snap
@@ -10,7 +10,7 @@ exports[` matches snapshot 1`] = `
-
-
+
alertname:
@@ -18,7 +18,7 @@ exports[` matches snapshot 1`] = `
foo
-
+
job:
@@ -26,7 +26,7 @@ exports[` matches snapshot 1`] = `
foo
-
+
instance:
@@ -36,7 +36,7 @@ exports[` matches snapshot 1`] = `
-
-
+
alertname:
@@ -44,7 +44,7 @@ exports[` matches snapshot 1`] = `
bar
-
+
job:
@@ -52,7 +52,7 @@ exports[` matches snapshot 1`] = `
bar
-
+
instance:
@@ -62,7 +62,7 @@ exports[` matches snapshot 1`] = `
-
-
+
alertname:
@@ -70,7 +70,7 @@ exports[` matches snapshot 1`] = `
bar
-
+
job:
@@ -78,7 +78,7 @@ exports[` matches snapshot 1`] = `
bar
-
+
instance: