mirror of
https://github.com/prymitive/karma
synced 2026-05-09 03:36:44 +00:00
fix(ui): fix grid label menu z-index
This commit is contained in:
committed by
Łukasz Mierzwa
parent
ae261c5f3a
commit
98edd7b073
@@ -109,8 +109,15 @@ const Grid: FC<{
|
||||
repack();
|
||||
});
|
||||
|
||||
const [isMenuOpen, setIsMenuOpen] = useState<boolean>(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
position: isMenuOpen ? "relative" : undefined,
|
||||
zIndex: isMenuOpen ? 102 : undefined,
|
||||
}}
|
||||
>
|
||||
<CSSTransition
|
||||
key={grid.labelValue}
|
||||
in={grid.labelName !== ""}
|
||||
@@ -126,6 +133,8 @@ const Grid: FC<{
|
||||
isExpanded={isExpanded}
|
||||
onToggle={onCollapseClick}
|
||||
paddingTop={paddingTop}
|
||||
onMenuOpen={() => setIsMenuOpen(true)}
|
||||
onMenuClose={() => setIsMenuOpen(false)}
|
||||
/>
|
||||
</CSSTransition>
|
||||
<div
|
||||
@@ -198,7 +207,7 @@ const Grid: FC<{
|
||||
</CSSTransition>
|
||||
)}
|
||||
</TransitionGroup>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -5,15 +5,25 @@ import { mount } from "enzyme";
|
||||
import fetchMock from "fetch-mock";
|
||||
|
||||
import { MockGrid } from "__fixtures__/Stories";
|
||||
import { MockThemeContextWithoutAnimations } from "__fixtures__/Theme";
|
||||
import { mockMatchMedia } from "__fixtures__/matchMedia";
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
import { Settings } from "Stores/Settings";
|
||||
import { SilenceFormStore } from "Stores/SilenceFormStore";
|
||||
import type { APIGridT } from "Models/APITypes";
|
||||
import { ThemeContext } from "Components/Theme";
|
||||
import AlertGrid from ".";
|
||||
import { GridLabelSelect } from "./GridLabelSelect";
|
||||
|
||||
let alertStore: AlertStore;
|
||||
let settingsStore: Settings;
|
||||
let silenceFormStore: SilenceFormStore;
|
||||
let grid: APIGridT;
|
||||
|
||||
declare let global: any;
|
||||
declare let document: any;
|
||||
declare let window: any;
|
||||
|
||||
beforeEach(() => {
|
||||
fetchMock.reset();
|
||||
fetchMock.mock("*", {
|
||||
@@ -22,6 +32,7 @@ beforeEach(() => {
|
||||
|
||||
alertStore = new AlertStore([]);
|
||||
settingsStore = new Settings(null);
|
||||
silenceFormStore = new SilenceFormStore();
|
||||
grid = {
|
||||
labelName: "foo",
|
||||
labelValue: "bar",
|
||||
@@ -35,6 +46,15 @@ beforeEach(() => {
|
||||
};
|
||||
alertStore.data.setLabelNames(["alertname", "job", "cluster"]);
|
||||
|
||||
window.matchMedia = mockMatchMedia({});
|
||||
global.ResizeObserver = jest.fn((cb) => {
|
||||
return {
|
||||
observe: jest.fn(),
|
||||
disconnect: jest.fn(),
|
||||
};
|
||||
});
|
||||
global.ResizeObserverEntry = jest.fn();
|
||||
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
@@ -44,6 +64,8 @@ const MountedGridLabelSelect = () => {
|
||||
alertStore={alertStore}
|
||||
settingsStore={settingsStore}
|
||||
grid={grid}
|
||||
onMenuOpen={jest.fn()}
|
||||
onMenuClose={jest.fn()}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -126,4 +148,46 @@ describe("<GridLabelSelect />", () => {
|
||||
expect(tree.find("div.components-grid-label-select-menu")).toHaveLength(0);
|
||||
await act(() => promise);
|
||||
});
|
||||
|
||||
it("opening label select sets z-index", async () => {
|
||||
const promise = Promise.resolve();
|
||||
alertStore.data.setGrids([
|
||||
{
|
||||
labelName: "foo",
|
||||
labelValue: "bar",
|
||||
alertGroups: [],
|
||||
totalGroups: 0,
|
||||
stateCount: {
|
||||
unprocessed: 1,
|
||||
suppressed: 2,
|
||||
active: 3,
|
||||
},
|
||||
},
|
||||
]);
|
||||
const tree = mount(
|
||||
<AlertGrid
|
||||
alertStore={alertStore}
|
||||
settingsStore={settingsStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
/>,
|
||||
{
|
||||
wrappingComponent: ThemeContext.Provider,
|
||||
wrappingComponentProps: { value: MockThemeContextWithoutAnimations },
|
||||
}
|
||||
);
|
||||
|
||||
tree.find("span.components-grid-label-select-dropdown").simulate("click");
|
||||
expect(tree.find("div.components-grid-label-select-menu")).toHaveLength(1);
|
||||
expect(tree.find("div").at(1).props().style?.zIndex).toBe(102);
|
||||
|
||||
tree.find("span.components-grid-label-select-dropdown").simulate("click");
|
||||
act(() => {
|
||||
jest.runOnlyPendingTimers();
|
||||
});
|
||||
tree.update();
|
||||
expect(tree.find("div.components-grid-label-select-menu")).toHaveLength(0);
|
||||
expect(tree.find("div").at(1).props().style?.zIndex).toBeUndefined();
|
||||
|
||||
await act(() => promise);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -131,47 +131,57 @@ const GridLabelSelect: FC<{
|
||||
alertStore: AlertStore;
|
||||
settingsStore: Settings;
|
||||
grid: APIGridT;
|
||||
}> = observer(({ alertStore, settingsStore, grid }) => {
|
||||
const [isVisible, setIsVisible] = useState<boolean>(false);
|
||||
const hide = useCallback(() => setIsVisible(false), []);
|
||||
const toggle = useCallback(() => setIsVisible(!isVisible), [isVisible]);
|
||||
onMenuOpen: () => void;
|
||||
onMenuClose: () => void;
|
||||
}> = observer(
|
||||
({ alertStore, settingsStore, grid, onMenuOpen, onMenuClose }) => {
|
||||
const [isVisible, setIsVisible] = useState<boolean>(false);
|
||||
const hide = useCallback(() => setIsVisible(false), []);
|
||||
const toggle = useCallback(() => {
|
||||
if (isVisible) {
|
||||
onMenuClose();
|
||||
} else {
|
||||
onMenuOpen();
|
||||
}
|
||||
setIsVisible(!isVisible);
|
||||
}, [isVisible, onMenuOpen, onMenuClose]);
|
||||
const ref = useRef<HTMLDivElement | null>(null);
|
||||
useOnClickOutside(ref, hide, isVisible);
|
||||
|
||||
const ref = useRef<HTMLDivElement | null>(null);
|
||||
useOnClickOutside(ref, hide, isVisible);
|
||||
|
||||
return (
|
||||
<div ref={ref} className="components-label badge ps-1 pe-2">
|
||||
<Manager>
|
||||
<Reference>
|
||||
{({ ref }) => (
|
||||
<span
|
||||
ref={ref}
|
||||
onClick={toggle}
|
||||
className="border-0 rounded-0 bg-inherit cursor-pointer px-1 py-0 components-grid-label-select-dropdown"
|
||||
data-toggle="dropdown"
|
||||
>
|
||||
<FontAwesomeIcon className="text-muted" icon={faCaretDown} />
|
||||
</span>
|
||||
)}
|
||||
</Reference>
|
||||
<DropdownSlide in={isVisible} unmountOnExit>
|
||||
<Popper modifiers={CommonPopperModifiers}>
|
||||
{({ placement, ref, style }) => (
|
||||
<Dropdown
|
||||
popperPlacement={placement}
|
||||
popperRef={ref}
|
||||
popperStyle={style}
|
||||
alertStore={alertStore}
|
||||
settingsStore={settingsStore}
|
||||
grid={grid}
|
||||
onClose={toggle}
|
||||
/>
|
||||
return (
|
||||
<div ref={ref} className="components-label badge ps-1 pe-2">
|
||||
<Manager>
|
||||
<Reference>
|
||||
{({ ref }) => (
|
||||
<span
|
||||
ref={ref}
|
||||
onClick={toggle}
|
||||
className="border-0 rounded-0 bg-inherit cursor-pointer px-1 py-0 components-grid-label-select-dropdown"
|
||||
data-toggle="dropdown"
|
||||
>
|
||||
<FontAwesomeIcon className="text-muted" icon={faCaretDown} />
|
||||
</span>
|
||||
)}
|
||||
</Popper>
|
||||
</DropdownSlide>
|
||||
</Manager>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
</Reference>
|
||||
<DropdownSlide in={isVisible} unmountOnExit>
|
||||
<Popper modifiers={CommonPopperModifiers}>
|
||||
{({ placement, ref, style }) => (
|
||||
<Dropdown
|
||||
popperPlacement={placement}
|
||||
popperRef={ref}
|
||||
popperStyle={style}
|
||||
alertStore={alertStore}
|
||||
settingsStore={settingsStore}
|
||||
grid={grid}
|
||||
onClose={toggle}
|
||||
/>
|
||||
)}
|
||||
</Popper>
|
||||
</DropdownSlide>
|
||||
</Manager>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export { GridLabelSelect };
|
||||
|
||||
@@ -19,6 +19,8 @@ const Swimlane: FC<{
|
||||
isExpanded: boolean;
|
||||
onToggle: (event: MouseEvent) => void;
|
||||
paddingTop: number;
|
||||
onMenuOpen: () => void;
|
||||
onMenuClose: () => void;
|
||||
}> = ({
|
||||
alertStore,
|
||||
settingsStore,
|
||||
@@ -26,6 +28,8 @@ const Swimlane: FC<{
|
||||
isExpanded,
|
||||
onToggle,
|
||||
paddingTop,
|
||||
onMenuOpen,
|
||||
onMenuClose,
|
||||
}) => {
|
||||
return (
|
||||
<h5
|
||||
@@ -59,6 +63,8 @@ const Swimlane: FC<{
|
||||
alertStore={alertStore}
|
||||
settingsStore={settingsStore}
|
||||
grid={grid}
|
||||
onMenuOpen={onMenuOpen}
|
||||
onMenuClose={onMenuClose}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -77,18 +77,17 @@ const AlertGrid: FC<{
|
||||
}}
|
||||
/>
|
||||
{alertStore.data.grids.map((grid) => (
|
||||
<div key={`${grid.labelName}/${grid.labelValue}`}>
|
||||
<Grid
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
settingsStore={settingsStore}
|
||||
gridSizesConfig={gridSizesConfig}
|
||||
groupWidth={groupWidth}
|
||||
grid={grid}
|
||||
outerPadding={alertStore.data.gridPadding}
|
||||
paddingTop={paddingTop}
|
||||
/>
|
||||
</div>
|
||||
<Grid
|
||||
key={`${grid.labelName}/${grid.labelValue}`}
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
settingsStore={settingsStore}
|
||||
gridSizesConfig={gridSizesConfig}
|
||||
groupWidth={groupWidth}
|
||||
grid={grid}
|
||||
outerPadding={alertStore.data.gridPadding}
|
||||
paddingTop={paddingTop}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user