mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
EventBus: add origin to all events and support nested EventBus (#33548)
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { EventBusSrv, EventBusWithSource } from './EventBus';
|
import { EventBusSrv } from './EventBus';
|
||||||
import { BusEvent, BusEventWithPayload } from './types';
|
import { BusEvent, BusEventWithPayload } from './types';
|
||||||
import { eventFactory } from './eventFactory';
|
import { eventFactory } from './eventFactory';
|
||||||
import { DataHoverEvent } from './common';
|
import { DataHoverEvent } from './common';
|
||||||
@@ -50,8 +50,8 @@ describe('EventBus', () => {
|
|||||||
describe('EventBusWithSource', () => {
|
describe('EventBusWithSource', () => {
|
||||||
it('can add sources to the source path', () => {
|
it('can add sources to the source path', () => {
|
||||||
const bus = new EventBusSrv();
|
const bus = new EventBusSrv();
|
||||||
const busWithSource = new EventBusWithSource(bus, 'foo');
|
const busWithSource = bus.newScopedBus('foo');
|
||||||
expect(busWithSource.source).toEqual('foo');
|
expect((busWithSource as any).path).toEqual(['foo']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('adds the source to the event payload', () => {
|
it('adds the source to the event payload', () => {
|
||||||
@@ -60,11 +60,11 @@ describe('EventBus', () => {
|
|||||||
|
|
||||||
bus.subscribe(DataHoverEvent, (event) => events.push(event));
|
bus.subscribe(DataHoverEvent, (event) => events.push(event));
|
||||||
|
|
||||||
const busWithSource = new EventBusWithSource(bus, 'foo');
|
const busWithSource = bus.newScopedBus('foo');
|
||||||
busWithSource.publish({ type: DataHoverEvent.type });
|
busWithSource.publish({ type: DataHoverEvent.type });
|
||||||
|
|
||||||
expect(events.length).toEqual(1);
|
expect(events.length).toEqual(1);
|
||||||
expect(events[0].payload.source).toEqual('foo');
|
expect(events[0].origin).toEqual(busWithSource);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import EventEmitter from 'eventemitter3';
|
import EventEmitter from 'eventemitter3';
|
||||||
import { Unsubscribable, Observable } from 'rxjs';
|
import { Unsubscribable, Observable } from 'rxjs';
|
||||||
import { PayloadWithSource } from './common';
|
import { filter } from 'rxjs/operators';
|
||||||
import {
|
import {
|
||||||
EventBus,
|
EventBus,
|
||||||
LegacyEmitter,
|
LegacyEmitter,
|
||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
LegacyEventHandler,
|
LegacyEventHandler,
|
||||||
BusEvent,
|
BusEvent,
|
||||||
AppEvent,
|
AppEvent,
|
||||||
BusEventWithPayload,
|
EventFilterOptions,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,6 +44,10 @@ export class EventBusSrv implements EventBus, LegacyEmitter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newScopedBus(key: string, filter?: EventFilterOptions): EventBus {
|
||||||
|
return new ScopedEventBus([key], this, filter);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Legacy functions
|
* Legacy functions
|
||||||
*/
|
*/
|
||||||
@@ -94,40 +98,48 @@ export class EventBusSrv implements EventBus, LegacyEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @alpha
|
|
||||||
*
|
|
||||||
* Wraps EventBus and adds a source to help with identifying if a subscriber should react to the event or not.
|
* Wraps EventBus and adds a source to help with identifying if a subscriber should react to the event or not.
|
||||||
*/
|
*/
|
||||||
export class EventBusWithSource implements EventBus {
|
class ScopedEventBus implements EventBus {
|
||||||
source: string;
|
// will be mutated by panel runners
|
||||||
eventBus: EventBus;
|
filterConfig: EventFilterOptions;
|
||||||
|
|
||||||
constructor(eventBus: EventBus, source: string) {
|
// The path is not yet exposed, but can be used to indicate nested groups and support faster filtering
|
||||||
this.eventBus = eventBus;
|
constructor(public path: string[], private eventBus: EventBus, filter?: EventFilterOptions) {
|
||||||
this.source = source;
|
this.filterConfig = filter ?? { onlyLocal: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
publish<T extends BusEvent>(event: T): void {
|
publish<T extends BusEvent>(event: T): void {
|
||||||
const decoratedEvent = {
|
if (!event.origin) {
|
||||||
...event,
|
(event as any).origin = this;
|
||||||
...{ payload: { ...event.payload, ...{ source: this.source } } },
|
}
|
||||||
};
|
this.eventBus.publish(event);
|
||||||
this.eventBus.publish(decoratedEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe<T extends BusEvent>(eventType: BusEventType<T>, handler: BusEventHandler<T>): Unsubscribable {
|
filter = (event: BusEvent) => {
|
||||||
return this.eventBus.subscribe(eventType, handler);
|
if (this.filterConfig.onlyLocal) {
|
||||||
|
return event.origin === this;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
getStream<T extends BusEvent>(eventType: BusEventType<T>): Observable<T> {
|
getStream<T extends BusEvent>(eventType: BusEventType<T>): Observable<T> {
|
||||||
return this.eventBus.getStream(eventType);
|
return this.eventBus.getStream(eventType).pipe(filter(this.filter)) as Observable<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// syntax sugar
|
||||||
|
subscribe<T extends BusEvent>(typeFilter: BusEventType<T>, handler: BusEventHandler<T>): Unsubscribable {
|
||||||
|
return this.getStream(typeFilter).subscribe({ next: handler });
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAllListeners(): void {
|
removeAllListeners(): void {
|
||||||
this.eventBus.removeAllListeners();
|
this.eventBus.removeAllListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
isOwnEvent(event: BusEventWithPayload<PayloadWithSource>): boolean {
|
/**
|
||||||
return event.payload.source === this.source;
|
* Creates a nested event bus structure
|
||||||
|
*/
|
||||||
|
newScopedBus(key: string, filter: EventFilterOptions): EventBus {
|
||||||
|
return new ScopedEventBus([...this.path, key], this, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,7 @@ import { DataFrame } from '../types';
|
|||||||
import { BusEventWithPayload } from './types';
|
import { BusEventWithPayload } from './types';
|
||||||
|
|
||||||
/** @alpha */
|
/** @alpha */
|
||||||
export interface PayloadWithSource {
|
export interface DataHoverPayload {
|
||||||
source?: string; // source from where the event originates
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @alpha */
|
|
||||||
export interface DataHoverPayload extends PayloadWithSource {
|
|
||||||
raw: any; // Original mouse event (includes pageX etc)
|
raw: any; // Original mouse event (includes pageX etc)
|
||||||
|
|
||||||
x: Record<string, any>; // { time: 5678 },
|
x: Record<string, any>; // { time: 5678 },
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { Unsubscribable, Observable } from 'rxjs';
|
|||||||
export interface BusEvent {
|
export interface BusEvent {
|
||||||
readonly type: string;
|
readonly type: string;
|
||||||
readonly payload?: any;
|
readonly payload?: any;
|
||||||
|
readonly origin?: EventBus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,6 +53,14 @@ export interface BusEventHandler<T extends BusEvent> {
|
|||||||
(event: T): void;
|
(event: T): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @alpha
|
||||||
|
* Main minimal interface
|
||||||
|
*/
|
||||||
|
export interface EventFilterOptions {
|
||||||
|
onlyLocal: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @alpha
|
* @alpha
|
||||||
* Main minimal interface
|
* Main minimal interface
|
||||||
@@ -62,20 +71,29 @@ export interface EventBus {
|
|||||||
*/
|
*/
|
||||||
publish<T extends BusEvent>(event: T): void;
|
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
|
* Get observable of events
|
||||||
*/
|
*/
|
||||||
getStream<T extends BusEvent>(eventType: BusEventType<T>): Observable<T>;
|
getStream<T extends BusEvent>(eventType: BusEventType<T>): Observable<T>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to an event stream
|
||||||
|
*
|
||||||
|
* This function is a wrapper around the `getStream(...)` function
|
||||||
|
*/
|
||||||
|
subscribe<T extends BusEvent>(eventType: BusEventType<T>, handler: BusEventHandler<T>): Unsubscribable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all event subscriptions
|
* Remove all event subscriptions
|
||||||
*/
|
*/
|
||||||
removeAllListeners(): void;
|
removeAllListeners(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new bus scoped that knows where it exists in a heiarchy
|
||||||
|
*
|
||||||
|
* @internal -- This is included for internal use only should not be used directly
|
||||||
|
*/
|
||||||
|
newScopedBus(key: string, filter: EventFilterOptions): EventBus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
import { EventBusWithSource } from '@grafana/data';
|
import { EventBusSrv, EventBus } from '@grafana/data';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
interface PanelContext {
|
/** @alpha */
|
||||||
eventBus?: EventBusWithSource;
|
export interface PanelContext {
|
||||||
|
eventBus: EventBus;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PanelContextRoot = React.createContext<PanelContext>({});
|
const PanelContextRoot = React.createContext<PanelContext>({
|
||||||
|
eventBus: new EventBusSrv(),
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @alpha
|
* @alpha
|
||||||
|
|||||||
@@ -37,4 +37,4 @@ export {
|
|||||||
ErrorIndicatorProps as PanelChromeErrorIndicatorProps,
|
ErrorIndicatorProps as PanelChromeErrorIndicatorProps,
|
||||||
} from './ErrorIndicator';
|
} from './ErrorIndicator';
|
||||||
|
|
||||||
export { usePanelContext, PanelContextProvider } from './PanelContext';
|
export { usePanelContext, PanelContextProvider, PanelContext } from './PanelContext';
|
||||||
|
|||||||
@@ -143,25 +143,17 @@ function useSliceHighlightState() {
|
|||||||
const { eventBus } = usePanelContext();
|
const { eventBus } = usePanelContext();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!eventBus) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const setHighlightedSlice = (event: DataHoverEvent) => {
|
const setHighlightedSlice = (event: DataHoverEvent) => {
|
||||||
if (eventBus.isOwnEvent(event)) {
|
|
||||||
setHighlightedTitle(event.payload.dataId);
|
setHighlightedTitle(event.payload.dataId);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const resetHighlightedSlice = (event: DataHoverClearEvent) => {
|
const resetHighlightedSlice = (event: DataHoverClearEvent) => {
|
||||||
if (eventBus.isOwnEvent(event)) {
|
|
||||||
setHighlightedTitle(undefined);
|
setHighlightedTitle(undefined);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const subs = new Subscription()
|
const subs = new Subscription()
|
||||||
.add(eventBus.subscribe(DataHoverEvent, setHighlightedSlice))
|
.add(eventBus.getStream(DataHoverEvent).subscribe({ next: setHighlightedSlice }))
|
||||||
.add(eventBus.subscribe(DataHoverClearEvent, resetHighlightedSlice));
|
.add(eventBus.getStream(DataHoverClearEvent).subscribe({ next: resetHighlightedSlice }));
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
subs.unsubscribe();
|
subs.unsubscribe();
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ export {
|
|||||||
PanelChromeErrorIndicator,
|
PanelChromeErrorIndicator,
|
||||||
PanelChromeErrorIndicatorProps,
|
PanelChromeErrorIndicatorProps,
|
||||||
PanelContextProvider,
|
PanelContextProvider,
|
||||||
|
PanelContext,
|
||||||
usePanelContext,
|
usePanelContext,
|
||||||
} from './PanelChrome';
|
} from './PanelChrome';
|
||||||
export { VizLayout, VizLayoutComponentType, VizLayoutLegendProps, VizLayoutProps } from './VizLayout/VizLayout';
|
export { VizLayout, VizLayoutComponentType, VizLayoutLegendProps, VizLayoutProps } from './VizLayout/VizLayout';
|
||||||
|
|||||||
@@ -18,15 +18,19 @@ export const AnnotationPicker = ({ annotation, events, onEnabledChanged }: Annot
|
|||||||
const onCancel = () => getDashboardQueryRunner().cancel(annotation);
|
const onCancel = () => getDashboardQueryRunner().cancel(annotation);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const started = events.subscribe(AnnotationQueryStarted, (event) => {
|
const started = events.getStream(AnnotationQueryStarted).subscribe({
|
||||||
|
next: (event) => {
|
||||||
if (event.payload === annotation) {
|
if (event.payload === annotation) {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const stopped = events.subscribe(AnnotationQueryFinished, (event) => {
|
const stopped = events.getStream(AnnotationQueryFinished).subscribe({
|
||||||
|
next: (event) => {
|
||||||
if (event.payload === annotation) {
|
if (event.payload === annotation) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import classNames from 'classnames';
|
|||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
// Components
|
// Components
|
||||||
import { PanelHeader } from './PanelHeader/PanelHeader';
|
import { PanelHeader } from './PanelHeader/PanelHeader';
|
||||||
import { ErrorBoundary, PanelContextProvider } from '@grafana/ui';
|
import { ErrorBoundary, PanelContextProvider, PanelContext } from '@grafana/ui';
|
||||||
// Utils & Services
|
// Utils & Services
|
||||||
import { getTimeSrv, TimeSrv } from '../services/TimeSrv';
|
import { getTimeSrv, TimeSrv } from '../services/TimeSrv';
|
||||||
import { applyPanelTimeOverrides } from 'app/features/dashboard/utils/panel';
|
import { applyPanelTimeOverrides } from 'app/features/dashboard/utils/panel';
|
||||||
@@ -15,7 +15,8 @@ import { DashboardModel, PanelModel } from '../state';
|
|||||||
import { PANEL_BORDER } from 'app/core/constants';
|
import { PANEL_BORDER } from 'app/core/constants';
|
||||||
import {
|
import {
|
||||||
AbsoluteTimeRange,
|
AbsoluteTimeRange,
|
||||||
EventBusWithSource,
|
EventBusSrv,
|
||||||
|
EventFilterOptions,
|
||||||
FieldConfigSource,
|
FieldConfigSource,
|
||||||
getDefaultTimeRange,
|
getDefaultTimeRange,
|
||||||
LoadingState,
|
LoadingState,
|
||||||
@@ -47,22 +48,34 @@ export interface State {
|
|||||||
renderCounter: number;
|
renderCounter: number;
|
||||||
errorMessage?: string;
|
errorMessage?: string;
|
||||||
refreshWhenInView: boolean;
|
refreshWhenInView: boolean;
|
||||||
eventBus: EventBusWithSource;
|
context: PanelContext;
|
||||||
data: PanelData;
|
data: PanelData;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PanelChrome extends Component<Props, State> {
|
export class PanelChrome extends Component<Props, State> {
|
||||||
private readonly timeSrv: TimeSrv = getTimeSrv();
|
private readonly timeSrv: TimeSrv = getTimeSrv();
|
||||||
private subs = new Subscription();
|
private subs = new Subscription();
|
||||||
|
private eventFilter: EventFilterOptions = { onlyLocal: true };
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
// Can this eventBus be on PanelModel?
|
||||||
|
// when we have more complex event filtering, that may be a better option
|
||||||
|
const eventBus = props.dashboard.events
|
||||||
|
? props.dashboard.events.newScopedBus(
|
||||||
|
`panel:${props.panel.id}`, // panelID
|
||||||
|
this.eventFilter
|
||||||
|
)
|
||||||
|
: new EventBusSrv();
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
isFirstLoad: true,
|
isFirstLoad: true,
|
||||||
renderCounter: 0,
|
renderCounter: 0,
|
||||||
refreshWhenInView: false,
|
refreshWhenInView: false,
|
||||||
eventBus: new EventBusWithSource(props.dashboard.events, `panel-${props.panel.id}`),
|
context: {
|
||||||
|
eventBus,
|
||||||
|
},
|
||||||
data: this.getInitialPanelDataState(),
|
data: this.getInitialPanelDataState(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -297,10 +310,14 @@ export class PanelChrome extends Component<Props, State> {
|
|||||||
});
|
});
|
||||||
const panelOptions = panel.getOptions();
|
const panelOptions = panel.getOptions();
|
||||||
|
|
||||||
|
// Update the event filter (dashboard settings may have changed)
|
||||||
|
// Yes this is called ever render for a function that is triggered on every mouse move
|
||||||
|
this.eventFilter.onlyLocal = dashboard.graphTooltip === 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={panelContentClassNames}>
|
<div className={panelContentClassNames}>
|
||||||
<PanelContextProvider value={{ eventBus: this.state.eventBus }}>
|
<PanelContextProvider value={this.state.context}>
|
||||||
<PanelComponent
|
<PanelComponent
|
||||||
id={panel.id}
|
id={panel.id}
|
||||||
data={data}
|
data={data}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import {
|
|||||||
DataLinkBuiltInVars,
|
DataLinkBuiltInVars,
|
||||||
DataQuery,
|
DataQuery,
|
||||||
DataTransformerConfig,
|
DataTransformerConfig,
|
||||||
EventBus,
|
|
||||||
EventBusSrv,
|
EventBusSrv,
|
||||||
FieldConfigSource,
|
FieldConfigSource,
|
||||||
PanelPlugin,
|
PanelPlugin,
|
||||||
@@ -170,13 +169,18 @@ export class PanelModel implements DataConfigSource {
|
|||||||
isInView = false;
|
isInView = false;
|
||||||
configRev = 0; // increments when configs change
|
configRev = 0; // increments when configs change
|
||||||
hasRefreshed?: boolean;
|
hasRefreshed?: boolean;
|
||||||
events: EventBus;
|
|
||||||
cacheTimeout?: any;
|
cacheTimeout?: any;
|
||||||
cachedPluginOptions: Record<string, PanelOptionsCache> = {};
|
cachedPluginOptions: Record<string, PanelOptionsCache> = {};
|
||||||
legend?: { show: boolean; sort?: string; sortDesc?: boolean };
|
legend?: { show: boolean; sort?: string; sortDesc?: boolean };
|
||||||
plugin?: PanelPlugin;
|
plugin?: PanelPlugin;
|
||||||
dataSupport?: PanelPluginDataSupport;
|
dataSupport?: PanelPluginDataSupport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The PanelModel event bus only used for internal and legacy angular support.
|
||||||
|
* The EventBus passed to panels is based on the dashboard event model.
|
||||||
|
*/
|
||||||
|
events: EventBusSrv;
|
||||||
|
|
||||||
private queryRunner?: PanelQueryRunner;
|
private queryRunner?: PanelQueryRunner;
|
||||||
|
|
||||||
constructor(model: any) {
|
constructor(model: any) {
|
||||||
|
|||||||
@@ -55,10 +55,11 @@ async function setupTestContext({
|
|||||||
const props: Props = {
|
const props: Props = {
|
||||||
data: { state: LoadingState.Done, timeRange: getDefaultTimeRange(), series: [] },
|
data: { state: LoadingState.Done, timeRange: getDefaultTimeRange(), series: [] },
|
||||||
eventBus: {
|
eventBus: {
|
||||||
|
subscribe: jest.fn(),
|
||||||
getStream: jest.fn(),
|
getStream: jest.fn(),
|
||||||
publish: jest.fn(),
|
publish: jest.fn(),
|
||||||
removeAllListeners: jest.fn(),
|
removeAllListeners: jest.fn(),
|
||||||
subscribe: jest.fn(),
|
newScopedBus: jest.fn(),
|
||||||
},
|
},
|
||||||
fieldConfig: ({} as unknown) as FieldConfigSource,
|
fieldConfig: ({} as unknown) as FieldConfigSource,
|
||||||
height: 400,
|
height: 400,
|
||||||
|
|||||||
@@ -3,12 +3,10 @@ import { CustomScrollbar } from '@grafana/ui';
|
|||||||
import {
|
import {
|
||||||
BusEvent,
|
BusEvent,
|
||||||
CircularVector,
|
CircularVector,
|
||||||
DataHoverPayload,
|
|
||||||
DataHoverEvent,
|
DataHoverEvent,
|
||||||
DataHoverClearEvent,
|
DataHoverClearEvent,
|
||||||
DataSelectEvent,
|
DataSelectEvent,
|
||||||
EventBus,
|
EventBus,
|
||||||
BusEventHandler,
|
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { PartialObserver, Unsubscribable } from 'rxjs';
|
import { PartialObserver, Unsubscribable } from 'rxjs';
|
||||||
|
|
||||||
@@ -24,22 +22,25 @@ interface State {
|
|||||||
interface BusEventEx {
|
interface BusEventEx {
|
||||||
key: number;
|
key: number;
|
||||||
type: string;
|
type: string;
|
||||||
payload: DataHoverPayload;
|
path: string;
|
||||||
|
payload: any;
|
||||||
}
|
}
|
||||||
let counter = 100;
|
let counter = 100;
|
||||||
|
|
||||||
export class EventBusLoggerPanel extends PureComponent<Props, State> {
|
export class EventBusLoggerPanel extends PureComponent<Props, State> {
|
||||||
history = new CircularVector<BusEventEx>({ capacity: 40, append: 'head' });
|
history = new CircularVector<BusEventEx>({ capacity: 40, append: 'head' });
|
||||||
subs: Unsubscribable[] = [];
|
subs: Unsubscribable[];
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = { counter };
|
this.state = { counter };
|
||||||
|
|
||||||
this.subs.push(props.eventBus.subscribe(DataHoverEvent, this.hoverHandler));
|
const subs: Unsubscribable[] = [];
|
||||||
props.eventBus.getStream(DataHoverClearEvent).subscribe(this.eventObserver);
|
subs.push(props.eventBus.getStream(DataHoverEvent).subscribe(this.eventObserver));
|
||||||
props.eventBus.getStream(DataSelectEvent).subscribe(this.eventObserver);
|
subs.push(props.eventBus.getStream(DataHoverClearEvent).subscribe(this.eventObserver));
|
||||||
|
subs.push(props.eventBus.getStream(DataSelectEvent).subscribe(this.eventObserver));
|
||||||
|
this.subs = subs;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
@@ -48,17 +49,17 @@ export class EventBusLoggerPanel extends PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hoverHandler: BusEventHandler<DataHoverEvent> = (event: DataHoverEvent) => {
|
eventObserver: PartialObserver<BusEvent> = {
|
||||||
|
next: (event: BusEvent) => {
|
||||||
|
const origin = event.origin as any;
|
||||||
this.history.add({
|
this.history.add({
|
||||||
key: counter++,
|
key: counter++,
|
||||||
type: event.type,
|
type: event.type,
|
||||||
|
path: origin?.path,
|
||||||
payload: event.payload,
|
payload: event.payload,
|
||||||
});
|
});
|
||||||
this.setState({ counter });
|
this.setState({ counter });
|
||||||
};
|
},
|
||||||
|
|
||||||
eventObserver: PartialObserver<BusEvent> = {
|
|
||||||
next: (v: BusEvent) => {},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -66,7 +67,7 @@ export class EventBusLoggerPanel extends PureComponent<Props, State> {
|
|||||||
<CustomScrollbar autoHeightMin="100%" autoHeightMax="100%">
|
<CustomScrollbar autoHeightMin="100%" autoHeightMax="100%">
|
||||||
{this.history.map((v, idx) => (
|
{this.history.map((v, idx) => (
|
||||||
<div key={v.key}>
|
<div key={v.key}>
|
||||||
{v.key} {v.type} / X:{JSON.stringify(v.payload.x)} / Y:{JSON.stringify(v.payload.y)}
|
{JSON.stringify(v.path)} {v.type} / X:{JSON.stringify(v.payload.x)} / Y:{JSON.stringify(v.payload.y)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</CustomScrollbar>
|
</CustomScrollbar>
|
||||||
|
|||||||
Reference in New Issue
Block a user