mirror of
https://github.com/prymitive/karma
synced 2026-05-07 03:26:52 +00:00
refactor(ui): move label list preview to a dedicated component
This will be reused in delete confirmation modal
This commit is contained in:
53
ui/src/Components/LabelSetList/index.js
Normal file
53
ui/src/Components/LabelSetList/index.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import hash from "object-hash";
|
||||
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
import { StaticLabel } from "Components/Labels/StaticLabel";
|
||||
|
||||
// take a list of groups and outputs a list of label sets, this ignores
|
||||
// the receiver, so we'll end up with only unique alerts
|
||||
const GroupListToUniqueLabelsList = groups => {
|
||||
const alerts = {};
|
||||
for (const group of groups) {
|
||||
for (const alert of group.alerts) {
|
||||
const alertLabels = Object.assign(
|
||||
{},
|
||||
group.labels,
|
||||
group.shared.labels,
|
||||
alert.labels
|
||||
);
|
||||
const alertHash = hash(alertLabels);
|
||||
alerts[alertHash] = alertLabels;
|
||||
}
|
||||
}
|
||||
return Object.values(alerts);
|
||||
};
|
||||
|
||||
// used in new silence form preview stage and when deleting silences
|
||||
const LabelSetList = ({ alertStore, labelsList }) =>
|
||||
labelsList.length > 0 ? (
|
||||
<ul className="list-group list-group-flush">
|
||||
{labelsList.map(labels => (
|
||||
<li key={hash(labels)} className="list-group-item px-0 pt-2 pb-1">
|
||||
{Object.entries(labels).map(([name, value]) => (
|
||||
<StaticLabel
|
||||
key={name}
|
||||
alertStore={alertStore}
|
||||
name={name}
|
||||
value={value}
|
||||
/>
|
||||
))}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<p className="text-muted text-center">No alerts matched</p>
|
||||
);
|
||||
LabelSetList.propTypes = {
|
||||
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
|
||||
labelsList: PropTypes.arrayOf(PropTypes.object).isRequired
|
||||
};
|
||||
|
||||
export { LabelSetList, GroupListToUniqueLabelsList };
|
||||
@@ -4,8 +4,6 @@ import PropTypes from "prop-types";
|
||||
import { observable, action } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
import hash from "object-hash";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faArrowLeft } from "@fortawesome/free-solid-svg-icons/faArrowLeft";
|
||||
import { faCheckCircle } from "@fortawesome/free-solid-svg-icons/faCheckCircle";
|
||||
@@ -13,7 +11,10 @@ import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclama
|
||||
|
||||
import { AlertStore, FormatBackendURI, FormatAlertsQ } from "Stores/AlertStore";
|
||||
import { SilenceFormStore } from "Stores/SilenceFormStore";
|
||||
import { StaticLabel } from "Components/Labels/StaticLabel";
|
||||
import {
|
||||
LabelSetList,
|
||||
GroupListToUniqueLabelsList
|
||||
} from "Components/LabelSetList";
|
||||
import { MatcherToFilter, AlertManagersToFilter } from "../Matchers";
|
||||
|
||||
const FetchError = ({ message }) => (
|
||||
@@ -28,27 +29,6 @@ FetchError.propTypes = {
|
||||
message: PropTypes.node.isRequired
|
||||
};
|
||||
|
||||
const Preview = ({ alertStore, labelsList }) => (
|
||||
<ul className="list-group list-group-flush">
|
||||
{labelsList.map(labels => (
|
||||
<li key={hash(labels)} className="list-group-item px-0 pt-2 pb-1">
|
||||
{Object.entries(labels).map(([name, value]) => (
|
||||
<StaticLabel
|
||||
key={name}
|
||||
alertStore={alertStore}
|
||||
name={name}
|
||||
value={value}
|
||||
/>
|
||||
))}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
Preview.propTypes = {
|
||||
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
|
||||
labelsList: PropTypes.arrayOf(PropTypes.object).isRequired
|
||||
};
|
||||
|
||||
const SilencePreview = observer(
|
||||
class SilencePreview extends Component {
|
||||
static propTypes = {
|
||||
@@ -64,20 +44,7 @@ const SilencePreview = observer(
|
||||
// take a list of groups and outputs a list of label sets, this ignores
|
||||
// the receiver, so we'll end up with only unique alerts
|
||||
groupsToUniqueLabels(groups) {
|
||||
const alerts = {};
|
||||
for (const group of groups) {
|
||||
for (const alert of group.alerts) {
|
||||
const alertLabels = Object.assign(
|
||||
{},
|
||||
group.labels,
|
||||
group.shared.labels,
|
||||
alert.labels
|
||||
);
|
||||
const alertHash = hash(alertLabels);
|
||||
alerts[alertHash] = alertLabels;
|
||||
}
|
||||
}
|
||||
this.alertLabels = Object.values(alerts);
|
||||
this.alertLabels = GroupListToUniqueLabelsList(groups);
|
||||
},
|
||||
setError(value) {
|
||||
this.error = value;
|
||||
@@ -135,7 +102,7 @@ const SilencePreview = observer(
|
||||
silence.
|
||||
</p>
|
||||
<div>
|
||||
<Preview
|
||||
<LabelSetList
|
||||
alertStore={alertStore}
|
||||
labelsList={this.matchedAlerts.alertLabels}
|
||||
/>
|
||||
|
||||
@@ -95,10 +95,10 @@ describe("<SilencePreview />", () => {
|
||||
tree.update();
|
||||
expect(tree.find("FetchError")).toHaveLength(1);
|
||||
expect(consoleSpy).toHaveBeenCalled();
|
||||
expect(tree.find("Preview")).toHaveLength(0);
|
||||
expect(tree.find("LabelSetList")).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("renders Preview on successful fetch", async () => {
|
||||
it("renders LabelSetList on successful fetch", async () => {
|
||||
fetch.mockResponse(JSON.stringify(MockAPIResponse()));
|
||||
|
||||
const tree = MountedSilencePreview();
|
||||
@@ -106,7 +106,7 @@ describe("<SilencePreview />", () => {
|
||||
|
||||
tree.update();
|
||||
expect(tree.find("FetchError")).toHaveLength(0);
|
||||
expect(tree.find("Preview")).toHaveLength(1);
|
||||
expect(tree.find("LabelSetList")).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("clicking on the submit button moves form to the 'Submit' stage", () => {
|
||||
|
||||
Reference in New Issue
Block a user