mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
EventBus: Introduces new event bus with emitter backward compatible interface (#27564)
* updated * Experimenting with event bus with legacy support * Before switch to emitter * EventBus & Emitter unification * Everything using new EventBus * Making progress * Fixing merge issues * Final merge issues * Updated * Updates * Fix * Updated * Update * Update * Rename methods to publish and subscribe * Ts fixes * Updated * updated * fixing doc warnigns * removed unused file
This commit is contained in:
parent
d84d8a134f
commit
74c65eca26
@ -25,6 +25,7 @@
|
||||
"@braintree/sanitize-url": "4.0.0",
|
||||
"@types/d3-interpolate": "^1.3.1",
|
||||
"apache-arrow": "0.16.0",
|
||||
"eventemitter3": "4.0.7",
|
||||
"lodash": "4.17.19",
|
||||
"rxjs": "6.6.3",
|
||||
"xss": "1.0.6"
|
||||
|
173
packages/grafana-data/src/events/EventBus.test.ts
Normal file
173
packages/grafana-data/src/events/EventBus.test.ts
Normal file
@ -0,0 +1,173 @@
|
||||
import { EventBusSrv } from './EventBus';
|
||||
import { BusEventWithPayload } from './types';
|
||||
import { eventFactory } from './eventFactory';
|
||||
|
||||
interface LoginEventPayload {
|
||||
logins: number;
|
||||
}
|
||||
|
||||
interface HelloEventPayload {
|
||||
hellos: number;
|
||||
}
|
||||
|
||||
class LoginEvent extends BusEventWithPayload<LoginEventPayload> {
|
||||
static type = 'login-event';
|
||||
}
|
||||
|
||||
class HelloEvent extends BusEventWithPayload<HelloEventPayload> {
|
||||
static type = 'hello-event';
|
||||
}
|
||||
|
||||
type LegacyEventPayload = [string, string];
|
||||
|
||||
export const legacyEvent = eventFactory<LegacyEventPayload>('legacy-event');
|
||||
|
||||
class AlertSuccessEvent extends BusEventWithPayload<LegacyEventPayload> {
|
||||
static type = 'legacy-event';
|
||||
}
|
||||
|
||||
describe('EventBus', () => {
|
||||
it('Can create events', () => {
|
||||
expect(new LoginEvent({ logins: 1 }).type).toBe('login-event');
|
||||
});
|
||||
|
||||
it('Can subscribe specific event', () => {
|
||||
const bus = new EventBusSrv();
|
||||
const events: LoginEvent[] = [];
|
||||
|
||||
bus.subscribe(LoginEvent, event => {
|
||||
events.push(event);
|
||||
});
|
||||
|
||||
bus.publish(new LoginEvent({ logins: 10 }));
|
||||
bus.publish(new HelloEvent({ hellos: 10 }));
|
||||
|
||||
expect(events[0].payload.logins).toBe(10);
|
||||
expect(events.length).toBe(1);
|
||||
});
|
||||
|
||||
describe('Legacy emitter behavior', () => {
|
||||
it('Supports legacy events', () => {
|
||||
const bus = new EventBusSrv();
|
||||
const events: any = [];
|
||||
const handler = (event: LegacyEventPayload) => {
|
||||
events.push(event);
|
||||
};
|
||||
|
||||
bus.on(legacyEvent, handler);
|
||||
bus.emit(legacyEvent, ['hello', 'hello2']);
|
||||
|
||||
bus.off(legacyEvent, handler);
|
||||
bus.emit(legacyEvent, ['hello', 'hello2']);
|
||||
|
||||
expect(events.length).toEqual(1);
|
||||
expect(events[0]).toEqual(['hello', 'hello2']);
|
||||
});
|
||||
|
||||
it('Interoperability with legacy events', () => {
|
||||
const bus = new EventBusSrv();
|
||||
const legacyEvents: any = [];
|
||||
const newEvents: any = [];
|
||||
|
||||
bus.on(legacyEvent, event => {
|
||||
legacyEvents.push(event);
|
||||
});
|
||||
|
||||
bus.subscribe(AlertSuccessEvent, event => {
|
||||
newEvents.push(event);
|
||||
});
|
||||
|
||||
bus.emit(legacyEvent, ['legacy', 'params']);
|
||||
bus.publish(new AlertSuccessEvent(['new', 'event']));
|
||||
|
||||
expect(legacyEvents).toEqual([
|
||||
['legacy', 'params'],
|
||||
['new', 'event'],
|
||||
]);
|
||||
|
||||
expect(newEvents).toEqual([
|
||||
{
|
||||
type: 'legacy-event',
|
||||
payload: ['legacy', 'params'],
|
||||
},
|
||||
{
|
||||
type: 'legacy-event',
|
||||
payload: ['new', 'event'],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should notfiy subscribers', () => {
|
||||
const bus = new EventBusSrv();
|
||||
let sub1Called = false;
|
||||
let sub2Called = false;
|
||||
|
||||
bus.on(legacyEvent, () => {
|
||||
sub1Called = true;
|
||||
});
|
||||
bus.on(legacyEvent, () => {
|
||||
sub2Called = true;
|
||||
});
|
||||
|
||||
bus.emit(legacyEvent, null);
|
||||
|
||||
expect(sub1Called).toBe(true);
|
||||
expect(sub2Called).toBe(true);
|
||||
});
|
||||
|
||||
it('when subscribing twice', () => {
|
||||
const bus = new EventBusSrv();
|
||||
let sub1Called = 0;
|
||||
|
||||
function handler() {
|
||||
sub1Called += 1;
|
||||
}
|
||||
|
||||
bus.on(legacyEvent, handler);
|
||||
bus.on(legacyEvent, handler);
|
||||
|
||||
bus.emit(legacyEvent, null);
|
||||
|
||||
expect(sub1Called).toBe(2);
|
||||
});
|
||||
|
||||
it('should handle errors', () => {
|
||||
const bus = new EventBusSrv();
|
||||
let sub1Called = 0;
|
||||
let sub2Called = 0;
|
||||
|
||||
bus.on(legacyEvent, () => {
|
||||
sub1Called++;
|
||||
throw { message: 'hello' };
|
||||
});
|
||||
|
||||
bus.on(legacyEvent, () => {
|
||||
sub2Called++;
|
||||
});
|
||||
|
||||
try {
|
||||
bus.emit(legacyEvent, null);
|
||||
} catch (_) {}
|
||||
try {
|
||||
bus.emit(legacyEvent, null);
|
||||
} catch (_) {}
|
||||
|
||||
expect(sub1Called).toBe(2);
|
||||
expect(sub2Called).toBe(0);
|
||||
});
|
||||
|
||||
it('removeAllListeners should unsubscribe to all', () => {
|
||||
const bus = new EventBusSrv();
|
||||
const events: LoginEvent[] = [];
|
||||
|
||||
bus.subscribe(LoginEvent, event => {
|
||||
events.push(event);
|
||||
});
|
||||
|
||||
bus.removeAllListeners();
|
||||
bus.publish(new LoginEvent({ logins: 10 }));
|
||||
|
||||
expect(events.length).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
85
packages/grafana-data/src/events/EventBus.ts
Normal file
85
packages/grafana-data/src/events/EventBus.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import EventEmitter from 'eventemitter3';
|
||||
import { Unsubscribable, Observable } from 'rxjs';
|
||||
import { AppEvent } from './types';
|
||||
import { EventBus, LegacyEmitter, BusEventHandler, BusEventType, LegacyEventHandler, BusEvent } from './types';
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
*/
|
||||
export class EventBusSrv implements EventBus, LegacyEmitter {
|
||||
private emitter: EventEmitter;
|
||||
|
||||
constructor() {
|
||||
this.emitter = new EventEmitter();
|
||||
}
|
||||
|
||||
publish<T extends BusEvent>(event: T): void {
|
||||
this.emitter.emit(event.type, event);
|
||||
}
|
||||
|
||||
subscribe<T extends BusEvent>(typeFilter: BusEventType<T>, handler: BusEventHandler<T>): Unsubscribable {
|
||||
return this.getStream(typeFilter).subscribe({ next: handler });
|
||||
}
|
||||
|
||||
getStream<T extends BusEvent>(eventType: BusEventType<T>): Observable<T> {
|
||||
return new Observable<T>(observer => {
|
||||
const handler = (event: T) => {
|
||||
observer.next(event);
|
||||
};
|
||||
|
||||
this.emitter.on(eventType.type, handler);
|
||||
|
||||
return () => {
|
||||
this.emitter.off(eventType.type, handler);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy functions
|
||||
*/
|
||||
emit<T>(event: AppEvent<T> | string, payload?: T | any): void {
|
||||
// console.log(`Deprecated emitter function used (emit), use $emit`);
|
||||
|
||||
if (typeof event === 'string') {
|
||||
this.emitter.emit(event, { type: event, payload });
|
||||
} else {
|
||||
this.emitter.emit(event.name, { type: event.name, payload });
|
||||
}
|
||||
}
|
||||
|
||||
on<T>(event: AppEvent<T> | string, handler: LegacyEventHandler<T>, scope?: any) {
|
||||
// console.log(`Deprecated emitter function used (on), use $on`);
|
||||
|
||||
// need this wrapper to make old events compatible with old handlers
|
||||
handler.wrapper = (emittedEvent: BusEvent) => {
|
||||
handler(emittedEvent.payload);
|
||||
};
|
||||
|
||||
if (typeof event === 'string') {
|
||||
this.emitter.on(event, handler.wrapper);
|
||||
} else {
|
||||
this.emitter.on(event.name, handler.wrapper);
|
||||
}
|
||||
|
||||
if (scope) {
|
||||
const unbind = scope.$on('$destroy', () => {
|
||||
this.off(event, handler);
|
||||
unbind();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
off<T>(event: AppEvent<T> | string, handler: LegacyEventHandler<T>) {
|
||||
if (typeof event === 'string') {
|
||||
this.emitter.off(event, handler.wrapper);
|
||||
return;
|
||||
}
|
||||
|
||||
this.emitter.off(event.name, handler.wrapper);
|
||||
}
|
||||
|
||||
removeAllListeners() {
|
||||
this.emitter.removeAllListeners();
|
||||
}
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
import { AppEvent } from './appEvents';
|
||||
|
||||
export type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
|
||||
export type Subtract<T, K> = Omit<T, keyof K>;
|
||||
import { AppEvent } from './types';
|
||||
|
||||
const typeList: Set<string> = new Set();
|
||||
|
||||
export function eventFactory<T = undefined>(name: string): AppEvent<T> {
|
||||
if (typeList.has(name)) {
|
||||
throw new Error(`There is already an event defined with type '${name}'`);
|
3
packages/grafana-data/src/events/index.ts
Normal file
3
packages/grafana-data/src/events/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './eventFactory';
|
||||
export * from './types';
|
||||
export * from './EventBus';
|
115
packages/grafana-data/src/events/types.ts
Normal file
115
packages/grafana-data/src/events/types.ts
Normal file
@ -0,0 +1,115 @@
|
||||
import { Unsubscribable, Observable } from 'rxjs';
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
* internal interface
|
||||
*/
|
||||
export interface BusEvent {
|
||||
readonly type: string;
|
||||
readonly payload?: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
* Base event type
|
||||
*/
|
||||
export abstract class BusEventBase implements BusEvent {
|
||||
readonly type: string;
|
||||
readonly payload?: any;
|
||||
|
||||
constructor() {
|
||||
//@ts-ignore
|
||||
this.type = this.__proto__.constructor.type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
* Base event type with payload
|
||||
*/
|
||||
export abstract class BusEventWithPayload<T> extends BusEventBase {
|
||||
readonly payload: T;
|
||||
|
||||
constructor(payload: T) {
|
||||
super();
|
||||
this.payload = payload;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Interface for an event type constructor
|
||||
*/
|
||||
export interface BusEventType<T extends BusEvent> {
|
||||
type: string;
|
||||
new (...args: any[]): T;
|
||||
}
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
* Event callback/handler type
|
||||
*/
|
||||
export interface BusEventHandler<T extends BusEvent> {
|
||||
(event: T): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
* Main minimal interface
|
||||
*/
|
||||
export interface EventBus {
|
||||
/**
|
||||
* Publish single vent
|
||||
*/
|
||||
publish<T extends BusEvent>(event: T): void;
|
||||
|
||||
/**
|
||||
* Subscribe to single event
|
||||
*/
|
||||
subscribe<T extends BusEvent>(eventType: BusEventType<T>, handler: BusEventHandler<T>): Unsubscribable;
|
||||
|
||||
/**
|
||||
* Get observable of events
|
||||
*/
|
||||
getStream<T extends BusEvent>(eventType: BusEventType<T>): Observable<T>;
|
||||
|
||||
/**
|
||||
* Remove all event subscriptions
|
||||
*/
|
||||
removeAllListeners(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated event type
|
||||
*/
|
||||
export interface AppEvent<T> {
|
||||
readonly name: string;
|
||||
payload?: T;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface LegacyEmitter {
|
||||
/**
|
||||
* @deprecated use $emit
|
||||
*/
|
||||
emit<T>(event: AppEvent<T> | string, payload?: T): void;
|
||||
|
||||
/**
|
||||
* @deprecated use $on
|
||||
*/
|
||||
on<T>(event: AppEvent<T> | string, handler: LegacyEventHandler<T>, scope?: any): void;
|
||||
|
||||
/**
|
||||
* @deprecated use $on
|
||||
*/
|
||||
off<T>(event: AppEvent<T> | string, handler: (payload?: T | any) => void): void;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface LegacyEventHandler<T> {
|
||||
(payload: T): void;
|
||||
wrapper?: (event: BusEvent) => void;
|
||||
}
|
||||
|
||||
/** @alpha */
|
||||
export interface EventBusExtended extends EventBus, LegacyEmitter {}
|
@ -12,4 +12,5 @@ export * from './datetime';
|
||||
export * from './text';
|
||||
export * from './valueFormats';
|
||||
export * from './field';
|
||||
export * from './events';
|
||||
export { PanelPlugin } from './panel/PanelPlugin';
|
||||
|
@ -1,13 +0,0 @@
|
||||
import { eventFactory } from './utils';
|
||||
|
||||
export interface AppEvent<T> {
|
||||
readonly name: string;
|
||||
payload?: T;
|
||||
}
|
||||
|
||||
export type AlertPayload = [string, string?];
|
||||
export type AlertErrorPayload = [string, (string | Error)?];
|
||||
|
||||
export const alertSuccess = eventFactory<AlertPayload>('alert-success');
|
||||
export const alertWarning = eventFactory<AlertPayload>('alert-warning');
|
||||
export const alertError = eventFactory<AlertErrorPayload>('alert-error');
|
@ -7,7 +7,6 @@ export * from './navModel';
|
||||
export * from './select';
|
||||
export * from './time';
|
||||
export * from './thresholds';
|
||||
export * from './utils';
|
||||
export * from './valueMapping';
|
||||
export * from './displayValue';
|
||||
export * from './graph';
|
||||
@ -27,12 +26,7 @@ export * from './orgs';
|
||||
export * from './flot';
|
||||
export * from './trace';
|
||||
export * from './explore';
|
||||
export * from './legacyEvents';
|
||||
export * from './live';
|
||||
|
||||
import * as AppEvents from './appEvents';
|
||||
import { AppEvent } from './appEvents';
|
||||
export { AppEvent, AppEvents };
|
||||
|
||||
import * as PanelEvents from './panelEvents';
|
||||
export { PanelEvents };
|
||||
export { GrafanaConfig, BuildInfo, FeatureToggles, LicenseInfo } from './config';
|
||||
|
47
packages/grafana-data/src/types/legacyEvents.ts
Normal file
47
packages/grafana-data/src/types/legacyEvents.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import { DataQueryError, DataQueryResponseData } from './datasource';
|
||||
import { AngularPanelMenuItem } from './panel';
|
||||
import { DataFrame } from './dataFrame';
|
||||
import { eventFactory } from '../events/eventFactory';
|
||||
import { BusEventBase, BusEventWithPayload } from '../events/types';
|
||||
|
||||
export type AlertPayload = [string, string?];
|
||||
export type AlertErrorPayload = [string, (string | Error)?];
|
||||
|
||||
export const AppEvents = {
|
||||
alertSuccess: eventFactory<AlertPayload>('alert-success'),
|
||||
alertWarning: eventFactory<AlertPayload>('alert-warning'),
|
||||
alertError: eventFactory<AlertErrorPayload>('alert-error'),
|
||||
};
|
||||
|
||||
export const PanelEvents = {
|
||||
refresh: eventFactory('refresh'),
|
||||
componentDidMount: eventFactory('component-did-mount'),
|
||||
dataReceived: eventFactory<DataQueryResponseData[]>('data-received'),
|
||||
dataError: eventFactory<DataQueryError>('data-error'),
|
||||
dataFramesReceived: eventFactory<DataFrame[]>('data-frames-received'),
|
||||
dataSnapshotLoad: eventFactory<DataQueryResponseData[]>('data-snapshot-load'),
|
||||
editModeInitialized: eventFactory('init-edit-mode'),
|
||||
initPanelActions: eventFactory<AngularPanelMenuItem[]>('init-panel-actions'),
|
||||
panelInitialized: eventFactory('panel-initialized'),
|
||||
panelSizeChanged: eventFactory('panel-size-changed'),
|
||||
panelTeardown: eventFactory('panel-teardown'),
|
||||
render: eventFactory<any>('render'),
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export interface LegacyGraphHoverEventPayload {
|
||||
pos: any;
|
||||
panel: {
|
||||
id: number;
|
||||
};
|
||||
}
|
||||
|
||||
/** @alpha */
|
||||
export class LegacyGraphHoverEvent extends BusEventWithPayload<LegacyGraphHoverEventPayload> {
|
||||
static type = 'graph-hover';
|
||||
}
|
||||
|
||||
/** @alpha */
|
||||
export class LegacyGraphHoverClearEvent extends BusEventBase {
|
||||
static type = 'graph-hover-clear';
|
||||
}
|
@ -4,6 +4,7 @@ import { ScopedVars } from './ScopedVars';
|
||||
import { LoadingState } from './data';
|
||||
import { DataFrame } from './dataFrame';
|
||||
import { AbsoluteTimeRange, TimeRange, TimeZone } from './time';
|
||||
import { EventBus } from '../events';
|
||||
import { FieldConfigSource } from './fieldOverrides';
|
||||
import { Registry } from '../utils';
|
||||
import { StandardEditorProps } from '../field';
|
||||
@ -77,6 +78,9 @@ export interface PanelProps<T = any> {
|
||||
/** Panel title */
|
||||
title: string;
|
||||
|
||||
/** EventBus */
|
||||
eventBus: EventBus;
|
||||
|
||||
/** Panel options change handler */
|
||||
onOptionsChange: (options: T) => void;
|
||||
|
||||
|
@ -1,28 +0,0 @@
|
||||
import { eventFactory } from './utils';
|
||||
import { DataQueryError, DataQueryResponseData } from './datasource';
|
||||
import { AngularPanelMenuItem } from './panel';
|
||||
import { DataFrame } from './dataFrame';
|
||||
|
||||
/** Payloads */
|
||||
export interface PanelChangeViewPayload {
|
||||
fullscreen?: boolean;
|
||||
edit?: boolean;
|
||||
panelId?: number;
|
||||
toggle?: boolean;
|
||||
}
|
||||
|
||||
/** Events */
|
||||
export const refresh = eventFactory('refresh');
|
||||
export const componentDidMount = eventFactory('component-did-mount');
|
||||
export const dataError = eventFactory<DataQueryError>('data-error');
|
||||
export const dataReceived = eventFactory<DataQueryResponseData[]>('data-received');
|
||||
export const dataFramesReceived = eventFactory<DataFrame[]>('data-frames-received');
|
||||
export const dataSnapshotLoad = eventFactory<DataQueryResponseData[]>('data-snapshot-load');
|
||||
export const editModeInitialized = eventFactory('init-edit-mode');
|
||||
export const initPanelActions = eventFactory<AngularPanelMenuItem[]>('init-panel-actions');
|
||||
export const panelChangeView = eventFactory<PanelChangeViewPayload>('panel-change-view');
|
||||
export const panelInitialized = eventFactory('panel-initialized');
|
||||
export const panelSizeChanged = eventFactory('panel-size-changed');
|
||||
export const panelTeardown = eventFactory('panel-teardown');
|
||||
export const render = eventFactory<any>('render');
|
||||
export const viewModeChanged = eventFactory('view-mode-changed');
|
@ -1,5 +1,5 @@
|
||||
import { Emitter } from './utils/emitter';
|
||||
import { EventBusSrv, EventBusExtended } from '@grafana/data';
|
||||
|
||||
export const appEvents = new Emitter();
|
||||
export const appEvents: EventBusExtended = new EventBusSrv();
|
||||
|
||||
export default appEvents;
|
||||
|
@ -19,7 +19,6 @@ import { colors, JsonExplorer } from '@grafana/ui/';
|
||||
|
||||
import { infoPopover } from './components/info_popover';
|
||||
import { arrayJoin } from './directives/array_join';
|
||||
import { Emitter } from './utils/emitter';
|
||||
import { switchDirective } from './components/switch';
|
||||
import { dashboardSelector } from './components/dashboard_selector';
|
||||
import { queryPartEditorDirective } from './components/query_part/query_part_editor';
|
||||
@ -47,7 +46,6 @@ export {
|
||||
coreModule,
|
||||
switchDirective,
|
||||
infoPopover,
|
||||
Emitter,
|
||||
appEvents,
|
||||
dashboardSelector,
|
||||
queryPartEditorDirective,
|
||||
|
@ -11,7 +11,6 @@ import { DashboardSearchHit } from 'app/features/search/types';
|
||||
import { FolderDTO } from 'app/types';
|
||||
import { coreModule } from 'app/core/core_module';
|
||||
import { ContextSrv, contextSrv } from './context_srv';
|
||||
import { Emitter } from '../utils/emitter';
|
||||
import { parseInitFromOptions, parseUrlFromOptions } from '../utils/fetch';
|
||||
import { isDataQuery, isLocalUrl } from '../utils/query';
|
||||
import { FetchQueue } from './FetchQueue';
|
||||
@ -22,7 +21,7 @@ const CANCEL_ALL_REQUESTS_REQUEST_ID = 'cancel_all_requests_request_id';
|
||||
|
||||
export interface BackendSrvDependencies {
|
||||
fromFetch: (input: string | Request, init?: RequestInit) => Observable<Response>;
|
||||
appEvents: Emitter;
|
||||
appEvents: typeof appEvents;
|
||||
contextSrv: ContextSrv;
|
||||
logout: () => void;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import _ from 'lodash';
|
||||
import Mousetrap from 'mousetrap';
|
||||
import 'mousetrap-global-bind';
|
||||
import { ILocationService, IRootScopeService, ITimeoutService } from 'angular';
|
||||
import { locationUtil } from '@grafana/data';
|
||||
import { LegacyGraphHoverClearEvent, locationUtil } from '@grafana/data';
|
||||
|
||||
import coreModule from 'app/core/core_module';
|
||||
import appEvents from 'app/core/app_events';
|
||||
@ -197,7 +197,7 @@ export class KeybindingSrv {
|
||||
setupDashboardBindings(scope: IRootScopeService & AppEventEmitter, dashboard: DashboardModel) {
|
||||
this.bind('mod+o', () => {
|
||||
dashboard.graphTooltip = (dashboard.graphTooltip + 1) % 3;
|
||||
appEvents.emit(CoreEvents.graphHoverClear);
|
||||
dashboard.events.publish(new LegacyGraphHoverClearEvent());
|
||||
dashboard.startRefresh();
|
||||
});
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
import 'whatwg-fetch'; // fetch polyfill needed for PhantomJs rendering
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { delay } from 'rxjs/operators';
|
||||
import { AppEvents, DataQueryErrorType } from '@grafana/data';
|
||||
import { AppEvents, DataQueryErrorType, EventBusExtended } from '@grafana/data';
|
||||
|
||||
import { BackendSrv } from '../services/backend_srv';
|
||||
import { Emitter } from '../utils/emitter';
|
||||
import { ContextSrv, User } from '../services/context_srv';
|
||||
import { describe, expect } from '../../../test/lib/common';
|
||||
import { BackendSrvRequest, FetchError } from '@grafana/runtime';
|
||||
@ -35,9 +34,11 @@ const getTestContext = (overides?: object) => {
|
||||
};
|
||||
return of(mockedResponse);
|
||||
});
|
||||
const appEventsMock: Emitter = ({
|
||||
|
||||
const appEventsMock: EventBusExtended = ({
|
||||
emit: jest.fn(),
|
||||
} as any) as Emitter;
|
||||
} as any) as EventBusExtended;
|
||||
|
||||
const user: User = ({
|
||||
isSignedIn: props.isSignedIn,
|
||||
orgId: props.orgId,
|
||||
|
@ -1,67 +0,0 @@
|
||||
import { Emitter } from '../utils/emitter';
|
||||
import { eventFactory } from '@grafana/data';
|
||||
|
||||
const testEvent = eventFactory('test');
|
||||
|
||||
describe('Emitter', () => {
|
||||
describe('given 2 subscribers', () => {
|
||||
it('should notfiy subscribers', () => {
|
||||
const events = new Emitter();
|
||||
let sub1Called = false;
|
||||
let sub2Called = false;
|
||||
|
||||
events.on(testEvent, () => {
|
||||
sub1Called = true;
|
||||
});
|
||||
events.on(testEvent, () => {
|
||||
sub2Called = true;
|
||||
});
|
||||
|
||||
events.emit(testEvent, null);
|
||||
|
||||
expect(sub1Called).toBe(true);
|
||||
expect(sub2Called).toBe(true);
|
||||
});
|
||||
|
||||
it('when subscribing twice', () => {
|
||||
const events = new Emitter();
|
||||
let sub1Called = 0;
|
||||
|
||||
function handler() {
|
||||
sub1Called += 1;
|
||||
}
|
||||
|
||||
events.on(testEvent, handler);
|
||||
events.on(testEvent, handler);
|
||||
|
||||
events.emit(testEvent, null);
|
||||
|
||||
expect(sub1Called).toBe(2);
|
||||
});
|
||||
|
||||
it('should handle errors', () => {
|
||||
const events = new Emitter();
|
||||
let sub1Called = 0;
|
||||
let sub2Called = 0;
|
||||
|
||||
events.on(testEvent, () => {
|
||||
sub1Called++;
|
||||
throw { message: 'hello' };
|
||||
});
|
||||
|
||||
events.on(testEvent, () => {
|
||||
sub2Called++;
|
||||
});
|
||||
|
||||
try {
|
||||
events.emit(testEvent, null);
|
||||
} catch (_) {}
|
||||
try {
|
||||
events.emit(testEvent, null);
|
||||
} catch (_) {}
|
||||
|
||||
expect(sub1Called).toBe(2);
|
||||
expect(sub2Called).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,101 +0,0 @@
|
||||
import EventEmitter3, { EventEmitter } from 'eventemitter3';
|
||||
import { AppEvent } from '@grafana/data';
|
||||
|
||||
export class Emitter {
|
||||
private emitter: EventEmitter3;
|
||||
|
||||
constructor() {
|
||||
this.emitter = new EventEmitter();
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED.
|
||||
*/
|
||||
emit(name: string, data?: any): void;
|
||||
|
||||
/**
|
||||
* Emits an `event` with `payload`.
|
||||
*/
|
||||
emit<T extends undefined>(event: AppEvent<T>): void;
|
||||
emit<T extends (U extends any ? Partial<T> : unknown) extends T ? Partial<T> : never, U = any>(
|
||||
event: AppEvent<T>
|
||||
): void;
|
||||
emit<T>(event: AppEvent<T>, payload: T): void;
|
||||
emit<T>(event: AppEvent<T> | string, payload?: T | any): void {
|
||||
if (typeof event === 'string') {
|
||||
console.warn(`Using strings as events is deprecated and will be removed in a future version. (${event})`);
|
||||
this.emitter.emit(event, payload);
|
||||
} else {
|
||||
this.emitter.emit(event.name, payload);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED.
|
||||
*/
|
||||
on(name: string, handler: (payload?: any) => void, scope?: any): void;
|
||||
|
||||
/**
|
||||
* Handles `event` with `handler()` when emitted.
|
||||
*/
|
||||
on<T extends undefined>(event: AppEvent<T>, handler: () => void, scope?: any): void;
|
||||
on<T extends (U extends any ? Partial<T> : unknown) extends T ? Partial<T> : never, U = any>(
|
||||
event: AppEvent<T>,
|
||||
handler: () => void,
|
||||
scope?: any
|
||||
): void;
|
||||
on<T>(event: AppEvent<T>, handler: (payload: T) => void, scope?: any): void;
|
||||
on<T>(event: AppEvent<T> | string, handler: (payload?: T | any) => void, scope?: any) {
|
||||
if (typeof event === 'string') {
|
||||
console.warn(`Using strings as events is deprecated and will be removed in a future version. (${event})`);
|
||||
this.emitter.on(event, handler);
|
||||
|
||||
if (scope) {
|
||||
const unbind = scope.$on('$destroy', () => {
|
||||
this.emitter.off(event, handler);
|
||||
unbind();
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.emitter.on(event.name, handler);
|
||||
|
||||
if (scope) {
|
||||
const unbind = scope.$on('$destroy', () => {
|
||||
this.emitter.off(event.name, handler);
|
||||
unbind();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED.
|
||||
*/
|
||||
off(name: string, handler: (payload?: any) => void): void;
|
||||
|
||||
off<T extends undefined>(event: AppEvent<T>, handler: () => void): void;
|
||||
off<T extends (U extends any ? Partial<T> : unknown) extends T ? Partial<T> : never, U = any>(
|
||||
event: AppEvent<T>,
|
||||
handler: () => void,
|
||||
scope?: any
|
||||
): void;
|
||||
off<T>(event: AppEvent<T>, handler: (payload: T) => void): void;
|
||||
off<T>(event: AppEvent<T> | string, handler: (payload?: T | any) => void) {
|
||||
if (typeof event === 'string') {
|
||||
console.warn(`Using strings as events is deprecated and will be removed in a future version. (${event})`);
|
||||
this.emitter.off(event, handler);
|
||||
return;
|
||||
}
|
||||
|
||||
this.emitter.off(event.name, handler);
|
||||
}
|
||||
|
||||
removeAllListeners(evt?: string) {
|
||||
this.emitter.removeAllListeners(evt);
|
||||
}
|
||||
|
||||
getEventCount(): number {
|
||||
return (this.emitter as any)._eventsCount;
|
||||
}
|
||||
}
|
@ -39,8 +39,8 @@ export class SettingsCtrl {
|
||||
|
||||
this.$scope.$on('$destroy', () => {
|
||||
this.dashboard.updateSubmenuVisibility();
|
||||
|
||||
setTimeout(() => {
|
||||
this.$rootScope.appEvent(CoreEvents.dashScroll, { restore: true });
|
||||
this.dashboard.startRefresh();
|
||||
});
|
||||
});
|
||||
@ -53,7 +53,6 @@ export class SettingsCtrl {
|
||||
this.onRouteUpdated();
|
||||
|
||||
this.$rootScope.onAppEvent(CoreEvents.routeUpdated, this.onRouteUpdated.bind(this), $scope);
|
||||
this.$rootScope.appEvent(CoreEvents.dashScroll, { animate: false, pos: 0 });
|
||||
|
||||
appEvents.on(CoreEvents.dashboardSaved, this.onPostSave.bind(this), $scope);
|
||||
|
||||
|
@ -57,9 +57,7 @@ export class HistoryListCtrl {
|
||||
}
|
||||
}
|
||||
|
||||
dismiss() {
|
||||
this.$rootScope.appEvent(CoreEvents.hideDashEditor);
|
||||
}
|
||||
dismiss() {}
|
||||
|
||||
addToLog() {
|
||||
this.start = this.start + this.limit;
|
||||
|
@ -24,7 +24,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
||||
"autoUpdate": undefined,
|
||||
"description": undefined,
|
||||
"editable": true,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -53,7 +53,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -138,7 +138,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
||||
"autoUpdate": undefined,
|
||||
"description": undefined,
|
||||
"editable": true,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -167,7 +167,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -233,7 +233,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
||||
"autoUpdate": undefined,
|
||||
"description": undefined,
|
||||
"editable": true,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -262,7 +262,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -384,7 +384,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
||||
"autoUpdate": undefined,
|
||||
"description": undefined,
|
||||
"editable": true,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -413,7 +413,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -498,7 +498,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
||||
"autoUpdate": undefined,
|
||||
"description": undefined,
|
||||
"editable": true,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -527,7 +527,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -593,7 +593,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
||||
"autoUpdate": undefined,
|
||||
"description": undefined,
|
||||
"editable": true,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -622,7 +622,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -693,7 +693,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
||||
"autoUpdate": undefined,
|
||||
"description": undefined,
|
||||
"editable": true,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -722,7 +722,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
|
@ -52,8 +52,9 @@ export interface State {
|
||||
}
|
||||
|
||||
export class PanelChrome extends PureComponent<Props, State> {
|
||||
timeSrv: TimeSrv = getTimeSrv();
|
||||
querySubscription: Unsubscribable;
|
||||
readonly timeSrv: TimeSrv = getTimeSrv();
|
||||
|
||||
querySubscription?: Unsubscribable;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
@ -73,6 +74,7 @@ export class PanelChrome extends PureComponent<Props, State> {
|
||||
componentDidMount() {
|
||||
const { panel, dashboard } = this.props;
|
||||
|
||||
// Subscribe to panel events
|
||||
panel.events.on(PanelEvents.refresh, this.onRefresh);
|
||||
panel.events.on(PanelEvents.render, this.onRender);
|
||||
|
||||
@ -244,7 +246,7 @@ export class PanelChrome extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
renderPanel(width: number, height: number) {
|
||||
const { panel, plugin } = this.props;
|
||||
const { panel, plugin, dashboard } = this.props;
|
||||
const { renderCounter, data, isFirstLoad } = this.state;
|
||||
const { theme } = config;
|
||||
const { state: loadingState } = data;
|
||||
@ -291,6 +293,7 @@ export class PanelChrome extends PureComponent<Props, State> {
|
||||
onOptionsChange={this.onOptionsChange}
|
||||
onFieldConfigChange={this.onFieldConfigChange}
|
||||
onChangeTimeRange={this.onChangeTimeRange}
|
||||
eventBus={dashboard.events}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
|
@ -68,7 +68,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
"autoUpdate": undefined,
|
||||
"description": undefined,
|
||||
"editable": true,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {
|
||||
"panel-added": EE {
|
||||
@ -123,7 +123,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -151,7 +151,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -179,7 +179,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -207,7 +207,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -258,7 +258,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -310,7 +310,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
"autoUpdate": undefined,
|
||||
"description": undefined,
|
||||
"editable": true,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {
|
||||
"panel-added": EE {
|
||||
@ -365,7 +365,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -393,7 +393,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -421,7 +421,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -449,7 +449,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -500,7 +500,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -552,7 +552,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
"autoUpdate": undefined,
|
||||
"description": undefined,
|
||||
"editable": true,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {
|
||||
"panel-added": EE {
|
||||
@ -607,7 +607,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -635,7 +635,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -663,7 +663,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -691,7 +691,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -742,7 +742,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -794,7 +794,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
"autoUpdate": undefined,
|
||||
"description": undefined,
|
||||
"editable": true,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {
|
||||
"panel-added": EE {
|
||||
@ -849,7 +849,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -877,7 +877,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -905,7 +905,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -933,7 +933,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
@ -984,7 +984,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
||||
PanelModel {
|
||||
"cachedPluginOptions": Object {},
|
||||
"datasource": null,
|
||||
"events": Emitter {
|
||||
"events": EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
|
@ -5,7 +5,6 @@ import _ from 'lodash';
|
||||
// Utils & Services
|
||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||
import { AngularComponent, getAngularLoader } from '@grafana/runtime';
|
||||
import { Emitter } from 'app/core/utils/emitter';
|
||||
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
// Types
|
||||
import { PanelModel } from '../state/PanelModel';
|
||||
@ -19,6 +18,7 @@ import {
|
||||
PanelEvents,
|
||||
TimeRange,
|
||||
toLegacyResponseData,
|
||||
EventBusExtended,
|
||||
} from '@grafana/data';
|
||||
import { QueryEditorRowTitle } from './QueryEditorRowTitle';
|
||||
import { QueryOperationRow } from 'app/core/components/QueryOperationRow/QueryOperationRow';
|
||||
@ -331,7 +331,7 @@ export interface AngularQueryComponentScope {
|
||||
target: DataQuery;
|
||||
panel: PanelModel;
|
||||
dashboard: DashboardModel;
|
||||
events: Emitter;
|
||||
events: EventBusExtended;
|
||||
refresh: () => void;
|
||||
render: () => void;
|
||||
datasource: DataSourceApi | null;
|
||||
|
@ -4,7 +4,6 @@ import _ from 'lodash';
|
||||
import { DEFAULT_ANNOTATION_COLOR } from '@grafana/ui';
|
||||
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT, REPEAT_DIR_VERTICAL } from 'app/core/constants';
|
||||
// Utils & Services
|
||||
import { Emitter } from 'app/core/utils/emitter';
|
||||
import { contextSrv } from 'app/core/services/context_srv';
|
||||
import sortByKeys from 'app/core/utils/sort_by_keys';
|
||||
// Types
|
||||
@ -19,6 +18,8 @@ import {
|
||||
TimeRange,
|
||||
TimeZone,
|
||||
UrlQueryValue,
|
||||
EventBusSrv,
|
||||
EventBusExtended,
|
||||
} from '@grafana/data';
|
||||
import { CoreEvents, DashboardMeta, KIOSK_MODE_TV } from 'app/types';
|
||||
import { GetVariables, getVariables } from 'app/features/variables/state/selectors';
|
||||
@ -82,7 +83,7 @@ export class DashboardModel {
|
||||
// repeat process cycles
|
||||
iteration?: number;
|
||||
meta: DashboardMeta;
|
||||
events: Emitter;
|
||||
events: EventBusExtended;
|
||||
|
||||
static nonPersistedProperties: { [str: string]: boolean } = {
|
||||
events: true,
|
||||
@ -101,7 +102,7 @@ export class DashboardModel {
|
||||
data = {};
|
||||
}
|
||||
|
||||
this.events = new Emitter();
|
||||
this.events = new EventBusSrv();
|
||||
this.id = data.id || null;
|
||||
this.uid = data.uid || null;
|
||||
this.revision = data.revision;
|
||||
|
@ -2,7 +2,6 @@
|
||||
import _ from 'lodash';
|
||||
// Utils
|
||||
import { getTemplateSrv } from '@grafana/runtime';
|
||||
import { Emitter } from 'app/core/utils/emitter';
|
||||
import { getNextRefIdChar } from 'app/core/utils/query';
|
||||
// Types
|
||||
import {
|
||||
@ -19,6 +18,8 @@ import {
|
||||
ScopedVars,
|
||||
ThresholdsConfig,
|
||||
ThresholdsMode,
|
||||
EventBusExtended,
|
||||
EventBusSrv,
|
||||
} from '@grafana/data';
|
||||
import { EDIT_PANEL_ID } from 'app/core/constants';
|
||||
import config from 'app/core/config';
|
||||
@ -145,7 +146,7 @@ export class PanelModel implements DataConfigSource {
|
||||
isInView: boolean;
|
||||
|
||||
hasRefreshed: boolean;
|
||||
events: Emitter;
|
||||
events: EventBusExtended;
|
||||
cacheTimeout?: any;
|
||||
cachedPluginOptions?: any;
|
||||
legend?: { show: boolean; sort?: string; sortDesc?: boolean };
|
||||
@ -154,7 +155,7 @@ export class PanelModel implements DataConfigSource {
|
||||
private queryRunner?: PanelQueryRunner;
|
||||
|
||||
constructor(model: any) {
|
||||
this.events = new Emitter();
|
||||
this.events = new EventBusSrv();
|
||||
this.restoreModel(model);
|
||||
this.replaceVariables = this.replaceVariables.bind(this);
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ export class PanelQueryRunner {
|
||||
}
|
||||
|
||||
this.subscription = observable.subscribe({
|
||||
next: (data: PanelData) => {
|
||||
next: data => {
|
||||
this.lastResult = preProcessPanelData(data, this.lastResult);
|
||||
// Store preprocessed query results for applying overrides later on in the pipeline
|
||||
this.subject.next(this.lastResult);
|
||||
|
@ -20,6 +20,8 @@ import {
|
||||
TimeZone,
|
||||
ExploreUrlState,
|
||||
LogsModel,
|
||||
EventBusExtended,
|
||||
EventBusSrv,
|
||||
} from '@grafana/data';
|
||||
|
||||
import store from 'app/core/store';
|
||||
@ -50,7 +52,6 @@ import {
|
||||
getTimeRangeFromUrl,
|
||||
lastUsedDatasourceKeyForOrgId,
|
||||
} from 'app/core/utils/explore';
|
||||
import { Emitter } from 'app/core/utils/emitter';
|
||||
import { ExploreToolbar } from './ExploreToolbar';
|
||||
import { NoDataSourceCallToAction } from './NoDataSourceCallToAction';
|
||||
import { getTimeZone } from '../profile/state/selectors';
|
||||
@ -159,11 +160,11 @@ interface ExploreState {
|
||||
*/
|
||||
export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
||||
el: any;
|
||||
exploreEvents: Emitter;
|
||||
exploreEvents: EventBusExtended;
|
||||
|
||||
constructor(props: ExploreProps) {
|
||||
super(props);
|
||||
this.exploreEvents = new Emitter();
|
||||
this.exploreEvents = new EventBusSrv();
|
||||
this.state = {
|
||||
openDrawer: undefined,
|
||||
};
|
||||
|
@ -5,9 +5,7 @@ import React, { PureComponent } from 'react';
|
||||
import { getAngularLoader, AngularComponent } from '@grafana/runtime';
|
||||
|
||||
// Types
|
||||
import { Emitter } from 'app/core/utils/emitter';
|
||||
import { DataQuery } from '@grafana/data';
|
||||
import { TimeRange } from '@grafana/data';
|
||||
import { DataQuery, TimeRange, EventBusExtended } from '@grafana/data';
|
||||
import 'app/features/plugins/plugin_loader';
|
||||
|
||||
interface QueryEditorProps {
|
||||
@ -16,7 +14,7 @@ interface QueryEditorProps {
|
||||
onExecuteQuery?: () => void;
|
||||
onQueryChange?: (value: DataQuery) => void;
|
||||
initialQuery: DataQuery;
|
||||
exploreEvents: Emitter;
|
||||
exploreEvents: EventBusExtended;
|
||||
range: TimeRange;
|
||||
textEditModeEnabled?: boolean;
|
||||
}
|
||||
|
@ -2,14 +2,14 @@ import React from 'react';
|
||||
import { QueryRow, QueryRowProps } from './QueryRow';
|
||||
import { shallow } from 'enzyme';
|
||||
import { ExploreId } from 'app/types/explore';
|
||||
import { Emitter } from 'app/core/utils/emitter';
|
||||
import { EventBusExtended } from '@grafana/data';
|
||||
import { DataSourceApi, TimeRange, AbsoluteTimeRange, PanelData } from '@grafana/data';
|
||||
|
||||
const setup = (propOverrides?: object) => {
|
||||
const props: QueryRowProps = {
|
||||
exploreId: ExploreId.left,
|
||||
index: 1,
|
||||
exploreEvents: {} as Emitter,
|
||||
exploreEvents: {} as EventBusExtended,
|
||||
changeQuery: jest.fn(),
|
||||
datasourceInstance: {} as DataSourceApi,
|
||||
highlightLogsExpressionAction: jest.fn() as any,
|
||||
|
@ -20,18 +20,18 @@ import {
|
||||
TimeRange,
|
||||
AbsoluteTimeRange,
|
||||
LoadingState,
|
||||
EventBusExtended,
|
||||
} from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
|
||||
import { ExploreItemState, ExploreId } from 'app/types/explore';
|
||||
import { Emitter } from 'app/core/utils/emitter';
|
||||
import { highlightLogsExpressionAction, removeQueryRowAction } from './state/actionTypes';
|
||||
import { ErrorContainer } from './ErrorContainer';
|
||||
|
||||
interface PropsFromParent {
|
||||
exploreId: ExploreId;
|
||||
index: number;
|
||||
exploreEvents: Emitter;
|
||||
exploreEvents: EventBusExtended;
|
||||
}
|
||||
|
||||
export interface QueryRowProps extends PropsFromParent {
|
||||
|
@ -5,12 +5,12 @@ import React, { PureComponent } from 'react';
|
||||
import QueryRow from './QueryRow';
|
||||
|
||||
// Types
|
||||
import { Emitter } from 'app/core/utils/emitter';
|
||||
import { EventBusExtended } from '@grafana/data';
|
||||
import { ExploreId } from 'app/types/explore';
|
||||
|
||||
interface QueryRowsProps {
|
||||
className?: string;
|
||||
exploreEvents: Emitter;
|
||||
exploreEvents: EventBusExtended;
|
||||
exploreId: ExploreId;
|
||||
queryKeys: string[];
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ exports[`Explore should render component 1`] = `
|
||||
>
|
||||
<QueryRows
|
||||
exploreEvents={
|
||||
Emitter {
|
||||
EventBusSrv {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {},
|
||||
"_eventsCount": 0,
|
||||
|
@ -2,7 +2,6 @@
|
||||
import { Unsubscribable } from 'rxjs';
|
||||
import { createAction } from '@reduxjs/toolkit';
|
||||
|
||||
import { Emitter } from 'app/core/core';
|
||||
import {
|
||||
AbsoluteTimeRange,
|
||||
DataQuery,
|
||||
@ -13,6 +12,7 @@ import {
|
||||
LogsDedupStrategy,
|
||||
QueryFixAction,
|
||||
TimeRange,
|
||||
EventBusExtended,
|
||||
} from '@grafana/data';
|
||||
import { ExploreId, ExploreItemState, ExplorePanelData } from 'app/types/explore';
|
||||
|
||||
@ -52,7 +52,7 @@ export interface HighlightLogsExpressionPayload {
|
||||
export interface InitializeExplorePayload {
|
||||
exploreId: ExploreId;
|
||||
containerWidth: number;
|
||||
eventBridge: Emitter;
|
||||
eventBridge: EventBusExtended;
|
||||
queries: DataQuery[];
|
||||
range: TimeRange;
|
||||
originPanelId?: number | null;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { PayloadAction } from '@reduxjs/toolkit';
|
||||
import { DataQuery, DefaultTimeZone, toUtc, ExploreUrlState } from '@grafana/data';
|
||||
import { DataQuery, DefaultTimeZone, toUtc, ExploreUrlState, EventBusExtended } from '@grafana/data';
|
||||
|
||||
import { cancelQueries, loadDatasource, navigateToExplore, refreshExplore } from './actions';
|
||||
import { ExploreId, ExploreUpdateState } from 'app/types';
|
||||
@ -13,7 +13,6 @@ import {
|
||||
scanStopAction,
|
||||
setQueriesAction,
|
||||
} from './actionTypes';
|
||||
import { Emitter } from 'app/core/core';
|
||||
import { makeInitialUpdateState } from './reducers';
|
||||
import { PanelModel } from 'app/features/dashboard/state';
|
||||
import { updateLocation } from '../../../core/actions';
|
||||
@ -61,7 +60,7 @@ jest.mock('app/core/utils/explore', () => ({
|
||||
const setup = (updateOverides?: Partial<ExploreUpdateState>) => {
|
||||
const exploreId = ExploreId.left;
|
||||
const containerWidth = 1920;
|
||||
const eventBridge = {} as Emitter;
|
||||
const eventBridge = {} as EventBusExtended;
|
||||
const timeZone = DefaultTimeZone;
|
||||
const range = testRange;
|
||||
const urlState: ExploreUrlState = {
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
LoadingState,
|
||||
LogsDedupStrategy,
|
||||
PanelData,
|
||||
EventBusExtended,
|
||||
QueryFixAction,
|
||||
RawTimeRange,
|
||||
TimeRange,
|
||||
@ -21,7 +22,6 @@ import {
|
||||
// Services & Utils
|
||||
import store from 'app/core/store';
|
||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||
import { Emitter } from 'app/core/core';
|
||||
import {
|
||||
buildQueryTransaction,
|
||||
clearQueryKeys,
|
||||
@ -280,7 +280,7 @@ export function initializeExplore(
|
||||
queries: DataQuery[],
|
||||
range: TimeRange,
|
||||
containerWidth: number,
|
||||
eventBridge: Emitter,
|
||||
eventBridge: EventBusExtended,
|
||||
originPanelId?: number | null
|
||||
): ThunkResult<void> {
|
||||
return async (dispatch, getState) => {
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
PanelEvents,
|
||||
sortLogsResult,
|
||||
toLegacyResponseData,
|
||||
EventBusExtended,
|
||||
} from '@grafana/data';
|
||||
import { RefreshPicker } from '@grafana/ui';
|
||||
import { LocationUpdate } from '@grafana/runtime';
|
||||
@ -62,7 +63,6 @@ import {
|
||||
updateDatasourceInstanceAction,
|
||||
} from './actionTypes';
|
||||
import { updateLocation } from '../../../core/actions';
|
||||
import { Emitter } from 'app/core/core';
|
||||
|
||||
export const DEFAULT_RANGE = {
|
||||
from: 'now-6h',
|
||||
@ -111,7 +111,7 @@ export const makeExploreItemState = (): ExploreItemState => ({
|
||||
graphResult: null,
|
||||
logsResult: null,
|
||||
dedupStrategy: LogsDedupStrategy.none,
|
||||
eventBridge: (null as unknown) as Emitter,
|
||||
eventBridge: (null as unknown) as EventBusExtended,
|
||||
});
|
||||
|
||||
export const createEmptyQueryResponse = (): PanelData => ({
|
||||
|
@ -1,9 +1,8 @@
|
||||
import _ from 'lodash';
|
||||
import config from 'app/core/config';
|
||||
import { profiler } from 'app/core/core';
|
||||
import { Emitter } from 'app/core/utils/emitter';
|
||||
import { auto } from 'angular';
|
||||
import { AppEvent, PanelEvents, PanelPluginMeta, AngularPanelMenuItem } from '@grafana/data';
|
||||
import { AppEvent, PanelEvents, PanelPluginMeta, AngularPanelMenuItem, EventBusExtended } from '@grafana/data';
|
||||
import { DashboardModel } from '../dashboard/state';
|
||||
|
||||
export class PanelCtrl {
|
||||
@ -21,7 +20,7 @@ export class PanelCtrl {
|
||||
height: number;
|
||||
width: number;
|
||||
containerHeight: any;
|
||||
events: Emitter;
|
||||
events: EventBusExtended;
|
||||
loading: boolean;
|
||||
timing: any;
|
||||
|
||||
|
@ -97,6 +97,7 @@ function createBarGaugePanelWithData(data: PanelData): ReactWrapper<PanelProps<B
|
||||
width={532}
|
||||
transparent={false}
|
||||
height={250}
|
||||
eventBus={{} as any}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import './jquery.flot.events';
|
||||
import $ from 'jquery';
|
||||
import _ from 'lodash';
|
||||
import { tickStep } from 'app/core/utils/ticks';
|
||||
import { appEvents, coreModule, updateLegendValues } from 'app/core/core';
|
||||
import { coreModule, updateLegendValues } from 'app/core/core';
|
||||
import GraphTooltip from './graph_tooltip';
|
||||
import { ThresholdManager } from './threshold_manager';
|
||||
import { TimeRegionManager } from './time_region_manager';
|
||||
@ -37,6 +37,8 @@ import {
|
||||
getTimeField,
|
||||
getValueFormat,
|
||||
hasLinks,
|
||||
LegacyGraphHoverClearEvent,
|
||||
LegacyGraphHoverEvent,
|
||||
LinkModelSupplier,
|
||||
PanelEvents,
|
||||
toUtc,
|
||||
@ -45,7 +47,6 @@ import { GraphContextMenuCtrl } from './GraphContextMenuCtrl';
|
||||
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
import { ContextSrv } from 'app/core/services/context_srv';
|
||||
import { getFieldLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
|
||||
import { CoreEvents } from 'app/types';
|
||||
|
||||
const LegendWithThemeProvider = provideTheme(Legend);
|
||||
|
||||
@ -86,8 +87,11 @@ class GraphElement {
|
||||
this.ctrl.events.on(PanelEvents.render, this.onRender.bind(this));
|
||||
|
||||
// global events
|
||||
appEvents.on(CoreEvents.graphHover, this.onGraphHover.bind(this), scope);
|
||||
appEvents.on(CoreEvents.graphHoverClear, this.onGraphHoverClear.bind(this), scope);
|
||||
// Using old way here to use the scope unsubscribe model as the new $on function does not take scope
|
||||
this.ctrl.dashboard.events.on(LegacyGraphHoverEvent.type, this.onGraphHover.bind(this), this.scope);
|
||||
this.ctrl.dashboard.events.on(LegacyGraphHoverClearEvent.type, this.onGraphHoverClear.bind(this), this.scope);
|
||||
|
||||
// plot events
|
||||
this.elem.bind('plotselected', this.onPlotSelected.bind(this));
|
||||
this.elem.bind('plotclick', this.onPlotClick.bind(this));
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'jquery';
|
||||
import { appEvents } from 'app/core/core';
|
||||
import { CoreEvents } from 'app/types';
|
||||
import { textUtil, systemDateFormats } from '@grafana/data';
|
||||
import { textUtil, systemDateFormats, LegacyGraphHoverClearEvent, LegacyGraphHoverEvent } from '@grafana/data';
|
||||
|
||||
export default function GraphTooltip(this: any, elem: any, dashboard: any, scope: any, getSeriesFn: any) {
|
||||
const self = this;
|
||||
@ -157,7 +157,7 @@ export default function GraphTooltip(this: any, elem: any, dashboard: any, scope
|
||||
plot.unhighlight();
|
||||
}
|
||||
}
|
||||
appEvents.emit(CoreEvents.graphHoverClear);
|
||||
dashboard.events.$emit(new LegacyGraphHoverClearEvent());
|
||||
});
|
||||
|
||||
elem.bind('plothover', (event: any, pos: { panelRelY: number; pageY: number }, item: any) => {
|
||||
@ -165,7 +165,7 @@ export default function GraphTooltip(this: any, elem: any, dashboard: any, scope
|
||||
|
||||
// broadcast to other graph panels that we are hovering!
|
||||
pos.panelRelY = (pos.pageY - elem.offset().top) / elem.height();
|
||||
appEvents.emit(CoreEvents.graphHover, { pos: pos, panel: panel });
|
||||
dashboard.events.$emit(new LegacyGraphHoverEvent({ pos: pos, panel: panel }));
|
||||
});
|
||||
|
||||
elem.bind('plotclick', (event: any, pos: any, item: any) => {
|
||||
|
@ -20,13 +20,12 @@ import '../module';
|
||||
import { GraphCtrl } from '../module';
|
||||
import { MetricsPanelCtrl } from 'app/features/panel/metrics_panel_ctrl';
|
||||
import { PanelCtrl } from 'app/features/panel/panel_ctrl';
|
||||
|
||||
import config from 'app/core/config';
|
||||
|
||||
import TimeSeries from 'app/core/time_series2';
|
||||
import $ from 'jquery';
|
||||
import { graphDirective } from '../graph';
|
||||
import { dateTime } from '@grafana/data';
|
||||
import { dateTime, EventBusSrv } from '@grafana/data';
|
||||
|
||||
const ctx = {} as any;
|
||||
let ctrl: any;
|
||||
@ -84,6 +83,7 @@ describe('grafanaGraph', () => {
|
||||
hiddenSeries: {},
|
||||
dashboard: {
|
||||
getTimezone: () => 'browser',
|
||||
events: new EventBusSrv(),
|
||||
},
|
||||
range: {
|
||||
from: dateTime([2015, 1, 1, 10]),
|
||||
|
@ -1,7 +1,7 @@
|
||||
import _ from 'lodash';
|
||||
import $ from 'jquery';
|
||||
import * as d3 from 'd3';
|
||||
import { appEvents, contextSrv } from 'app/core/core';
|
||||
import { contextSrv } from 'app/core/core';
|
||||
import * as ticksUtils from 'app/core/utils/ticks';
|
||||
import { HeatmapTooltip } from './heatmap_tooltip';
|
||||
import { mergeZeroBuckets } from './heatmap_data_converter';
|
||||
@ -12,10 +12,11 @@ import {
|
||||
getValueFormat,
|
||||
formattedValueToString,
|
||||
dateTimeFormat,
|
||||
LegacyGraphHoverEvent,
|
||||
LegacyGraphHoverClearEvent,
|
||||
getColorForTheme,
|
||||
} from '@grafana/data';
|
||||
import { graphTimeFormat } from '@grafana/ui';
|
||||
import { CoreEvents } from 'app/types';
|
||||
import { config } from 'app/core/config';
|
||||
|
||||
const MIN_CARD_SIZE = 1,
|
||||
@ -84,9 +85,8 @@ export class HeatmapRenderer {
|
||||
/////////////////////////////
|
||||
|
||||
// Shared crosshair and tooltip
|
||||
appEvents.on(CoreEvents.graphHover, this.onGraphHover.bind(this), this.scope);
|
||||
|
||||
appEvents.on(CoreEvents.graphHoverClear, this.onGraphHoverClear.bind(this), this.scope);
|
||||
this.ctrl.dashboard.events.on(LegacyGraphHoverEvent.type, this.onGraphHover.bind(this), this.scope);
|
||||
this.ctrl.dashboard.events.on(LegacyGraphHoverClearEvent.type, this.onGraphHoverClear.bind(this), this.scope);
|
||||
|
||||
// Register selection listeners
|
||||
this.$heatmap.on('mousedown', this.onMouseDown.bind(this));
|
||||
@ -735,7 +735,7 @@ export class HeatmapRenderer {
|
||||
}
|
||||
|
||||
onMouseLeave() {
|
||||
appEvents.emit(CoreEvents.graphHoverClear);
|
||||
this.ctrl.dashboard.$emit(new LegacyGraphHoverClearEvent());
|
||||
this.clearCrosshair();
|
||||
}
|
||||
|
||||
@ -781,7 +781,7 @@ export class HeatmapRenderer {
|
||||
// Set minimum offset to prevent showing legend from another panel
|
||||
pos.panelRelY = Math.max(pos.offset.y / this.height, 0.001);
|
||||
// broadcast to other graph panels that we are hovering
|
||||
appEvents.emit(CoreEvents.graphHover, { pos: pos, panel: this.panel });
|
||||
this.ctrl.dashboard.events.emit$(new LegacyGraphHoverEvent({ pos: pos, panel: this.panel }));
|
||||
}
|
||||
|
||||
limitSelection(x2: number) {
|
||||
|
@ -9,6 +9,7 @@ import { TextOptions } from './types';
|
||||
import { CustomScrollbar, stylesFactory } from '@grafana/ui';
|
||||
import { css, cx } from 'emotion';
|
||||
import DangerouslySetHtmlContent from 'dangerously-set-html-content';
|
||||
import { Unsubscribable } from 'rxjs';
|
||||
|
||||
interface Props extends PanelProps<TextOptions> {}
|
||||
|
||||
@ -17,6 +18,8 @@ interface State {
|
||||
}
|
||||
|
||||
export class TextPanel extends PureComponent<Props, State> {
|
||||
eventSub?: Unsubscribable;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
|
@ -209,8 +209,6 @@ export function grafanaAppDirective(
|
||||
for (const drop of Drop.drops) {
|
||||
drop.destroy();
|
||||
}
|
||||
|
||||
appEvents.emit(CoreEvents.hideDashSearch);
|
||||
});
|
||||
|
||||
// handle kiosk mode
|
||||
|
@ -90,14 +90,13 @@ export interface DashScrollPayload {
|
||||
pos?: number;
|
||||
}
|
||||
|
||||
export interface PanelChangeViewPayload {}
|
||||
|
||||
/**
|
||||
* Events
|
||||
*/
|
||||
|
||||
export const showDashSearch = eventFactory<ShowDashSearchPayload>('show-dash-search');
|
||||
export const hideDashSearch = eventFactory('hide-dash-search');
|
||||
export const hideDashEditor = eventFactory('hide-dash-editor');
|
||||
export const dashScroll = eventFactory<DashScrollPayload>('dash-scroll');
|
||||
export const panelChangeView = eventFactory<PanelChangeViewPayload>('panel-change-view');
|
||||
export const dashLinksUpdated = eventFactory('dash-links-updated');
|
||||
export const saveDashboard = eventFactory<SaveDashboardPayload>('save-dashboard');
|
||||
export const dashboardFetchStart = eventFactory('dashboard-fetch-start');
|
||||
@ -119,9 +118,6 @@ export const showModalReact = eventFactory<ShowModalReactPayload>('show-modal-re
|
||||
export const dsRequestResponse = eventFactory<DataSourceResponsePayload>('ds-request-response');
|
||||
export const dsRequestError = eventFactory<any>('ds-request-error');
|
||||
|
||||
export const graphHover = eventFactory<GraphHoverPayload>('graph-hover');
|
||||
export const graphHoverClear = eventFactory('graph-hover-clear');
|
||||
|
||||
export const toggleSidemenuMobile = eventFactory('toggle-sidemenu-mobile');
|
||||
export const toggleSidemenuHidden = eventFactory('toggle-sidemenu-hidden');
|
||||
|
||||
|
@ -15,10 +15,9 @@ import {
|
||||
QueryHint,
|
||||
RawTimeRange,
|
||||
TimeRange,
|
||||
EventBusExtended,
|
||||
} from '@grafana/data';
|
||||
|
||||
import { Emitter } from 'app/core/core';
|
||||
|
||||
export enum ExploreId {
|
||||
left = 'left',
|
||||
right = 'right',
|
||||
@ -74,7 +73,7 @@ export interface ExploreItemState {
|
||||
/**
|
||||
* Emitter to send events to the rest of Grafana.
|
||||
*/
|
||||
eventBridge: Emitter;
|
||||
eventBridge: EventBusExtended;
|
||||
/**
|
||||
* List of timeseries to be shown in the Explore graph result viewer.
|
||||
*/
|
||||
|
@ -12752,6 +12752,11 @@ eventemitter3@4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb"
|
||||
integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==
|
||||
|
||||
eventemitter3@4.0.7:
|
||||
version "4.0.7"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
|
||||
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
|
||||
|
||||
eventemitter3@^3.1.0:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
|
||||
|
Loading…
Reference in New Issue
Block a user