Commit e375fb0f by Torkel Ödegaard Committed by GitHub

PanelEvents: Isolating angular panel events into it's own event bus + more event…

PanelEvents: Isolating angular panel events into it's own event bus + more event refactoring  (#29904)

* PanelEvents: Isolate angular events from panel model events, use new Event patterns

* Removing some events that are not longer needed

* Updated DashboardModel

* Update

* Review fixes
parent 334dfa7e
...@@ -22,7 +22,6 @@ export const PanelEvents = { ...@@ -22,7 +22,6 @@ export const PanelEvents = {
dataSnapshotLoad: eventFactory<DataQueryResponseData[]>('data-snapshot-load'), dataSnapshotLoad: eventFactory<DataQueryResponseData[]>('data-snapshot-load'),
editModeInitialized: eventFactory('init-edit-mode'), editModeInitialized: eventFactory('init-edit-mode'),
initPanelActions: eventFactory<AngularPanelMenuItem[]>('init-panel-actions'), initPanelActions: eventFactory<AngularPanelMenuItem[]>('init-panel-actions'),
panelSizeChanged: eventFactory('panel-size-changed'),
panelTeardown: eventFactory('panel-teardown'), panelTeardown: eventFactory('panel-teardown'),
render: eventFactory<any>('render'), render: eventFactory<any>('render'),
}; };
......
...@@ -14,7 +14,6 @@ import { ...@@ -14,7 +14,6 @@ import {
CoreApp, CoreApp,
DataQueryRequest, DataQueryRequest,
DataSourceApi, DataSourceApi,
PanelEvents,
rangeUtil, rangeUtil,
ScopedVars, ScopedVars,
} from '@grafana/data'; } from '@grafana/data';
...@@ -26,6 +25,7 @@ import { map, mergeMap } from 'rxjs/operators'; ...@@ -26,6 +25,7 @@ import { map, mergeMap } from 'rxjs/operators';
import { AnnotationQueryOptions, AnnotationQueryResponse } from './types'; import { AnnotationQueryOptions, AnnotationQueryResponse } from './types';
import { standardAnnotationSupport } from './standardAnnotationSupport'; import { standardAnnotationSupport } from './standardAnnotationSupport';
import { runRequest } from '../query/state/runRequest'; import { runRequest } from '../query/state/runRequest';
import { RefreshEvent } from 'app/types/events';
let counter = 100; let counter = 100;
function getNextRequestId() { function getNextRequestId() {
...@@ -41,7 +41,7 @@ export class AnnotationsSrv { ...@@ -41,7 +41,7 @@ export class AnnotationsSrv {
// always clearPromiseCaches when loading new dashboard // always clearPromiseCaches when loading new dashboard
this.clearPromiseCaches(); this.clearPromiseCaches();
// clear promises on refresh events // clear promises on refresh events
dashboard.on(PanelEvents.refresh, this.clearPromiseCaches.bind(this)); dashboard.events.subscribe(RefreshEvent, this.clearPromiseCaches.bind(this));
} }
clearPromiseCaches() { clearPromiseCaches() {
......
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { Button, JSONFormatter, LoadingPlaceholder } from '@grafana/ui'; import { Button, JSONFormatter, LoadingPlaceholder } from '@grafana/ui';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { AppEvents, PanelEvents, DataFrame } from '@grafana/data'; import { AppEvents, DataFrame } from '@grafana/data';
import appEvents from 'app/core/app_events'; import appEvents from 'app/core/app_events';
import { CopyToClipboard } from 'app/core/components/CopyToClipboard/CopyToClipboard'; import { CopyToClipboard } from 'app/core/components/CopyToClipboard/CopyToClipboard';
...@@ -10,8 +10,9 @@ import { getPanelInspectorStyles } from './styles'; ...@@ -10,8 +10,9 @@ import { getPanelInspectorStyles } from './styles';
import { supportsDataQuery } from '../PanelEditor/utils'; import { supportsDataQuery } from '../PanelEditor/utils';
import { config } from '@grafana/runtime'; import { config } from '@grafana/runtime';
import { css } from 'emotion'; import { css } from 'emotion';
import { Unsubscribable } from 'rxjs'; import { Subscription } from 'rxjs';
import { backendSrv } from 'app/core/services/backend_srv'; import { backendSrv } from 'app/core/services/backend_srv';
import { RefreshEvent } from 'app/types/events';
interface DsQuery { interface DsQuery {
isLoading: boolean; isLoading: boolean;
...@@ -39,9 +40,8 @@ interface State { ...@@ -39,9 +40,8 @@ interface State {
} }
export class QueryInspector extends PureComponent<Props, State> { export class QueryInspector extends PureComponent<Props, State> {
formattedJson: any; private formattedJson: any;
clipboard: any; private subs = new Subscription();
subscription?: Unsubscribable;
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
...@@ -58,11 +58,15 @@ export class QueryInspector extends PureComponent<Props, State> { ...@@ -58,11 +58,15 @@ export class QueryInspector extends PureComponent<Props, State> {
} }
componentDidMount() { componentDidMount() {
this.subscription = backendSrv.getInspectorStream().subscribe({ const { panel } = this.props;
next: response => this.onDataSourceResponse(response),
}); this.subs.add(
backendSrv.getInspectorStream().subscribe({
next: response => this.onDataSourceResponse(response),
})
);
this.props.panel.events.on(PanelEvents.refresh, this.onPanelRefresh); this.subs.add(panel.events.subscribe(RefreshEvent, this.onPanelRefresh));
this.updateQueryList(); this.updateQueryList();
} }
...@@ -112,13 +116,7 @@ export class QueryInspector extends PureComponent<Props, State> { ...@@ -112,13 +116,7 @@ export class QueryInspector extends PureComponent<Props, State> {
}; };
componentWillUnmount() { componentWillUnmount() {
const { panel } = this.props; this.subs.unsubscribe();
if (this.subscription) {
this.subscription.unsubscribe();
}
panel.events.off(PanelEvents.refresh, this.onPanelRefresh);
} }
onPanelRefresh = () => { onPanelRefresh = () => {
......
...@@ -28,7 +28,6 @@ interface GridWrapperProps { ...@@ -28,7 +28,6 @@ interface GridWrapperProps {
onDragStop: ItemCallback; onDragStop: ItemCallback;
onResize: ItemCallback; onResize: ItemCallback;
onResizeStop: ItemCallback; onResizeStop: ItemCallback;
onWidthChange: () => void;
className: string; className: string;
isResizable?: boolean; isResizable?: boolean;
isDraggable?: boolean; isDraggable?: boolean;
...@@ -43,7 +42,6 @@ function GridWrapper({ ...@@ -43,7 +42,6 @@ function GridWrapper({
onDragStop, onDragStop,
onResize, onResize,
onResizeStop, onResizeStop,
onWidthChange,
className, className,
isResizable, isResizable,
isDraggable, isDraggable,
...@@ -56,7 +54,6 @@ function GridWrapper({ ...@@ -56,7 +54,6 @@ function GridWrapper({
if (ignoreNextWidthChange) { if (ignoreNextWidthChange) {
ignoreNextWidthChange = false; ignoreNextWidthChange = false;
} else if (!viewPanel && Math.abs(width - lastGridWidth) > 8) { } else if (!viewPanel && Math.abs(width - lastGridWidth) > 8) {
onWidthChange();
lastGridWidth = width; lastGridWidth = width;
} }
} }
...@@ -164,12 +161,6 @@ export class DashboardGrid extends PureComponent<Props> { ...@@ -164,12 +161,6 @@ export class DashboardGrid extends PureComponent<Props> {
this.forceUpdate(); this.forceUpdate();
}; };
onWidthChange = () => {
for (const panel of this.props.dashboard.panels) {
panel.resizeDone();
}
};
updateGridPos = (item: ReactGridLayout.Layout, layout: ReactGridLayout.Layout[]) => { updateGridPos = (item: ReactGridLayout.Layout, layout: ReactGridLayout.Layout[]) => {
this.panelMap[item.i!].updateGridPos(item); this.panelMap[item.i!].updateGridPos(item);
...@@ -184,7 +175,6 @@ export class DashboardGrid extends PureComponent<Props> { ...@@ -184,7 +175,6 @@ export class DashboardGrid extends PureComponent<Props> {
onResizeStop: ItemCallback = (layout, oldItem, newItem) => { onResizeStop: ItemCallback = (layout, oldItem, newItem) => {
this.updateGridPos(newItem, layout); this.updateGridPos(newItem, layout);
this.panelMap[newItem.i!].resizeDone();
}; };
onDragStop: ItemCallback = (layout, oldItem, newItem) => { onDragStop: ItemCallback = (layout, oldItem, newItem) => {
...@@ -277,7 +267,6 @@ export class DashboardGrid extends PureComponent<Props> { ...@@ -277,7 +267,6 @@ export class DashboardGrid extends PureComponent<Props> {
isResizable={dashboard.meta.canEdit} isResizable={dashboard.meta.canEdit}
isDraggable={dashboard.meta.canEdit} isDraggable={dashboard.meta.canEdit}
onLayoutChange={this.onLayoutChange} onLayoutChange={this.onLayoutChange}
onWidthChange={this.onWidthChange}
onDragStop={this.onDragStop} onDragStop={this.onDragStop}
onResize={this.onResize} onResize={this.onResize}
onResizeStop={this.onResizeStop} onResizeStop={this.onResizeStop}
......
// Libraries // Libraries
import React, { Component } from 'react'; import React, { Component } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { Unsubscribable } from 'rxjs'; import { Subscription } from 'rxjs';
// Components // Components
import { PanelHeader } from './PanelHeader/PanelHeader'; import { PanelHeader } from './PanelHeader/PanelHeader';
import { ErrorBoundary } from '@grafana/ui'; import { ErrorBoundary } from '@grafana/ui';
...@@ -20,7 +20,6 @@ import { ...@@ -20,7 +20,6 @@ import {
DefaultTimeRange, DefaultTimeRange,
toUtc, toUtc,
toDataFrameDTO, toDataFrameDTO,
PanelEvents,
PanelData, PanelData,
PanelPlugin, PanelPlugin,
FieldConfigSource, FieldConfigSource,
...@@ -28,6 +27,7 @@ import { ...@@ -28,6 +27,7 @@ import {
} from '@grafana/data'; } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { loadSnapshotData } from '../utils/loadSnapshotData'; import { loadSnapshotData } from '../utils/loadSnapshotData';
import { RefreshEvent, RenderEvent } from 'app/types/events';
const DEFAULT_PLUGIN_ERROR = 'Error in plugin'; const DEFAULT_PLUGIN_ERROR = 'Error in plugin';
...@@ -52,9 +52,8 @@ export interface State { ...@@ -52,9 +52,8 @@ export interface State {
} }
export class PanelChrome extends Component<Props, State> { export class PanelChrome extends Component<Props, State> {
readonly timeSrv: TimeSrv = getTimeSrv(); private readonly timeSrv: TimeSrv = getTimeSrv();
private subs = new Subscription();
querySubscription?: Unsubscribable;
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
...@@ -75,8 +74,8 @@ export class PanelChrome extends Component<Props, State> { ...@@ -75,8 +74,8 @@ export class PanelChrome extends Component<Props, State> {
const { panel, dashboard } = this.props; const { panel, dashboard } = this.props;
// Subscribe to panel events // Subscribe to panel events
panel.events.on(PanelEvents.refresh, this.onRefresh); this.subs.add(panel.events.subscribe(RefreshEvent, this.onRefresh));
panel.events.on(PanelEvents.render, this.onRender); this.subs.add(panel.events.subscribe(RenderEvent, this.onRender));
dashboard.panelInitialized(this.props.panel); dashboard.panelInitialized(this.props.panel);
...@@ -93,21 +92,18 @@ export class PanelChrome extends Component<Props, State> { ...@@ -93,21 +92,18 @@ export class PanelChrome extends Component<Props, State> {
this.setState({ isFirstLoad: false }); this.setState({ isFirstLoad: false });
} }
this.querySubscription = panel this.subs.add(
.getQueryRunner() panel
.getData({ withTransforms: true, withFieldConfig: true }) .getQueryRunner()
.subscribe({ .getData({ withTransforms: true, withFieldConfig: true })
next: data => this.onDataUpdate(data), .subscribe({
}); next: data => this.onDataUpdate(data),
})
);
} }
componentWillUnmount() { componentWillUnmount() {
this.props.panel.events.off(PanelEvents.refresh, this.onRefresh); this.subs.unsubscribe();
this.props.panel.events.off(PanelEvents.render, this.onRender);
if (this.querySubscription) {
this.querySubscription.unsubscribe();
}
} }
componentDidUpdate(prevProps: Props) { componentDidUpdate(prevProps: Props) {
......
// Libraries // Libraries
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { Unsubscribable } from 'rxjs'; import { Subscription } from 'rxjs';
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux'; import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';
// Components // Components
import { PanelHeader } from './PanelHeader/PanelHeader'; import { PanelHeader } from './PanelHeader/PanelHeader';
...@@ -13,10 +13,11 @@ import config from 'app/core/config'; ...@@ -13,10 +13,11 @@ import config from 'app/core/config';
// Types // Types
import { DashboardModel, PanelModel } from '../state'; import { DashboardModel, PanelModel } from '../state';
import { StoreState } from 'app/types'; import { StoreState } from 'app/types';
import { DefaultTimeRange, LoadingState, PanelData, PanelEvents, PanelPlugin } from '@grafana/data'; import { DefaultTimeRange, LoadingState, PanelData, PanelPlugin } from '@grafana/data';
import { updateLocation } from 'app/core/actions'; import { updateLocation } from 'app/core/actions';
import { PANEL_BORDER } from 'app/core/constants'; import { PANEL_BORDER } from 'app/core/constants';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { RenderEvent } from 'app/types/events';
interface OwnProps { interface OwnProps {
panel: PanelModel; panel: PanelModel;
...@@ -59,7 +60,7 @@ export class PanelChromeAngularUnconnected extends PureComponent<Props, State> { ...@@ -59,7 +60,7 @@ export class PanelChromeAngularUnconnected extends PureComponent<Props, State> {
element: HTMLElement | null = null; element: HTMLElement | null = null;
timeSrv: TimeSrv = getTimeSrv(); timeSrv: TimeSrv = getTimeSrv();
scopeProps?: AngularScopeProps; scopeProps?: AngularScopeProps;
querySubscription: Unsubscribable; subs = new Subscription();
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
...@@ -80,16 +81,13 @@ export class PanelChromeAngularUnconnected extends PureComponent<Props, State> { ...@@ -80,16 +81,13 @@ export class PanelChromeAngularUnconnected extends PureComponent<Props, State> {
const queryRunner = panel.getQueryRunner(); const queryRunner = panel.getQueryRunner();
// we are not displaying any of this data so no need for transforms or field config // we are not displaying any of this data so no need for transforms or field config
this.querySubscription = queryRunner.getData({ withTransforms: false, withFieldConfig: false }).subscribe({ this.subs.add(
next: (data: PanelData) => this.onPanelDataUpdate(data), queryRunner.getData({ withTransforms: false, withFieldConfig: false }).subscribe({
}); next: (data: PanelData) => this.onPanelDataUpdate(data),
} })
);
subscribeToRenderEvent() { this.subs.add(panel.events.subscribe(RenderEvent, this.onPanelRenderEvent));
// Subscribe to render event, this is as far as I know only needed for changes to title & transparent
// These changes are modified in the model and only way to communicate that change is via this event
// Need to find another solution for this in tthe future (panel title in redux?)
this.props.panel.events.on(PanelEvents.render, this.onPanelRenderEvent);
} }
onPanelRenderEvent = (payload?: any) => { onPanelRenderEvent = (payload?: any) => {
...@@ -126,12 +124,7 @@ export class PanelChromeAngularUnconnected extends PureComponent<Props, State> { ...@@ -126,12 +124,7 @@ export class PanelChromeAngularUnconnected extends PureComponent<Props, State> {
componentWillUnmount() { componentWillUnmount() {
this.cleanUpAngularPanel(); this.cleanUpAngularPanel();
this.subs.unsubscribe();
if (this.querySubscription) {
this.querySubscription.unsubscribe();
}
this.props.panel.events.off(PanelEvents.render, this.onPanelRenderEvent);
} }
componentDidUpdate(prevProps: Props, prevState: State) { componentDidUpdate(prevProps: Props, prevState: State) {
...@@ -146,7 +139,7 @@ export class PanelChromeAngularUnconnected extends PureComponent<Props, State> { ...@@ -146,7 +139,7 @@ export class PanelChromeAngularUnconnected extends PureComponent<Props, State> {
if (this.scopeProps) { if (this.scopeProps) {
this.scopeProps.size.height = this.getInnerPanelHeight(); this.scopeProps.size.height = this.getInnerPanelHeight();
this.scopeProps.size.width = this.getInnerPanelWidth(); this.scopeProps.size.width = this.getInnerPanelWidth();
panel.events.emit(PanelEvents.panelSizeChanged); panel.render();
} }
} }
} }
...@@ -189,9 +182,6 @@ export class PanelChromeAngularUnconnected extends PureComponent<Props, State> { ...@@ -189,9 +182,6 @@ export class PanelChromeAngularUnconnected extends PureComponent<Props, State> {
panelId: panel.id, panelId: panel.id,
angularComponent: loader.load(this.element, this.scopeProps, template), angularComponent: loader.load(this.element, this.scopeProps, template),
}); });
// need to to this every time we load an angular as all events are unsubscribed when panel is destroyed
this.subscribeToRenderEvent();
} }
cleanUpAngularPanel() { cleanUpAngularPanel() {
......
...@@ -41,7 +41,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` ...@@ -41,7 +41,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
onLayoutChange={[Function]} onLayoutChange={[Function]}
onResize={[Function]} onResize={[Function]}
onResizeStop={[Function]} onResizeStop={[Function]}
onWidthChange={[Function]}
viewPanel={null} viewPanel={null}
> >
<div <div
......
...@@ -16,7 +16,6 @@ import { ...@@ -16,7 +16,6 @@ import {
DateTimeInput, DateTimeInput,
EventBusExtended, EventBusExtended,
EventBusSrv, EventBusSrv,
PanelEvents,
TimeRange, TimeRange,
TimeZone, TimeZone,
UrlQueryValue, UrlQueryValue,
...@@ -27,7 +26,7 @@ import { variableAdapters } from 'app/features/variables/adapters'; ...@@ -27,7 +26,7 @@ import { variableAdapters } from 'app/features/variables/adapters';
import { onTimeRangeUpdated } from 'app/features/variables/state/actions'; import { onTimeRangeUpdated } from 'app/features/variables/state/actions';
import { dispatch } from '../../../store/store'; import { dispatch } from '../../../store/store';
import { isAllVariable } from '../../variables/utils'; import { isAllVariable } from '../../variables/utils';
import { DashboardPanelsChangedEvent } from 'app/types/events'; import { DashboardPanelsChangedEvent, RefreshEvent, RenderEvent } from 'app/types/events';
export interface CloneOptions { export interface CloneOptions {
saveVariables?: boolean; saveVariables?: boolean;
...@@ -266,7 +265,7 @@ export class DashboardModel { ...@@ -266,7 +265,7 @@ export class DashboardModel {
} }
startRefresh() { startRefresh() {
this.events.emit(PanelEvents.refresh); this.events.publish(new RefreshEvent());
if (this.panelInEdit) { if (this.panelInEdit) {
this.panelInEdit.refresh(); this.panelInEdit.refresh();
...@@ -281,8 +280,7 @@ export class DashboardModel { ...@@ -281,8 +280,7 @@ export class DashboardModel {
} }
render() { render() {
this.events.emit(PanelEvents.render); this.events.publish(new RenderEvent());
for (const panel of this.panels) { for (const panel of this.panels) {
panel.render(); panel.render();
} }
...@@ -884,11 +882,15 @@ export class DashboardModel { ...@@ -884,11 +882,15 @@ export class DashboardModel {
return rowPanels; return rowPanels;
} }
/** @deprecated */
on<T>(event: AppEvent<T>, callback: (payload?: T) => void) { on<T>(event: AppEvent<T>, callback: (payload?: T) => void) {
console.log('DashboardModel.on is deprecated use events.subscribe');
this.events.on(event, callback); this.events.on(event, callback);
} }
/** @deprecated */
off<T>(event: AppEvent<T>, callback: (payload?: T) => void) { off<T>(event: AppEvent<T>, callback: (payload?: T) => void) {
console.log('DashboardModel.off is deprecated');
this.events.off(event, callback); this.events.off(event, callback);
} }
......
...@@ -28,7 +28,13 @@ import { ...@@ -28,7 +28,13 @@ import {
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';
import { PanelQueryRunner } from '../../query/state/PanelQueryRunner'; import { PanelQueryRunner } from '../../query/state/PanelQueryRunner';
import { PanelOptionsChangedEvent, PanelQueriesChangedEvent, PanelTransformationsChangedEvent } from 'app/types/events'; import {
PanelOptionsChangedEvent,
PanelQueriesChangedEvent,
PanelTransformationsChangedEvent,
RefreshEvent,
RenderEvent,
} from 'app/types/events';
import { getTimeSrv } from '../services/TimeSrv'; import { getTimeSrv } from '../services/TimeSrv';
import { getAllVariableValuesForUrl } from '../../variables/getAllVariableValuesForUrl'; import { getAllVariableValuesForUrl } from '../../variables/getAllVariableValuesForUrl';
...@@ -258,36 +264,22 @@ export class PanelModel implements DataConfigSource { ...@@ -258,36 +264,22 @@ export class PanelModel implements DataConfigSource {
} }
updateGridPos(newPos: GridPos) { updateGridPos(newPos: GridPos) {
let sizeChanged = false;
if (this.gridPos.w !== newPos.w || this.gridPos.h !== newPos.h) {
sizeChanged = true;
}
this.gridPos.x = newPos.x; this.gridPos.x = newPos.x;
this.gridPos.y = newPos.y; this.gridPos.y = newPos.y;
this.gridPos.w = newPos.w; this.gridPos.w = newPos.w;
this.gridPos.h = newPos.h; this.gridPos.h = newPos.h;
if (sizeChanged) {
this.events.emit(PanelEvents.panelSizeChanged);
}
}
resizeDone() {
this.events.emit(PanelEvents.panelSizeChanged);
} }
refresh() { refresh() {
this.hasRefreshed = true; this.hasRefreshed = true;
this.events.emit(PanelEvents.refresh); this.events.publish(new RefreshEvent());
} }
render() { render() {
if (!this.hasRefreshed) { if (!this.hasRefreshed) {
this.refresh(); this.refresh();
} else { } else {
this.events.emit(PanelEvents.render); this.events.publish(new RenderEvent());
} }
} }
......
...@@ -2,7 +2,14 @@ import _ from 'lodash'; ...@@ -2,7 +2,14 @@ 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 { auto } from 'angular'; import { auto } from 'angular';
import { AppEvent, PanelEvents, PanelPluginMeta, AngularPanelMenuItem, EventBusExtended } from '@grafana/data'; import {
AppEvent,
PanelEvents,
PanelPluginMeta,
AngularPanelMenuItem,
EventBusExtended,
EventBusSrv,
} from '@grafana/data';
import { DashboardModel } from '../dashboard/state'; import { DashboardModel } from '../dashboard/state';
export class PanelCtrl { export class PanelCtrl {
...@@ -30,7 +37,7 @@ export class PanelCtrl { ...@@ -30,7 +37,7 @@ export class PanelCtrl {
this.$scope = $scope; this.$scope = $scope;
this.$timeout = $injector.get('$timeout'); this.$timeout = $injector.get('$timeout');
this.editorTabs = []; this.editorTabs = [];
this.events = this.panel.events; this.events = new EventBusSrv();
this.timing = {}; // not used but here to not break plugins this.timing = {}; // not used but here to not break plugins
const plugin = config.panels[this.panel.type]; const plugin = config.panels[this.panel.type];
......
...@@ -4,6 +4,8 @@ import baron from 'baron'; ...@@ -4,6 +4,8 @@ import baron from 'baron';
import { PanelEvents } from '@grafana/data'; import { PanelEvents } from '@grafana/data';
import { PanelModel } from '../dashboard/state'; import { PanelModel } from '../dashboard/state';
import { PanelCtrl } from './panel_ctrl'; import { PanelCtrl } from './panel_ctrl';
import { Subscription } from 'rxjs';
import { RefreshEvent, RenderEvent } from 'app/types/events';
const module = angular.module('grafana.directives'); const module = angular.module('grafana.directives');
...@@ -20,6 +22,7 @@ module.directive('grafanaPanel', ($rootScope, $document, $timeout) => { ...@@ -20,6 +22,7 @@ module.directive('grafanaPanel', ($rootScope, $document, $timeout) => {
link: (scope: any, elem) => { link: (scope: any, elem) => {
const ctrl: PanelCtrl = scope.ctrl; const ctrl: PanelCtrl = scope.ctrl;
const panel: PanelModel = scope.ctrl.panel; const panel: PanelModel = scope.ctrl.panel;
const subs = new Subscription();
let panelScrollbar: any; let panelScrollbar: any;
...@@ -58,32 +61,38 @@ module.directive('grafanaPanel', ($rootScope, $document, $timeout) => { ...@@ -58,32 +61,38 @@ module.directive('grafanaPanel', ($rootScope, $document, $timeout) => {
} }
}); });
function onPanelSizeChanged() { function updateDimensionsFromParentScope() {
$timeout(() => {
resizeScrollableContent();
ctrl.render();
});
}
function onPanelModelRender(payload?: any) {
ctrl.height = scope.$parent.$parent.size.height; ctrl.height = scope.$parent.$parent.size.height;
ctrl.width = scope.$parent.$parent.size.width; ctrl.width = scope.$parent.$parent.size.width;
} }
function onPanelModelRefresh() { // Pass PanelModel events down to angular controller event emitter
ctrl.height = scope.$parent.$parent.size.height; subs.add(
ctrl.width = scope.$parent.$parent.size.width; panel.events.subscribe(RefreshEvent, () => {
} updateDimensionsFromParentScope();
ctrl.events.emit('refresh');
panel.events.on(PanelEvents.refresh, onPanelModelRefresh); })
panel.events.on(PanelEvents.render, onPanelModelRender); );
panel.events.on(PanelEvents.panelSizeChanged, onPanelSizeChanged);
subs.add(
panel.events.subscribe(RenderEvent, () => {
updateDimensionsFromParentScope();
$timeout(() => {
resizeScrollableContent();
ctrl.events.emit('render');
});
})
);
scope.$on('$destroy', () => { scope.$on('$destroy', () => {
elem.off(); elem.off();
panel.events.emit(PanelEvents.panelTeardown); // Remove PanelModel.event subs
panel.events.removeAllListeners(); subs.unsubscribe();
// Remove Angular controller event subs
ctrl.events.emit(PanelEvents.panelTeardown);
ctrl.events.removeAllListeners();
if (panelScrollbar) { if (panelScrollbar) {
panelScrollbar.dispose(); panelScrollbar.dispose();
......
...@@ -4,7 +4,7 @@ import _ from 'lodash'; ...@@ -4,7 +4,7 @@ import _ from 'lodash';
import config from 'app/core/config'; import config from 'app/core/config';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
import { DataSourceApi } from '@grafana/data'; import { DataSourceApi, PanelEvents } from '@grafana/data';
import { importPanelPlugin, importDataSourcePlugin, importAppPlugin } from './plugin_loader'; import { importPanelPlugin, importDataSourcePlugin, importAppPlugin } from './plugin_loader';
import DatasourceSrv from './datasource_srv'; import DatasourceSrv from './datasource_srv';
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl'; import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
...@@ -229,7 +229,7 @@ function pluginDirectiveLoader( ...@@ -229,7 +229,7 @@ function pluginDirectiveLoader(
elem.append(child); elem.append(child);
setTimeout(() => { setTimeout(() => {
scope.$applyAsync(() => { scope.$applyAsync(() => {
scope.$broadcast('component-did-mount'); scope.$broadcast(PanelEvents.componentDidMount.name);
}); });
}); });
}); });
......
...@@ -148,3 +148,11 @@ export class PanelOptionsChangedEvent extends BusEventBase { ...@@ -148,3 +148,11 @@ export class PanelOptionsChangedEvent extends BusEventBase {
export class DashboardPanelsChangedEvent extends BusEventBase { export class DashboardPanelsChangedEvent extends BusEventBase {
static type = 'dashboard-panels-changed'; static type = 'dashboard-panels-changed';
} }
export class RefreshEvent extends BusEventBase {
static type = 'refresh';
}
export class RenderEvent extends BusEventBase {
static type = 'render';
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment