diff --git a/ui/src/Components/Labels/FilterInputLabel/index.test.tsx b/ui/src/Components/Labels/FilterInputLabel/index.test.tsx
index 889d72e72..07bb5d6ae 100644
--- a/ui/src/Components/Labels/FilterInputLabel/index.test.tsx
+++ b/ui/src/Components/Labels/FilterInputLabel/index.test.tsx
@@ -86,7 +86,11 @@ describe(" className", () => {
it("applied filter included in staticColorLabels with '=' matcher should use 'btn-info' class", () => {
alertStore.settings.setValues({
...alertStore.settings.values,
- ...{ staticColorLabels: ["foo"] },
+ ...{
+ labels: {
+ foo: { isStatic: true, isValueOnly: false },
+ },
+ },
});
ValidateClass("=", true, "btn-info");
});
@@ -94,7 +98,11 @@ describe(" className", () => {
it("applied filter included in staticColorLabels with any matcher other than '=' should use 'btn-default' class", () => {
alertStore.settings.setValues({
...alertStore.settings.values,
- ...{ staticColorLabels: ["foo"] },
+ ...{
+ labels: {
+ foo: { isStatic: true, isValueOnly: false },
+ },
+ },
});
for (const matcher of NonEqualMatchers) {
ValidateClass(matcher, true, "btn-default");
diff --git a/ui/src/Components/Labels/FilteringLabel/index.test.tsx b/ui/src/Components/Labels/FilteringLabel/index.test.tsx
index 3ecb19c17..6a7cfd67d 100644
--- a/ui/src/Components/Labels/FilteringLabel/index.test.tsx
+++ b/ui/src/Components/Labels/FilteringLabel/index.test.tsx
@@ -84,7 +84,11 @@ describe("", () => {
it("doesn't render the name if it's included in valueOnlyLabels", () => {
alertStore.settings.setValues({
...alertStore.settings.values,
- valueOnlyLabels: ["foo"],
+ ...{
+ labels: {
+ foo: { isStatic: false, isValueOnly: true },
+ },
+ },
});
const tree = mount(
@@ -95,45 +99,15 @@ describe("", () => {
it("renders the name if it's not included in valueOnlyLabels", () => {
alertStore.settings.setValues({
...alertStore.settings.values,
- valueOnlyLabels: ["bar"],
+ ...{
+ labels: {
+ bar: { isStatic: false, isValueOnly: true },
+ },
+ },
});
const tree = mount(
);
expect(tree.text()).toBe("foo: bar");
});
-
- it("doesn't render the name if it matches a regex in valueOnlyRegexLabels", () => {
- alertStore.settings.setValues({
- ...alertStore.settings.values,
- valueOnlyRegexLabels: ["^fo*$"],
- });
- const tree = mount(
-
- );
- expect(tree.text()).toBe("bar");
- });
-
- it("renders the name if it does not match any regex in valueOnlyRegexLabels", () => {
- alertStore.settings.setValues({
- ...alertStore.settings.values,
- valueOnlyRegexLabels: ["^[^o]*$"],
- });
- const tree = mount(
-
- );
- expect(tree.text()).toBe("foo: bar");
- });
-
- it("renders the name if valueOnlyRegexLabels provides invalid regex", () => {
- alertStore.settings.setValues({
- ...alertStore.settings.values,
- valueOnlyRegexLabels: ["^fo**$"],
- });
- jest.spyOn(global.console, "error").mockImplementation(() => {});
- const tree = mount(
-
- );
- expect(tree.text()).toBe("foo: bar");
- });
});
diff --git a/ui/src/Components/Labels/FilteringLabel/index.tsx b/ui/src/Components/Labels/FilteringLabel/index.tsx
index c82e566c0..14cb1e5e7 100644
--- a/ui/src/Components/Labels/FilteringLabel/index.tsx
+++ b/ui/src/Components/Labels/FilteringLabel/index.tsx
@@ -33,23 +33,10 @@ const FilteringLabel: FC<{
"components-label-with-hover"
);
- function isRegex(value: string): boolean {
- try {
- RegExp(value);
- return true;
- } catch {
- console.error(`Invalid regex '${value}'`);
- return false;
- }
- }
-
return (
- {alertStore.settings.values.valueOnlyLabels.includes(name) ||
- alertStore.settings.values.valueOnlyRegexLabels.some(
- (regex) => isRegex(regex) && name.match(regex)
- ) ? null : (
+ {alertStore.settings.values.labels[name]?.isValueOnly ? null : (
<>
{name}:{" "}
>
diff --git a/ui/src/Components/Labels/Utils.test.ts b/ui/src/Components/Labels/Utils.test.ts
index 93f2b55c4..b7ce615a9 100644
--- a/ui/src/Components/Labels/Utils.test.ts
+++ b/ui/src/Components/Labels/Utils.test.ts
@@ -17,8 +17,15 @@ describe("", () => {
it("static label uses StaticColorLabelClassMap.badge", () => {
alertStore.settings.setValues({
...alertStore.settings.values,
- ...{ staticColorLabels: ["foo", "job", "bar"] },
+ ...{
+ labels: {
+ foo: { isStatic: true, isValueOnly: false },
+ job: { isStatic: true, isValueOnly: false },
+ bar: { isStatic: true, isValueOnly: false },
+ },
+ },
});
+ expect(alertStore.settings.values.labels.foo.isStatic).toBe(true);
const cs = GetClassAndStyle(alertStore, "foo", "bar");
expect(cs.colorClassNames).toContain(StaticColorLabelClassMap.badge);
});
@@ -27,7 +34,9 @@ describe("", () => {
it(`non-static label doesn't use StaticColorLabelClassMap.${key}`, () => {
alertStore.settings.setValues({
...alertStore.settings.values,
- ...{ staticColorLabels: [] },
+ ...{
+ labels: {},
+ },
});
const cs = GetClassAndStyle(alertStore, "foo", "bar");
expect(cs.colorClassNames).not.toContain(StaticColorLabelClassMap.badge);
@@ -73,7 +82,13 @@ describe("", () => {
it("style prop on a label included in staticColorLabels should be empty", () => {
alertStore.settings.setValues({
...alertStore.settings.values,
- ...{ staticColorLabels: ["foo", "job", "bar"] },
+ ...{
+ labels: {
+ foo: { isStatic: true, isValueOnly: false },
+ job: { isStatic: true, isValueOnly: false },
+ bar: { isStatic: true, isValueOnly: false },
+ },
+ },
});
const cs = GetClassAndStyle(alertStore, "foo", "bar");
expect(cs.style).toEqual({});
@@ -82,7 +97,7 @@ describe("", () => {
it("style prop on a label without any color information should be empty", () => {
alertStore.settings.setValues({
...alertStore.settings.values,
- ...{ staticColorLabels: [] },
+ ...{ labels: {} },
});
const cs = GetClassAndStyle(alertStore, "foo", "bar");
expect(cs.style).toEqual({});
diff --git a/ui/src/Components/Labels/Utils.ts b/ui/src/Components/Labels/Utils.ts
index 4ff7df111..d9521f03c 100644
--- a/ui/src/Components/Labels/Utils.ts
+++ b/ui/src/Components/Labels/Utils.ts
@@ -33,6 +33,8 @@ const GetClassAndStyle = (
colorClassNames: [],
};
+ const labelSettings = alertStore.settings.values.labels[name];
+
if (name === StaticLabels.AlertName) {
data.colorClassNames.push(AlertNameLabelClassMap[elementType]);
} else if (name === StaticLabels.State) {
@@ -41,7 +43,7 @@ const GetClassAndStyle = (
? `bg-${StateLabelClassMap[value as AlertStateT]} text-white`
: DefaultLabelClassMap[elementType]
);
- } else if (alertStore.settings.values.staticColorLabels.includes(name)) {
+ } else if (labelSettings?.isStatic) {
data.colorClassNames.push(StaticColorLabelClassMap[elementType]);
} else {
const c = alertStore.data.getColorData(name, value);
diff --git a/ui/src/Models/APITypes.ts b/ui/src/Models/APITypes.ts
index 7ada29a7d..951f3a98b 100644
--- a/ui/src/Models/APITypes.ts
+++ b/ui/src/Models/APITypes.ts
@@ -176,10 +176,14 @@ export interface APILabelCounterT {
hits: number;
}
+export interface APILabelSettingsT {
+ isStatic: boolean;
+ isValueOnly: boolean;
+}
+
+export type APILabelsSettingsT = { [key: string]: APILabelSettingsT };
+
export interface APISettingsT {
- staticColorLabels: string[];
- valueOnlyLabels: string[];
- valueOnlyRegexLabels: string[];
annotationsDefaultHidden: boolean;
annotationsHidden: string[];
annotationsVisible: string[];
@@ -205,6 +209,7 @@ export interface APISettingsT {
};
historyEnabled: boolean;
gridGroupLimit: number;
+ labels: APILabelsSettingsT;
}
export interface APIAlertsResponseT {
diff --git a/ui/src/Stores/AlertStore.test.ts b/ui/src/Stores/AlertStore.test.ts
index 0297cdea6..91a28ecfb 100644
--- a/ui/src/Stores/AlertStore.test.ts
+++ b/ui/src/Stores/AlertStore.test.ts
@@ -693,7 +693,12 @@ describe("AlertStore.fetch", () => {
store.fetch("", false, "", "", false, {}, 5, {})
).resolves.toBeUndefined();
expect(store.settings.values).toMatchObject({
- staticColorLabels: ["job"],
+ labels: {
+ job: {
+ isStatic: true,
+ isValueOnly: false,
+ },
+ },
annotationsDefaultHidden: false,
annotationsHidden: [],
annotationsVisible: [],
@@ -705,7 +710,12 @@ describe("AlertStore.fetch", () => {
store.fetch("", false, "", "", false, {}, 5, {})
).resolves.toBeUndefined();
expect(store.settings.values).toMatchObject({
- staticColorLabels: ["job"],
+ labels: {
+ job: {
+ isStatic: true,
+ isValueOnly: false,
+ },
+ },
annotationsDefaultHidden: false,
annotationsHidden: [],
annotationsVisible: [],
diff --git a/ui/src/Stores/AlertStore.ts b/ui/src/Stores/AlertStore.ts
index 6b1a2c59a..cce3e37d4 100644
--- a/ui/src/Stores/AlertStore.ts
+++ b/ui/src/Stores/AlertStore.ts
@@ -461,9 +461,6 @@ class AlertStore {
this.settings = observable(
{
values: {
- staticColorLabels: [] as string[],
- valueOnlyLabels: [] as string[],
- valueOnlyRegexLabels: [] as string[],
annotationsDefaultHidden: false as boolean,
annotationsHidden: [] as string[],
annotationsVisible: [] as string[],
@@ -489,6 +486,7 @@ class AlertStore {
},
historyEnabled: true,
gridGroupLimit: 40,
+ labels: {},
} as APISettingsT,
setValues(v: APISettingsT) {
this.values = v;
diff --git a/ui/src/__fixtures__/Fetch.ts b/ui/src/__fixtures__/Fetch.ts
index 47bc98446..3ed95a9f6 100644
--- a/ui/src/__fixtures__/Fetch.ts
+++ b/ui/src/__fixtures__/Fetch.ts
@@ -71,15 +71,15 @@ const EmptyAPIResponse = (): APIAlertsResponseT => ({
author: "karma / author missing",
comment: "ACK! Mock comment",
},
- staticColorLabels: ["job"],
- valueOnlyLabels: [],
- valueOnlyRegexLabels: [],
annotationsDefaultHidden: false,
annotationsHidden: [],
annotationsVisible: [],
annotationsEnableHTML: false,
historyEnabled: true,
gridGroupLimit: 40,
+ labels: {
+ job: { isStatic: true, isValueOnly: false },
+ },
},
authentication: {
username: "",
@@ -95,10 +95,31 @@ const MockAPIResponse = (): APIAlertsResponseT => {
labelValue: "",
alertGroups: [
MockAlertGroup(
- [{ name: "alertname", value: "foo" }],
- [MockAlert([], [{ name: "instance", value: "foo" }], "suppressed")],
+ [
+ {
+ name: "alertname",
+ value: "foo",
+ },
+ ],
+ [
+ MockAlert(
+ [],
+ [
+ {
+ name: "instance",
+ value: "foo",
+ },
+ ],
+ "suppressed"
+ ),
+ ],
[],
- [{ name: "cluster", value: "dev" }],
+ [
+ {
+ name: "cluster",
+ value: "dev",
+ },
+ ],
{}
),
],
diff --git a/ui/src/__fixtures__/Stories.ts b/ui/src/__fixtures__/Stories.ts
index 6685ea4a2..cdc5fcabc 100644
--- a/ui/src/__fixtures__/Stories.ts
+++ b/ui/src/__fixtures__/Stories.ts
@@ -64,7 +64,12 @@ const MockGroup = (
},
]
: [],
- [{ name: "instance", value: `instance${i}` }],
+ [
+ {
+ name: "instance",
+ value: `instance${i}`,
+ },
+ ],
state
);
alert.startsAt = subMinutes(new Date(), alertCount).toISOString();
@@ -72,7 +77,10 @@ const MockGroup = (
}
const group = MockAlertGroup(
[
- { name: "alertname", value: "Fake Alert" },
+ {
+ name: "alertname",
+ value: "Fake Alert",
+ },
{ name: "group", value: groupName },
],
alerts,
@@ -174,8 +182,14 @@ const MockGrid = (alertStore: AlertStore): void => {
}
if (i < 3) {
group.shared.labels = [
- { name: "cluster", value: `prod${i}` },
- { name: "job", value: "textfile_exporter" },
+ {
+ name: "cluster",
+ value: `prod${i}`,
+ },
+ {
+ name: "job",
+ value: "textfile_exporter",
+ },
];
}
if (i < 5) {
diff --git a/ui/src/__fixtures__/useFetchGet.ts b/ui/src/__fixtures__/useFetchGet.ts
index 5408b1f29..6502c172d 100644
--- a/ui/src/__fixtures__/useFetchGet.ts
+++ b/ui/src/__fixtures__/useFetchGet.ts
@@ -105,7 +105,16 @@ const useFetchGetMock = (
},
{
re: /^\.\/alertList\.json\?q=/,
- response: { alerts: [[{ name: "instance", value: "foo" }]] },
+ response: {
+ alerts: [
+ [
+ {
+ name: "instance",
+ value: "foo",
+ },
+ ],
+ ],
+ },
},
// silence browser
{