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",
|
"@braintree/sanitize-url": "4.0.0",
|
||||||
"@types/d3-interpolate": "^1.3.1",
|
"@types/d3-interpolate": "^1.3.1",
|
||||||
"apache-arrow": "0.16.0",
|
"apache-arrow": "0.16.0",
|
||||||
|
"eventemitter3": "4.0.7",
|
||||||
"lodash": "4.17.19",
|
"lodash": "4.17.19",
|
||||||
"rxjs": "6.6.3",
|
"rxjs": "6.6.3",
|
||||||
"xss": "1.0.6"
|
"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';
|
import { AppEvent } from './types';
|
||||||
|
|
||||||
export type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
|
|
||||||
export type Subtract<T, K> = Omit<T, keyof K>;
|
|
||||||
|
|
||||||
const typeList: Set<string> = new Set();
|
const typeList: Set<string> = new Set();
|
||||||
|
|
||||||
export function eventFactory<T = undefined>(name: string): AppEvent<T> {
|
export function eventFactory<T = undefined>(name: string): AppEvent<T> {
|
||||||
if (typeList.has(name)) {
|
if (typeList.has(name)) {
|
||||||
throw new Error(`There is already an event defined with type '${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 './text';
|
||||||
export * from './valueFormats';
|
export * from './valueFormats';
|
||||||
export * from './field';
|
export * from './field';
|
||||||
|
export * from './events';
|
||||||
export { PanelPlugin } from './panel/PanelPlugin';
|
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 './select';
|
||||||
export * from './time';
|
export * from './time';
|
||||||
export * from './thresholds';
|
export * from './thresholds';
|
||||||
export * from './utils';
|
|
||||||
export * from './valueMapping';
|
export * from './valueMapping';
|
||||||
export * from './displayValue';
|
export * from './displayValue';
|
||||||
export * from './graph';
|
export * from './graph';
|
||||||
@ -27,12 +26,7 @@ export * from './orgs';
|
|||||||
export * from './flot';
|
export * from './flot';
|
||||||
export * from './trace';
|
export * from './trace';
|
||||||
export * from './explore';
|
export * from './explore';
|
||||||
|
export * from './legacyEvents';
|
||||||
export * from './live';
|
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';
|
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 { LoadingState } from './data';
|
||||||
import { DataFrame } from './dataFrame';
|
import { DataFrame } from './dataFrame';
|
||||||
import { AbsoluteTimeRange, TimeRange, TimeZone } from './time';
|
import { AbsoluteTimeRange, TimeRange, TimeZone } from './time';
|
||||||
|
import { EventBus } from '../events';
|
||||||
import { FieldConfigSource } from './fieldOverrides';
|
import { FieldConfigSource } from './fieldOverrides';
|
||||||
import { Registry } from '../utils';
|
import { Registry } from '../utils';
|
||||||
import { StandardEditorProps } from '../field';
|
import { StandardEditorProps } from '../field';
|
||||||
@ -77,6 +78,9 @@ export interface PanelProps<T = any> {
|
|||||||
/** Panel title */
|
/** Panel title */
|
||||||
title: string;
|
title: string;
|
||||||
|
|
||||||
|
/** EventBus */
|
||||||
|
eventBus: EventBus;
|
||||||
|
|
||||||
/** Panel options change handler */
|
/** Panel options change handler */
|
||||||
onOptionsChange: (options: T) => void;
|
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;
|
export default appEvents;
|
||||||
|
@ -19,7 +19,6 @@ import { colors, JsonExplorer } from '@grafana/ui/';
|
|||||||
|
|
||||||
import { infoPopover } from './components/info_popover';
|
import { infoPopover } from './components/info_popover';
|
||||||
import { arrayJoin } from './directives/array_join';
|
import { arrayJoin } from './directives/array_join';
|
||||||
import { Emitter } from './utils/emitter';
|
|
||||||
import { switchDirective } from './components/switch';
|
import { switchDirective } from './components/switch';
|
||||||
import { dashboardSelector } from './components/dashboard_selector';
|
import { dashboardSelector } from './components/dashboard_selector';
|
||||||
import { queryPartEditorDirective } from './components/query_part/query_part_editor';
|
import { queryPartEditorDirective } from './components/query_part/query_part_editor';
|
||||||
@ -47,7 +46,6 @@ export {
|
|||||||
coreModule,
|
coreModule,
|
||||||
switchDirective,
|
switchDirective,
|
||||||
infoPopover,
|
infoPopover,
|
||||||
Emitter,
|
|
||||||
appEvents,
|
appEvents,
|
||||||
dashboardSelector,
|
dashboardSelector,
|
||||||
queryPartEditorDirective,
|
queryPartEditorDirective,
|
||||||
|
@ -11,7 +11,6 @@ import { DashboardSearchHit } from 'app/features/search/types';
|
|||||||
import { FolderDTO } from 'app/types';
|
import { FolderDTO } from 'app/types';
|
||||||
import { coreModule } from 'app/core/core_module';
|
import { coreModule } from 'app/core/core_module';
|
||||||
import { ContextSrv, contextSrv } from './context_srv';
|
import { ContextSrv, contextSrv } from './context_srv';
|
||||||
import { Emitter } from '../utils/emitter';
|
|
||||||
import { parseInitFromOptions, parseUrlFromOptions } from '../utils/fetch';
|
import { parseInitFromOptions, parseUrlFromOptions } from '../utils/fetch';
|
||||||
import { isDataQuery, isLocalUrl } from '../utils/query';
|
import { isDataQuery, isLocalUrl } from '../utils/query';
|
||||||
import { FetchQueue } from './FetchQueue';
|
import { FetchQueue } from './FetchQueue';
|
||||||
@ -22,7 +21,7 @@ const CANCEL_ALL_REQUESTS_REQUEST_ID = 'cancel_all_requests_request_id';
|
|||||||
|
|
||||||
export interface BackendSrvDependencies {
|
export interface BackendSrvDependencies {
|
||||||
fromFetch: (input: string | Request, init?: RequestInit) => Observable<Response>;
|
fromFetch: (input: string | Request, init?: RequestInit) => Observable<Response>;
|
||||||
appEvents: Emitter;
|
appEvents: typeof appEvents;
|
||||||
contextSrv: ContextSrv;
|
contextSrv: ContextSrv;
|
||||||
logout: () => void;
|
logout: () => void;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import _ from 'lodash';
|
|||||||
import Mousetrap from 'mousetrap';
|
import Mousetrap from 'mousetrap';
|
||||||
import 'mousetrap-global-bind';
|
import 'mousetrap-global-bind';
|
||||||
import { ILocationService, IRootScopeService, ITimeoutService } from 'angular';
|
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 coreModule from 'app/core/core_module';
|
||||||
import appEvents from 'app/core/app_events';
|
import appEvents from 'app/core/app_events';
|
||||||
@ -197,7 +197,7 @@ export class KeybindingSrv {
|
|||||||
setupDashboardBindings(scope: IRootScopeService & AppEventEmitter, dashboard: DashboardModel) {
|
setupDashboardBindings(scope: IRootScopeService & AppEventEmitter, dashboard: DashboardModel) {
|
||||||
this.bind('mod+o', () => {
|
this.bind('mod+o', () => {
|
||||||
dashboard.graphTooltip = (dashboard.graphTooltip + 1) % 3;
|
dashboard.graphTooltip = (dashboard.graphTooltip + 1) % 3;
|
||||||
appEvents.emit(CoreEvents.graphHoverClear);
|
dashboard.events.publish(new LegacyGraphHoverClearEvent());
|
||||||
dashboard.startRefresh();
|
dashboard.startRefresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import 'whatwg-fetch'; // fetch polyfill needed for PhantomJs rendering
|
import 'whatwg-fetch'; // fetch polyfill needed for PhantomJs rendering
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { delay } from 'rxjs/operators';
|
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 { BackendSrv } from '../services/backend_srv';
|
||||||
import { Emitter } from '../utils/emitter';
|
|
||||||
import { ContextSrv, User } from '../services/context_srv';
|
import { ContextSrv, User } from '../services/context_srv';
|
||||||
import { describe, expect } from '../../../test/lib/common';
|
import { describe, expect } from '../../../test/lib/common';
|
||||||
import { BackendSrvRequest, FetchError } from '@grafana/runtime';
|
import { BackendSrvRequest, FetchError } from '@grafana/runtime';
|
||||||
@ -35,9 +34,11 @@ const getTestContext = (overides?: object) => {
|
|||||||
};
|
};
|
||||||
return of(mockedResponse);
|
return of(mockedResponse);
|
||||||
});
|
});
|
||||||
const appEventsMock: Emitter = ({
|
|
||||||
|
const appEventsMock: EventBusExtended = ({
|
||||||
emit: jest.fn(),
|
emit: jest.fn(),
|
||||||
} as any) as Emitter;
|
} as any) as EventBusExtended;
|
||||||
|
|
||||||
const user: User = ({
|
const user: User = ({
|
||||||
isSignedIn: props.isSignedIn,
|
isSignedIn: props.isSignedIn,
|
||||||
orgId: props.orgId,
|
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.$scope.$on('$destroy', () => {
|
||||||
this.dashboard.updateSubmenuVisibility();
|
this.dashboard.updateSubmenuVisibility();
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$rootScope.appEvent(CoreEvents.dashScroll, { restore: true });
|
|
||||||
this.dashboard.startRefresh();
|
this.dashboard.startRefresh();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -53,7 +53,6 @@ export class SettingsCtrl {
|
|||||||
this.onRouteUpdated();
|
this.onRouteUpdated();
|
||||||
|
|
||||||
this.$rootScope.onAppEvent(CoreEvents.routeUpdated, this.onRouteUpdated.bind(this), $scope);
|
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);
|
appEvents.on(CoreEvents.dashboardSaved, this.onPostSave.bind(this), $scope);
|
||||||
|
|
||||||
|
@ -57,9 +57,7 @@ export class HistoryListCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dismiss() {
|
dismiss() {}
|
||||||
this.$rootScope.appEvent(CoreEvents.hideDashEditor);
|
|
||||||
}
|
|
||||||
|
|
||||||
addToLog() {
|
addToLog() {
|
||||||
this.start = this.start + this.limit;
|
this.start = this.start + this.limit;
|
||||||
|
@ -24,7 +24,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
|||||||
"autoUpdate": undefined,
|
"autoUpdate": undefined,
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -53,7 +53,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -138,7 +138,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
|||||||
"autoUpdate": undefined,
|
"autoUpdate": undefined,
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -167,7 +167,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -233,7 +233,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
|||||||
"autoUpdate": undefined,
|
"autoUpdate": undefined,
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -262,7 +262,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -384,7 +384,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
|||||||
"autoUpdate": undefined,
|
"autoUpdate": undefined,
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -413,7 +413,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -498,7 +498,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
|||||||
"autoUpdate": undefined,
|
"autoUpdate": undefined,
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -527,7 +527,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -593,7 +593,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
|||||||
"autoUpdate": undefined,
|
"autoUpdate": undefined,
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -622,7 +622,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -693,7 +693,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
|||||||
"autoUpdate": undefined,
|
"autoUpdate": undefined,
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -722,7 +722,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
|
@ -52,8 +52,9 @@ export interface State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PanelChrome extends PureComponent<Props, State> {
|
export class PanelChrome extends PureComponent<Props, State> {
|
||||||
timeSrv: TimeSrv = getTimeSrv();
|
readonly timeSrv: TimeSrv = getTimeSrv();
|
||||||
querySubscription: Unsubscribable;
|
|
||||||
|
querySubscription?: Unsubscribable;
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -73,6 +74,7 @@ export class PanelChrome extends PureComponent<Props, State> {
|
|||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { panel, dashboard } = this.props;
|
const { panel, dashboard } = this.props;
|
||||||
|
|
||||||
|
// Subscribe to panel events
|
||||||
panel.events.on(PanelEvents.refresh, this.onRefresh);
|
panel.events.on(PanelEvents.refresh, this.onRefresh);
|
||||||
panel.events.on(PanelEvents.render, this.onRender);
|
panel.events.on(PanelEvents.render, this.onRender);
|
||||||
|
|
||||||
@ -244,7 +246,7 @@ export class PanelChrome extends PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderPanel(width: number, height: number) {
|
renderPanel(width: number, height: number) {
|
||||||
const { panel, plugin } = this.props;
|
const { panel, plugin, dashboard } = this.props;
|
||||||
const { renderCounter, data, isFirstLoad } = this.state;
|
const { renderCounter, data, isFirstLoad } = this.state;
|
||||||
const { theme } = config;
|
const { theme } = config;
|
||||||
const { state: loadingState } = data;
|
const { state: loadingState } = data;
|
||||||
@ -291,6 +293,7 @@ export class PanelChrome extends PureComponent<Props, State> {
|
|||||||
onOptionsChange={this.onOptionsChange}
|
onOptionsChange={this.onOptionsChange}
|
||||||
onFieldConfigChange={this.onFieldConfigChange}
|
onFieldConfigChange={this.onFieldConfigChange}
|
||||||
onChangeTimeRange={this.onChangeTimeRange}
|
onChangeTimeRange={this.onChangeTimeRange}
|
||||||
|
eventBus={dashboard.events}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -68,7 +68,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
"autoUpdate": undefined,
|
"autoUpdate": undefined,
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {
|
"_events": Object {
|
||||||
"panel-added": EE {
|
"panel-added": EE {
|
||||||
@ -123,7 +123,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -151,7 +151,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -179,7 +179,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -207,7 +207,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -258,7 +258,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -310,7 +310,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
"autoUpdate": undefined,
|
"autoUpdate": undefined,
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {
|
"_events": Object {
|
||||||
"panel-added": EE {
|
"panel-added": EE {
|
||||||
@ -365,7 +365,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -393,7 +393,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -421,7 +421,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -449,7 +449,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -500,7 +500,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -552,7 +552,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
"autoUpdate": undefined,
|
"autoUpdate": undefined,
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {
|
"_events": Object {
|
||||||
"panel-added": EE {
|
"panel-added": EE {
|
||||||
@ -607,7 +607,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -635,7 +635,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -663,7 +663,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -691,7 +691,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -742,7 +742,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -794,7 +794,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
"autoUpdate": undefined,
|
"autoUpdate": undefined,
|
||||||
"description": undefined,
|
"description": undefined,
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {
|
"_events": Object {
|
||||||
"panel-added": EE {
|
"panel-added": EE {
|
||||||
@ -849,7 +849,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -877,7 +877,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -905,7 +905,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -933,7 +933,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
@ -984,7 +984,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
PanelModel {
|
PanelModel {
|
||||||
"cachedPluginOptions": Object {},
|
"cachedPluginOptions": Object {},
|
||||||
"datasource": null,
|
"datasource": null,
|
||||||
"events": Emitter {
|
"events": EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
|
@ -5,7 +5,6 @@ import _ from 'lodash';
|
|||||||
// Utils & Services
|
// Utils & Services
|
||||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||||
import { AngularComponent, getAngularLoader } from '@grafana/runtime';
|
import { AngularComponent, getAngularLoader } from '@grafana/runtime';
|
||||||
import { Emitter } from 'app/core/utils/emitter';
|
|
||||||
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||||
// Types
|
// Types
|
||||||
import { PanelModel } from '../state/PanelModel';
|
import { PanelModel } from '../state/PanelModel';
|
||||||
@ -19,6 +18,7 @@ import {
|
|||||||
PanelEvents,
|
PanelEvents,
|
||||||
TimeRange,
|
TimeRange,
|
||||||
toLegacyResponseData,
|
toLegacyResponseData,
|
||||||
|
EventBusExtended,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { QueryEditorRowTitle } from './QueryEditorRowTitle';
|
import { QueryEditorRowTitle } from './QueryEditorRowTitle';
|
||||||
import { QueryOperationRow } from 'app/core/components/QueryOperationRow/QueryOperationRow';
|
import { QueryOperationRow } from 'app/core/components/QueryOperationRow/QueryOperationRow';
|
||||||
@ -331,7 +331,7 @@ export interface AngularQueryComponentScope {
|
|||||||
target: DataQuery;
|
target: DataQuery;
|
||||||
panel: PanelModel;
|
panel: PanelModel;
|
||||||
dashboard: DashboardModel;
|
dashboard: DashboardModel;
|
||||||
events: Emitter;
|
events: EventBusExtended;
|
||||||
refresh: () => void;
|
refresh: () => void;
|
||||||
render: () => void;
|
render: () => void;
|
||||||
datasource: DataSourceApi | null;
|
datasource: DataSourceApi | null;
|
||||||
|
@ -4,7 +4,6 @@ import _ from 'lodash';
|
|||||||
import { DEFAULT_ANNOTATION_COLOR } from '@grafana/ui';
|
import { DEFAULT_ANNOTATION_COLOR } from '@grafana/ui';
|
||||||
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT, REPEAT_DIR_VERTICAL } from 'app/core/constants';
|
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT, REPEAT_DIR_VERTICAL } from 'app/core/constants';
|
||||||
// Utils & Services
|
// Utils & Services
|
||||||
import { Emitter } from 'app/core/utils/emitter';
|
|
||||||
import { contextSrv } from 'app/core/services/context_srv';
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
import sortByKeys from 'app/core/utils/sort_by_keys';
|
import sortByKeys from 'app/core/utils/sort_by_keys';
|
||||||
// Types
|
// Types
|
||||||
@ -19,6 +18,8 @@ import {
|
|||||||
TimeRange,
|
TimeRange,
|
||||||
TimeZone,
|
TimeZone,
|
||||||
UrlQueryValue,
|
UrlQueryValue,
|
||||||
|
EventBusSrv,
|
||||||
|
EventBusExtended,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { CoreEvents, DashboardMeta, KIOSK_MODE_TV } from 'app/types';
|
import { CoreEvents, DashboardMeta, KIOSK_MODE_TV } from 'app/types';
|
||||||
import { GetVariables, getVariables } from 'app/features/variables/state/selectors';
|
import { GetVariables, getVariables } from 'app/features/variables/state/selectors';
|
||||||
@ -82,7 +83,7 @@ export class DashboardModel {
|
|||||||
// repeat process cycles
|
// repeat process cycles
|
||||||
iteration?: number;
|
iteration?: number;
|
||||||
meta: DashboardMeta;
|
meta: DashboardMeta;
|
||||||
events: Emitter;
|
events: EventBusExtended;
|
||||||
|
|
||||||
static nonPersistedProperties: { [str: string]: boolean } = {
|
static nonPersistedProperties: { [str: string]: boolean } = {
|
||||||
events: true,
|
events: true,
|
||||||
@ -101,7 +102,7 @@ export class DashboardModel {
|
|||||||
data = {};
|
data = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.events = new Emitter();
|
this.events = new EventBusSrv();
|
||||||
this.id = data.id || null;
|
this.id = data.id || null;
|
||||||
this.uid = data.uid || null;
|
this.uid = data.uid || null;
|
||||||
this.revision = data.revision;
|
this.revision = data.revision;
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
// Utils
|
// Utils
|
||||||
import { getTemplateSrv } from '@grafana/runtime';
|
import { getTemplateSrv } from '@grafana/runtime';
|
||||||
import { Emitter } from 'app/core/utils/emitter';
|
|
||||||
import { getNextRefIdChar } from 'app/core/utils/query';
|
import { getNextRefIdChar } from 'app/core/utils/query';
|
||||||
// Types
|
// Types
|
||||||
import {
|
import {
|
||||||
@ -19,6 +18,8 @@ import {
|
|||||||
ScopedVars,
|
ScopedVars,
|
||||||
ThresholdsConfig,
|
ThresholdsConfig,
|
||||||
ThresholdsMode,
|
ThresholdsMode,
|
||||||
|
EventBusExtended,
|
||||||
|
EventBusSrv,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { EDIT_PANEL_ID } from 'app/core/constants';
|
import { EDIT_PANEL_ID } from 'app/core/constants';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
@ -145,7 +146,7 @@ export class PanelModel implements DataConfigSource {
|
|||||||
isInView: boolean;
|
isInView: boolean;
|
||||||
|
|
||||||
hasRefreshed: boolean;
|
hasRefreshed: boolean;
|
||||||
events: Emitter;
|
events: EventBusExtended;
|
||||||
cacheTimeout?: any;
|
cacheTimeout?: any;
|
||||||
cachedPluginOptions?: any;
|
cachedPluginOptions?: any;
|
||||||
legend?: { show: boolean; sort?: string; sortDesc?: boolean };
|
legend?: { show: boolean; sort?: string; sortDesc?: boolean };
|
||||||
@ -154,7 +155,7 @@ export class PanelModel implements DataConfigSource {
|
|||||||
private queryRunner?: PanelQueryRunner;
|
private queryRunner?: PanelQueryRunner;
|
||||||
|
|
||||||
constructor(model: any) {
|
constructor(model: any) {
|
||||||
this.events = new Emitter();
|
this.events = new EventBusSrv();
|
||||||
this.restoreModel(model);
|
this.restoreModel(model);
|
||||||
this.replaceVariables = this.replaceVariables.bind(this);
|
this.replaceVariables = this.replaceVariables.bind(this);
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ export class PanelQueryRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.subscription = observable.subscribe({
|
this.subscription = observable.subscribe({
|
||||||
next: (data: PanelData) => {
|
next: data => {
|
||||||
this.lastResult = preProcessPanelData(data, this.lastResult);
|
this.lastResult = preProcessPanelData(data, this.lastResult);
|
||||||
// Store preprocessed query results for applying overrides later on in the pipeline
|
// Store preprocessed query results for applying overrides later on in the pipeline
|
||||||
this.subject.next(this.lastResult);
|
this.subject.next(this.lastResult);
|
||||||
|
@ -20,6 +20,8 @@ import {
|
|||||||
TimeZone,
|
TimeZone,
|
||||||
ExploreUrlState,
|
ExploreUrlState,
|
||||||
LogsModel,
|
LogsModel,
|
||||||
|
EventBusExtended,
|
||||||
|
EventBusSrv,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
|
|
||||||
import store from 'app/core/store';
|
import store from 'app/core/store';
|
||||||
@ -50,7 +52,6 @@ import {
|
|||||||
getTimeRangeFromUrl,
|
getTimeRangeFromUrl,
|
||||||
lastUsedDatasourceKeyForOrgId,
|
lastUsedDatasourceKeyForOrgId,
|
||||||
} from 'app/core/utils/explore';
|
} from 'app/core/utils/explore';
|
||||||
import { Emitter } from 'app/core/utils/emitter';
|
|
||||||
import { ExploreToolbar } from './ExploreToolbar';
|
import { ExploreToolbar } from './ExploreToolbar';
|
||||||
import { NoDataSourceCallToAction } from './NoDataSourceCallToAction';
|
import { NoDataSourceCallToAction } from './NoDataSourceCallToAction';
|
||||||
import { getTimeZone } from '../profile/state/selectors';
|
import { getTimeZone } from '../profile/state/selectors';
|
||||||
@ -159,11 +160,11 @@ interface ExploreState {
|
|||||||
*/
|
*/
|
||||||
export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
||||||
el: any;
|
el: any;
|
||||||
exploreEvents: Emitter;
|
exploreEvents: EventBusExtended;
|
||||||
|
|
||||||
constructor(props: ExploreProps) {
|
constructor(props: ExploreProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.exploreEvents = new Emitter();
|
this.exploreEvents = new EventBusSrv();
|
||||||
this.state = {
|
this.state = {
|
||||||
openDrawer: undefined,
|
openDrawer: undefined,
|
||||||
};
|
};
|
||||||
|
@ -5,9 +5,7 @@ import React, { PureComponent } from 'react';
|
|||||||
import { getAngularLoader, AngularComponent } from '@grafana/runtime';
|
import { getAngularLoader, AngularComponent } from '@grafana/runtime';
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { Emitter } from 'app/core/utils/emitter';
|
import { DataQuery, TimeRange, EventBusExtended } from '@grafana/data';
|
||||||
import { DataQuery } from '@grafana/data';
|
|
||||||
import { TimeRange } from '@grafana/data';
|
|
||||||
import 'app/features/plugins/plugin_loader';
|
import 'app/features/plugins/plugin_loader';
|
||||||
|
|
||||||
interface QueryEditorProps {
|
interface QueryEditorProps {
|
||||||
@ -16,7 +14,7 @@ interface QueryEditorProps {
|
|||||||
onExecuteQuery?: () => void;
|
onExecuteQuery?: () => void;
|
||||||
onQueryChange?: (value: DataQuery) => void;
|
onQueryChange?: (value: DataQuery) => void;
|
||||||
initialQuery: DataQuery;
|
initialQuery: DataQuery;
|
||||||
exploreEvents: Emitter;
|
exploreEvents: EventBusExtended;
|
||||||
range: TimeRange;
|
range: TimeRange;
|
||||||
textEditModeEnabled?: boolean;
|
textEditModeEnabled?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,14 @@ import React from 'react';
|
|||||||
import { QueryRow, QueryRowProps } from './QueryRow';
|
import { QueryRow, QueryRowProps } from './QueryRow';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import { ExploreId } from 'app/types/explore';
|
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';
|
import { DataSourceApi, TimeRange, AbsoluteTimeRange, PanelData } from '@grafana/data';
|
||||||
|
|
||||||
const setup = (propOverrides?: object) => {
|
const setup = (propOverrides?: object) => {
|
||||||
const props: QueryRowProps = {
|
const props: QueryRowProps = {
|
||||||
exploreId: ExploreId.left,
|
exploreId: ExploreId.left,
|
||||||
index: 1,
|
index: 1,
|
||||||
exploreEvents: {} as Emitter,
|
exploreEvents: {} as EventBusExtended,
|
||||||
changeQuery: jest.fn(),
|
changeQuery: jest.fn(),
|
||||||
datasourceInstance: {} as DataSourceApi,
|
datasourceInstance: {} as DataSourceApi,
|
||||||
highlightLogsExpressionAction: jest.fn() as any,
|
highlightLogsExpressionAction: jest.fn() as any,
|
||||||
|
@ -20,18 +20,18 @@ import {
|
|||||||
TimeRange,
|
TimeRange,
|
||||||
AbsoluteTimeRange,
|
AbsoluteTimeRange,
|
||||||
LoadingState,
|
LoadingState,
|
||||||
|
EventBusExtended,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
|
||||||
import { ExploreItemState, ExploreId } from 'app/types/explore';
|
import { ExploreItemState, ExploreId } from 'app/types/explore';
|
||||||
import { Emitter } from 'app/core/utils/emitter';
|
|
||||||
import { highlightLogsExpressionAction, removeQueryRowAction } from './state/actionTypes';
|
import { highlightLogsExpressionAction, removeQueryRowAction } from './state/actionTypes';
|
||||||
import { ErrorContainer } from './ErrorContainer';
|
import { ErrorContainer } from './ErrorContainer';
|
||||||
|
|
||||||
interface PropsFromParent {
|
interface PropsFromParent {
|
||||||
exploreId: ExploreId;
|
exploreId: ExploreId;
|
||||||
index: number;
|
index: number;
|
||||||
exploreEvents: Emitter;
|
exploreEvents: EventBusExtended;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface QueryRowProps extends PropsFromParent {
|
export interface QueryRowProps extends PropsFromParent {
|
||||||
|
@ -5,12 +5,12 @@ import React, { PureComponent } from 'react';
|
|||||||
import QueryRow from './QueryRow';
|
import QueryRow from './QueryRow';
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { Emitter } from 'app/core/utils/emitter';
|
import { EventBusExtended } from '@grafana/data';
|
||||||
import { ExploreId } from 'app/types/explore';
|
import { ExploreId } from 'app/types/explore';
|
||||||
|
|
||||||
interface QueryRowsProps {
|
interface QueryRowsProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
exploreEvents: Emitter;
|
exploreEvents: EventBusExtended;
|
||||||
exploreId: ExploreId;
|
exploreId: ExploreId;
|
||||||
queryKeys: string[];
|
queryKeys: string[];
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ exports[`Explore should render component 1`] = `
|
|||||||
>
|
>
|
||||||
<QueryRows
|
<QueryRows
|
||||||
exploreEvents={
|
exploreEvents={
|
||||||
Emitter {
|
EventBusSrv {
|
||||||
"emitter": EventEmitter {
|
"emitter": EventEmitter {
|
||||||
"_events": Object {},
|
"_events": Object {},
|
||||||
"_eventsCount": 0,
|
"_eventsCount": 0,
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
import { Unsubscribable } from 'rxjs';
|
import { Unsubscribable } from 'rxjs';
|
||||||
import { createAction } from '@reduxjs/toolkit';
|
import { createAction } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import { Emitter } from 'app/core/core';
|
|
||||||
import {
|
import {
|
||||||
AbsoluteTimeRange,
|
AbsoluteTimeRange,
|
||||||
DataQuery,
|
DataQuery,
|
||||||
@ -13,6 +12,7 @@ import {
|
|||||||
LogsDedupStrategy,
|
LogsDedupStrategy,
|
||||||
QueryFixAction,
|
QueryFixAction,
|
||||||
TimeRange,
|
TimeRange,
|
||||||
|
EventBusExtended,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { ExploreId, ExploreItemState, ExplorePanelData } from 'app/types/explore';
|
import { ExploreId, ExploreItemState, ExplorePanelData } from 'app/types/explore';
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ export interface HighlightLogsExpressionPayload {
|
|||||||
export interface InitializeExplorePayload {
|
export interface InitializeExplorePayload {
|
||||||
exploreId: ExploreId;
|
exploreId: ExploreId;
|
||||||
containerWidth: number;
|
containerWidth: number;
|
||||||
eventBridge: Emitter;
|
eventBridge: EventBusExtended;
|
||||||
queries: DataQuery[];
|
queries: DataQuery[];
|
||||||
range: TimeRange;
|
range: TimeRange;
|
||||||
originPanelId?: number | null;
|
originPanelId?: number | null;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { PayloadAction } from '@reduxjs/toolkit';
|
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 { cancelQueries, loadDatasource, navigateToExplore, refreshExplore } from './actions';
|
||||||
import { ExploreId, ExploreUpdateState } from 'app/types';
|
import { ExploreId, ExploreUpdateState } from 'app/types';
|
||||||
@ -13,7 +13,6 @@ import {
|
|||||||
scanStopAction,
|
scanStopAction,
|
||||||
setQueriesAction,
|
setQueriesAction,
|
||||||
} from './actionTypes';
|
} from './actionTypes';
|
||||||
import { Emitter } from 'app/core/core';
|
|
||||||
import { makeInitialUpdateState } from './reducers';
|
import { makeInitialUpdateState } from './reducers';
|
||||||
import { PanelModel } from 'app/features/dashboard/state';
|
import { PanelModel } from 'app/features/dashboard/state';
|
||||||
import { updateLocation } from '../../../core/actions';
|
import { updateLocation } from '../../../core/actions';
|
||||||
@ -61,7 +60,7 @@ jest.mock('app/core/utils/explore', () => ({
|
|||||||
const setup = (updateOverides?: Partial<ExploreUpdateState>) => {
|
const setup = (updateOverides?: Partial<ExploreUpdateState>) => {
|
||||||
const exploreId = ExploreId.left;
|
const exploreId = ExploreId.left;
|
||||||
const containerWidth = 1920;
|
const containerWidth = 1920;
|
||||||
const eventBridge = {} as Emitter;
|
const eventBridge = {} as EventBusExtended;
|
||||||
const timeZone = DefaultTimeZone;
|
const timeZone = DefaultTimeZone;
|
||||||
const range = testRange;
|
const range = testRange;
|
||||||
const urlState: ExploreUrlState = {
|
const urlState: ExploreUrlState = {
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
LoadingState,
|
LoadingState,
|
||||||
LogsDedupStrategy,
|
LogsDedupStrategy,
|
||||||
PanelData,
|
PanelData,
|
||||||
|
EventBusExtended,
|
||||||
QueryFixAction,
|
QueryFixAction,
|
||||||
RawTimeRange,
|
RawTimeRange,
|
||||||
TimeRange,
|
TimeRange,
|
||||||
@ -21,7 +22,6 @@ import {
|
|||||||
// Services & Utils
|
// Services & Utils
|
||||||
import store from 'app/core/store';
|
import store from 'app/core/store';
|
||||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||||
import { Emitter } from 'app/core/core';
|
|
||||||
import {
|
import {
|
||||||
buildQueryTransaction,
|
buildQueryTransaction,
|
||||||
clearQueryKeys,
|
clearQueryKeys,
|
||||||
@ -280,7 +280,7 @@ export function initializeExplore(
|
|||||||
queries: DataQuery[],
|
queries: DataQuery[],
|
||||||
range: TimeRange,
|
range: TimeRange,
|
||||||
containerWidth: number,
|
containerWidth: number,
|
||||||
eventBridge: Emitter,
|
eventBridge: EventBusExtended,
|
||||||
originPanelId?: number | null
|
originPanelId?: number | null
|
||||||
): ThunkResult<void> {
|
): ThunkResult<void> {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
PanelEvents,
|
PanelEvents,
|
||||||
sortLogsResult,
|
sortLogsResult,
|
||||||
toLegacyResponseData,
|
toLegacyResponseData,
|
||||||
|
EventBusExtended,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { RefreshPicker } from '@grafana/ui';
|
import { RefreshPicker } from '@grafana/ui';
|
||||||
import { LocationUpdate } from '@grafana/runtime';
|
import { LocationUpdate } from '@grafana/runtime';
|
||||||
@ -62,7 +63,6 @@ import {
|
|||||||
updateDatasourceInstanceAction,
|
updateDatasourceInstanceAction,
|
||||||
} from './actionTypes';
|
} from './actionTypes';
|
||||||
import { updateLocation } from '../../../core/actions';
|
import { updateLocation } from '../../../core/actions';
|
||||||
import { Emitter } from 'app/core/core';
|
|
||||||
|
|
||||||
export const DEFAULT_RANGE = {
|
export const DEFAULT_RANGE = {
|
||||||
from: 'now-6h',
|
from: 'now-6h',
|
||||||
@ -111,7 +111,7 @@ export const makeExploreItemState = (): ExploreItemState => ({
|
|||||||
graphResult: null,
|
graphResult: null,
|
||||||
logsResult: null,
|
logsResult: null,
|
||||||
dedupStrategy: LogsDedupStrategy.none,
|
dedupStrategy: LogsDedupStrategy.none,
|
||||||
eventBridge: (null as unknown) as Emitter,
|
eventBridge: (null as unknown) as EventBusExtended,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const createEmptyQueryResponse = (): PanelData => ({
|
export const createEmptyQueryResponse = (): PanelData => ({
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
import { profiler } from 'app/core/core';
|
import { profiler } from 'app/core/core';
|
||||||
import { Emitter } from 'app/core/utils/emitter';
|
|
||||||
import { auto } from 'angular';
|
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';
|
import { DashboardModel } from '../dashboard/state';
|
||||||
|
|
||||||
export class PanelCtrl {
|
export class PanelCtrl {
|
||||||
@ -21,7 +20,7 @@ export class PanelCtrl {
|
|||||||
height: number;
|
height: number;
|
||||||
width: number;
|
width: number;
|
||||||
containerHeight: any;
|
containerHeight: any;
|
||||||
events: Emitter;
|
events: EventBusExtended;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
timing: any;
|
timing: any;
|
||||||
|
|
||||||
|
@ -97,6 +97,7 @@ function createBarGaugePanelWithData(data: PanelData): ReactWrapper<PanelProps<B
|
|||||||
width={532}
|
width={532}
|
||||||
transparent={false}
|
transparent={false}
|
||||||
height={250}
|
height={250}
|
||||||
|
eventBus={{} as any}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import './jquery.flot.events';
|
|||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { tickStep } from 'app/core/utils/ticks';
|
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 GraphTooltip from './graph_tooltip';
|
||||||
import { ThresholdManager } from './threshold_manager';
|
import { ThresholdManager } from './threshold_manager';
|
||||||
import { TimeRegionManager } from './time_region_manager';
|
import { TimeRegionManager } from './time_region_manager';
|
||||||
@ -37,6 +37,8 @@ import {
|
|||||||
getTimeField,
|
getTimeField,
|
||||||
getValueFormat,
|
getValueFormat,
|
||||||
hasLinks,
|
hasLinks,
|
||||||
|
LegacyGraphHoverClearEvent,
|
||||||
|
LegacyGraphHoverEvent,
|
||||||
LinkModelSupplier,
|
LinkModelSupplier,
|
||||||
PanelEvents,
|
PanelEvents,
|
||||||
toUtc,
|
toUtc,
|
||||||
@ -45,7 +47,6 @@ import { GraphContextMenuCtrl } from './GraphContextMenuCtrl';
|
|||||||
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||||
import { ContextSrv } from 'app/core/services/context_srv';
|
import { ContextSrv } from 'app/core/services/context_srv';
|
||||||
import { getFieldLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
|
import { getFieldLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
|
||||||
import { CoreEvents } from 'app/types';
|
|
||||||
|
|
||||||
const LegendWithThemeProvider = provideTheme(Legend);
|
const LegendWithThemeProvider = provideTheme(Legend);
|
||||||
|
|
||||||
@ -86,8 +87,11 @@ class GraphElement {
|
|||||||
this.ctrl.events.on(PanelEvents.render, this.onRender.bind(this));
|
this.ctrl.events.on(PanelEvents.render, this.onRender.bind(this));
|
||||||
|
|
||||||
// global events
|
// global events
|
||||||
appEvents.on(CoreEvents.graphHover, this.onGraphHover.bind(this), scope);
|
// Using old way here to use the scope unsubscribe model as the new $on function does not take scope
|
||||||
appEvents.on(CoreEvents.graphHoverClear, this.onGraphHoverClear.bind(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);
|
||||||
|
|
||||||
|
// plot events
|
||||||
this.elem.bind('plotselected', this.onPlotSelected.bind(this));
|
this.elem.bind('plotselected', this.onPlotSelected.bind(this));
|
||||||
this.elem.bind('plotclick', this.onPlotClick.bind(this));
|
this.elem.bind('plotclick', this.onPlotClick.bind(this));
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import { appEvents } from 'app/core/core';
|
import { appEvents } from 'app/core/core';
|
||||||
import { CoreEvents } from 'app/types';
|
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) {
|
export default function GraphTooltip(this: any, elem: any, dashboard: any, scope: any, getSeriesFn: any) {
|
||||||
const self = this;
|
const self = this;
|
||||||
@ -157,7 +157,7 @@ export default function GraphTooltip(this: any, elem: any, dashboard: any, scope
|
|||||||
plot.unhighlight();
|
plot.unhighlight();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
appEvents.emit(CoreEvents.graphHoverClear);
|
dashboard.events.$emit(new LegacyGraphHoverClearEvent());
|
||||||
});
|
});
|
||||||
|
|
||||||
elem.bind('plothover', (event: any, pos: { panelRelY: number; pageY: number }, item: any) => {
|
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!
|
// broadcast to other graph panels that we are hovering!
|
||||||
pos.panelRelY = (pos.pageY - elem.offset().top) / elem.height();
|
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) => {
|
elem.bind('plotclick', (event: any, pos: any, item: any) => {
|
||||||
|
@ -20,13 +20,12 @@ import '../module';
|
|||||||
import { GraphCtrl } from '../module';
|
import { GraphCtrl } from '../module';
|
||||||
import { MetricsPanelCtrl } from 'app/features/panel/metrics_panel_ctrl';
|
import { MetricsPanelCtrl } from 'app/features/panel/metrics_panel_ctrl';
|
||||||
import { PanelCtrl } from 'app/features/panel/panel_ctrl';
|
import { PanelCtrl } from 'app/features/panel/panel_ctrl';
|
||||||
|
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
|
|
||||||
import TimeSeries from 'app/core/time_series2';
|
import TimeSeries from 'app/core/time_series2';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import { graphDirective } from '../graph';
|
import { graphDirective } from '../graph';
|
||||||
import { dateTime } from '@grafana/data';
|
import { dateTime, EventBusSrv } from '@grafana/data';
|
||||||
|
|
||||||
const ctx = {} as any;
|
const ctx = {} as any;
|
||||||
let ctrl: any;
|
let ctrl: any;
|
||||||
@ -84,6 +83,7 @@ describe('grafanaGraph', () => {
|
|||||||
hiddenSeries: {},
|
hiddenSeries: {},
|
||||||
dashboard: {
|
dashboard: {
|
||||||
getTimezone: () => 'browser',
|
getTimezone: () => 'browser',
|
||||||
|
events: new EventBusSrv(),
|
||||||
},
|
},
|
||||||
range: {
|
range: {
|
||||||
from: dateTime([2015, 1, 1, 10]),
|
from: dateTime([2015, 1, 1, 10]),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import * as d3 from 'd3';
|
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 * as ticksUtils from 'app/core/utils/ticks';
|
||||||
import { HeatmapTooltip } from './heatmap_tooltip';
|
import { HeatmapTooltip } from './heatmap_tooltip';
|
||||||
import { mergeZeroBuckets } from './heatmap_data_converter';
|
import { mergeZeroBuckets } from './heatmap_data_converter';
|
||||||
@ -12,10 +12,11 @@ import {
|
|||||||
getValueFormat,
|
getValueFormat,
|
||||||
formattedValueToString,
|
formattedValueToString,
|
||||||
dateTimeFormat,
|
dateTimeFormat,
|
||||||
|
LegacyGraphHoverEvent,
|
||||||
|
LegacyGraphHoverClearEvent,
|
||||||
getColorForTheme,
|
getColorForTheme,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { graphTimeFormat } from '@grafana/ui';
|
import { graphTimeFormat } from '@grafana/ui';
|
||||||
import { CoreEvents } from 'app/types';
|
|
||||||
import { config } from 'app/core/config';
|
import { config } from 'app/core/config';
|
||||||
|
|
||||||
const MIN_CARD_SIZE = 1,
|
const MIN_CARD_SIZE = 1,
|
||||||
@ -84,9 +85,8 @@ export class HeatmapRenderer {
|
|||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
|
|
||||||
// Shared crosshair and tooltip
|
// Shared crosshair and tooltip
|
||||||
appEvents.on(CoreEvents.graphHover, this.onGraphHover.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);
|
||||||
appEvents.on(CoreEvents.graphHoverClear, this.onGraphHoverClear.bind(this), this.scope);
|
|
||||||
|
|
||||||
// Register selection listeners
|
// Register selection listeners
|
||||||
this.$heatmap.on('mousedown', this.onMouseDown.bind(this));
|
this.$heatmap.on('mousedown', this.onMouseDown.bind(this));
|
||||||
@ -735,7 +735,7 @@ export class HeatmapRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMouseLeave() {
|
onMouseLeave() {
|
||||||
appEvents.emit(CoreEvents.graphHoverClear);
|
this.ctrl.dashboard.$emit(new LegacyGraphHoverClearEvent());
|
||||||
this.clearCrosshair();
|
this.clearCrosshair();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -781,7 +781,7 @@ export class HeatmapRenderer {
|
|||||||
// Set minimum offset to prevent showing legend from another panel
|
// Set minimum offset to prevent showing legend from another panel
|
||||||
pos.panelRelY = Math.max(pos.offset.y / this.height, 0.001);
|
pos.panelRelY = Math.max(pos.offset.y / this.height, 0.001);
|
||||||
// broadcast to other graph panels that we are hovering
|
// 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) {
|
limitSelection(x2: number) {
|
||||||
|
@ -9,6 +9,7 @@ import { TextOptions } from './types';
|
|||||||
import { CustomScrollbar, stylesFactory } from '@grafana/ui';
|
import { CustomScrollbar, stylesFactory } from '@grafana/ui';
|
||||||
import { css, cx } from 'emotion';
|
import { css, cx } from 'emotion';
|
||||||
import DangerouslySetHtmlContent from 'dangerously-set-html-content';
|
import DangerouslySetHtmlContent from 'dangerously-set-html-content';
|
||||||
|
import { Unsubscribable } from 'rxjs';
|
||||||
|
|
||||||
interface Props extends PanelProps<TextOptions> {}
|
interface Props extends PanelProps<TextOptions> {}
|
||||||
|
|
||||||
@ -17,6 +18,8 @@ interface State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class TextPanel extends PureComponent<Props, State> {
|
export class TextPanel extends PureComponent<Props, State> {
|
||||||
|
eventSub?: Unsubscribable;
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
@ -209,8 +209,6 @@ export function grafanaAppDirective(
|
|||||||
for (const drop of Drop.drops) {
|
for (const drop of Drop.drops) {
|
||||||
drop.destroy();
|
drop.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
appEvents.emit(CoreEvents.hideDashSearch);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// handle kiosk mode
|
// handle kiosk mode
|
||||||
|
@ -90,14 +90,13 @@ export interface DashScrollPayload {
|
|||||||
pos?: number;
|
pos?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PanelChangeViewPayload {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Events
|
* Events
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const showDashSearch = eventFactory<ShowDashSearchPayload>('show-dash-search');
|
export const panelChangeView = eventFactory<PanelChangeViewPayload>('panel-change-view');
|
||||||
export const hideDashSearch = eventFactory('hide-dash-search');
|
|
||||||
export const hideDashEditor = eventFactory('hide-dash-editor');
|
|
||||||
export const dashScroll = eventFactory<DashScrollPayload>('dash-scroll');
|
|
||||||
export const dashLinksUpdated = eventFactory('dash-links-updated');
|
export const dashLinksUpdated = eventFactory('dash-links-updated');
|
||||||
export const saveDashboard = eventFactory<SaveDashboardPayload>('save-dashboard');
|
export const saveDashboard = eventFactory<SaveDashboardPayload>('save-dashboard');
|
||||||
export const dashboardFetchStart = eventFactory('dashboard-fetch-start');
|
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 dsRequestResponse = eventFactory<DataSourceResponsePayload>('ds-request-response');
|
||||||
export const dsRequestError = eventFactory<any>('ds-request-error');
|
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 toggleSidemenuMobile = eventFactory('toggle-sidemenu-mobile');
|
||||||
export const toggleSidemenuHidden = eventFactory('toggle-sidemenu-hidden');
|
export const toggleSidemenuHidden = eventFactory('toggle-sidemenu-hidden');
|
||||||
|
|
||||||
|
@ -15,10 +15,9 @@ import {
|
|||||||
QueryHint,
|
QueryHint,
|
||||||
RawTimeRange,
|
RawTimeRange,
|
||||||
TimeRange,
|
TimeRange,
|
||||||
|
EventBusExtended,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
|
|
||||||
import { Emitter } from 'app/core/core';
|
|
||||||
|
|
||||||
export enum ExploreId {
|
export enum ExploreId {
|
||||||
left = 'left',
|
left = 'left',
|
||||||
right = 'right',
|
right = 'right',
|
||||||
@ -74,7 +73,7 @@ export interface ExploreItemState {
|
|||||||
/**
|
/**
|
||||||
* Emitter to send events to the rest of Grafana.
|
* 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.
|
* 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"
|
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb"
|
||||||
integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==
|
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:
|
eventemitter3@^3.1.0:
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
|
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
|
||||||
|
Loading…
Reference in New Issue
Block a user