diff --git a/public/app/core/services/bridge_srv.ts b/public/app/core/services/bridge_srv.ts index 38448cea7da..440385d887d 100644 --- a/public/app/core/services/bridge_srv.ts +++ b/public/app/core/services/bridge_srv.ts @@ -1,13 +1,13 @@ import coreModule from 'app/core/core_module'; import appEvents from 'app/core/app_events'; -import { store } from 'app/store/store'; +import { dispatch, store } from 'app/store/store'; import { updateLocation } from 'app/core/actions'; import { ILocationService, ITimeoutService, IWindowService } from 'angular'; import { CoreEvents } from 'app/types'; import { GrafanaRootScope } from 'app/routes/GrafanaCtrl'; import { locationUtil, UrlQueryMap } from '@grafana/data'; import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; -import { VariableSrv } from 'app/features/templating/all'; +import { templateVarsChangedInUrl } from 'app/features/variables/state/actions'; // Services that handles angular -> redux store sync & other react <-> angular sync export class BridgeSrv { @@ -22,8 +22,7 @@ export class BridgeSrv { private $timeout: ITimeoutService, private $window: IWindowService, private $rootScope: GrafanaRootScope, - private $route: any, - private variableSrv: VariableSrv + private $route: any ) { this.fullPageReloadRoutes = ['/logout']; this.angularUrl = $location.url(); @@ -84,7 +83,7 @@ export class BridgeSrv { if (changes) { const dash = getDashboardSrv().getCurrent(); if (dash) { - this.variableSrv.templateVarsChangedInUrl(changes); + dispatch(templateVarsChangedInUrl(changes)); } } this.lastQuery = state.location.query; @@ -125,7 +124,7 @@ export function findTemplateVarChanges(query: UrlQueryMap, old: UrlQueryMap): Ur if (!key.startsWith('var-')) { continue; } - if (!query[key]) { + if (!query.hasOwnProperty(key)) { changes[key] = ''; // removed count++; } diff --git a/public/app/features/variables/state/actions.ts b/public/app/features/variables/state/actions.ts index 89abbf91a01..a706a06f84d 100644 --- a/public/app/features/variables/state/actions.ts +++ b/public/app/features/variables/state/actions.ts @@ -31,6 +31,7 @@ import { alignCurrentWithMulti } from '../shared/multiOptions'; import { isMulti } from '../guard'; import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; import { DashboardModel } from 'app/features/dashboard/state'; +import isEqual from 'lodash/isEqual'; // process flow queryVariable // thunk => processVariables @@ -448,3 +449,28 @@ const getQueryWithVariables = (getState: () => StoreState): UrlQueryMap => { return queryParamsNew; }; + +export const templateVarsChangedInUrl = (vars: UrlQueryMap): ThunkResult => async (dispatch, getState) => { + const update: Array> = []; + for (const variable of getVariables(getState())) { + const key = `var-${variable.name}`; + if (vars.hasOwnProperty(key)) { + if (isVariableUrlValueDifferentFromCurrent(variable, vars[key])) { + const promise = variableAdapters.get(variable.type).setValueFromUrl(variable, vars[key]); + update.push(promise); + } + } + } + + if (update.length) { + await Promise.all(update); + const dashboard = getState().dashboard.getModel(); + dashboard?.templateVariableValueUpdated(); + dashboard?.startRefresh(); + } +}; + +const isVariableUrlValueDifferentFromCurrent = (variable: VariableModel, urlValue: any): boolean => { + // lodash isEqual handles array of value equality checks as well + return !isEqual(variableAdapters.get(variable.type).getValueForUrl(variable), urlValue); +};