diff --git a/ui/src/Components/Grid/AlertGrid/AlertGroup/Alert/__snapshots__/index.test.js.snap b/ui/src/Components/Grid/AlertGrid/AlertGroup/Alert/__snapshots__/index.test.js.snap index 55c1afdf7..04320ba86 100644 --- a/ui/src/Components/Grid/AlertGrid/AlertGroup/Alert/__snapshots__/index.test.js.snap +++ b/ui/src/Components/Grid/AlertGrid/AlertGroup/Alert/__snapshots__/index.test.js.snap @@ -69,8 +69,13 @@ exports[` matches snapshot with showAlertmanagers=false showReceiver=fa aria-describedby=\\"tippy-tooltip-1\\" data-original-title=\\"Click to only show alerts with this label\\" > - - job: node_exporter + + + job: + + + node_exporter +
matches snapshot with showAlertmanagers=false showReceiver=fa aria-describedby=\\"tippy-tooltip-2\\" data-original-title=\\"Click to only show alerts with this label\\" > - - cluster: dev + + + cluster: + + + dev +
matches snapshot 1`] = ` aria-describedby=\\"tippy-tooltip-1\\" data-original-title=\\"Click to only show alerts with this label\\" > - - label1: foo + + + label1: + + + foo +
matches snapshot 1`] = ` aria-describedby=\\"tippy-tooltip-2\\" data-original-title=\\"Click to only show alerts with this label\\" > - - label2: bar + + + label2: + + + bar +
matches snapshot 1`] = ` aria-describedby=\\"tippy-tooltip-3\\" data-original-title=\\"Click to only show alerts with this label\\" > - - @alertmanager: default + + + @alertmanager: + + + default +
matches snapshot 1`] = ` aria-describedby=\\"tippy-tooltip-4\\" data-original-title=\\"Click to only show alerts with this label\\" > - - @receiver: by-name + + + @receiver: + + + by-name +
+
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 33a2ff890..f453a02e8 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,8 +108,13 @@ exports[` matches snapshot with expaned details 1`] = ` aria-describedby=\\"tippy-tooltip-6\\" data-original-title=\\"Click to only show alerts with this label\\" > - - @alertmanager: default + + + @alertmanager: + + + default + ", () => { it("renders Alertmanager labels in footer if showAlertmanagersInFooter=true", () => { MockAlerts(2); const tree = MountedAlertGroup(jest.fn(), true).find("AlertGroup"); - expect(tree.find("GroupFooter").html()).toMatch(/@alertmanager: default/); + expect(tree.find("GroupFooter").html()).toMatch(/@alertmanager/); }); it("doesn't render alertmanager labels in footer when they are unique", () => { @@ -80,10 +80,10 @@ describe("", () => { const tree = MountedAlertGroup(jest.fn(), true); const alerts = tree.find("ul.list-group"); - expect(alerts.html()).toMatch(/@alertmanager:/); + expect(alerts.html()).toMatch(/@alertmanager/); const footer = tree.find("GroupFooter"); - expect(footer.html()).not.toMatch(/@alertmanager:/); + expect(footer.html()).not.toMatch(/@alertmanager/); }); it("only renders titlebar when collapsed", () => { diff --git a/ui/src/Components/LabelSetList/__snapshots__/index.test.js.snap b/ui/src/Components/LabelSetList/__snapshots__/index.test.js.snap index 34bc72fee..ecb061e13 100644 --- a/ui/src/Components/LabelSetList/__snapshots__/index.test.js.snap +++ b/ui/src/Components/LabelSetList/__snapshots__/index.test.js.snap @@ -8,23 +8,43 @@ exports[` matches snapshot with populated list 1`] = `

  • - - foo: bar + + + foo: + + + bar +
  • - - job: node_exporter + + + job: + + + node_exporter +
  • - - instance: server1 + + + instance: + + + server1 +
  • - - cluster: prod + + + cluster: + + + prod +
