diff --git a/ui/package.json b/ui/package.json index 592f9e965..9af8ecbbb 100644 --- a/ui/package.json +++ b/ui/package.json @@ -43,6 +43,7 @@ "react-resize-detector": "3.1.3", "react-scripts": "2.0.4", "react-select": "2.1.0", + "react-tippy": "1.2.3", "react-transition-group": "2.5.0", "whatwg-fetch": "3.0.0" }, diff --git a/ui/src/Components/Grid/AlertGrid/AlertGroup/Alert/__snapshots__/index.test.js.snap b/ui/src/Components/Grid/AlertGrid/AlertGroup/Alert/__snapshots__/index.test.js.snap index 82930fa36..55c1afdf7 100644 --- a/ui/src/Components/Grid/AlertGrid/AlertGroup/Alert/__snapshots__/index.test.js.snap +++ b/ui/src/Components/Grid/AlertGrid/AlertGroup/Alert/__snapshots__/index.test.js.snap @@ -63,12 +63,26 @@ exports[` matches snapshot with showAlertmanagers=false showReceiver=fa a day ago - - job: node_exporter - - - cluster: dev - +
+ + job: node_exporter + +
+
+ + cluster: dev + +
matches snapshot 1`] = ` hidden - - label1: foo - - - label2: bar - - - @alertmanager: default - - - @receiver: by-name - +
+ + label1: foo + +
+
+ + label2: bar + +
+
+ + @alertmanager: default + +
+
+ + @receiver: by-name + +
- + + + diff --git a/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/__snapshots__/index.test.js.snap b/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/__snapshots__/index.test.js.snap index 45c7a1302..a50c3fed5 100644 --- a/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/__snapshots__/index.test.js.snap +++ b/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/__snapshots__/index.test.js.snap @@ -18,19 +18,26 @@ exports[` matches snapshot when data is present in alertStore 1`] = ` Fake silence - - - - + + + + me@example.com @@ -66,19 +73,26 @@ exports[` matches snapshot with expaned details 1`] = ` Fake silence - - - - + + + + me@example.com @@ -88,9 +102,16 @@ exports[` matches snapshot with expaned details 1`] = `
- - @alertmanager: default - +
+ + @alertmanager: default + +
- + + + {silence.createdBy} diff --git a/ui/src/Components/Grid/AlertGrid/AlertGroup/index.js b/ui/src/Components/Grid/AlertGrid/AlertGroup/index.js index 89b4486e3..e1dedd169 100644 --- a/ui/src/Components/Grid/AlertGrid/AlertGroup/index.js +++ b/ui/src/Components/Grid/AlertGrid/AlertGroup/index.js @@ -11,23 +11,31 @@ import { faPlus } from "@fortawesome/free-solid-svg-icons/faPlus"; import { faMinus } from "@fortawesome/free-solid-svg-icons/faMinus"; import { APIGroup } from "Models/API"; -import { MountFade } from "Components/Animations/MountFade"; import { Settings } from "Stores/Settings"; import { SilenceFormStore } from "Stores/SilenceFormStore"; +import { MountFade } from "Components/Animations/MountFade"; +import { TooltipWrapper } from "Components/TooltipWrapper"; import { GroupHeader } from "./GroupHeader"; import { Alert } from "./Alert"; import { GroupFooter } from "./GroupFooter"; -const LoadButton = ({ icon, action }) => { +const LoadButton = ({ icon, action, tooltip }) => { return ( - + + + ); }; LoadButton.propTypes = { icon: FontAwesomeIcon.propTypes.icon.isRequired, - action: PropTypes.func.isRequired + action: PropTypes.func.isRequired, + tooltip: PropTypes.node.isRequired }; const AllAlertsAreUsingSameAlertmanagers = alerts => { @@ -183,13 +191,21 @@ const AlertGroup = observer( ))} {group.alerts.length > this.defaultRenderCount ? (
  • - + {this.renderConfig.alertsToRender} {" of "} {group.alerts.length} - +
  • ) : null} diff --git a/ui/src/Components/Labels/FilterInputLabel/index.js b/ui/src/Components/Labels/FilterInputLabel/index.js index cd61e8f60..9e273ccd9 100644 --- a/ui/src/Components/Labels/FilterInputLabel/index.js +++ b/ui/src/Components/Labels/FilterInputLabel/index.js @@ -12,6 +12,7 @@ import { faSpinner } from "@fortawesome/free-solid-svg-icons/faSpinner"; import { AlertStore } from "Stores/AlertStore"; import { DefaultLabelClass } from "Common/Colors"; import { QueryOperators } from "Common/Query"; +import { TooltipWrapper } from "Components/TooltipWrapper"; import { BaseLabel } from "Components/Labels/BaseLabel"; import "./index.css"; @@ -93,13 +94,15 @@ const FilterInputLabel = observer( )} - + + + ); } diff --git a/ui/src/Components/Labels/FilteringCounterBadge/index.js b/ui/src/Components/Labels/FilteringCounterBadge/index.js index 66c9312ee..8cff69161 100644 --- a/ui/src/Components/Labels/FilteringCounterBadge/index.js +++ b/ui/src/Components/Labels/FilteringCounterBadge/index.js @@ -4,6 +4,7 @@ import PropTypes from "prop-types"; import { inject, observer } from "mobx-react"; import { AlertStore } from "Stores/AlertStore"; +import { TooltipWrapper } from "Components/TooltipWrapper"; import { BaseLabel } from "Components/Labels/BaseLabel"; // Same as FilteringLabel but for labels that are counters (usually @state) @@ -25,16 +26,18 @@ const FilteringCounterBadge = inject("alertStore")( if (counter === 0) return null; return ( - this.handleClick(e)} - > - {counter} - + + this.handleClick(e)} + > + {counter} + + ); } } diff --git a/ui/src/Components/Labels/FilteringCounterBadge/index.test.js b/ui/src/Components/Labels/FilteringCounterBadge/index.test.js index 4acfdd158..a92f35964 100644 --- a/ui/src/Components/Labels/FilteringCounterBadge/index.test.js +++ b/ui/src/Components/Labels/FilteringCounterBadge/index.test.js @@ -45,7 +45,7 @@ const validateOnClick = value => { counter={1} /> ); - tree.simulate("click"); + tree.find(".components-label").simulate("click"); expect(alertStore.filters.values).toHaveLength(1); expect(alertStore.filters.values).toContainEqual( NewUnappliedFilter(`@state=${value}`) diff --git a/ui/src/Components/Labels/FilteringLabel/__snapshots__/index.test.js.snap b/ui/src/Components/Labels/FilteringLabel/__snapshots__/index.test.js.snap index cd6d7a583..3abe48666 100644 --- a/ui/src/Components/Labels/FilteringLabel/__snapshots__/index.test.js.snap +++ b/ui/src/Components/Labels/FilteringLabel/__snapshots__/index.test.js.snap @@ -2,8 +2,15 @@ exports[` matches snapshot 1`] = ` " - - foo: bar - +
    + + foo: bar + +
    " `; diff --git a/ui/src/Components/Labels/FilteringLabel/index.js b/ui/src/Components/Labels/FilteringLabel/index.js index 46885ee24..59ee92cfb 100644 --- a/ui/src/Components/Labels/FilteringLabel/index.js +++ b/ui/src/Components/Labels/FilteringLabel/index.js @@ -2,6 +2,7 @@ import React from "react"; import { inject, observer } from "mobx-react"; +import { TooltipWrapper } from "Components/TooltipWrapper"; import { BaseLabel } from "Components/Labels/BaseLabel"; // Renders a label element that after clicking adds current label as a filter @@ -11,16 +12,18 @@ const FilteringLabel = inject("alertStore")( render() { const { name, value } = this.props; return ( - this.handleClick(e)} - > - {name}: {value} - + + this.handleClick(e)} + > + {name}: {value} + + ); } } diff --git a/ui/src/Components/Labels/FilteringLabel/index.test.js b/ui/src/Components/Labels/FilteringLabel/index.test.js index 883264334..585da237b 100644 --- a/ui/src/Components/Labels/FilteringLabel/index.test.js +++ b/ui/src/Components/Labels/FilteringLabel/index.test.js @@ -18,7 +18,7 @@ const RenderAndClick = (name, value) => { const tree = mount( ); - tree.simulate("click"); + tree.find(".components-label").simulate("click"); }; describe("", () => { diff --git a/ui/src/Components/MainModal/index.js b/ui/src/Components/MainModal/index.js index 150bd1db7..5f8387743 100644 --- a/ui/src/Components/MainModal/index.js +++ b/ui/src/Components/MainModal/index.js @@ -10,6 +10,7 @@ import { faCog } from "@fortawesome/free-solid-svg-icons/faCog"; import { AlertStore } from "Stores/AlertStore"; import { Settings } from "Stores/Settings"; import { MountModal } from "Components/Animations/MountModal"; +import { TooltipWrapper } from "Components/TooltipWrapper"; import { MainModalContent } from "./MainModalContent"; const MainModal = observer( @@ -46,12 +47,14 @@ const MainModal = observer( return (
  • - - - + + + + +
  • matches snapshot with 0 alerts 1`] = `
    • - - - + + - - - + + + + +
  • - - - + + - - - + + + + +
  • matches snapshot with 5 alerts 1`] = `
    • - - - + + - - - + + + + +
    • - - - + + - - - + + + + +
    ))} - + + + {showDelete ? ( - + + + ) : null} diff --git a/ui/src/Components/SilenceModal/index.js b/ui/src/Components/SilenceModal/index.js index b615af585..9d58e8a2e 100644 --- a/ui/src/Components/SilenceModal/index.js +++ b/ui/src/Components/SilenceModal/index.js @@ -10,6 +10,7 @@ import { AlertStore } from "Stores/AlertStore"; import { SilenceFormStore } from "Stores/SilenceFormStore"; import { Settings } from "Stores/Settings"; import { MountModal } from "Components/Animations/MountModal"; +import { TooltipWrapper } from "Components/TooltipWrapper"; import { SilenceModalContent } from "./SilenceModalContent"; import "./index.css"; @@ -53,12 +54,14 @@ const SilenceModal = observer( return (
  • - - - + + + + +
  • ( + + {children} + +); +Tooltip.propTypes = { + children: PropTypes.node.isRequired +}; + +export { TooltipWrapper }; diff --git a/ui/src/Stores/SilenceFormStore.js b/ui/src/Stores/SilenceFormStore.js index 5f16b0903..76ca3a5ed 100644 --- a/ui/src/Stores/SilenceFormStore.js +++ b/ui/src/Stores/SilenceFormStore.js @@ -148,6 +148,9 @@ class SilenceFormStore { } this.matchers = matchers; + // ensure that silenceID is nulled, since it's used to edit silences + // and this is used to silence groups + this.silenceID = null; }, fillFormFromSilence(alertmanager, silence) { diff --git a/ui/src/Stores/SilenceFormStore.test.js b/ui/src/Stores/SilenceFormStore.test.js index b25a288ea..b8994373f 100644 --- a/ui/src/Stores/SilenceFormStore.test.js +++ b/ui/src/Stores/SilenceFormStore.test.js @@ -187,6 +187,13 @@ describe("SilenceFormStore.data", () => { ); }); + it("fillMatchersFromGroup() resets silenceID if set", () => { + store.data.silenceID = "12345"; + const group = MockGroup(); + store.data.fillMatchersFromGroup(group, [group.alerts[0]]); + expect(store.data.silenceID).toBeNull(); + }); + it("fillFormFromSilence() sets silenceID", () => { const alertmanager = MockAlertmanager(); const silence = MockSilence(); diff --git a/ui/yarn.lock b/ui/yarn.lock index 2b21cb319..da2f09706 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -8135,7 +8135,7 @@ pnp-webpack-plugin@1.1.0: resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.1.0.tgz#947a96d1db94bb5a1fc014d83b581e428699ac8c" integrity sha512-CPCdcFxx7fEcDMWTDjXe2Wypt4JuMt4q5Q2UrpTcyBBkLiCIyPEh/mCGmUWIcNkKGyXwQ9Y2wVhlKm6ketiBNQ== -popper.js@^1.14.1: +popper.js@^1.11.1, popper.js@^1.14.1: version "1.14.4" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.4.tgz#8eec1d8ff02a5a3a152dd43414a15c7b79fd69b6" integrity sha1-juwdj/AqWjoVLdQ0FKFce3n9abY= @@ -9324,6 +9324,13 @@ react-themeable@^1.1.0: dependencies: object-assign "^3.0.0" +react-tippy@1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/react-tippy/-/react-tippy-1.2.3.tgz#8aef183ec4986ca7c5c556465013d95196fecfd8" + integrity sha512-cEmhw29DbVP33n9ayo0nLzibuSz6o0A77cZtzno7zGsfOH8tUEGai/8a7TXRIKHPYDooW8iJkJBIPDnxmEu00g== + dependencies: + popper.js "^1.11.1" + react-transition-group@2.5.0, react-transition-group@^2.2.1: version "2.5.0" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.5.0.tgz#70bca0e3546102c4dc5cf3f5f57f73447cce6874"