@grafana/runtime
Version:
Grafana Runtime Library
1 lines • 10 kB
Source Map (JSON)
{"version":3,"file":"LocationService.mjs","sources":["../../../src/services/LocationService.tsx"],"sourcesContent":["import * as H from 'history';\nimport React, { useContext } from 'react';\nimport { BehaviorSubject, Observable } from 'rxjs';\n\nimport { deprecationWarning, UrlQueryMap, urlUtil } from '@grafana/data';\nimport { attachDebugger, createLogger } from '@grafana/ui';\n\nimport { config } from '../config';\n\nimport { LocationUpdate } from './LocationSrv';\n\n/**\n * @public\n * A wrapper to help work with browser location and history\n */\nexport interface LocationService {\n partial: (query: Record<string, any>, replace?: boolean) => void;\n push: (location: H.Path | H.LocationDescriptor<any>) => void;\n replace: (location: H.Path | H.LocationDescriptor<any>) => void;\n reload: () => void;\n getLocation: () => H.Location;\n getHistory: () => H.History;\n getSearch: () => URLSearchParams;\n getSearchObject: () => UrlQueryMap;\n getLocationObservable: () => Observable<H.Location>;\n\n /**\n * This is from the old LocationSrv interface\n * @deprecated use partial, push or replace instead */\n update: (update: LocationUpdate) => void;\n}\n\n/** @internal */\nexport class HistoryWrapper implements LocationService {\n private readonly history: H.History;\n private locationObservable: BehaviorSubject<H.Location>;\n\n constructor(history?: H.History) {\n // If no history passed create an in memory one if being called from test\n this.history =\n history ||\n (process.env.NODE_ENV === 'test'\n ? H.createMemoryHistory({ initialEntries: ['/'] })\n : H.createBrowserHistory({ basename: config.appSubUrl ?? '/' }));\n\n this.locationObservable = new BehaviorSubject(this.history.location);\n\n this.history.listen((location) => {\n this.locationObservable.next(location);\n });\n\n this.partial = this.partial.bind(this);\n this.push = this.push.bind(this);\n this.replace = this.replace.bind(this);\n this.getSearch = this.getSearch.bind(this);\n this.getHistory = this.getHistory.bind(this);\n this.getLocation = this.getLocation.bind(this);\n }\n\n getLocationObservable() {\n return this.locationObservable.asObservable();\n }\n\n getHistory() {\n return this.history;\n }\n\n getSearch() {\n return new URLSearchParams(this.history.location.search);\n }\n\n partial(query: Record<string, any>, replace?: boolean) {\n const currentLocation = this.history.location;\n const newQuery = this.getSearchObject();\n\n for (const key in query) {\n // removing params with null | undefined\n if (query[key] === null || query[key] === undefined) {\n delete newQuery[key];\n } else {\n newQuery[key] = query[key];\n }\n }\n\n const updatedUrl = urlUtil.renderUrl(currentLocation.pathname, newQuery);\n\n if (replace) {\n this.history.replace(updatedUrl, this.history.location.state);\n } else {\n this.history.push(updatedUrl, this.history.location.state);\n }\n }\n\n push(location: H.Path | H.LocationDescriptor) {\n this.history.push(location);\n }\n\n replace(location: H.Path | H.LocationDescriptor) {\n this.history.replace(location);\n }\n\n reload() {\n const prevState = (this.history.location.state as any)?.routeReloadCounter;\n this.history.replace({\n ...this.history.location,\n state: { routeReloadCounter: prevState ? prevState + 1 : 1 },\n });\n }\n\n getLocation() {\n return this.history.location;\n }\n\n getSearchObject() {\n return locationSearchToObject(this.history.location.search);\n }\n\n /** @deprecated use partial, push or replace instead */\n update(options: LocationUpdate) {\n deprecationWarning('LocationSrv', 'update', 'partial, push or replace');\n if (options.partial && options.query) {\n this.partial(options.query, options.partial);\n } else {\n const newLocation: H.LocationDescriptor = {\n pathname: options.path,\n };\n if (options.query) {\n newLocation.search = urlUtil.toUrlParams(options.query);\n }\n if (options.replace) {\n this.replace(newLocation);\n } else {\n this.push(newLocation);\n }\n }\n }\n}\n\n/**\n * @public\n * Parses a location search string to an object\n * */\nexport function locationSearchToObject(search: string | number): UrlQueryMap {\n let queryString = typeof search === 'number' ? String(search) : search;\n\n if (queryString.length > 0) {\n if (queryString.startsWith('?')) {\n return urlUtil.parseKeyValue(queryString.substring(1));\n }\n return urlUtil.parseKeyValue(queryString);\n }\n\n return {};\n}\n\n/**\n * @public\n */\nexport let locationService: LocationService = new HistoryWrapper();\n\n/**\n * Used for tests only\n * @internal\n */\nexport const setLocationService = (location: LocationService) => {\n if (process.env.NODE_ENV !== 'test') {\n throw new Error('locationService can be only overriden in test environment');\n }\n locationService = location;\n};\n\nconst navigationLog = createLogger('Router');\n\n/** @internal */\nexport const navigationLogger = navigationLog.logger;\n\n// For debugging purposes the location service is attached to global _debug variable\nattachDebugger('location', locationService, navigationLog);\n\n// Simple context so the location service can be used without being a singleton\nconst LocationServiceContext = React.createContext<LocationService | undefined>(undefined);\n\nexport function useLocationService(): LocationService {\n const service = useContext(LocationServiceContext);\n if (!service) {\n throw new Error('useLocationService must be used within a LocationServiceProvider');\n }\n return service;\n}\n\nexport const LocationServiceProvider: React.FC<{ service: LocationService; children: React.ReactNode }> = ({\n service,\n children,\n}) => {\n return <LocationServiceContext.Provider value={service}>{children}</LocationServiceContext.Provider>;\n};\n"],"names":[],"mappings":"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"}