mirror of
https://github.com/prymitive/karma
synced 2026-05-11 03:46:48 +00:00
fix(ui): rewrite GroupHeader & GroupFooter components with hooks
This commit is contained in:
committed by
Łukasz Mierzwa
parent
dd3d9bdc73
commit
2440b7778e
@@ -1,7 +1,7 @@
|
||||
import React, { Component } from "react";
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { observer } from "mobx-react";
|
||||
import { useObserver } from "mobx-react";
|
||||
|
||||
import { APIGroup } from "Models/API";
|
||||
import { StaticLabels } from "Common/Query";
|
||||
@@ -11,92 +11,79 @@ import { FilteringLabel } from "Components/Labels/FilteringLabel";
|
||||
import { RenderNonLinkAnnotation, RenderLinkAnnotation } from "../Annotation";
|
||||
import { RenderSilence } from "../Silences";
|
||||
|
||||
const GroupFooter = observer(
|
||||
class GroupFooter extends Component {
|
||||
static propTypes = {
|
||||
group: APIGroup.isRequired,
|
||||
alertmanagers: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
afterUpdate: PropTypes.func.isRequired,
|
||||
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
|
||||
silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
group,
|
||||
alertmanagers,
|
||||
afterUpdate,
|
||||
alertStore,
|
||||
silenceFormStore,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div className="card-footer components-grid-alertgrid-alertgroup-footer px-2 py-1">
|
||||
<div className="mb-1">
|
||||
{group.shared.annotations
|
||||
.filter((a) => a.isLink === false)
|
||||
.map((a) => (
|
||||
<RenderNonLinkAnnotation
|
||||
key={a.name}
|
||||
name={a.name}
|
||||
value={a.value}
|
||||
visible={a.visible}
|
||||
afterUpdate={afterUpdate}
|
||||
alertStore={alertStore}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{Object.entries(group.shared.labels).map(([name, value]) => (
|
||||
<FilteringLabel
|
||||
key={name}
|
||||
name={name}
|
||||
value={value}
|
||||
const GroupFooter = ({
|
||||
group,
|
||||
alertmanagers,
|
||||
afterUpdate,
|
||||
alertStore,
|
||||
silenceFormStore,
|
||||
}) => {
|
||||
return useObserver(() => (
|
||||
<div className="card-footer components-grid-alertgrid-alertgroup-footer px-2 py-1">
|
||||
<div className="mb-1">
|
||||
{group.shared.annotations
|
||||
.filter((a) => a.isLink === false)
|
||||
.map((a) => (
|
||||
<RenderNonLinkAnnotation
|
||||
key={a.name}
|
||||
name={a.name}
|
||||
value={a.value}
|
||||
visible={a.visible}
|
||||
afterUpdate={afterUpdate}
|
||||
alertStore={alertStore}
|
||||
/>
|
||||
))}
|
||||
{alertmanagers.map((am) => (
|
||||
<FilteringLabel
|
||||
key={am}
|
||||
name={StaticLabels.AlertManager}
|
||||
value={am}
|
||||
alertStore={alertStore}
|
||||
/>
|
||||
))}
|
||||
<FilteringLabel
|
||||
name={StaticLabels.Receiver}
|
||||
value={group.receiver}
|
||||
alertStore={alertStore}
|
||||
/>
|
||||
{group.shared.annotations
|
||||
.filter((a) => a.isLink === true)
|
||||
.map((a) => (
|
||||
<RenderLinkAnnotation
|
||||
key={a.name}
|
||||
name={a.name}
|
||||
value={a.value}
|
||||
/>
|
||||
))}
|
||||
{Object.keys(group.shared.silences).length === 0 ? null : (
|
||||
<div className="components-grid-alertgrid-alertgroup-shared-silence rounded-0 border-0">
|
||||
{Object.entries(
|
||||
group.shared.silences
|
||||
).map(([cluster, silences]) =>
|
||||
silences.map((silenceID) =>
|
||||
RenderSilence(
|
||||
alertStore,
|
||||
silenceFormStore,
|
||||
afterUpdate,
|
||||
cluster,
|
||||
silenceID
|
||||
)
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{Object.entries(group.shared.labels).map(([name, value]) => (
|
||||
<FilteringLabel
|
||||
key={name}
|
||||
name={name}
|
||||
value={value}
|
||||
alertStore={alertStore}
|
||||
/>
|
||||
))}
|
||||
{alertmanagers.map((am) => (
|
||||
<FilteringLabel
|
||||
key={am}
|
||||
name={StaticLabels.AlertManager}
|
||||
value={am}
|
||||
alertStore={alertStore}
|
||||
/>
|
||||
))}
|
||||
<FilteringLabel
|
||||
name={StaticLabels.Receiver}
|
||||
value={group.receiver}
|
||||
alertStore={alertStore}
|
||||
/>
|
||||
{group.shared.annotations
|
||||
.filter((a) => a.isLink === true)
|
||||
.map((a) => (
|
||||
<RenderLinkAnnotation key={a.name} name={a.name} value={a.value} />
|
||||
))}
|
||||
{Object.keys(group.shared.silences).length === 0 ? null : (
|
||||
<div className="components-grid-alertgrid-alertgroup-shared-silence rounded-0 border-0">
|
||||
{Object.entries(group.shared.silences).map(([cluster, silences]) =>
|
||||
silences.map((silenceID) =>
|
||||
RenderSilence(
|
||||
alertStore,
|
||||
silenceFormStore,
|
||||
afterUpdate,
|
||||
cluster,
|
||||
silenceID
|
||||
)
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
)}
|
||||
</div>
|
||||
));
|
||||
};
|
||||
GroupFooter.propTypes = {
|
||||
group: APIGroup.isRequired,
|
||||
alertmanagers: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
afterUpdate: PropTypes.func.isRequired,
|
||||
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
|
||||
silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
|
||||
};
|
||||
|
||||
export { GroupFooter };
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { Component } from "react";
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { observer } from "mobx-react";
|
||||
import { useObserver } from "mobx-react";
|
||||
|
||||
import { APIGroup } from "Models/API";
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
@@ -13,119 +13,110 @@ import { AlertAck } from "Components/AlertAck";
|
||||
import { ToggleIcon } from "Components/ToggleIcon";
|
||||
import { GroupMenu } from "./GroupMenu";
|
||||
|
||||
const GroupHeader = observer(
|
||||
class GroupHeader extends Component {
|
||||
static propTypes = {
|
||||
collapseStore: PropTypes.shape({
|
||||
value: PropTypes.bool.isRequired,
|
||||
toggle: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
group: APIGroup.isRequired,
|
||||
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
|
||||
silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
|
||||
themedCounters: PropTypes.bool.isRequired,
|
||||
setIsMenuOpen: PropTypes.func.isRequired,
|
||||
gridLabelValue: PropTypes.string.isRequired,
|
||||
};
|
||||
const GroupHeader = ({
|
||||
collapseStore,
|
||||
group,
|
||||
alertStore,
|
||||
silenceFormStore,
|
||||
themedCounters,
|
||||
setIsMenuOpen,
|
||||
gridLabelValue,
|
||||
}) => {
|
||||
const onCollapseClick = (event) => {
|
||||
// left click => toggle current group
|
||||
// left click + alt => toggle all groups
|
||||
collapseStore.toggle();
|
||||
|
||||
onCollapseClick = (event) => {
|
||||
const { collapseStore, gridLabelValue } = this.props;
|
||||
|
||||
// left click => toggle current group
|
||||
// left click + alt => toggle all groups
|
||||
|
||||
collapseStore.toggle();
|
||||
|
||||
if (event.altKey === true) {
|
||||
const toggleEvent = new CustomEvent("alertGroupCollapse", {
|
||||
detail: {
|
||||
gridLabelValue: gridLabelValue,
|
||||
value: collapseStore.value,
|
||||
},
|
||||
});
|
||||
window.dispatchEvent(toggleEvent);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
collapseStore,
|
||||
group,
|
||||
alertStore,
|
||||
silenceFormStore,
|
||||
themedCounters,
|
||||
setIsMenuOpen,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<h5
|
||||
className={`card-header mb-0 d-flex flex-row px-2 py-1 ${
|
||||
collapseStore.value ? "border-bottom-0" : ""
|
||||
}`}
|
||||
>
|
||||
<span className="flex-shrink-0 flex-grow-0">
|
||||
<GroupMenu
|
||||
group={group}
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
themed={!themedCounters}
|
||||
setIsMenuOpen={setIsMenuOpen}
|
||||
/>
|
||||
</span>
|
||||
<span className="flex-shrink-1 flex-grow-1" style={{ minWidth: 0 }}>
|
||||
{Object.keys(group.labels).map((name) => (
|
||||
<FilteringLabel
|
||||
key={name}
|
||||
name={name}
|
||||
value={group.labels[name]}
|
||||
alertStore={alertStore}
|
||||
/>
|
||||
))}
|
||||
</span>
|
||||
<span className="flex-shrink-0 flex-grow-0 ml-auto pl-1">
|
||||
{group.stateCount.active > 0 && (
|
||||
<AlertAck
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
group={group}
|
||||
/>
|
||||
)}
|
||||
<FilteringCounterBadge
|
||||
name="@state"
|
||||
value="unprocessed"
|
||||
counter={group.stateCount.unprocessed}
|
||||
themed={themedCounters}
|
||||
alertStore={alertStore}
|
||||
/>
|
||||
<FilteringCounterBadge
|
||||
name="@state"
|
||||
value="suppressed"
|
||||
counter={group.stateCount.suppressed}
|
||||
themed={themedCounters}
|
||||
alertStore={alertStore}
|
||||
/>
|
||||
<FilteringCounterBadge
|
||||
name="@state"
|
||||
value="active"
|
||||
counter={group.stateCount.active}
|
||||
themed={themedCounters}
|
||||
alertStore={alertStore}
|
||||
/>
|
||||
<span
|
||||
className={`${
|
||||
themedCounters ? "text-muted" : "text-white"
|
||||
} cursor-pointer badge px-0 components-label mr-0 pl-2 pl-sm-1`}
|
||||
onClick={this.onCollapseClick}
|
||||
>
|
||||
<TooltipWrapper title="Click to toggle this group details or Alt+Click to toggle all groups">
|
||||
<ToggleIcon isOpen={!collapseStore.value} />
|
||||
</TooltipWrapper>
|
||||
</span>
|
||||
</span>
|
||||
</h5>
|
||||
);
|
||||
if (event.altKey === true) {
|
||||
const toggleEvent = new CustomEvent("alertGroupCollapse", {
|
||||
detail: {
|
||||
gridLabelValue: gridLabelValue,
|
||||
value: collapseStore.value,
|
||||
},
|
||||
});
|
||||
window.dispatchEvent(toggleEvent);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
return useObserver(() => (
|
||||
<h5
|
||||
className={`card-header mb-0 d-flex flex-row px-2 py-1 ${
|
||||
collapseStore.value ? "border-bottom-0" : ""
|
||||
}`}
|
||||
>
|
||||
<span className="flex-shrink-0 flex-grow-0">
|
||||
<GroupMenu
|
||||
group={group}
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
themed={!themedCounters}
|
||||
setIsMenuOpen={setIsMenuOpen}
|
||||
/>
|
||||
</span>
|
||||
<span className="flex-shrink-1 flex-grow-1" style={{ minWidth: 0 }}>
|
||||
{Object.keys(group.labels).map((name) => (
|
||||
<FilteringLabel
|
||||
key={name}
|
||||
name={name}
|
||||
value={group.labels[name]}
|
||||
alertStore={alertStore}
|
||||
/>
|
||||
))}
|
||||
</span>
|
||||
<span className="flex-shrink-0 flex-grow-0 ml-auto pl-1">
|
||||
{group.stateCount.active > 0 && (
|
||||
<AlertAck
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
group={group}
|
||||
/>
|
||||
)}
|
||||
<FilteringCounterBadge
|
||||
name="@state"
|
||||
value="unprocessed"
|
||||
counter={group.stateCount.unprocessed}
|
||||
themed={themedCounters}
|
||||
alertStore={alertStore}
|
||||
/>
|
||||
<FilteringCounterBadge
|
||||
name="@state"
|
||||
value="suppressed"
|
||||
counter={group.stateCount.suppressed}
|
||||
themed={themedCounters}
|
||||
alertStore={alertStore}
|
||||
/>
|
||||
<FilteringCounterBadge
|
||||
name="@state"
|
||||
value="active"
|
||||
counter={group.stateCount.active}
|
||||
themed={themedCounters}
|
||||
alertStore={alertStore}
|
||||
/>
|
||||
<span
|
||||
className={`${
|
||||
themedCounters ? "text-muted" : "text-white"
|
||||
} cursor-pointer badge px-0 components-label mr-0 pl-2 pl-sm-1`}
|
||||
onClick={onCollapseClick}
|
||||
>
|
||||
<TooltipWrapper title="Click to toggle this group details or Alt+Click to toggle all groups">
|
||||
<ToggleIcon isOpen={!collapseStore.value} />
|
||||
</TooltipWrapper>
|
||||
</span>
|
||||
</span>
|
||||
</h5>
|
||||
));
|
||||
};
|
||||
GroupHeader.propTypes = {
|
||||
collapseStore: PropTypes.shape({
|
||||
value: PropTypes.bool.isRequired,
|
||||
toggle: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
group: APIGroup.isRequired,
|
||||
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
|
||||
silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
|
||||
themedCounters: PropTypes.bool.isRequired,
|
||||
setIsMenuOpen: PropTypes.func.isRequired,
|
||||
gridLabelValue: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export { GroupHeader };
|
||||
|
||||
Reference in New Issue
Block a user