mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Runtime: Add provider and access hook for location service (#90759)
This commit is contained in:
@@ -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.", "2"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
|
[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.", "0"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
||||||
|
|||||||
@@ -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('LocationService', () => {
|
||||||
describe('getSearchObject', () => {
|
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 }) => (
|
||||||
|
<LocationServiceProvider service={locationServiceLocal}>{children}</LocationServiceProvider>
|
||||||
|
);
|
||||||
|
const hookResult = renderHook(() => useLocationService(), { wrapper });
|
||||||
|
expect(hookResult.result.current).toBe(locationServiceLocal);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as H from 'history';
|
import * as H from 'history';
|
||||||
|
import React, { useContext } from 'react';
|
||||||
|
|
||||||
import { deprecationWarning, UrlQueryMap, urlUtil } from '@grafana/data';
|
import { deprecationWarning, UrlQueryMap, urlUtil } from '@grafana/data';
|
||||||
import { attachDebugger, createLogger } from '@grafana/ui';
|
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
|
// For debugging purposes the location service is attached to global _debug variable
|
||||||
attachDebugger('location', locationService, navigationLog);
|
attachDebugger('location', locationService, navigationLog);
|
||||||
|
|
||||||
|
// Simple context so the location service can be used without being a singleton
|
||||||
|
const LocationServiceContext = React.createContext<LocationService | undefined>(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 <LocationServiceContext.Provider value={service}>{children}</LocationServiceContext.Provider>;
|
||||||
|
};
|
||||||
@@ -4,7 +4,13 @@ import { Provider } from 'react-redux';
|
|||||||
import { Router, Redirect, Switch, RouteComponentProps } from 'react-router-dom';
|
import { Router, Redirect, Switch, RouteComponentProps } from 'react-router-dom';
|
||||||
import { CompatRouter, CompatRoute } from 'react-router-dom-v5-compat';
|
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 { ErrorBoundaryAlert, GlobalStyles, ModalRoot, PortalContainer, Stack } from '@grafana/ui';
|
||||||
import { getAppRoutes } from 'app/routes/routes';
|
import { getAppRoutes } from 'app/routes/routes';
|
||||||
import { store } from 'app/store/store';
|
import { store } from 'app/store/store';
|
||||||
@@ -104,29 +110,31 @@ export class AppWrapper extends Component<AppWrapperProps, AppWrapperState> {
|
|||||||
options={{ enableHistory: true, callbacks: { onSelectAction: commandPaletteActionSelected } }}
|
options={{ enableHistory: true, callbacks: { onSelectAction: commandPaletteActionSelected } }}
|
||||||
>
|
>
|
||||||
<Router history={locationService.getHistory()}>
|
<Router history={locationService.getHistory()}>
|
||||||
<CompatRouter>
|
<LocationServiceProvider service={locationService}>
|
||||||
<ModalsContextProvider>
|
<CompatRouter>
|
||||||
<GlobalStyles />
|
<ModalsContextProvider>
|
||||||
<div className="grafana-app">
|
<GlobalStyles />
|
||||||
<AppChrome>
|
<div className="grafana-app">
|
||||||
<AngularRoot />
|
<AppChrome>
|
||||||
<AppNotificationList />
|
<AngularRoot />
|
||||||
<Stack gap={0} grow={1} direction="column">
|
<AppNotificationList />
|
||||||
{pageBanners.map((Banner, index) => (
|
<Stack gap={0} grow={1} direction="column">
|
||||||
<Banner key={index.toString()} />
|
{pageBanners.map((Banner, index) => (
|
||||||
|
<Banner key={index.toString()} />
|
||||||
|
))}
|
||||||
|
{ready && this.renderRoutes()}
|
||||||
|
</Stack>
|
||||||
|
{bodyRenderHooks.map((Hook, index) => (
|
||||||
|
<Hook key={index.toString()} />
|
||||||
))}
|
))}
|
||||||
{ready && this.renderRoutes()}
|
</AppChrome>
|
||||||
</Stack>
|
</div>
|
||||||
{bodyRenderHooks.map((Hook, index) => (
|
<LiveConnectionWarning />
|
||||||
<Hook key={index.toString()} />
|
<ModalRoot />
|
||||||
))}
|
<PortalContainer />
|
||||||
</AppChrome>
|
</ModalsContextProvider>
|
||||||
</div>
|
</CompatRouter>
|
||||||
<LiveConnectionWarning />
|
</LocationServiceProvider>
|
||||||
<ModalRoot />
|
|
||||||
<PortalContainer />
|
|
||||||
</ModalsContextProvider>
|
|
||||||
</CompatRouter>
|
|
||||||
</Router>
|
</Router>
|
||||||
</KBarProvider>
|
</KBarProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
|||||||
Reference in New Issue
Block a user