DashboardSrv.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import coreModule from 'app/core/core_module';
  2. import { appEvents } from 'app/core/app_events';
  3. import locationUtil from 'app/core/utils/location_util';
  4. import { DashboardModel } from '../state/DashboardModel';
  5. import { removePanel } from '../utils/panel';
  6. export class DashboardSrv {
  7. dashboard: DashboardModel;
  8. /** @ngInject */
  9. constructor(private backendSrv, private $rootScope, private $location) {
  10. appEvents.on('save-dashboard', this.saveDashboard.bind(this), $rootScope);
  11. appEvents.on('panel-change-view', this.onPanelChangeView);
  12. appEvents.on('remove-panel', this.onRemovePanel);
  13. }
  14. create(dashboard, meta) {
  15. return new DashboardModel(dashboard, meta);
  16. }
  17. setCurrent(dashboard: DashboardModel) {
  18. this.dashboard = dashboard;
  19. }
  20. getCurrent(): DashboardModel {
  21. return this.dashboard;
  22. }
  23. onRemovePanel = (panelId: number) => {
  24. const dashboard = this.getCurrent();
  25. removePanel(dashboard, dashboard.getPanelById(panelId), true);
  26. };
  27. onPanelChangeView = (options) => {
  28. const urlParams = this.$location.search();
  29. // handle toggle logic
  30. if (options.fullscreen === urlParams.fullscreen) {
  31. // I hate using these truthy converters (!!) but in this case
  32. // I think it's appropriate. edit can be null/false/undefined and
  33. // here i want all of those to compare the same
  34. if (!!options.edit === !!urlParams.edit) {
  35. delete urlParams.fullscreen;
  36. delete urlParams.edit;
  37. delete urlParams.panelId;
  38. this.$location.search(urlParams);
  39. return;
  40. }
  41. }
  42. if (options.fullscreen) {
  43. urlParams.fullscreen = true;
  44. } else {
  45. delete urlParams.fullscreen;
  46. }
  47. if (options.edit) {
  48. urlParams.edit = true;
  49. } else {
  50. delete urlParams.edit;
  51. }
  52. if (options.panelId || options.panelId === 0) {
  53. urlParams.panelId = options.panelId;
  54. } else {
  55. delete urlParams.panelId;
  56. }
  57. this.$location.search(urlParams);
  58. };
  59. handleSaveDashboardError(clone, options, err) {
  60. options = options || {};
  61. options.overwrite = true;
  62. if (err.data && err.data.status === 'version-mismatch') {
  63. err.isHandled = true;
  64. this.$rootScope.appEvent('confirm-modal', {
  65. title: 'Conflict',
  66. text: 'Someone else has updated this dashboard.',
  67. text2: 'Would you still like to save this dashboard?',
  68. yesText: 'Save & Overwrite',
  69. icon: 'fa-warning',
  70. onConfirm: () => {
  71. this.save(clone, options);
  72. },
  73. });
  74. }
  75. if (err.data && err.data.status === 'name-exists') {
  76. err.isHandled = true;
  77. this.$rootScope.appEvent('confirm-modal', {
  78. title: 'Conflict',
  79. text: 'A dashboard with the same name in selected folder already exists.',
  80. text2: 'Would you still like to save this dashboard?',
  81. yesText: 'Save & Overwrite',
  82. icon: 'fa-warning',
  83. onConfirm: () => {
  84. this.save(clone, options);
  85. },
  86. });
  87. }
  88. if (err.data && err.data.status === 'plugin-dashboard') {
  89. err.isHandled = true;
  90. this.$rootScope.appEvent('confirm-modal', {
  91. title: 'Plugin Dashboard',
  92. text: err.data.message,
  93. text2: 'Your changes will be lost when you update the plugin. Use Save As to create custom version.',
  94. yesText: 'Overwrite',
  95. icon: 'fa-warning',
  96. altActionText: 'Save As',
  97. onAltAction: () => {
  98. this.showSaveAsModal();
  99. },
  100. onConfirm: () => {
  101. this.save(clone, { overwrite: true });
  102. },
  103. });
  104. }
  105. }
  106. postSave(clone, data) {
  107. this.dashboard.version = data.version;
  108. // important that these happens before location redirect below
  109. this.$rootScope.appEvent('dashboard-saved', this.dashboard);
  110. this.$rootScope.appEvent('alert-success', ['Dashboard saved']);
  111. const newUrl = locationUtil.stripBaseFromUrl(data.url);
  112. const currentPath = this.$location.path();
  113. if (newUrl !== currentPath) {
  114. this.$location.url(newUrl).replace();
  115. }
  116. return this.dashboard;
  117. }
  118. save(clone, options) {
  119. options = options || {};
  120. options.folderId = options.folderId >= 0 ? options.folderId : this.dashboard.meta.folderId || clone.folderId;
  121. return this.backendSrv
  122. .saveDashboard(clone, options)
  123. .then(this.postSave.bind(this, clone))
  124. .catch(this.handleSaveDashboardError.bind(this, clone, options));
  125. }
  126. saveDashboard(options?, clone?) {
  127. if (clone) {
  128. this.setCurrent(this.create(clone, this.dashboard.meta));
  129. }
  130. if (this.dashboard.meta.provisioned) {
  131. return this.showDashboardProvisionedModal();
  132. }
  133. if (!this.dashboard.meta.canSave && options.makeEditable !== true) {
  134. return Promise.resolve();
  135. }
  136. if (this.dashboard.title === 'New dashboard') {
  137. return this.showSaveAsModal();
  138. }
  139. if (this.dashboard.version > 0) {
  140. return this.showSaveModal();
  141. }
  142. return this.save(this.dashboard.getSaveModelClone(), options);
  143. }
  144. saveJSONDashboard(json: string) {
  145. return this.save(JSON.parse(json), {});
  146. }
  147. showDashboardProvisionedModal() {
  148. this.$rootScope.appEvent('show-modal', {
  149. templateHtml: '<save-provisioned-dashboard-modal dismiss="dismiss()"></save-provisioned-dashboard-modal>',
  150. });
  151. }
  152. showSaveAsModal() {
  153. this.$rootScope.appEvent('show-modal', {
  154. templateHtml: '<save-dashboard-as-modal dismiss="dismiss()"></save-dashboard-as-modal>',
  155. modalClass: 'modal--narrow',
  156. });
  157. }
  158. showSaveModal() {
  159. this.$rootScope.appEvent('show-modal', {
  160. templateHtml: '<save-dashboard-modal dismiss="dismiss()"></save-dashboard-modal>',
  161. modalClass: 'modal--narrow',
  162. });
  163. }
  164. starDashboard(dashboardId, isStarred) {
  165. let promise;
  166. if (isStarred) {
  167. promise = this.backendSrv.delete('/api/user/stars/dashboard/' + dashboardId).then(() => {
  168. return false;
  169. });
  170. } else {
  171. promise = this.backendSrv.post('/api/user/stars/dashboard/' + dashboardId).then(() => {
  172. return true;
  173. });
  174. }
  175. return promise.then(res => {
  176. if (this.dashboard && this.dashboard.id === dashboardId) {
  177. this.dashboard.meta.isStarred = res;
  178. }
  179. return res;
  180. });
  181. }
  182. }
  183. coreModule.service('dashboardSrv', DashboardSrv);