diff --git a/ui/src/Components/SilenceModal/DateTimeSelect/Duration.js b/ui/src/Components/SilenceModal/DateTimeSelect/Duration.js
index 5076f083c..a1229aadf 100644
--- a/ui/src/Components/SilenceModal/DateTimeSelect/Duration.js
+++ b/ui/src/Components/SilenceModal/DateTimeSelect/Duration.js
@@ -1,4 +1,4 @@
-import React, { Component } from "react";
+import React, { useEffect, useRef } from "react";
import PropTypes from "prop-types";
import { observer } from "mobx-react";
@@ -7,60 +7,75 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faAngleUp } from "@fortawesome/free-solid-svg-icons/faAngleUp";
import { faAngleDown } from "@fortawesome/free-solid-svg-icons/faAngleDown";
-const Duration = observer(
- class Duration extends Component {
- static propTypes = {
- value: PropTypes.number.isRequired,
- label: PropTypes.string.isRequired,
- onInc: PropTypes.func.isRequired,
- onDec: PropTypes.func.isRequired,
+const Duration = observer(({ value, label, onInc, onDec }) => {
+ const rootRef = useRef(null);
+
+ useEffect(() => {
+ const cancelWheel = (event) => event.preventDefault();
+
+ const elem = rootRef.current;
+
+ elem.addEventListener("wheel", cancelWheel, { passive: false });
+
+ return () => {
+ elem.removeEventListener("wheel", cancelWheel);
};
+ }, []);
- render() {
- const { value, label, onInc, onDec } = this.props;
-
- return (
-
-
-
-
- |
-
-
-
- |
- |
-
-
-
- {value}
- |
-
- {label}
- |
-
-
- |
-
-
-
- |
- |
-
-
-
-
- );
+ const onWheel = (event) => {
+ if (event.deltaY < 0) {
+ onInc();
+ } else {
+ onDec();
}
- }
-);
+ };
+
+ return (
+
+
+
+
+ |
+
+
+
+ |
+ |
+
+
+
+ {value}
+ |
+
+ {label}
+ |
+
+
+ |
+
+
+
+ |
+ |
+
+
+
+
+ );
+});
+Duration.propTypes = {
+ value: PropTypes.number.isRequired,
+ label: PropTypes.string.isRequired,
+ onInc: PropTypes.func.isRequired,
+ onDec: PropTypes.func.isRequired,
+};
export { Duration };
diff --git a/ui/src/Components/SilenceModal/DateTimeSelect/HourMinute.js b/ui/src/Components/SilenceModal/DateTimeSelect/HourMinute.js
index c5f175590..cee2033ac 100644
--- a/ui/src/Components/SilenceModal/DateTimeSelect/HourMinute.js
+++ b/ui/src/Components/SilenceModal/DateTimeSelect/HourMinute.js
@@ -1,4 +1,4 @@
-import React, { Component } from "react";
+import React, { useEffect, useRef } from "react";
import PropTypes from "prop-types";
import { observer } from "mobx-react";
@@ -9,8 +9,8 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faAngleUp } from "@fortawesome/free-solid-svg-icons/faAngleUp";
import { faAngleDown } from "@fortawesome/free-solid-svg-icons/faAngleDown";
-const IconTd = ({ icon, onClick }) => (
-
+const IconTd = ({ icon, onClick, onWheel, className }) => (
+ |
(
IconTd.propTypes = {
icon: FontAwesomeIcon.propTypes.icon.isRequired,
onClick: PropTypes.func.isRequired,
+ onWheel: PropTypes.func.isRequired,
+ className: PropTypes.string.isRequired,
};
const HourMinute = observer(
- class HourMinute extends Component {
- static propTypes = {
- dateValue: PropTypes.instanceOf(moment).isRequired,
- onHourInc: PropTypes.func.isRequired,
- onHourDec: PropTypes.func.isRequired,
- onMinuteInc: PropTypes.func.isRequired,
- onMinuteDec: PropTypes.func.isRequired,
+ ({ dateValue, onHourInc, onHourDec, onMinuteInc, onMinuteDec }) => {
+ const rootRef = useRef(null);
+
+ useEffect(() => {
+ const cancelWheel = (event) => event.preventDefault();
+
+ const elem = rootRef.current;
+
+ elem.addEventListener("wheel", cancelWheel, { passive: false });
+
+ return () => {
+ elem.removeEventListener("wheel", cancelWheel);
+ };
+ }, []);
+
+ const onHourWheel = (event) => {
+ if (event.deltaY < 0) {
+ onHourInc();
+ } else {
+ onHourDec();
+ }
};
- render() {
- const {
- dateValue,
- onHourInc,
- onHourDec,
- onMinuteInc,
- onMinuteDec,
- } = this.props;
+ const onMinuteWheel = (event) => {
+ if (event.deltaY < 0) {
+ onMinuteInc();
+ } else {
+ onMinuteDec();
+ }
+ };
- const hour = dateValue.hour();
- const minute = dateValue.minute();
+ const hour = dateValue.hour();
+ const minute = dateValue.minute();
- return (
-
-
-
-
-
- |
-
-
-
-
- {hour > 9 ? hour : `0${hour}`}
- |
-
- :
- |
-
- {minute > 9 ? minute : `0${minute}`}
- |
-
-
-
- |
-
-
-
-
-
- );
- }
+ return (
+
+
+
+
+
+ |
+
+
+
+
+ {hour > 9 ? hour : `0${hour}`}
+ |
+
+ :
+ |
+
+ {minute > 9 ? minute : `0${minute}`}
+ |
+
+
+
+ |
+
+
+
+
+
+ );
}
);
+HourMinute.propTypes = {
+ dateValue: PropTypes.instanceOf(moment).isRequired,
+ onHourInc: PropTypes.func.isRequired,
+ onHourDec: PropTypes.func.isRequired,
+ onMinuteInc: PropTypes.func.isRequired,
+ onMinuteDec: PropTypes.func.isRequired,
+};
export { HourMinute };
diff --git a/ui/src/Components/SilenceModal/DateTimeSelect/__snapshots__/index.test.js.snap b/ui/src/Components/SilenceModal/DateTimeSelect/__snapshots__/index.test.js.snap
index 0b3858635..f412069e2 100644
--- a/ui/src/Components/SilenceModal/DateTimeSelect/__snapshots__/index.test.js.snap
+++ b/ui/src/Components/SilenceModal/DateTimeSelect/__snapshots__/index.test.js.snap
@@ -36,7 +36,7 @@ exports[` 'Duration' tab matches snapshot 1`] = `
-
+
@@ -98,7 +98,7 @@ exports[` 'Duration' tab matches snapshot 1`] = `
-
+
@@ -160,7 +160,7 @@ exports[` 'Duration' tab matches snapshot 1`] = `
-
+
@@ -613,11 +613,11 @@ exports[` 'Ends' tab matches snapshot 1`] = `
-
+
- |
+ |
'Ends' tab matches snapshot 1`] = `
|
|
-
+ |
'Ends' tab matches snapshot 1`] = `
|
- |
+ |
00
@@ -667,14 +667,14 @@ exports[` 'Ends' tab matches snapshot 1`] = `
:
|
-
+ |
00
|
- |
+ |
'Ends' tab matches snapshot 1`] = `
|
|
-
+ |
'Starts' tab matches snapshot 1`] = `
-
+
- |
+ |
'Starts' tab matches snapshot 1`] = `
|
|
-
+ |
'Starts' tab matches snapshot 1`] = `
|
- |
+ |
00
@@ -1155,14 +1155,14 @@ exports[` 'Starts' tab matches snapshot 1`] = `
:
|
-
+ |
00
|
- |
+ |
'Starts' tab matches snapshot 1`] = `
|
|
-
+ |
", () => {
expect(toDiffableHtml(tree.html())).toMatchSnapshot();
});
+ it("'Duration' tab unmounts without crashing", () => {
+ const tree = MountedDateTimeSelect();
+ tree.unmount();
+ });
+
it("clicking on the 'Starts' tab switches content to 'startsAt' selection", () => {
const tree = MountedDateTimeSelect();
const tab = tree.find(".nav-link").at(0);
@@ -74,6 +79,12 @@ describe("", () => {
expect(toDiffableHtml(tree.html())).toMatchSnapshot();
});
+ it("'Starts' tab unmounts without crashing", () => {
+ const tree = MountedDateTimeSelect();
+ tree.find(".nav-link").at(0).simulate("click");
+ tree.unmount();
+ });
+
it("clicking on the 'Ends' tab switches content to 'endsAt' selection", () => {
const tree = MountedDateTimeSelect();
const tab = tree.find(".nav-link").at(1);
@@ -89,6 +100,12 @@ describe("", () => {
expect(toDiffableHtml(tree.html())).toMatchSnapshot();
});
+ it("'Ends' tab unmounts without crashing", () => {
+ const tree = MountedDateTimeSelect();
+ tree.find(".nav-link").at(1).simulate("click");
+ tree.unmount();
+ });
+
it("clicking on the 'Duration' tabs switches content to duration selection", () => {
const tree = MountedDateTimeSelect();
// first switch to 'Starts'
@@ -143,6 +160,27 @@ const ValidateTimeButton = (
expect(diffMS).toBe(expectedDiff);
};
+const ValidateTimeWheel = (tab, storeKey, className, deltaY, expectedDiff) => {
+ const elem = tab.find(className);
+
+ const oldTimeValue = moment(silenceFormStore.data[storeKey]);
+
+ elem.simulate("wheel", { deltaY: deltaY });
+ // fire real event so cancel listener will trigger
+ const event = new Event("wheel", { deltaY: deltaY });
+ tab
+ .find("div.components-hour-minute")
+ .at(0)
+ .getDOMNode()
+ .dispatchEvent(event);
+
+ expect(silenceFormStore.data[storeKey].toISOString()).not.toBe(
+ oldTimeValue.toISOString()
+ );
+ const diffMS = silenceFormStore.data[storeKey].diff(oldTimeValue);
+ expect(diffMS).toBe(expectedDiff);
+};
+
const MountedTabContentStart = () => {
return mount();
};
@@ -164,20 +202,96 @@ describe("", () => {
ValidateTimeButton(tree, "startsAt", 0, /angle-up/, 3600 * 1000);
});
+ it("scrolling up on the hour button adds 1h to startsAt", () => {
+ const tree = MountedTabContentStart();
+ ValidateTimeWheel(
+ tree,
+ "startsAt",
+ "td.components-hour-up",
+ -1,
+ 3600 * 1000
+ );
+ });
+
it("clicking on the minute inc button adds 1m to startsAt", () => {
const tree = MountedTabContentStart();
ValidateTimeButton(tree, "startsAt", 1, /angle-up/, 60 * 1000);
});
+ it("scrolling up on the minute button adds 1m to startsAt", () => {
+ const tree = MountedTabContentStart();
+ ValidateTimeWheel(
+ tree,
+ "startsAt",
+ "td.components-minute-up",
+ -2,
+ 60 * 1000
+ );
+ });
+
it("clicking on the hour dec button subtracts 1h from startsAt", () => {
const tree = MountedTabContentStart();
ValidateTimeButton(tree, "startsAt", 2, /angle-down/, -1 * 3600 * 1000);
});
+ it("scrolling down on the hour button subtracts 1h from startsAt", () => {
+ const tree = MountedTabContentStart();
+ ValidateTimeWheel(
+ tree,
+ "startsAt",
+ "td.components-hour-down",
+ 1,
+ -1 * 3600 * 1000
+ );
+ });
+
+ it("scrolling up on the minute adds 1m to startsAt", () => {
+ const tree = MountedTabContentStart();
+ ValidateTimeWheel(tree, "startsAt", "td.components-minute", -2, 60 * 1000);
+ });
+
+ it("scrolling down on the minute subtracts 1m from startsAt", () => {
+ const tree = MountedTabContentStart();
+ ValidateTimeWheel(
+ tree,
+ "startsAt",
+ "td.components-minute",
+ 1,
+ -1 * 60 * 1000
+ );
+ });
+
it("clicking on the minute dec button subtracts 1m from startsAt", () => {
const tree = MountedTabContentStart();
ValidateTimeButton(tree, "startsAt", 3, /angle-down/, -1 * 60 * 1000);
});
+
+ it("scrolling down on the minute button subtracts 1m from startsAt", () => {
+ const tree = MountedTabContentStart();
+ ValidateTimeWheel(
+ tree,
+ "startsAt",
+ "td.components-minute-down",
+ 2,
+ -1 * 60 * 1000
+ );
+ });
+
+ it("scrolling up on the minute subtracts 1m from startsAt", () => {
+ const tree = MountedTabContentStart();
+ ValidateTimeWheel(tree, "startsAt", "td.components-minute", -50, 60 * 1000);
+ });
+
+ it("scrolling down on the minute subtracts 1m from startsAt", () => {
+ const tree = MountedTabContentStart();
+ ValidateTimeWheel(
+ tree,
+ "startsAt",
+ "td.components-minute",
+ 1,
+ -1 * 60 * 1000
+ );
+ });
});
const MountedTabContentEnd = () => {
@@ -201,20 +315,90 @@ describe("", () => {
ValidateTimeButton(tree, "endsAt", 0, /angle-up/, 3600 * 1000);
});
+ it("scrolling up on the hour button adds 1h to endsAt", () => {
+ const tree = MountedTabContentEnd();
+ ValidateTimeWheel(tree, "endsAt", "td.components-hour-up", -1, 3600 * 1000);
+ });
+
+ it("scrolling up on the hour adds 1h to endsAt", () => {
+ const tree = MountedTabContentEnd();
+ ValidateTimeWheel(tree, "endsAt", "td.components-hour", -1, 3600 * 1000);
+ });
+
+ it("scrolling down on the hour subtracts 1h from endsAt", () => {
+ const tree = MountedTabContentEnd();
+ ValidateTimeWheel(
+ tree,
+ "endsAt",
+ "td.components-hour",
+ 1,
+ -1 * 3600 * 1000
+ );
+ });
+
it("clicking on the minute inc button adds 1m to endsAt", () => {
const tree = MountedTabContentEnd();
ValidateTimeButton(tree, "endsAt", 1, /angle-up/, 60 * 1000);
});
+ it("scrolling up on the minute button adds 1m to endsAt", () => {
+ const tree = MountedTabContentEnd();
+ ValidateTimeWheel(
+ tree,
+ "endsAt",
+ "td.components-minute-up",
+ -10,
+ 60 * 1000
+ );
+ });
+
it("clicking on the hour dec button subtracts 1h from endsAt", () => {
const tree = MountedTabContentEnd();
ValidateTimeButton(tree, "endsAt", 2, /angle-down/, -1 * 3600 * 1000);
});
+ it("scrolling down on the hour button subtracts 1h from endsAt", () => {
+ const tree = MountedTabContentEnd();
+ ValidateTimeWheel(
+ tree,
+ "endsAt",
+ "td.components-hour-down",
+ 1,
+ -1 * 3600 * 1000
+ );
+ });
+
it("clicking on the minute dec button subtracts 1m from endsAt", () => {
const tree = MountedTabContentEnd();
ValidateTimeButton(tree, "endsAt", 3, /angle-down/, -1 * 60 * 1000);
});
+
+ it("scrolling down on the minute button subtracts 1m from endsAt", () => {
+ const tree = MountedTabContentEnd();
+ ValidateTimeWheel(
+ tree,
+ "endsAt",
+ "td.components-minute-down",
+ 50,
+ -1 * 60 * 1000
+ );
+ });
+
+ it("scrolling up on the minute adds 1m to endsAt", () => {
+ const tree = MountedTabContentEnd();
+ ValidateTimeWheel(tree, "endsAt", "td.components-minute", -10, 60 * 1000);
+ });
+
+ it("scrolling down on the minute subtracts 1m from endsAt", () => {
+ const tree = MountedTabContentEnd();
+ ValidateTimeWheel(
+ tree,
+ "endsAt",
+ "td.components-minute",
+ 15,
+ -1 * 60 * 1000
+ );
+ });
});
const ValidateDurationButton = (elemIndex, iconMatch, expectedDiff) => {
@@ -233,30 +417,74 @@ const ValidateDurationButton = (elemIndex, iconMatch, expectedDiff) => {
expect(diffMS).toBe(expectedDiff);
};
+const ValidateDurationWheel = (elemIndex, deltaY, expectedDiff) => {
+ const tree = mount(
+
+ );
+ const elem = tree.find(".components-duration").at(elemIndex);
+
+ const oldEndsAt = moment(silenceFormStore.data.endsAt);
+
+ elem.simulate("wheel", { deltaY: deltaY });
+ // fire real event so cancel listener will trigger
+ const event = new Event("wheel", { deltaY: deltaY });
+ elem.getDOMNode().dispatchEvent(event);
+
+ expect(silenceFormStore.data.endsAt.toISOString()).not.toBe(
+ oldEndsAt.toISOString()
+ );
+ const diffMS = silenceFormStore.data.endsAt.diff(oldEndsAt);
+ expect(diffMS).toBe(expectedDiff);
+};
+
describe("", () => {
it("clicking on the day inc button adds 1d to endsAt", () => {
ValidateDurationButton(0, /angle-up/, 24 * 3600 * 1000);
});
+ it("scrolling up on the day button adds 1d to endsAt", () => {
+ ValidateDurationWheel(0, -1, 24 * 3600 * 1000);
+ });
+
it("clicking on the day dec button subtracts 1d from endsAt", () => {
ValidateDurationButton(2, /angle-down/, -1 * 24 * 3600 * 1000);
});
+ it("scrolling down on the day button subtracts 1d from endsAt", () => {
+ ValidateDurationWheel(0, 1, -1 * 24 * 3600 * 1000);
+ });
+
it("clicking on the hour inc button adds 1h to endsAt", () => {
ValidateDurationButton(3, /angle-up/, 3600 * 1000);
});
+ it("scrolling up on the hour inc button adds 1h to endsAt", () => {
+ ValidateDurationWheel(1, -2, 3600 * 1000);
+ });
+
it("clicking on the hour dec button subtracts 1h from endsAt", () => {
ValidateDurationButton(5, /angle-down/, -1 * 3600 * 1000);
});
+ it("scrolling down on the hour dec button subtracts 1h from endsAt", () => {
+ ValidateDurationWheel(1, 2, -1 * 3600 * 1000);
+ });
+
it("clicking on the minute inc button adds 5m to endsAt", () => {
ValidateDurationButton(6, /angle-up/, 5 * 60 * 1000);
});
+ it("scrolling up on the minute inc button adds 5m to endsAt", () => {
+ ValidateDurationWheel(2, -1, 5 * 60 * 1000);
+ });
+
it("clicking on the minute dec button subtracts 5m from endsAt", () => {
ValidateDurationButton(8, /angle-down/, -1 * 5 * 60 * 1000);
});
+
+ it("scrolling down on the minute dec button subtracts 5m from endsAt", () => {
+ ValidateDurationWheel(2, 1, -1 * 5 * 60 * 1000);
+ });
});
const SetDurationTo = (hours, minutes) => {
| | |