diff --git a/CHANGELOG.md b/CHANGELOG.md
index c47f8e7ae..a51566808 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
# Changelog
+## [unreleased]
+
+### Changed
+
+- Multi-grid label dropdown will only show label names from visible alerts.
+
## v0.80
### Added
diff --git a/ui/src/Components/Grid/AlertGrid/GridLabelSelect.test.tsx b/ui/src/Components/Grid/AlertGrid/GridLabelSelect.test.tsx
index 301c3a54b..466c5222f 100644
--- a/ui/src/Components/Grid/AlertGrid/GridLabelSelect.test.tsx
+++ b/ui/src/Components/Grid/AlertGrid/GridLabelSelect.test.tsx
@@ -5,9 +5,12 @@ import { mount } from "enzyme";
import fetchMock from "fetch-mock";
+import { MockGrid } from "__fixtures__/Stories";
+import { AlertStore } from "Stores/AlertStore";
import { Settings } from "Stores/Settings";
import { GridLabelSelect } from "./GridLabelSelect";
+let alertStore: AlertStore;
let settingsStore: Settings;
beforeEach(() => {
@@ -16,13 +19,16 @@ beforeEach(() => {
body: JSON.stringify([]),
});
+ alertStore = new AlertStore([]);
settingsStore = new Settings(null);
jest.useFakeTimers();
});
const MountedGridLabelSelect = () => {
- return mount();
+ return mount(
+
+ );
};
describe("", () => {
@@ -35,6 +41,7 @@ describe("", () => {
it("clicking toggle renders select dropdown", async () => {
const promise = Promise.resolve();
+ MockGrid(alertStore);
const tree = MountedGridLabelSelect();
const toggle = tree.find("span.components-grid-label-select-dropdown");
toggle.simulate("click");
@@ -42,6 +49,22 @@ describe("", () => {
await act(() => promise);
});
+ it("clicking an option updates grid settings", async () => {
+ const promise = Promise.resolve();
+ MockGrid(alertStore);
+ const tree = MountedGridLabelSelect();
+
+ const toggle = tree.find("span.components-grid-label-select-dropdown");
+ toggle.simulate("click");
+ expect(tree.find("div.components-grid-label-select-menu")).toHaveLength(1);
+
+ settingsStore.multiGridConfig.config.gridLabel = "foo";
+ const options = tree.find("div.react-select__option");
+ options.at(4).simulate("click");
+ expect(settingsStore.multiGridConfig.config.gridLabel).toBe("cluster");
+ await act(() => promise);
+ });
+
it("clicking toggle twice hides select dropdown", async () => {
const promise = Promise.resolve();
const tree = MountedGridLabelSelect();
diff --git a/ui/src/Components/Grid/AlertGrid/GridLabelSelect.tsx b/ui/src/Components/Grid/AlertGrid/GridLabelSelect.tsx
index 6be20491e..0e5425e2e 100644
--- a/ui/src/Components/Grid/AlertGrid/GridLabelSelect.tsx
+++ b/ui/src/Components/Grid/AlertGrid/GridLabelSelect.tsx
@@ -11,23 +11,96 @@ import { observer } from "mobx-react-lite";
import { Manager, Reference, Popper } from "react-popper";
+import AsyncSelect from "react-select/async";
+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCaretDown } from "@fortawesome/free-solid-svg-icons/faCaretDown";
+import { AlertStore } from "Stores/AlertStore";
import { Settings } from "Stores/Settings";
import { CommonPopperModifiers } from "Common/Popper";
+import { NewLabelName, StringToOption, OptionT } from "Common/Select";
import { DropdownSlide } from "Components/Animations/DropdownSlide";
+import { ThemeContext } from "Components/Theme";
import { useOnClickOutside } from "Hooks/useOnClickOutside";
-import { GridLabelName } from "Components/MainModal/Configuration/GridLabelName";
const NullContainer: FC = () => null;
+const GridLabelNameSelect: FC<{
+ alertStore: AlertStore;
+ settingsStore: Settings;
+}> = ({ alertStore, settingsStore }) => {
+ const loadOptions = (
+ inputValue: string,
+ callback: (options: OptionT[]) => void
+ ) => {
+ const labelNames: { [key: string]: boolean } = {
+ "@alertmanager": true,
+ "@cluster": true,
+ "@receiver": true,
+ };
+
+ alertStore.data.grids.forEach((grid) => {
+ labelNames[grid.labelName] = true;
+ grid.alertGroups.forEach((group) => {
+ Object.keys(group.labels).forEach((name) => {
+ labelNames[name] = true;
+ });
+ Object.keys(group.shared.labels).forEach((name) => {
+ labelNames[name] = true;
+ });
+ group.alerts.forEach((alert) => {
+ Object.keys(alert.labels).forEach((name) => {
+ labelNames[name] = true;
+ });
+ });
+ });
+ });
+
+ callback(
+ Object.keys(labelNames)
+ .sort()
+ .map((key) => StringToOption(key))
+ );
+ };
+
+ const context = React.useContext(ThemeContext);
+
+ return (
+ {
+ settingsStore.multiGridConfig.config.gridLabel = (option as OptionT).value;
+ }}
+ menuIsOpen={true}
+ components={{
+ ClearIndicator: null,
+ IndicatorSeparator: null,
+ DropdownIndicator: null,
+ ValueContainer: NullContainer,
+ Control: NullContainer,
+ }}
+ />
+ );
+};
+
const Dropdown: FC<{
popperPlacement?: string;
popperRef?: Ref;
popperStyle?: CSSProperties;
+ alertStore: AlertStore;
settingsStore: Settings;
-}> = ({ popperPlacement, popperRef, popperStyle, settingsStore }) => {
+}> = ({
+ popperPlacement,
+ popperRef,
+ popperStyle,
+ alertStore,
+ settingsStore,
+}) => {
return (
-
);
};
const GridLabelSelect: FC<{
+ alertStore: AlertStore;
settingsStore: Settings;
-}> = observer(({ settingsStore }) => {
+}> = observer(({ alertStore, settingsStore }) => {
const [isVisible, setIsVisible] = useState(false);
const hide = useCallback(() => setIsVisible(false), []);
const toggle = useCallback(() => setIsVisible(!isVisible), [isVisible]);
@@ -86,6 +153,7 @@ const GridLabelSelect: FC<{
popperPlacement={placement}
popperRef={ref}
popperStyle={style}
+ alertStore={alertStore}
settingsStore={settingsStore}
/>
)}
diff --git a/ui/src/Components/Grid/AlertGrid/Swimlane.tsx b/ui/src/Components/Grid/AlertGrid/Swimlane.tsx
index 22a0d686b..63d0e0cee 100644
--- a/ui/src/Components/Grid/AlertGrid/Swimlane.tsx
+++ b/ui/src/Components/Grid/AlertGrid/Swimlane.tsx
@@ -41,7 +41,10 @@ const Swimlane: FC<{
className="flex-shrink-0 flex-grow-1 px-0"
style={{ minWidth: "0px" }}
>
-
+
)}
diff --git a/ui/src/Components/MainModal/Configuration/GridLabelName.tsx b/ui/src/Components/MainModal/Configuration/GridLabelName.tsx
index 9939b09dc..13068d55d 100644
--- a/ui/src/Components/MainModal/Configuration/GridLabelName.tsx
+++ b/ui/src/Components/MainModal/Configuration/GridLabelName.tsx
@@ -1,7 +1,6 @@
import React, { FC } from "react";
import Creatable from "react-select/creatable";
-import { GroupTypeBase, SelectComponentsConfig } from "react-select";
import { useFetchGet } from "Hooks/useFetchGet";
import { FormatBackendURI } from "Stores/AlertStore";
@@ -25,11 +24,7 @@ const staticValues = [
const GridLabelName: FC<{
settingsStore: Settings;
- isOpen?: boolean | undefined;
- selectComponents?:
- | Partial>>
- | undefined;
-}> = ({ settingsStore, isOpen = undefined, selectComponents = undefined }) => {
+}> = ({ settingsStore }) => {
const { response } = useFetchGet(
FormatBackendURI(`labelNames.json`)
);
@@ -56,8 +51,6 @@ const GridLabelName: FC<{
onChange={(option) => {
settingsStore.multiGridConfig.config.gridLabel = (option as OptionT).value;
}}
- menuIsOpen={isOpen}
- components={selectComponents}
/>
);
};