import { UrlQueryMap, urlUtil } from '@grafana/data'; import { config, locationService } from '@grafana/runtime'; import { UrlSyncManager } from '@grafana/scenes'; import { DashboardScene } from '../scene/DashboardScene'; export const PRESERVED_SCENE_STATE_KEY = `grafana.dashboard.preservedUrlFiltersState`; export function restoreDashboardStateFromLocalStorage(dashboard: DashboardScene) { const preservedUrlState = window.sessionStorage.getItem(PRESERVED_SCENE_STATE_KEY); if (preservedUrlState) { const preservedQueryParams = new URLSearchParams(preservedUrlState); const currentQueryParams = locationService.getSearch(); // iterate over preserved query params and append them to current query params if they don't already exist preservedQueryParams.forEach((value, key) => { if (!currentQueryParams.has(key)) { currentQueryParams.append(key, value); } }); for (const key of Array.from(currentQueryParams.keys())) { // preserve non-variable query params, i.e. time range if (!key.startsWith('var-')) { continue; } // remove params for variables that are not present on the target dashboard if (!dashboard.state.$variables?.getByName(key.replace('var-', ''))) { currentQueryParams.delete(key); } } const finalParams = currentQueryParams.toString(); if (finalParams) { locationService.replace({ search: finalParams }); } } } /** * Scenes behavior that will capture currently selected variables and time range and save them to local storage, so that they can be applied when the next dashboard is loaded. */ export function preserveDashboardSceneStateInLocalStorage(scene: DashboardScene) { if (!config.featureToggles.preserveDashboardStateWhenNavigating) { return; } return () => { // Skipping saving state for default home dashboard if (!scene.state.uid) { return; } const urlStates: UrlQueryMap = Object.fromEntries( Object.entries(new UrlSyncManager().getUrlState(scene)).filter( ([key]) => key.startsWith('var-') || key === 'from' || key === 'to' || key === 'timezone' ) ); const nonEmptyUrlStates = Object.fromEntries( Object.entries(urlStates).filter(([key, value]) => !(Array.isArray(value) && value.length === 0)) ); // If there's anything to preserve, save it to local storage if (Object.keys(nonEmptyUrlStates).length > 0) { window.sessionStorage.setItem(PRESERVED_SCENE_STATE_KEY, urlUtil.renderUrl('', nonEmptyUrlStates)); } else { window.sessionStorage.removeItem(PRESERVED_SCENE_STATE_KEY); } }; }