refactor(ui): change label style to make the value more visible

Fixes #18
This commit is contained in:
Łukasz Mierzwa
2018-10-15 19:05:49 +01:00
parent 794b54e5b9
commit 8bc2c83de3
22 changed files with 355 additions and 125 deletions
@@ -69,8 +69,13 @@ exports[`<Alert /> matches snapshot with showAlertmanagers=false showReceiver=fa
aria-describedby=\\"tippy-tooltip-1\\"
data-original-title=\\"Click to only show alerts with this label\\"
>
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate badge badge-warning mw-100\\">
job: node_exporter
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
job:
</span>
<span class=\\"components-label-value\\">
node_exporter
</span>
</span>
</div>
<div class
@@ -79,8 +84,13 @@ exports[`<Alert /> matches snapshot with showAlertmanagers=false showReceiver=fa
aria-describedby=\\"tippy-tooltip-2\\"
data-original-title=\\"Click to only show alerts with this label\\"
>
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate badge badge-warning mw-100\\">
cluster: dev
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
cluster:
</span>
<span class=\\"components-label-value\\">
dev
</span>
</span>
</div>
<a href=\\"http://localhost\\"
@@ -48,8 +48,13 @@ exports[`<GroupFooter /> matches snapshot 1`] = `
aria-describedby=\\"tippy-tooltip-1\\"
data-original-title=\\"Click to only show alerts with this label\\"
>
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate badge badge-warning mw-100\\">
label1: foo
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
label1:
</span>
<span class=\\"components-label-value\\">
foo
</span>
</span>
</div>
<div class
@@ -58,8 +63,13 @@ exports[`<GroupFooter /> matches snapshot 1`] = `
aria-describedby=\\"tippy-tooltip-2\\"
data-original-title=\\"Click to only show alerts with this label\\"
>
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate badge badge-warning mw-100\\">
label2: bar
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
label2:
</span>
<span class=\\"components-label-value\\">
bar
</span>
</span>
</div>
<div class
@@ -68,8 +78,13 @@ exports[`<GroupFooter /> matches snapshot 1`] = `
aria-describedby=\\"tippy-tooltip-3\\"
data-original-title=\\"Click to only show alerts with this label\\"
>
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate badge badge-warning mw-100\\">
@alertmanager: default
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
@alertmanager:
</span>
<span class=\\"components-label-value\\">
default
</span>
</span>
</div>
<div class
@@ -78,8 +93,13 @@ exports[`<GroupFooter /> matches snapshot 1`] = `
aria-describedby=\\"tippy-tooltip-4\\"
data-original-title=\\"Click to only show alerts with this label\\"
>
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate badge badge-warning mw-100\\">
@receiver: by-name
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
@receiver:
</span>
<span class=\\"components-label-value\\">
by-name
</span>
</span>
</div>
<a href=\\"http://link.example.com\\"
@@ -29,7 +29,7 @@ const GroupHeader = observer(
const { collapseStore, group, silenceFormStore } = this.props;
return (
<h5 className="card-title text-center mb-0 clearfix">
<h5 className="card-title mb-0 clearfix">
<span className="float-left">
<GroupMenu group={group} silenceFormStore={silenceFormStore} />
</span>
@@ -108,8 +108,13 @@ exports[`<Silence /> matches snapshot with expaned details 1`] = `
aria-describedby=\\"tippy-tooltip-6\\"
data-original-title=\\"Click to only show alerts with this label\\"
>
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate badge badge-warning mw-100\\">
@alertmanager: default
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
@alertmanager:
</span>
<span class=\\"components-label-value\\">
default
</span>
</span>
</div>
<a href=\\"file:///mock/#/silences/4cf5fd82-1edd-4169-99d1-ff8415e72179\\"
@@ -62,7 +62,7 @@ describe("<AlertGroup />", () => {
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("<AlertGroup />", () => {
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", () => {
@@ -8,23 +8,43 @@ exports[`<LabelSetList /> matches snapshot with populated list 1`] = `
</p>
<ul class=\\"list-group list-group-flush mb-3\\">
<li class=\\"list-group-item px-0 pt-2 pb-1\\">
<span class=\\"components-label text-nowrap text-truncate badge badge-warning mw-100\\">
foo: bar
<span class=\\"components-label text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
foo:
</span>
<span class=\\"components-label-value\\">
bar
</span>
</span>
</li>
<li class=\\"list-group-item px-0 pt-2 pb-1\\">
<span class=\\"components-label text-nowrap text-truncate badge badge-warning mw-100\\">
job: node_exporter
<span class=\\"components-label text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
job:
</span>
<span class=\\"components-label-value\\">
node_exporter
</span>
</span>
</li>
<li class=\\"list-group-item px-0 pt-2 pb-1\\">
<span class=\\"components-label text-nowrap text-truncate badge badge-warning mw-100\\">
instance: server1
<span class=\\"components-label text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
instance:
</span>
<span class=\\"components-label-value\\">
server1
</span>
</span>
</li>
<li class=\\"list-group-item px-0 pt-2 pb-1\\">
<span class=\\"components-label text-nowrap text-truncate badge badge-warning mw-100\\">
cluster: prod
<span class=\\"components-label text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
cluster:
</span>
<span class=\\"components-label-value\\">
prod
</span>
</span>
</li>
</ul>
@@ -1,9 +0,0 @@
.components-label-with-hover:hover {
filter: brightness(0.85);
text-decoration: none;
cursor: pointer;
}
.components-label {
margin-right: 0.25rem;
}
+15 -10
View File
@@ -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;
}
@@ -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;
}
}
@@ -64,32 +64,4 @@ describe("<BaseLabel />", () => {
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)"
});
});
});
@@ -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)}
>
<span className="align-text-bottom">&times;</span>
<span className={`align-text-bottom ${badgeClass}`}>&times;</span>
</button>
{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"
/>
</TooltipWrapper>
@@ -109,7 +109,6 @@ describe("<FilterInputLabel /> style", () => {
MockColors();
const tree = ShallowLabel("=", true, true);
expect(tree.props().style).toMatchObject({
color: "rgba(44, 62, 80, 255)",
backgroundColor: "rgba(4, 5, 6, 200)"
});
});
@@ -8,8 +8,13 @@ exports[`<FilteringLabel /> matches snapshot 1`] = `
aria-describedby=\\"tippy-tooltip-1\\"
data-original-title=\\"Click to only show alerts with this label\\"
>
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate badge badge-warning mw-100\\">
foo: bar
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
foo:
</span>
<span class=\\"components-label-value\\">
bar
</span>
</span>
</div>
"
@@ -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 (
<TooltipWrapper title="Click to only show alerts with this label">
<span
className={`components-label components-label-with-hover text-nowrap text-truncate badge badge-${this.getColorClass(
name,
value
)} mw-100`}
className={`${classNames.join(" ")}`}
style={this.getColorStyle(name, value)}
onClick={e => this.handleClick(e)}
>
{name}: {value}
<span className="components-label-name">{name}:</span>{" "}
<span className="components-label-value">{value}</span>
</span>
</TooltipWrapper>
);
@@ -14,10 +14,14 @@ beforeEach(() => {
alertStore = new AlertStore([]);
});
const RenderAndClick = (name, value) => {
const tree = mount(
const MountedFilteringLabel = (name, value) => {
return mount(
<FilteringLabel alertStore={alertStore} name={name} value={value} />
);
).find(".components-label");
};
const RenderAndClick = (name, value) => {
const tree = MountedFilteringLabel(name, value);
tree.find(".components-label").simulate("click");
};
@@ -48,4 +52,26 @@ describe("<FilteringLabel />", () => {
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);
});
});
@@ -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) {
@@ -12,16 +12,20 @@ beforeEach(() => {
alertStore = new AlertStore([]);
});
const ShallowHistoryLabel = (name, matcher, value) => {
return shallow(
<HistoryLabel
alertStore={alertStore}
name={name}
matcher={matcher}
value={value}
/>
);
};
describe("<HistoryLabel />", () => {
it("renders name, matcher and value if all are set", () => {
const tree = shallow(
<HistoryLabel
alertStore={alertStore}
name="foo"
matcher="="
value="bar"
/>
);
const tree = ShallowHistoryLabel("foo", "=", "bar");
expect(tree.text()).toBe("foo=bar");
});
@@ -31,4 +35,30 @@ describe("<HistoryLabel />", () => {
);
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);
});
});
@@ -1,9 +1,14 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<FilteringLabel /> matches snapshot 1`] = `
exports[`<StaticLabel /> matches snapshot 1`] = `
"
<span class=\\"components-label text-nowrap text-truncate badge badge-warning mw-100\\">
foo: bar
<span class=\\"components-label text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
foo:
</span>
<span class=\\"components-label-value\\">
bar
</span>
</span>
"
`;
+14 -5
View File
@@ -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 (
<span
className={`components-label text-nowrap text-truncate badge badge-${this.getColorClass(
name,
value
)} mw-100`}
className={`${classNames.join(" ")}`}
style={this.getColorStyle(name, value)}
>
{name}: {value}
<span className="components-label-name">{name}:</span>{" "}
<span className="components-label-value">{value}</span>
</span>
);
}
@@ -14,11 +14,39 @@ beforeEach(() => {
alertStore = new AlertStore([]);
});
describe("<FilteringLabel />", () => {
const MountedStaticLabel = () => {
return mount(<StaticLabel alertStore={alertStore} name="foo" value="bar" />);
};
describe("<StaticLabel />", () => {
it("matches snapshot", () => {
const tree = mount(
<StaticLabel alertStore={alertStore} name="foo" value="bar" />
);
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);
});
});
@@ -9,36 +9,81 @@ exports[`<SilencePreview /> matches snapshot 1`] = `
</p>
<ul class=\\"list-group list-group-flush mb-3\\">
<li class=\\"list-group-item px-0 pt-2 pb-1\\">
<span class=\\"components-label text-nowrap text-truncate badge badge-dark mw-100\\">
alertname: foo
<span class=\\"components-label text-nowrap text-truncate mw-100 badge badge-dark components-label-dark\\">
<span class=\\"components-label-name\\">
alertname:
</span>
<span class=\\"components-label-value\\">
foo
</span>
</span>
<span class=\\"components-label text-nowrap text-truncate badge badge-warning mw-100\\">
job: foo
<span class=\\"components-label text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
job:
</span>
<span class=\\"components-label-value\\">
foo
</span>
</span>
<span class=\\"components-label text-nowrap text-truncate badge badge-warning mw-100\\">
instance: foo1
<span class=\\"components-label text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
instance:
</span>
<span class=\\"components-label-value\\">
foo1
</span>
</span>
</li>
<li class=\\"list-group-item px-0 pt-2 pb-1\\">
<span class=\\"components-label text-nowrap text-truncate badge badge-dark mw-100\\">
alertname: bar
<span class=\\"components-label text-nowrap text-truncate mw-100 badge badge-dark components-label-dark\\">
<span class=\\"components-label-name\\">
alertname:
</span>
<span class=\\"components-label-value\\">
bar
</span>
</span>
<span class=\\"components-label text-nowrap text-truncate badge badge-warning mw-100\\">
job: bar
<span class=\\"components-label text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
job:
</span>
<span class=\\"components-label-value\\">
bar
</span>
</span>
<span class=\\"components-label text-nowrap text-truncate badge badge-warning mw-100\\">
instance: bar1
<span class=\\"components-label text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
instance:
</span>
<span class=\\"components-label-value\\">
bar1
</span>
</span>
</li>
<li class=\\"list-group-item px-0 pt-2 pb-1\\">
<span class=\\"components-label text-nowrap text-truncate badge badge-dark mw-100\\">
alertname: bar
<span class=\\"components-label text-nowrap text-truncate mw-100 badge badge-dark components-label-dark\\">
<span class=\\"components-label-name\\">
alertname:
</span>
<span class=\\"components-label-value\\">
bar
</span>
</span>
<span class=\\"components-label text-nowrap text-truncate badge badge-warning mw-100\\">
job: bar
<span class=\\"components-label text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
job:
</span>
<span class=\\"components-label-value\\">
bar
</span>
</span>
<span class=\\"components-label text-nowrap text-truncate badge badge-warning mw-100\\">
instance: bar2
<span class=\\"components-label text-nowrap text-truncate mw-100 badge badge-warning components-label-dark\\">
<span class=\\"components-label-name\\">
instance:
</span>
<span class=\\"components-label-value\\">
bar2
</span>
</span>
</li>
</ul>
+6 -1
View File
@@ -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" }
);