fix(ui): fix alert menu content being under other alert groups

Because every alert group uses 'position: absolute' our menu content rendered after clicking on group header or each alert dropdown is hidden under neighbour groups. To fix this we'll add 'z-index: 100' to the group with currently open menu.
This commit is contained in:
Łukasz Mierzwa
2019-05-10 20:06:02 +01:00
parent 3ff0aa7057
commit f50ac75363
9 changed files with 120 additions and 34 deletions

View File

@@ -95,22 +95,29 @@ const AlertMenu = observer(
group: APIGroup.isRequired,
alert: APIAlert.isRequired,
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired
silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
setIsMenuOpen: PropTypes.func.isRequired
};
collapse = observable(
{
value: true,
toggle() {
this.value = !this.value;
constructor(props) {
super(props);
this.collapse = observable(
{
value: true,
toggle() {
this.value = !this.value;
props.setIsMenuOpen(!this.value);
},
hide() {
this.value = true;
props.setIsMenuOpen(!this.value);
}
},
hide() {
this.value = true;
}
},
{ toggle: action.bound, hide: action.bound },
{ name: "Alert menu toggle" }
);
{ toggle: action.bound, hide: action.bound },
{ name: "Alert menu toggle" }
);
}
handleClickOutside = action(event => {
this.collapse.hide();

View File

@@ -22,6 +22,7 @@ beforeEach(() => {
});
const MockAfterClick = jest.fn();
const MockSetIsMenuOpen = jest.fn();
const MountedAlertMenu = group => {
return mount(
@@ -31,6 +32,7 @@ const MountedAlertMenu = group => {
alert={alert}
alertStore={alertStore}
silenceFormStore={silenceFormStore}
setIsMenuOpen={MockSetIsMenuOpen}
/>
</Provider>
).find("AlertMenu");

View File

@@ -28,7 +28,8 @@ const Alert = observer(
showReceiver: PropTypes.bool.isRequired,
afterUpdate: PropTypes.func.isRequired,
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired
silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
setIsMenuOpen: PropTypes.func.isRequired
};
render() {
@@ -39,7 +40,8 @@ const Alert = observer(
showReceiver,
afterUpdate,
alertStore,
silenceFormStore
silenceFormStore,
setIsMenuOpen
} = this.props;
let classNames = [
@@ -92,6 +94,7 @@ const Alert = observer(
alert={alert}
alertStore={alertStore}
silenceFormStore={silenceFormStore}
setIsMenuOpen={setIsMenuOpen}
/>
{alert.alertmanager
.map(am => am.inhibitedBy.length)

View File

@@ -30,6 +30,7 @@ afterEach(() => {
});
const MockAfterUpdate = jest.fn();
const MockSetIsMenuOpen = jest.fn();
const MockedAlert = () => {
return MockAlert(
@@ -54,6 +55,7 @@ const MountedAlert = (alert, group, showAlertmanagers, showReceiver) => {
afterUpdate={MockAfterUpdate}
alertStore={alertStore}
silenceFormStore={silenceFormStore}
setIsMenuOpen={MockSetIsMenuOpen}
/>
</Provider>
);

View File

@@ -93,22 +93,29 @@ const GroupMenu = observer(
group: APIGroup.isRequired,
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
themed: PropTypes.bool.isRequired
themed: PropTypes.bool.isRequired,
setIsMenuOpen: PropTypes.func.isRequired
};
collapse = observable(
{
value: true,
toggle() {
this.value = !this.value;
constructor(props) {
super(props);
this.collapse = observable(
{
value: true,
toggle() {
this.value = !this.value;
props.setIsMenuOpen(!this.value);
},
hide() {
this.value = true;
props.setIsMenuOpen(!this.value);
}
},
hide() {
this.value = true;
}
},
{ toggle: action.bound, hide: action.bound },
{ name: "Alert group menu toggle" }
);
{ toggle: action.bound, hide: action.bound },
{ name: "Alert group menu toggle" }
);
}
handleClickOutside = action(event => {
this.collapse.hide();

View File

@@ -20,6 +20,7 @@ beforeEach(() => {
});
const MockAfterClick = jest.fn();
const MockSetIsMenuOpen = jest.fn();
const MountedGroupMenu = (group, themed) => {
return mount(
@@ -29,6 +30,7 @@ const MountedGroupMenu = (group, themed) => {
alertStore={alertStore}
silenceFormStore={silenceFormStore}
themed={themed}
setIsMenuOpen={MockSetIsMenuOpen}
/>
</Provider>
).find("GroupMenu");

View File

@@ -25,7 +25,8 @@ const GroupHeader = observer(
group: APIGroup.isRequired,
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
themedCounters: PropTypes.bool.isRequired
themedCounters: PropTypes.bool.isRequired,
setIsMenuOpen: PropTypes.func.isRequired
};
render() {
@@ -34,7 +35,8 @@ const GroupHeader = observer(
group,
alertStore,
silenceFormStore,
themedCounters
themedCounters,
setIsMenuOpen
} = this.props;
return (
@@ -49,6 +51,7 @@ const GroupHeader = observer(
alertStore={alertStore}
silenceFormStore={silenceFormStore}
themed={!themedCounters}
setIsMenuOpen={setIsMenuOpen}
/>
</span>
<span className="flex-shrink-1 flex-grow-1" style={{ minWidth: 0 }}>

View File

@@ -71,9 +71,18 @@ const AlertGroup = observer(
alertGroupConfig.config.defaultRenderCount
);
this.renderConfig = observable({
alertsToRender: this.defaultRenderCount
});
this.renderConfig = observable(
{
alertsToRender: this.defaultRenderCount,
isMenuOpen: false,
setIsMenuOpen(val) {
this.isMenuOpen = val;
}
},
{
setIsMenuOpen: action.bound
}
);
let defaultCollapseState;
switch (alertGroupConfig.config.defaultCollapseState) {
@@ -194,11 +203,16 @@ const AlertGroup = observer(
}
}
let extraStyle = {};
if (this.renderConfig.isMenuOpen) {
extraStyle.zIndex = 100;
}
return (
<MountFade in={true}>
<div
className="components-grid-alertgrid-alertgroup p-1"
style={style}
style={{ ...style, ...extraStyle }}
>
<div className={`card ${cardBackgroundClass}`}>
<GroupHeader
@@ -207,6 +221,7 @@ const AlertGroup = observer(
alertStore={alertStore}
silenceFormStore={silenceFormStore}
themedCounters={themedCounters}
setIsMenuOpen={this.renderConfig.setIsMenuOpen}
/>
{this.collapse.value ? null : (
<div className="card-body bg-white px-2 py-1">
@@ -225,6 +240,7 @@ const AlertGroup = observer(
afterUpdate={afterUpdate}
alertStore={alertStore}
silenceFormStore={silenceFormStore}
setIsMenuOpen={this.renderConfig.setIsMenuOpen}
/>
))}
{group.alerts.length > this.defaultRenderCount ? (

View File

@@ -274,6 +274,50 @@ describe("<AlertGroup /> renderConfig", () => {
it("clicking + icon loads 5 more alert if there's 25 in total and we're showing 16", () => {
ValidateLoadButtonAction(25, 1, /fa-plus/, 22, 17);
});
it("uses 'z-index: 100' style after setIsMenuOpen() is called on any Alert", () => {
MockAlerts(5);
const tree = MountedAlertGroup(jest.fn(), false);
const instance = tree.find("AlertGroup").instance();
expect(instance.renderConfig.isMenuOpen).toBe(false);
tree
.find("Alert")
.at(0)
.props()
.setIsMenuOpen(true);
expect(instance.renderConfig.isMenuOpen).toBe(true);
tree.update();
expect(
tree
.find(".components-grid-alertgrid-alertgroup")
.at(0)
.props().style.zIndex
).toEqual(100);
});
it("uses 'z-index: 100' style after setIsMenuOpen() is called on AlertGroup header menu", () => {
MockAlerts(5);
const tree = MountedAlertGroup(jest.fn(), false);
const instance = tree.find("AlertGroup").instance();
expect(instance.renderConfig.isMenuOpen).toBe(false);
tree
.find("GroupHeader")
.at(0)
.props()
.setIsMenuOpen(true);
expect(instance.renderConfig.isMenuOpen).toBe(true);
tree.update();
expect(
tree
.find(".components-grid-alertgrid-alertgroup")
.at(0)
.props().style.zIndex
).toEqual(100);
});
});
describe("<AlertGroup /> card theme", () => {