viewStateSrv.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. define([
  2. 'angular',
  3. 'lodash',
  4. 'jquery',
  5. 'app/core/config'
  6. ],
  7. function (angular, _, $, config) {
  8. 'use strict';
  9. var module = angular.module('grafana.services');
  10. module.factory('dashboardViewStateSrv', function($location, $timeout) {
  11. // represents the transient view state
  12. // like fullscreen panel & edit
  13. function DashboardViewState($scope) {
  14. var self = this;
  15. self.state = {};
  16. self.panelScopes = [];
  17. self.$scope = $scope;
  18. self.dashboard = $scope.dashboard;
  19. $scope.exitFullscreen = function() {
  20. if (self.state.fullscreen) {
  21. self.update({ fullscreen: false });
  22. }
  23. };
  24. $scope.onAppEvent('$routeUpdate', function() {
  25. var urlState = self.getQueryStringState();
  26. if (self.needsSync(urlState)) {
  27. self.update(urlState, true);
  28. }
  29. });
  30. $scope.onAppEvent('panel-change-view', function(evt, payload) {
  31. self.update(payload);
  32. });
  33. $scope.onAppEvent('panel-initialized', function(evt, payload) {
  34. self.registerPanel(payload.scope);
  35. });
  36. this.update(this.getQueryStringState());
  37. this.expandRowForPanel();
  38. }
  39. DashboardViewState.prototype.expandRowForPanel = function() {
  40. if (!this.state.panelId) { return; }
  41. var panelInfo = this.$scope.dashboard.getPanelInfoById(this.state.panelId);
  42. if (panelInfo) {
  43. panelInfo.row.collapse = false;
  44. }
  45. };
  46. DashboardViewState.prototype.needsSync = function(urlState) {
  47. return _.isEqual(this.state, urlState) === false;
  48. };
  49. DashboardViewState.prototype.getQueryStringState = function() {
  50. var state = $location.search();
  51. state.panelId = parseInt(state.panelId) || null;
  52. state.fullscreen = state.fullscreen ? true : null;
  53. state.edit = (state.edit === "true" || state.edit === true) || null;
  54. state.editview = state.editview || null;
  55. state.orgId = config.bootData.user.orgId;
  56. return state;
  57. };
  58. DashboardViewState.prototype.serializeToUrl = function() {
  59. var urlState = _.clone(this.state);
  60. urlState.fullscreen = this.state.fullscreen ? true : null;
  61. urlState.edit = this.state.edit ? true : null;
  62. return urlState;
  63. };
  64. DashboardViewState.prototype.update = function(state, fromRouteUpdated) {
  65. // implement toggle logic
  66. if (state.toggle) {
  67. delete state.toggle;
  68. if (this.state.fullscreen && state.fullscreen) {
  69. if (this.state.edit === state.edit) {
  70. state.fullscreen = !state.fullscreen;
  71. }
  72. }
  73. }
  74. // remember if editStateChanged
  75. this.editStateChanged = state.edit !== this.state.edit;
  76. _.extend(this.state, state);
  77. this.dashboard.meta.fullscreen = this.state.fullscreen;
  78. if (!this.state.fullscreen) {
  79. this.state.fullscreen = null;
  80. this.state.edit = null;
  81. // clear panel id unless in solo mode
  82. if (!this.dashboard.meta.soloMode) {
  83. this.state.panelId = null;
  84. }
  85. }
  86. // if no edit state cleanup tab parm
  87. if (!this.state.edit) {
  88. delete this.state.tab;
  89. }
  90. // do not update url params if we are here
  91. // from routeUpdated event
  92. if (fromRouteUpdated !== true) {
  93. $location.search(this.serializeToUrl());
  94. }
  95. this.syncState();
  96. };
  97. DashboardViewState.prototype.syncState = function() {
  98. if (this.panelScopes.length === 0) { return; }
  99. if (this.dashboard.meta.fullscreen) {
  100. var panelScope = this.getPanelScope(this.state.panelId);
  101. if (!panelScope) {
  102. return;
  103. }
  104. if (this.fullscreenPanel) {
  105. // if already fullscreen
  106. if (this.fullscreenPanel === panelScope && this.editStateChanged === false) {
  107. return;
  108. } else {
  109. this.leaveFullscreen(false);
  110. }
  111. }
  112. if (!panelScope.ctrl.editModeInitiated) {
  113. panelScope.ctrl.initEditMode();
  114. }
  115. if (!panelScope.ctrl.fullscreen) {
  116. this.enterFullscreen(panelScope);
  117. }
  118. } else if (this.fullscreenPanel) {
  119. this.leaveFullscreen(true);
  120. }
  121. };
  122. DashboardViewState.prototype.getPanelScope = function(id) {
  123. return _.find(this.panelScopes, function(panelScope) {
  124. return panelScope.ctrl.panel.id === id;
  125. });
  126. };
  127. DashboardViewState.prototype.leaveFullscreen = function(render) {
  128. var self = this;
  129. var ctrl = self.fullscreenPanel.ctrl;
  130. ctrl.editMode = false;
  131. ctrl.fullscreen = false;
  132. ctrl.dashboard.editMode = this.oldDashboardEditMode;
  133. this.$scope.appEvent('panel-fullscreen-exit', {panelId: ctrl.panel.id});
  134. if (!render) { return false;}
  135. $timeout(function() {
  136. if (self.oldTimeRange !== ctrl.range) {
  137. self.$scope.broadcastRefresh();
  138. } else {
  139. self.$scope.$broadcast('render');
  140. }
  141. delete self.fullscreenPanel;
  142. });
  143. };
  144. DashboardViewState.prototype.enterFullscreen = function(panelScope) {
  145. var ctrl = panelScope.ctrl;
  146. ctrl.editMode = this.state.edit && this.dashboard.meta.canEdit;
  147. ctrl.fullscreen = true;
  148. this.oldDashboardEditMode = this.dashboard.editMode;
  149. this.oldTimeRange = ctrl.range;
  150. this.fullscreenPanel = panelScope;
  151. this.dashboard.editMode = false;
  152. $(window).scrollTop(0);
  153. this.$scope.appEvent('panel-fullscreen-enter', {panelId: ctrl.panel.id});
  154. $timeout(function() {
  155. ctrl.render();
  156. });
  157. };
  158. DashboardViewState.prototype.registerPanel = function(panelScope) {
  159. var self = this;
  160. self.panelScopes.push(panelScope);
  161. if (!self.dashboard.meta.soloMode) {
  162. if (self.state.panelId === panelScope.ctrl.panel.id) {
  163. if (self.state.edit) {
  164. panelScope.ctrl.editPanel();
  165. } else {
  166. panelScope.ctrl.viewPanel();
  167. }
  168. }
  169. }
  170. var unbind = panelScope.$on('$destroy', function() {
  171. self.panelScopes = _.without(self.panelScopes, panelScope);
  172. unbind();
  173. });
  174. };
  175. return {
  176. create: function($scope) {
  177. return new DashboardViewState($scope);
  178. }
  179. };
  180. });
  181. });