grafana/public/app/core/services/bridge_srv.ts
Torkel Ödegaard 5a11abe954
Events: Remove unused or unnecessary events (#28783)
* Events: Removing unused or unnessary events

* More cleanup

* Updated
2020-11-03 15:29:43 +01:00

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);