panel_directive.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // @ts-ignore
  2. import baron from 'baron';
  3. import { Subscription } from 'rxjs';
  4. import { PanelEvents } from '@grafana/data';
  5. import { RefreshEvent } from '@grafana/runtime';
  6. import { coreModule } from 'app/angular/core_module';
  7. import { PanelDirectiveReadyEvent, RenderEvent } from 'app/types/events';
  8. import { PanelModel } from '../../features/dashboard/state';
  9. import { PanelCtrl } from './panel_ctrl';
  10. const panelTemplate = `
  11. <ng-transclude class="panel-height-helper"></ng-transclude>
  12. `;
  13. coreModule.directive('grafanaPanel', ($rootScope, $document, $timeout) => {
  14. return {
  15. restrict: 'E',
  16. template: panelTemplate,
  17. transclude: true,
  18. scope: { ctrl: '=' },
  19. link: (scope: any, elem) => {
  20. const ctrl: PanelCtrl = scope.ctrl;
  21. const panel: PanelModel = scope.ctrl.panel;
  22. const subs = new Subscription();
  23. let panelScrollbar: any;
  24. function resizeScrollableContent() {
  25. if (panelScrollbar) {
  26. panelScrollbar.update();
  27. }
  28. }
  29. ctrl.events.on(PanelEvents.componentDidMount, () => {
  30. if ((ctrl as any).__proto__.constructor.scrollable) {
  31. const scrollRootClass = 'baron baron__root baron__clipper panel-content--scrollable';
  32. const scrollerClass = 'baron__scroller';
  33. const scrollBarHTML = `
  34. <div class="baron__track">
  35. <div class="baron__bar"></div>
  36. </div>
  37. `;
  38. const scrollRoot = elem;
  39. const scroller = elem.find(':first').find(':first');
  40. scrollRoot.addClass(scrollRootClass);
  41. $(scrollBarHTML).appendTo(scrollRoot);
  42. scroller.addClass(scrollerClass);
  43. panelScrollbar = baron({
  44. root: scrollRoot[0],
  45. scroller: scroller[0],
  46. bar: '.baron__bar',
  47. barOnCls: '_scrollbar',
  48. scrollingCls: '_scrolling',
  49. });
  50. panelScrollbar.scroll();
  51. }
  52. });
  53. function updateDimensionsFromParentScope() {
  54. ctrl.height = scope.$parent.$parent.size.height;
  55. ctrl.width = scope.$parent.$parent.size.width;
  56. }
  57. updateDimensionsFromParentScope();
  58. // Pass PanelModel events down to angular controller event emitter
  59. subs.add(
  60. panel.events.subscribe(RefreshEvent, () => {
  61. updateDimensionsFromParentScope();
  62. ctrl.events.emit('refresh');
  63. })
  64. );
  65. subs.add(
  66. panel.events.subscribe(RenderEvent, (event) => {
  67. // this event originated from angular so no need to bubble it back
  68. if (event.payload?.fromAngular) {
  69. return;
  70. }
  71. updateDimensionsFromParentScope();
  72. $timeout(() => {
  73. resizeScrollableContent();
  74. ctrl.events.emit('render');
  75. });
  76. })
  77. );
  78. subs.add(
  79. ctrl.events.subscribe(RenderEvent, (event) => {
  80. // this event originated from angular so bubble it to react so the PanelChromeAngular can update the panel header alert state
  81. if (event.payload) {
  82. event.payload.fromAngular = true;
  83. panel.events.publish(event);
  84. }
  85. })
  86. );
  87. scope.$on('$destroy', () => {
  88. elem.off();
  89. // Remove PanelModel.event subs
  90. subs.unsubscribe();
  91. // Remove Angular controller event subs
  92. ctrl.events.emit(PanelEvents.panelTeardown);
  93. ctrl.events.removeAllListeners();
  94. if (panelScrollbar) {
  95. panelScrollbar.dispose();
  96. }
  97. });
  98. panel.events.publish(PanelDirectiveReadyEvent);
  99. },
  100. };
  101. });