From 3eac34f5f386e5f725f164ff6e745c5cb8c39847 Mon Sep 17 00:00:00 2001
From: Shahar Mor <shaharmor1@gmail.com>
Date: Thu, 10 Feb 2022 13:54:50 +0200
Subject: [PATCH] Kiosk: Reuse kiosk module (#44625)

* Reuse kiosk module, centralize kiosk query handling

* update kiosk tests to set correct kiosk value

* fix DashboardPage kiosk test

* remove unused UrlQueryValue, revert import change
---
 public/app/core/components/NavBar/NavBar.test.tsx    | 12 ++++++++++--
 public/app/core/components/NavBar/NavBar.tsx         |  8 ++++----
 .../app/core/components/NavBar/NavBarNext.test.tsx   | 12 ++++++++++--
 public/app/core/components/NavBar/NavBarNext.tsx     |  6 +++---
 public/app/core/navigation/kiosk.ts                  |  8 +++++---
 .../dashboard/containers/DashboardPage.test.tsx      |  3 ++-
 .../features/dashboard/containers/DashboardPage.tsx  |  7 +++----
 7 files changed, 37 insertions(+), 19 deletions(-)

diff --git a/public/app/core/components/NavBar/NavBar.test.tsx b/public/app/core/components/NavBar/NavBar.test.tsx
index 514c4d62206..94b89e36b35 100644
--- a/public/app/core/components/NavBar/NavBar.test.tsx
+++ b/public/app/core/components/NavBar/NavBar.test.tsx
@@ -39,10 +39,18 @@ describe('Render', () => {
     expect(sidemenu).toBeInTheDocument();
   });
 
-  it('should not render when in kiosk mode', async () => {
+  it('should not render when in kiosk mode is tv', async () => {
     setup();
 
-    locationService.partial({ kiosk: 'full' });
+    locationService.partial({ kiosk: 'tv' });
+    const sidemenu = screen.queryByTestId('sidemenu');
+    expect(sidemenu).not.toBeInTheDocument();
+  });
+
+  it('should not render when in kiosk mode is full', async () => {
+    setup();
+
+    locationService.partial({ kiosk: '1' });
     const sidemenu = screen.queryByTestId('sidemenu');
     expect(sidemenu).not.toBeInTheDocument();
   });
diff --git a/public/app/core/components/NavBar/NavBar.tsx b/public/app/core/components/NavBar/NavBar.tsx
index b1f9bb86589..a2c155df816 100644
--- a/public/app/core/components/NavBar/NavBar.tsx
+++ b/public/app/core/components/NavBar/NavBar.tsx
@@ -8,7 +8,8 @@ import { Icon, IconName, useTheme2 } from '@grafana/ui';
 import { locationService } from '@grafana/runtime';
 import { Branding } from 'app/core/components/Branding/Branding';
 import config from 'app/core/config';
-import { StoreState, KioskMode } from 'app/types';
+import { getKioskMode } from 'app/core/navigation/kiosk';
+import { KioskMode, StoreState } from 'app/types';
 import { enrichConfigItems, getActiveItem, isMatchOrChildMatch, isSearchActive, SEARCH_ITEM_ID } from './utils';
 import { OrgSwitcher } from '../OrgSwitcher';
 import NavBarItem from './NavBarItem';
@@ -43,8 +44,7 @@ export const NavBarUnconnected = React.memo(({ navBarTree }: Props) => {
   const theme = useTheme2();
   const styles = getStyles(theme);
   const location = useLocation();
-  const query = new URLSearchParams(location.search);
-  const kiosk = query.get('kiosk') as KioskMode;
+  const kiosk = getKioskMode();
   const [showSwitcherModal, setShowSwitcherModal] = useState(false);
   const toggleSwitcherModal = () => {
     setShowSwitcherModal(!showSwitcherModal);
@@ -60,7 +60,7 @@ export const NavBarUnconnected = React.memo(({ navBarTree }: Props) => {
 
   const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
 
-  if (kiosk !== null) {
+  if (kiosk !== KioskMode.Off) {
     return null;
   }
 
diff --git a/public/app/core/components/NavBar/NavBarNext.test.tsx b/public/app/core/components/NavBar/NavBarNext.test.tsx
index 10edfc295c1..12d80526cb5 100644
--- a/public/app/core/components/NavBar/NavBarNext.test.tsx
+++ b/public/app/core/components/NavBar/NavBarNext.test.tsx
@@ -39,10 +39,18 @@ describe('Render', () => {
     expect(sidemenu).toBeInTheDocument();
   });
 
-  it('should not render when in kiosk mode', async () => {
+  it('should not render when in kiosk mode is tv', async () => {
     setup();
 
-    locationService.partial({ kiosk: 'full' });
+    locationService.partial({ kiosk: 'tv' });
+    const sidemenu = screen.queryByTestId('sidemenu');
+    expect(sidemenu).not.toBeInTheDocument();
+  });
+
+  it('should not render when in kiosk mode is full', async () => {
+    setup();
+
+    locationService.partial({ kiosk: '1' });
     const sidemenu = screen.queryByTestId('sidemenu');
     expect(sidemenu).not.toBeInTheDocument();
   });
diff --git a/public/app/core/components/NavBar/NavBarNext.tsx b/public/app/core/components/NavBar/NavBarNext.tsx
index b3f04cd8b86..36e763d931d 100644
--- a/public/app/core/components/NavBar/NavBarNext.tsx
+++ b/public/app/core/components/NavBar/NavBarNext.tsx
@@ -5,6 +5,7 @@ import { cloneDeep } from 'lodash';
 import { GrafanaTheme2, NavModelItem, NavSection } from '@grafana/data';
 import { Icon, IconName, useTheme2 } from '@grafana/ui';
 import { locationService } from '@grafana/runtime';
+import { getKioskMode } from 'app/core/navigation/kiosk';
 import { KioskMode, StoreState } from 'app/types';
 import { enrichConfigItems, getActiveItem, isMatchOrChildMatch, isSearchActive, SEARCH_ITEM_ID } from './utils';
 import { OrgSwitcher } from '../OrgSwitcher';
@@ -40,8 +41,7 @@ export const NavBarNextUnconnected = React.memo(({ navBarTree }: Props) => {
   const theme = useTheme2();
   const styles = getStyles(theme);
   const location = useLocation();
-  const query = new URLSearchParams(location.search);
-  const kiosk = query.get('kiosk') as KioskMode;
+  const kiosk = getKioskMode();
   const [showSwitcherModal, setShowSwitcherModal] = useState(false);
   const toggleSwitcherModal = () => {
     setShowSwitcherModal(!showSwitcherModal);
@@ -57,7 +57,7 @@ export const NavBarNextUnconnected = React.memo(({ navBarTree }: Props) => {
   const activeItem = isSearchActive(location) ? searchItem : getActiveItem(navTree, location.pathname);
   const [menuOpen, setMenuOpen] = useState(false);
 
-  if (kiosk !== null) {
+  if (kiosk !== KioskMode.Off) {
     return null;
   }
 
diff --git a/public/app/core/navigation/kiosk.ts b/public/app/core/navigation/kiosk.ts
index 57cb7ce7bcc..b041d1f5272 100644
--- a/public/app/core/navigation/kiosk.ts
+++ b/public/app/core/navigation/kiosk.ts
@@ -1,4 +1,4 @@
-import { AppEvents, UrlQueryValue } from '@grafana/data';
+import { AppEvents } from '@grafana/data';
 import { locationService } from '@grafana/runtime';
 import appEvents from '../app_events';
 import { KioskMode } from '../../types';
@@ -22,8 +22,10 @@ export function toggleKioskMode() {
   locationService.partial({ kiosk });
 }
 
-export function getKioskMode(queryParam?: UrlQueryValue): KioskMode {
-  switch (queryParam) {
+export function getKioskMode(): KioskMode {
+  const kiosk = locationService.getSearchObject().kiosk;
+
+  switch (kiosk) {
     case 'tv':
       return KioskMode.TV;
     //  legacy support
diff --git a/public/app/features/dashboard/containers/DashboardPage.test.tsx b/public/app/features/dashboard/containers/DashboardPage.test.tsx
index a36aa31fbaa..617d5b5fd4f 100644
--- a/public/app/features/dashboard/containers/DashboardPage.test.tsx
+++ b/public/app/features/dashboard/containers/DashboardPage.test.tsx
@@ -288,8 +288,9 @@ describe('DashboardPage', () => {
 
   dashboardPageScenario('When in full kiosk mode', (ctx) => {
     ctx.setup(() => {
+      locationService.partial({ kiosk: true });
       ctx.mount({
-        queryParams: { kiosk: true },
+        queryParams: {},
         dashboard: getTestDashboard(),
       });
       ctx.rerender({ dashboard: ctx.dashboard });
diff --git a/public/app/features/dashboard/containers/DashboardPage.tsx b/public/app/features/dashboard/containers/DashboardPage.tsx
index 968d74b7c61..309adc30170 100644
--- a/public/app/features/dashboard/containers/DashboardPage.tsx
+++ b/public/app/features/dashboard/containers/DashboardPage.tsx
@@ -24,7 +24,7 @@ import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher';
 import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
 import { getTimeSrv } from '../services/TimeSrv';
 import { getKioskMode } from 'app/core/navigation/kiosk';
-import { GrafanaTheme2, TimeRange, UrlQueryValue } from '@grafana/data';
+import { GrafanaTheme2, TimeRange } from '@grafana/data';
 import { DashboardLoading } from '../components/DashboardLoading/DashboardLoading';
 import { DashboardFailed } from '../components/DashboardLoading/DashboardFailed';
 import { DashboardPrompt } from '../components/DashboardPrompt/DashboardPrompt';
@@ -45,7 +45,6 @@ type DashboardPageRouteSearchParams = {
   viewPanel?: string;
   editview?: string;
   inspect?: string;
-  kiosk?: UrlQueryValue;
   from?: string;
   to?: string;
   refresh?: string;
@@ -314,7 +313,7 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
   render() {
     const { dashboard, isInitSlow, initError, queryParams, theme } = this.props;
     const { editPanel, viewPanel, updateScrollTop } = this.state;
-    const kioskMode = getKioskMode(queryParams.kiosk);
+    const kioskMode = getKioskMode();
     const styles = getStyles(theme, kioskMode);
 
     if (!dashboard) {
@@ -380,7 +379,7 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
 /*
  * Styles
  */
-export const getStyles = stylesFactory((theme: GrafanaTheme2, kioskMode) => {
+export const getStyles = stylesFactory((theme: GrafanaTheme2, kioskMode: KioskMode) => {
   const contentPadding = kioskMode !== KioskMode.Full ? theme.spacing(0, 2, 2) : theme.spacing(2);
   return {
     dashboardContainer: css`