diff --git a/ui/src/Components/Animations/NavBarSlide/index.js b/ui/src/Components/Animations/NavBarSlide/index.js deleted file mode 100644 index 094a9c4d3..000000000 --- a/ui/src/Components/Animations/NavBarSlide/index.js +++ /dev/null @@ -1,22 +0,0 @@ -import React from "react"; -import PropTypes from "prop-types"; - -import { CSSTransition } from "react-transition-group"; - -const NavBarSlide = ({ children, duration, ...props }) => ( - - {children} - -); -NavBarSlide.propTypes = { - children: PropTypes.node.isRequired, -}; - -export { NavBarSlide }; diff --git a/ui/src/Components/NavBar/index.js b/ui/src/Components/NavBar/index.js index 4b8a30687..f0fde2f6b 100644 --- a/ui/src/Components/NavBar/index.js +++ b/ui/src/Components/NavBar/index.js @@ -8,14 +8,16 @@ import ReactResizeDetector from "react-resize-detector"; import IdleTimer from "react-idle-timer"; +import { Fade } from "react-reveal"; + import { AlertStore } from "Stores/AlertStore"; import { Settings } from "Stores/Settings"; import { SilenceFormStore } from "Stores/SilenceFormStore"; import { IsMobile } from "Common/Device"; -import { NavBarSlide } from "Components/Animations/NavBarSlide"; import { OverviewModal } from "Components/OverviewModal"; import { MainModal } from "Components/MainModal"; import { SilenceModal } from "Components/SilenceModal"; +import { ThemeContext } from "Components/Theme"; import { FetchIndicator } from "./FetchIndicator"; import { FilterInput } from "./FilterInput"; @@ -38,6 +40,7 @@ const NavBar = observer( super(props); this.idleTimer = null; + this.animationTimer = null; this.activityStatus = observable( { @@ -65,7 +68,10 @@ const NavBar = observer( ); this.activityStatusReaction = reaction( - () => props.alertStore.status.paused, + () => + props.alertStore.status.paused || + props.alertStore.filters.values.filter((f) => f.applied === false) + .length > 0, (paused) => paused ? this.idleTimer && this.idleTimer.pause() @@ -93,14 +99,32 @@ const NavBar = observer( document.body.style.paddingTop = `${paddingTop}px`; }; - onHide = () => { - this.activityStatus.hide(); - this.updateBodyPaddingTop(); + onToggle = () => { + if (this.activityStatus.idle) { + this.activityStatus.hide(); + this.updateBodyPaddingTop(); + } else { + this.updateBodyPaddingTop(); + this.activityStatus.show(); + } }; - onShow = () => { - this.updateBodyPaddingTop(); - this.activityStatus.show(); + onIdleTimerActive = () => { + clearTimeout(this.animationTimer); + this.activityStatus.setActive(); + this.onToggle(); + }; + + onIdleTimerIdle = () => { + const { settingsStore } = this.props; + + if (settingsStore.filterBarConfig.config.autohide) { + this.activityStatus.setIdle(); + this.animationTimer = setTimeout( + this.onToggle, + this.context.animations.duration + ); + } }; onResize = (width, height) => { @@ -126,30 +150,19 @@ const NavBar = observer( const isMobile = IsMobile(); - const isLoading = - alertStore.filters.values.filter((f) => f.applied === false).length > 0; - return ( { this.idleTimer = ref; }} - onActive={this.activityStatus.setActive} - onIdle={() => { - if (settingsStore.filterBarConfig.config.autohide) { - this.activityStatus.setIdle(); - } - }} + onActive={this.onIdleTimerActive} + onIdle={this.onIdleTimerIdle} timeout={isMobile ? MobileIdleTimeout : DesktopIdleTimeout} >
- + - +
); } } ); +NavBar.contextType = ThemeContext; export { NavBar }; diff --git a/ui/src/Components/NavBar/index.test.js b/ui/src/Components/NavBar/index.test.js index bdaf28f1c..e9249e2ca 100644 --- a/ui/src/Components/NavBar/index.test.js +++ b/ui/src/Components/NavBar/index.test.js @@ -4,9 +4,12 @@ import { shallow, mount } from "enzyme"; import moment from "moment"; +import { MockThemeContext } from "__mocks__/Theme"; import { AlertStore, NewUnappliedFilter } from "Stores/AlertStore"; import { Settings } from "Stores/Settings"; import { SilenceFormStore } from "Stores/SilenceFormStore"; +import { ThemeContext } from "Components/Theme"; + import { NavBar } from "."; let alertStore; @@ -17,9 +20,12 @@ beforeEach(() => { alertStore = new AlertStore([]); settingsStore = new Settings(); silenceFormStore = new SilenceFormStore(); + settingsStore.filterBarConfig.config.autohide = true; // fix startsAt & endsAt dates so they don't change between tests silenceFormStore.data.startsAt = moment([2018, 1, 30, 10, 25, 50]).utc(); silenceFormStore.data.endsAt = moment([2018, 1, 30, 11, 25, 50]).utc(); + + jest.spyOn(React, "useContext").mockImplementation(() => MockThemeContext); }); const RenderNavbar = () => { @@ -38,7 +44,11 @@ const MountedNavbar = () => { alertStore={alertStore} settingsStore={settingsStore} silenceFormStore={silenceFormStore} - /> + />, + { + wrappingComponent: ThemeContext.Provider, + wrappingComponentProps: { value: MockThemeContext }, + } ); }; @@ -151,9 +161,9 @@ describe("", () => { }); it("doesn't hide on mobile if there are unapplied filters", () => { - alertStore.filters.values.push(NewUnappliedFilter("cluster=dev")); global.window.innerWidth = 500; const tree = MountedNavbar(); + alertStore.filters.values.push(NewUnappliedFilter("cluster=dev")); jest.runTimersToTime(1000 * 13); tree.update(); expect(tree.find(".container").hasClass("visible")).toBe(true); @@ -161,9 +171,9 @@ describe("", () => { }); it("doesn't hide on desktop if there are unapplied filters", () => { - alertStore.filters.values.push(NewUnappliedFilter("cluster=dev")); global.window.innerWidth = 769; const tree = MountedNavbar(); + alertStore.filters.values.push(NewUnappliedFilter("cluster=dev")); jest.runTimersToTime(1000 * 60 * 3 + 1000); tree.update(); expect(tree.find(".container").hasClass("visible")).toBe(true); @@ -171,32 +181,32 @@ describe("", () => { }); it("hides on mobile if all unapplied filters finish applying", () => { - alertStore.filters.values.push(NewUnappliedFilter("cluster=dev")); global.window.innerWidth = 500; const tree = MountedNavbar(); + alertStore.filters.values.push(NewUnappliedFilter("cluster=dev")); jest.runTimersToTime(1000 * 13); tree.update(); expect(tree.find(".container").hasClass("visible")).toBe(true); expect(tree.find(".container").hasClass("invisible")).toBe(false); alertStore.filters.applyAllFilters(); - jest.runTimersToTime(1000); + jest.runTimersToTime(1000 * 13); tree.update(); expect(tree.find(".container").hasClass("visible")).toBe(false); expect(tree.find(".container").hasClass("invisible")).toBe(true); }); it("hides on desktop if all unapplied filters finish applying", () => { - alertStore.filters.values.push(NewUnappliedFilter("cluster=dev")); global.window.innerWidth = 769; const tree = MountedNavbar(); + alertStore.filters.values.push(NewUnappliedFilter("cluster=dev")); jest.runTimersToTime(1000 * 60 * 3 + 1000); tree.update(); expect(tree.find(".container").hasClass("visible")).toBe(true); expect(tree.find(".container").hasClass("invisible")).toBe(false); alertStore.filters.applyAllFilters(); - jest.runTimersToTime(1000); + jest.runTimersToTime(1000 * 60 * 3 + 1000); tree.update(); expect(tree.find(".container").hasClass("visible")).toBe(false); expect(tree.find(".container").hasClass("invisible")).toBe(true); @@ -206,13 +216,13 @@ describe("", () => { const tree = MountedNavbar(); const instance = tree.instance(); - instance.activityStatus.setIdle(); + instance.onIdleTimerIdle(); jest.runOnlyPendingTimers(); tree.update(); expect(tree.find(".container").hasClass("visible")).toBe(false); expect(tree.find(".container").hasClass("invisible")).toBe(true); - instance.activityStatus.setActive(); + instance.onIdleTimerActive(); jest.runOnlyPendingTimers(); tree.update(); expect(tree.find(".container").hasClass("visible")).toBe(true); @@ -223,7 +233,7 @@ describe("", () => { const tree = MountedNavbar(); const instance = tree.instance(); - instance.activityStatus.setIdle(); + instance.onIdleTimerIdle(); jest.runOnlyPendingTimers(); tree.update(); expect( diff --git a/ui/src/Styles/Components/NavBarSlide.scss b/ui/src/Styles/Components/NavBarSlide.scss deleted file mode 100644 index 36173329f..000000000 --- a/ui/src/Styles/Components/NavBarSlide.scss +++ /dev/null @@ -1,22 +0,0 @@ -.components-animation-navbar { - will-change: opacity; - transform: translateZ(0); -} - -.components-animation-navbar-appear, -.components-animation-navbar-enter { - opacity: 0.01; -} -.components-animation-navbar-appear-active, -.components-animation-navbar-enter-active { - opacity: 1; - transition: opacity 0.5s ease-in; -} - -.components-animation-navbar-exit { - opacity: 1; -} -.components-animation-navbar-exit-active { - opacity: 0.01; - transition: opacity 0.5s ease-out; -} diff --git a/ui/src/Styles/DarkTheme.scss b/ui/src/Styles/DarkTheme.scss index 3267ca12c..d95519011 100644 --- a/ui/src/Styles/DarkTheme.scss +++ b/ui/src/Styles/DarkTheme.scss @@ -122,7 +122,6 @@ $color-default: #708090; @import "Styles/Components/DropdownSlide"; @import "Styles/Components/History"; @import "Styles/Components/HistoryLabel"; -@import "Styles/Components/NavBarSlide"; @import "Styles/Components/SilenceModal"; @import "Styles/Components/Pagination"; diff --git a/ui/src/Styles/LightTheme.scss b/ui/src/Styles/LightTheme.scss index 0a4427a24..ff363343d 100644 --- a/ui/src/Styles/LightTheme.scss +++ b/ui/src/Styles/LightTheme.scss @@ -104,7 +104,6 @@ $color-default: #708090; @import "Styles/Components/DropdownSlide"; @import "Styles/Components/History"; @import "Styles/Components/HistoryLabel"; -@import "Styles/Components/NavBarSlide"; @import "Styles/Components/SilenceModal"; @import "Styles/Components/Pagination";