Files
grafana/public/app/core/services/bridge_srv.ts
Dominik Prokop d2a13c4715 FieldOverride: Support data links via field overrides (#23590)
* Move xss and sanitize packages to grafana-data

* Move text, url and location utils to grafana-data

* Move grafana config types to grafana-data

* Move field display value proxy to grafana-data

* Fix

* Move data links built in vars to grafana-data

* Attach links supplier to when applying field overrides

* Prep tests

* Use links suppliers attached via field overrides

* locationUtil dependencies type

* Move sanitize-url declaration to grafana-data

* Revert "Move sanitize-url declaration to grafana-data"

This reverts commit 11db9f5e55.

* Fix typo

* fix ts vol1

* Remove import from runtime in data.... Make TS happy at the same time ;)

* Lovely TS, please shut up

* Lovely TS, please shut up vol2

* fix tests

* Fixes

* minor refactor

* Attach get links to FieldDisplayValue for seamless usage

* Update packages/grafana-data/src/field/fieldOverrides.ts

* Make storybook build
2020-04-20 07:37:38 +02:00

137 lines
4.1 KiB
TypeScript

import coreModule from 'app/core/core_module';
import appEvents from 'app/core/app_events';
import { 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';
// Services that handles angular -> redux store sync & other react <-> angular sync
export class BridgeSrv {
private fullPageReloadRoutes: string[];
private lastQuery: UrlQueryMap = {};
private lastPath = '';
private angularUrl: string;
/** @ngInject */
constructor(
private $location: ILocationService,
private $timeout: ITimeoutService,
private $window: IWindowService,
private $rootScope: GrafanaRootScope,
private $route: any,
private variableSrv: VariableSrv
) {
this.fullPageReloadRoutes = ['/logout'];
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;
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();
}
});
console.log('store updating angular $location.url', url);
}
// Check for template variable changes on a dashboard
if (state.location.path === this.lastPath) {
const changes = findTemplateVarChanges(state.location.query, this.lastQuery);
if (changes) {
const dash = getDashboardSrv().getCurrent();
if (dash) {
this.variableSrv.templateVarsChangedInUrl(changes);
}
}
this.lastQuery = state.location.query;
} else {
this.lastQuery = {};
}
this.lastPath = state.location.path;
});
appEvents.on(CoreEvents.locationChange, payload => {
const urlWithoutBase = locationUtil.stripBaseFromUrl(payload.href);
if (this.fullPageReloadRoutes.indexOf(urlWithoutBase) > -1) {
this.$window.location.href = payload.href;
return;
}
this.$timeout(() => {
// A hack to use timeout when we're changing things (in this case the url) from outside of Angular.
this.$location.url(urlWithoutBase);
});
});
}
}
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;
}
if (query[key] !== old[key]) {
changes[key] = query[key];
count++;
}
}
for (const key in old) {
if (!key.startsWith('var-')) {
continue;
}
if (!query[key]) {
changes[key] = ''; // removed
count++;
}
}
return count ? changes : undefined;
}
coreModule.service('bridgeSrv', BridgeSrv);