// @ts-ignore import baron from 'baron'; import { Subscription } from 'rxjs'; import { PanelEvents } from '@grafana/data'; import { RefreshEvent } from '@grafana/runtime'; import { coreModule } from 'app/angular/core_module'; import { PanelDirectiveReadyEvent, RenderEvent } from 'app/types/events'; import { PanelModel } from '../../features/dashboard/state'; import { PanelCtrl } from './panel_ctrl'; const panelTemplate = ` `; coreModule.directive('grafanaPanel', ($rootScope, $document, $timeout) => { return { restrict: 'E', template: panelTemplate, transclude: true, scope: { ctrl: '=' }, link: (scope: any, elem) => { const ctrl: PanelCtrl = scope.ctrl; const panel: PanelModel = scope.ctrl.panel; const subs = new Subscription(); let panelScrollbar: any; function resizeScrollableContent() { if (panelScrollbar) { panelScrollbar.update(); } } ctrl.events.on(PanelEvents.componentDidMount, () => { if ((ctrl as any).__proto__.constructor.scrollable) { const scrollRootClass = 'baron baron__root baron__clipper panel-content--scrollable'; const scrollerClass = 'baron__scroller'; const scrollBarHTML = `
`; const scrollRoot = elem; const scroller = elem.find(':first').find(':first'); scrollRoot.addClass(scrollRootClass); $(scrollBarHTML).appendTo(scrollRoot); scroller.addClass(scrollerClass); panelScrollbar = baron({ root: scrollRoot[0], scroller: scroller[0], bar: '.baron__bar', barOnCls: '_scrollbar', scrollingCls: '_scrolling', }); panelScrollbar.scroll(); } }); function updateDimensionsFromParentScope() { ctrl.height = scope.$parent.$parent.size.height; ctrl.width = scope.$parent.$parent.size.width; } updateDimensionsFromParentScope(); // Pass PanelModel events down to angular controller event emitter subs.add( panel.events.subscribe(RefreshEvent, () => { updateDimensionsFromParentScope(); ctrl.events.emit('refresh'); }) ); subs.add( panel.events.subscribe(RenderEvent, (event) => { // this event originated from angular so no need to bubble it back if (event.payload?.fromAngular) { return; } updateDimensionsFromParentScope(); $timeout(() => { resizeScrollableContent(); ctrl.events.emit('render'); }); }) ); subs.add( ctrl.events.subscribe(RenderEvent, (event) => { // this event originated from angular so bubble it to react so the PanelChromeAngular can update the panel header alert state if (event.payload) { event.payload.fromAngular = true; panel.events.publish(event); } }) ); scope.$on('$destroy', () => { elem.off(); // Remove PanelModel.event subs subs.unsubscribe(); // Remove Angular controller event subs ctrl.events.emit(PanelEvents.panelTeardown); ctrl.events.removeAllListeners(); if (panelScrollbar) { panelScrollbar.dispose(); } }); panel.events.publish(PanelDirectiveReadyEvent); }, }; });