dashgrid.ts 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. ///<reference path="../../../headers/common.d.ts" />
  2. import $ from 'jquery';
  3. import coreModule from 'app/core/core_module';
  4. import {DashboardModel, CELL_HEIGHT, CELL_VMARGIN} from '../model';
  5. import 'jquery-ui';
  6. import 'gridstack';
  7. import 'gridstack.jquery-ui';
  8. const template = `
  9. <div class="grid-stack">
  10. <dash-grid-item ng-repeat="panel in ctrl.row.panels track by panel.id"
  11. class="grid-stack-item"
  12. grid-ctrl="ctrl"
  13. panel="panel">
  14. <plugin-component type="panel" class="grid-stack-item-content">
  15. </plugin-component>
  16. </dash-grid-item>
  17. </div>
  18. `;
  19. var rowIndex = 0;
  20. export class GridCtrl {
  21. options: any;
  22. row: any;
  23. dashboard: any;
  24. panels: any;
  25. gridstack: any;
  26. gridElem: any;
  27. isInitialized: boolean;
  28. isDestroyed: boolean;
  29. index: number;
  30. /** @ngInject */
  31. constructor(private $scope, private $element, private $timeout) {
  32. this.index = rowIndex;
  33. rowIndex += 1;
  34. }
  35. init() {
  36. this.gridElem = this.$element.find('.grid-stack');
  37. this.gridstack = this.gridElem.gridstack({
  38. animate: true,
  39. cellHeight: CELL_HEIGHT,
  40. verticalMargin: CELL_VMARGIN,
  41. acceptWidgets: '.grid-stack-item',
  42. handle: '.panel-header'
  43. }).data('gridstack');
  44. this.isInitialized = true;
  45. this.gridElem.on('added', (e, items) => {
  46. for (let item of items) {
  47. this.onGridStackItemAdded(item);
  48. }
  49. });
  50. this.gridElem.on('removed', (e, items) => {
  51. for (let item of items) {
  52. this.onGridStackItemRemoved(item);
  53. }
  54. });
  55. this.gridElem.on('change', (e, items) => {
  56. this.$timeout(() => this.onGridStackItemsChanged(items), 50);
  57. });
  58. }
  59. onGridStackItemAdded(item) {
  60. console.log('row: ' + this.index + ' item added', item);
  61. // if item has id dont need to do anything
  62. if (item.id) {
  63. return;
  64. }
  65. // if this comes from another row we need to remove it
  66. this.$timeout(() => this.gridstack.removeWidget(item.el, true));
  67. }
  68. onGridStackItemRemoved(item) {
  69. console.log('row: ' + this.index + ' item removed', item.id, item);
  70. // ignore items that have no panel id
  71. // if (!item.id) {
  72. // return;
  73. // }
  74. //
  75. // let panel = this.dashboard.getPanelById(parseInt(item.id));
  76. //
  77. // if (panel) {
  78. // panelChangingRow = panel
  79. // this.row.removePanel(panel, false);
  80. // }
  81. }
  82. onGridStackItemsChanged(items) {
  83. console.log('row: ' +this.index + ' changes', items);
  84. for (let item of items) {
  85. let isFromOtherRow = false;
  86. if (!item.id) {
  87. item.id = parseInt(item.el.attr('data-gs-id'));
  88. isFromOtherRow = true;
  89. }
  90. // find panel
  91. var panelInfo = this.dashboard.getPanelInfoById(parseInt(item.id));
  92. if (!panelInfo) {
  93. console.log('row: ' + this.index + ' item change but no panel found for item', item);
  94. continue;
  95. }
  96. // update panel model position
  97. let panel = panelInfo.panel;
  98. panel.x = item.x;
  99. panel.y = item.y;
  100. panel.width = item.width;
  101. panel.height = item.height;
  102. // wait a bit before adding
  103. if (isFromOtherRow) {
  104. let movePanelFn = (panel, row) => {
  105. return this.$timeout(() => {
  106. console.log('moving panel movel to another row', panel);
  107. // remove from source row
  108. row.removePanel(panel, false);
  109. // add this this row
  110. this.row.panels.push(panel);
  111. });
  112. };
  113. movePanelFn(panelInfo.panel, panelInfo.row);
  114. }
  115. }
  116. this.$scope.$broadcast('render');
  117. }
  118. destroy() {
  119. this.gridstack.destroy();
  120. this.gridstack = null;
  121. this.isDestroyed = true;
  122. }
  123. }
  124. /** @ngInject **/
  125. export function dashGrid($timeout) {
  126. return {
  127. restrict: 'E',
  128. template: template,
  129. controller: GridCtrl,
  130. bindToController: true,
  131. controllerAs: 'ctrl',
  132. scope: {
  133. row: "=",
  134. dashboard: "=",
  135. },
  136. link: function(scope, elem, attrs, ctrl) {
  137. $timeout(function() {
  138. ctrl.init();
  139. });
  140. scope.$on('$destroy', () => {
  141. ctrl.destroy();
  142. });
  143. }
  144. };
  145. }
  146. /** @ngInject **/
  147. export function dashGridItem($timeout, $rootScope) {
  148. return {
  149. restrict: "E",
  150. scope: {
  151. panel: '=',
  152. gridCtrl: '='
  153. },
  154. link: function (scope, element, attrs) {
  155. let gridCtrl = scope.gridCtrl;
  156. let panel = scope.panel;
  157. element.attr({
  158. 'data-gs-id': panel.id,
  159. 'data-gs-x': panel.x,
  160. 'data-gs-y': panel.y,
  161. 'data-gs-width': panel.width,
  162. 'data-gs-height': panel.height,
  163. });
  164. $rootScope.onAppEvent('panel-fullscreen-exit', (evt, payload) => {
  165. if (panel.id !== payload.panelId) {
  166. return;
  167. }
  168. element.removeClass('panel-fullscreen');
  169. }, scope);
  170. $rootScope.onAppEvent('panel-fullscreen-enter', (evt, payload) => {
  171. if (panel.id !== payload.panelId) {
  172. return;
  173. }
  174. element.addClass('panel-fullscreen');
  175. }, scope);
  176. scope.$on('$destroy', () => {
  177. console.log('grid-item scope $destroy');
  178. if (gridCtrl.isDestroyed) {
  179. return;
  180. }
  181. let node = element.data('_gridstack_node');
  182. if (node) {
  183. console.log('grid-item scope $destroy removeWidget');
  184. node._grid.removeWidget(element);
  185. }
  186. });
  187. if (gridCtrl.isInitialized) {
  188. gridCtrl.gridstack.makeWidget(element);
  189. }
  190. // scope.onItemRemoved({item: item});
  191. // ctrl.removeItem(element);
  192. //var item = element.data('_gridstack_node');
  193. //console.log('link item', item);
  194. //gridCtrl.bindItem(element);
  195. // element.bind('$destroy', function() {
  196. // var item = element.data('_gridstack_node');
  197. // scope.onItemRemoved({item: item});
  198. // ctrl.removeItem(element);
  199. // });
  200. }
  201. };
  202. }
  203. coreModule.directive('dashGrid', dashGrid);
  204. coreModule.directive('dashGridItem', dashGridItem);