mirror of
https://github.com/grafana/grafana.git
synced 2025-02-20 11:48:34 -06:00
153 lines
4.1 KiB
TypeScript
153 lines
4.1 KiB
TypeScript
import coreModule from 'app/core/core_module';
|
|
import { dispatch, store } from 'app/store/store';
|
|
import { updateLocation } from 'app/core/actions';
|
|
import { ILocationService, ITimeoutService } from 'angular';
|
|
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
|
|
import { UrlQueryMap } from '@grafana/data';
|
|
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
|
import { templateVarsChangedInUrl } from 'app/features/variables/state/actions';
|
|
import { isArray, isEqual } from 'lodash';
|
|
|
|
// Services that handles angular -> redux store sync & other react <-> angular sync
|
|
export class BridgeSrv {
|
|
private lastQuery: UrlQueryMap = {};
|
|
private lastPath = '';
|
|
private angularUrl: string;
|
|
private lastUrl: string | null = null;
|
|
|
|
/** @ngInject */
|
|
constructor(
|
|
private $location: ILocationService,
|
|
private $timeout: ITimeoutService,
|
|
private $rootScope: GrafanaRootScope,
|
|
private $route: any
|
|
) {
|
|
this.angularUrl = $location.url();
|
|
}
|
|
|
|
init() {
|
|
this.$rootScope.$on('$routeUpdate', (evt, data) => {
|
|
const state = store.getState();
|
|
|
|
this.angularUrl = this.$location.url();
|
|
|
|
if (state.location.url !== this.angularUrl) {
|
|
store.dispatch(
|
|
updateLocation({
|
|
path: this.$location.path(),
|
|
query: this.$location.search(),
|
|
routeParams: this.$route.current.params,
|
|
})
|
|
);
|
|
}
|
|
});
|
|
|
|
this.$rootScope.$on('$routeChangeSuccess', (evt, data) => {
|
|
this.angularUrl = this.$location.url();
|
|
|
|
store.dispatch(
|
|
updateLocation({
|
|
path: this.$location.path(),
|
|
query: this.$location.search(),
|
|
routeParams: this.$route.current.params,
|
|
})
|
|
);
|
|
});
|
|
|
|
// Listen for changes in redux location -> update angular location
|
|
store.subscribe(() => {
|
|
const state = store.getState();
|
|
const url = state.location.url;
|
|
|
|
// No url change ignore redux store change
|
|
if (url === this.lastUrl) {
|
|
return;
|
|
}
|
|
|
|
if (this.angularUrl !== url) {
|
|
// store angular url right away as otherwise we end up syncing multiple times
|
|
this.angularUrl = url;
|
|
|
|
this.$timeout(() => {
|
|
this.$location.url(url);
|
|
// some state changes should not trigger new browser history
|
|
if (state.location.replace) {
|
|
this.$location.replace();
|
|
}
|
|
});
|
|
}
|
|
|
|
// if only query params changed, check if variables changed
|
|
if (state.location.path === this.lastPath && state.location.query !== this.lastQuery) {
|
|
// Find template variable changes
|
|
const changes = findTemplateVarChanges(state.location.query, this.lastQuery);
|
|
// Store current query params to avoid recursion
|
|
this.lastQuery = state.location.query;
|
|
|
|
if (changes) {
|
|
const dash = getDashboardSrv().getCurrent();
|
|
if (dash) {
|
|
dispatch(templateVarsChangedInUrl(changes));
|
|
}
|
|
}
|
|
}
|
|
|
|
this.lastPath = state.location.path;
|
|
this.lastQuery = state.location.query;
|
|
this.lastUrl = state.location.url;
|
|
});
|
|
}
|
|
}
|
|
|
|
function getUrlValueForComparison(value: any): any {
|
|
if (isArray(value)) {
|
|
if (value.length === 0) {
|
|
value = undefined;
|
|
} else if (value.length === 1) {
|
|
value = value[0];
|
|
}
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
export function findTemplateVarChanges(query: UrlQueryMap, old: UrlQueryMap): UrlQueryMap | undefined {
|
|
let count = 0;
|
|
const changes: UrlQueryMap = {};
|
|
|
|
for (const key in query) {
|
|
if (!key.startsWith('var-')) {
|
|
continue;
|
|
}
|
|
|
|
let oldValue = getUrlValueForComparison(old[key]);
|
|
let newValue = getUrlValueForComparison(query[key]);
|
|
|
|
if (!isEqual(newValue, oldValue)) {
|
|
changes[key] = query[key];
|
|
count++;
|
|
}
|
|
}
|
|
|
|
for (const key in old) {
|
|
if (!key.startsWith('var-')) {
|
|
continue;
|
|
}
|
|
|
|
const value = old[key];
|
|
|
|
// ignore empty array values
|
|
if (isArray(value) && value.length === 0) {
|
|
continue;
|
|
}
|
|
|
|
if (!query.hasOwnProperty(key)) {
|
|
changes[key] = ''; // removed
|
|
count++;
|
|
}
|
|
}
|
|
return count ? changes : undefined;
|
|
}
|
|
|
|
coreModule.service('bridgeSrv', BridgeSrv);
|