From 04d8f0f06333178e106f3f1ed17a42d59d65cb85 Mon Sep 17 00:00:00 2001 From: Andrej Ocenas Date: Thu, 1 Aug 2024 15:59:20 +0200 Subject: [PATCH] Runtime: Add provider and access hook for location service (#90759) --- .betterer.results | 2 +- ...rvice.test.ts => LocationService.test.tsx} | 15 +++++- ...LocationService.ts => LocationService.tsx} | 19 +++++++ public/app/AppWrapper.tsx | 54 +++++++++++-------- 4 files changed, 65 insertions(+), 25 deletions(-) rename packages/grafana-runtime/src/services/{LocationService.test.ts => LocationService.test.tsx} (69%) rename packages/grafana-runtime/src/services/{LocationService.ts => LocationService.tsx} (86%) diff --git a/.betterer.results b/.betterer.results index b36213f0033..63f14419f75 100644 --- a/.betterer.results +++ b/.betterer.results @@ -514,7 +514,7 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "2"], [0, 0, 0, "Unexpected any. Specify a different type.", "3"] ], - "packages/grafana-runtime/src/services/LocationService.ts:5381": [ + "packages/grafana-runtime/src/services/LocationService.tsx:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"], [0, 0, 0, "Unexpected any. Specify a different type.", "2"], diff --git a/packages/grafana-runtime/src/services/LocationService.test.ts b/packages/grafana-runtime/src/services/LocationService.test.tsx similarity index 69% rename from packages/grafana-runtime/src/services/LocationService.test.ts rename to packages/grafana-runtime/src/services/LocationService.test.tsx index c01282b5ed5..0354f8f089b 100644 --- a/packages/grafana-runtime/src/services/LocationService.test.ts +++ b/packages/grafana-runtime/src/services/LocationService.test.tsx @@ -1,4 +1,6 @@ -import { locationService } from './LocationService'; +import { renderHook } from '@testing-library/react-hooks'; + +import { locationService, HistoryWrapper, useLocationService, LocationServiceProvider } from './LocationService'; describe('LocationService', () => { describe('getSearchObject', () => { @@ -51,4 +53,15 @@ describe('LocationService', () => { }); }); }); + + describe('hook access', () => { + it('can set and access service from a context', () => { + const locationServiceLocal = new HistoryWrapper(); + const wrapper: React.FunctionComponent<{ children: React.ReactNode }> = ({ children }) => ( + {children} + ); + const hookResult = renderHook(() => useLocationService(), { wrapper }); + expect(hookResult.result.current).toBe(locationServiceLocal); + }); + }); }); diff --git a/packages/grafana-runtime/src/services/LocationService.ts b/packages/grafana-runtime/src/services/LocationService.tsx similarity index 86% rename from packages/grafana-runtime/src/services/LocationService.ts rename to packages/grafana-runtime/src/services/LocationService.tsx index af707b0b93e..6a148b15482 100644 --- a/packages/grafana-runtime/src/services/LocationService.ts +++ b/packages/grafana-runtime/src/services/LocationService.tsx @@ -1,4 +1,5 @@ import * as H from 'history'; +import React, { useContext } from 'react'; import { deprecationWarning, UrlQueryMap, urlUtil } from '@grafana/data'; import { attachDebugger, createLogger } from '@grafana/ui'; @@ -162,3 +163,21 @@ export const navigationLogger = navigationLog.logger; // For debugging purposes the location service is attached to global _debug variable attachDebugger('location', locationService, navigationLog); + +// Simple context so the location service can be used without being a singleton +const LocationServiceContext = React.createContext(undefined); + +export function useLocationService(): LocationService { + const service = useContext(LocationServiceContext); + if (!service) { + throw new Error('useLocationService must be used within a LocationServiceProvider'); + } + return service; +} + +export const LocationServiceProvider: React.FC<{ service: LocationService; children: React.ReactNode }> = ({ + service, + children, +}) => { + return {children}; +}; diff --git a/public/app/AppWrapper.tsx b/public/app/AppWrapper.tsx index 7c0997d7cea..b73839203c2 100644 --- a/public/app/AppWrapper.tsx +++ b/public/app/AppWrapper.tsx @@ -4,7 +4,13 @@ import { Provider } from 'react-redux'; import { Router, Redirect, Switch, RouteComponentProps } from 'react-router-dom'; import { CompatRouter, CompatRoute } from 'react-router-dom-v5-compat'; -import { config, locationService, navigationLogger, reportInteraction } from '@grafana/runtime'; +import { + config, + locationService, + LocationServiceProvider, + navigationLogger, + reportInteraction, +} from '@grafana/runtime'; import { ErrorBoundaryAlert, GlobalStyles, ModalRoot, PortalContainer, Stack } from '@grafana/ui'; import { getAppRoutes } from 'app/routes/routes'; import { store } from 'app/store/store'; @@ -104,29 +110,31 @@ export class AppWrapper extends Component { options={{ enableHistory: true, callbacks: { onSelectAction: commandPaletteActionSelected } }} > - - - -
- - - - - {pageBanners.map((Banner, index) => ( - + + + + +
+ + + + + {pageBanners.map((Banner, index) => ( + + ))} + {ready && this.renderRoutes()} + + {bodyRenderHooks.map((Hook, index) => ( + ))} - {ready && this.renderRoutes()} - - {bodyRenderHooks.map((Hook, index) => ( - - ))} - -
- - - -
-
+
+
+ + + +
+
+