diff --git a/ui/src/Components/Labels/BaseLabel/index.css b/ui/src/Components/Labels/BaseLabel/index.css deleted file mode 100644 index 81563909f..000000000 --- a/ui/src/Components/Labels/BaseLabel/index.css +++ /dev/null @@ -1,9 +0,0 @@ -.components-label-with-hover:hover { - filter: brightness(0.85); - text-decoration: none; - cursor: pointer; -} - -.components-label { - margin-right: 0.25rem; -} diff --git a/ui/src/Components/Labels/BaseLabel/index.js b/ui/src/Components/Labels/BaseLabel/index.js index a86ee99c3..258926b35 100644 --- a/ui/src/Components/Labels/BaseLabel/index.js +++ b/ui/src/Components/Labels/BaseLabel/index.js @@ -5,7 +5,9 @@ import { AlertStore } from "Stores/AlertStore"; import { GetLabelColorClass, StaticColorLabelClass } from "Common/Colors"; import { QueryOperators, FormatQuery } from "Common/Query"; -import "./index.css"; +import "./index.scss"; + +const isBackgroundDark = brightness => brightness <= 125; // base class for shared code, not used directly class BaseLabel extends Component { @@ -21,6 +23,16 @@ class BaseLabel extends Component { return alertStore.settings.values.staticColorLabels.includes(name); } + isBackgroundDark(name, value) { + const { alertStore } = this.props; + + const c = alertStore.data.getColorData(name, value); + if (c) { + return isBackgroundDark(c.brightness); + } + return true; + } + getColorClass(name, value) { if (this.isStaticColorLabel(name)) { return StaticColorLabelClass; @@ -38,21 +50,14 @@ class BaseLabel extends Component { return style; } - if ( - alertStore.data.colors[name] !== undefined && - alertStore.data.colors[name][value] !== undefined - ) { - const c = alertStore.data.colors[name][value]; + 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(", ")})`; - style["color"] = - c.brightness <= 125 - ? "rgba(255, 255, 255, 255)" - : "rgba(44, 62, 80, 255)"; } return style; } diff --git a/ui/src/Components/Labels/BaseLabel/index.scss b/ui/src/Components/Labels/BaseLabel/index.scss new file mode 100644 index 000000000..2bb6bc87e --- /dev/null +++ b/ui/src/Components/Labels/BaseLabel/index.scss @@ -0,0 +1,35 @@ +@import "~bootswatch/dist/flatly/variables"; + +.components-label-with-hover:hover { + filter: brightness(0.85); + text-decoration: none; + cursor: pointer; +} + +.components-label { + margin-right: 0.25rem; +} + +.components-label-bright { + color: $black; + &.components-label-name, + .components-label-name { + color: lighten($black, 20%); + } + &.components-label-value, + .components-label-value { + color: $black; + } +} + +.components-label-dark { + color: $white; + &.components-label-name, + .components-label-name { + color: darken($white, 10%); + } + &.components-label-value, + .components-label-value { + color: $white; + } +} diff --git a/ui/src/Components/Labels/BaseLabel/index.test.js b/ui/src/Components/Labels/BaseLabel/index.test.js index bba969f4b..c0e2292a4 100644 --- a/ui/src/Components/Labels/BaseLabel/index.test.js +++ b/ui/src/Components/Labels/BaseLabel/index.test.js @@ -64,32 +64,4 @@ describe("", () => { const instance = FakeBaseLabel().instance(); expect(instance.getColorStyle("foo", "bar")).toMatchObject({}); }); - - it("getColorStyle() on a label with dark background color should have a bright font", () => { - alertStore.data.colors["foo"] = { - bar: { - brightness: 125, - background: { red: 4, green: 5, blue: 6, alpha: 200 } - } - }; - const instance = FakeBaseLabel().instance(); - expect(instance.getColorStyle("foo", "bar")).toMatchObject({ - color: "rgba(255, 255, 255, 255)", - backgroundColor: "rgba(4, 5, 6, 200)" - }); - }); - - it("getColorStyle() on a label with bright background color should have a dark font", () => { - alertStore.data.colors["foo"] = { - bar: { - brightness: 200, - background: { red: 4, green: 5, blue: 6, alpha: 200 } - } - }; - const instance = FakeBaseLabel().instance(); - expect(instance.getColorStyle("foo", "bar")).toMatchObject({ - color: "rgba(44, 62, 80, 255)", - backgroundColor: "rgba(4, 5, 6, 200)" - }); - }); }); diff --git a/ui/src/Components/Labels/FilterInputLabel/index.js b/ui/src/Components/Labels/FilterInputLabel/index.js index 9e273ccd9..9e69063f0 100644 --- a/ui/src/Components/Labels/FilterInputLabel/index.js +++ b/ui/src/Components/Labels/FilterInputLabel/index.js @@ -54,6 +54,7 @@ const FilterInputLabel = observer( "text-truncate", "mw-100" ]; + let badgeClass = ""; let style = {}; if (!filter.applied) { classNames.push("badge-secondary"); @@ -65,6 +66,10 @@ const FilterInputLabel = observer( `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}`); } @@ -77,7 +82,7 @@ const FilterInputLabel = observer( style={style} onClick={() => alertStore.filters.removeFilter(filter.raw)} > - × + × {filter.isValid ? ( filter.applied ? ( @@ -100,6 +105,7 @@ const FilterInputLabel = observer( value={filter.raw} propName="raw" change={this.onChange} + className={badgeClass} classEditing="py-0 border-0 bg-light" /> diff --git a/ui/src/Components/Labels/FilterInputLabel/index.test.js b/ui/src/Components/Labels/FilterInputLabel/index.test.js index 099228cf2..b65b10ca3 100644 --- a/ui/src/Components/Labels/FilterInputLabel/index.test.js +++ b/ui/src/Components/Labels/FilterInputLabel/index.test.js @@ -109,7 +109,6 @@ describe(" style", () => { MockColors(); const tree = ShallowLabel("=", true, true); expect(tree.props().style).toMatchObject({ - color: "rgba(44, 62, 80, 255)", backgroundColor: "rgba(4, 5, 6, 200)" }); }); 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 3abe48666..96dc9c86f 100644 --- a/ui/src/Components/Labels/FilteringLabel/__snapshots__/index.test.js.snap +++ b/ui/src/Components/Labels/FilteringLabel/__snapshots__/index.test.js.snap @@ -8,8 +8,13 @@ exports[` matches snapshot 1`] = ` aria-describedby=\\"tippy-tooltip-1\\" data-original-title=\\"Click to only show alerts with this label\\" > - - foo: bar + + + foo: + + + bar + " diff --git a/ui/src/Components/Labels/FilteringLabel/index.js b/ui/src/Components/Labels/FilteringLabel/index.js index 59ee92cfb..1a0b74d1b 100644 --- a/ui/src/Components/Labels/FilteringLabel/index.js +++ b/ui/src/Components/Labels/FilteringLabel/index.js @@ -11,17 +11,27 @@ const FilteringLabel = inject("alertStore")( class FilteringLabel extends BaseLabel { 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" + ]; + return ( this.handleClick(e)} > - {name}: {value} + {name}:{" "} + {value} ); diff --git a/ui/src/Components/Labels/FilteringLabel/index.test.js b/ui/src/Components/Labels/FilteringLabel/index.test.js index 585da237b..ab491b523 100644 --- a/ui/src/Components/Labels/FilteringLabel/index.test.js +++ b/ui/src/Components/Labels/FilteringLabel/index.test.js @@ -14,10 +14,14 @@ beforeEach(() => { alertStore = new AlertStore([]); }); -const RenderAndClick = (name, value) => { - const tree = mount( +const MountedFilteringLabel = (name, value) => { + return mount( - ); + ).find(".components-label"); +}; + +const RenderAndClick = (name, value) => { + const tree = MountedFilteringLabel(name, value); tree.find(".components-label").simulate("click"); }; @@ -48,4 +52,26 @@ describe("", () => { NewUnappliedFilter("bar=baz") ); }); + + it("label with dark background color should have 'components-label-dark' class", () => { + alertStore.data.colors["foo"] = { + bar: { + brightness: 125, + background: { red: 4, green: 5, blue: 6, alpha: 200 } + } + }; + const tree = MountedFilteringLabel("foo", "bar"); + expect(tree.hasClass("components-label-dark")).toBe(true); + }); + + it("label with bright background color should have 'components-label-bright' class", () => { + alertStore.data.colors["foo"] = { + bar: { + brightness: 200, + background: { red: 4, green: 5, blue: 6, alpha: 200 } + } + }; + const tree = MountedFilteringLabel("foo", "bar"); + expect(tree.hasClass("components-label-bright")).toBe(true); + }); }); diff --git a/ui/src/Components/Labels/HistoryLabel/index.js b/ui/src/Components/Labels/HistoryLabel/index.js index c2c10e877..06ea272c3 100644 --- a/ui/src/Components/Labels/HistoryLabel/index.js +++ b/ui/src/Components/Labels/HistoryLabel/index.js @@ -28,7 +28,11 @@ const HistoryLabel = observer( "text-nowrap", "text-truncate", "badge", - "mw-100" + "mw-100", + "components-label-value", + this.isBackgroundDark(name, value) + ? "components-label-dark" + : "components-label-bright" ]; let style = {}; if (matcher === QueryOperators.Equal) { diff --git a/ui/src/Components/Labels/HistoryLabel/index.test.js b/ui/src/Components/Labels/HistoryLabel/index.test.js index fb64c67ae..adad101f3 100644 --- a/ui/src/Components/Labels/HistoryLabel/index.test.js +++ b/ui/src/Components/Labels/HistoryLabel/index.test.js @@ -12,16 +12,20 @@ beforeEach(() => { alertStore = new AlertStore([]); }); +const ShallowHistoryLabel = (name, matcher, value) => { + return shallow( + + ); +}; + describe("", () => { it("renders name, matcher and value if all are set", () => { - const tree = shallow( - - ); + const tree = ShallowHistoryLabel("foo", "=", "bar"); expect(tree.text()).toBe("foo=bar"); }); @@ -31,4 +35,30 @@ describe("", () => { ); expect(tree.text()).toBe("bar"); }); + + it("label with dark background color should have 'components-label-dark' class", () => { + alertStore.data.colors["foo"] = { + bar: { + brightness: 125, + background: { red: 4, green: 5, blue: 6, alpha: 200 } + } + }; + const tree = ShallowHistoryLabel("foo", "=", "bar").find( + ".components-label" + ); + expect(tree.hasClass("components-label-dark")).toBe(true); + }); + + it("label with bright background color should have 'components-label-bright' class", () => { + alertStore.data.colors["foo"] = { + bar: { + brightness: 200, + background: { red: 4, green: 5, blue: 6, alpha: 200 } + } + }; + const tree = ShallowHistoryLabel("foo", "=", "bar").find( + ".components-label" + ); + expect(tree.hasClass("components-label-bright")).toBe(true); + }); }); 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 f08ea0003..2e863edc1 100644 --- a/ui/src/Components/Labels/StaticLabel/__snapshots__/index.test.js.snap +++ b/ui/src/Components/Labels/StaticLabel/__snapshots__/index.test.js.snap @@ -1,9 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` matches snapshot 1`] = ` +exports[` matches snapshot 1`] = ` " - - foo: bar + + + foo: + + + bar + " `; diff --git a/ui/src/Components/Labels/StaticLabel/index.js b/ui/src/Components/Labels/StaticLabel/index.js index 7ea7b07a8..4f58a12ac 100644 --- a/ui/src/Components/Labels/StaticLabel/index.js +++ b/ui/src/Components/Labels/StaticLabel/index.js @@ -10,15 +10,24 @@ const StaticLabel = inject("alertStore")( class FilteringLabel extends BaseLabel { 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" + ]; + return ( - {name}: {value} + {name}:{" "} + {value} ); } diff --git a/ui/src/Components/Labels/StaticLabel/index.test.js b/ui/src/Components/Labels/StaticLabel/index.test.js index e35cd9796..5daf783ff 100644 --- a/ui/src/Components/Labels/StaticLabel/index.test.js +++ b/ui/src/Components/Labels/StaticLabel/index.test.js @@ -14,11 +14,39 @@ beforeEach(() => { alertStore = new AlertStore([]); }); -describe("", () => { +const MountedStaticLabel = () => { + return mount(); +}; + +describe("", () => { it("matches snapshot", () => { - const tree = mount( - - ); + const tree = MountedStaticLabel(); expect(toDiffableHtml(tree.html())).toMatchSnapshot(); }); + + it("label with dark background color should have 'components-label-dark' class", () => { + alertStore.data.colors["foo"] = { + bar: { + brightness: 125, + background: { red: 4, green: 5, blue: 6, alpha: 200 } + } + }; + const tree = MountedStaticLabel(); + expect( + tree.find(".components-label").hasClass("components-label-dark") + ).toBe(true); + }); + + it("label with bright background color should have 'components-label-bright' class", () => { + alertStore.data.colors["foo"] = { + bar: { + brightness: 200, + background: { red: 4, green: 5, blue: 6, alpha: 200 } + } + }; + const tree = MountedStaticLabel(); + expect( + tree.find(".components-label").hasClass("components-label-bright") + ).toBe(true); + }); }); 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 6e46ce125..fd966fc22 100644 --- a/ui/src/Components/SilenceModal/SilencePreview/__snapshots__/index.test.js.snap +++ b/ui/src/Components/SilenceModal/SilencePreview/__snapshots__/index.test.js.snap @@ -9,36 +9,81 @@ exports[` matches snapshot 1`] = `

  • - - alertname: foo + + + alertname: + + + foo + - - job: foo + + + job: + + + foo + - - instance: foo1 + + + instance: + + + foo1 +
  • - - alertname: bar + + + alertname: + + + bar + - - job: bar + + + job: + + + bar + - - instance: bar1 + + + instance: + + + bar1 +
  • - - alertname: bar + + + alertname: + + + bar + - - job: bar + + + job: + + + bar + - - instance: bar2 + + + instance: + + + bar2 +
diff --git a/ui/src/Stores/AlertStore.js b/ui/src/Stores/AlertStore.js index f4ebb3568..23a98067a 100644 --- a/ui/src/Stores/AlertStore.js +++ b/ui/src/Stores/AlertStore.js @@ -143,9 +143,14 @@ class AlertStore { upstreams: { instances: [] }, getAlertmanagerByName(name) { return this.upstreams.instances.find(am => am.name === name); + }, + getColorData(name, value) { + if (this.colors[name] !== undefined) { + return this.colors[name][value]; + } } }, - { getAlertmanagerByName: action }, + {}, { name: "API Response data" } );