history.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. import './history_srv';
  2. import _ from 'lodash';
  3. import angular from 'angular';
  4. import moment from 'moment';
  5. import locationUtil from 'app/core/utils/location_util';
  6. import { DashboardModel } from '../dashboard_model';
  7. import { HistoryListOpts, RevisionsModel, CalculateDiffOptions, HistorySrv } from './history_srv';
  8. export class HistoryListCtrl {
  9. appending: boolean;
  10. dashboard: DashboardModel;
  11. delta: { basic: string; json: string };
  12. diff: string;
  13. limit: number;
  14. loading: boolean;
  15. max: number;
  16. mode: string;
  17. revisions: RevisionsModel[];
  18. start: number;
  19. newInfo: RevisionsModel;
  20. baseInfo: RevisionsModel;
  21. canCompare: boolean;
  22. isNewLatest: boolean;
  23. /** @ngInject */
  24. constructor(
  25. private $route,
  26. private $rootScope,
  27. private $location,
  28. private $q,
  29. private historySrv: HistorySrv,
  30. public $scope
  31. ) {
  32. this.appending = false;
  33. this.diff = 'basic';
  34. this.limit = 10;
  35. this.loading = false;
  36. this.max = 2;
  37. this.mode = 'list';
  38. this.start = 0;
  39. this.canCompare = false;
  40. this.$rootScope.onAppEvent('dashboard-saved', this.onDashboardSaved.bind(this), $scope);
  41. this.resetFromSource();
  42. }
  43. onDashboardSaved() {
  44. this.resetFromSource();
  45. }
  46. switchMode(mode: string) {
  47. this.mode = mode;
  48. if (this.mode === 'list') {
  49. this.reset();
  50. }
  51. }
  52. dismiss() {
  53. this.$rootScope.appEvent('hide-dash-editor');
  54. }
  55. addToLog() {
  56. this.start = this.start + this.limit;
  57. this.getLog(true);
  58. }
  59. revisionSelectionChanged() {
  60. let selected = _.filter(this.revisions, { checked: true }).length;
  61. this.canCompare = selected === 2;
  62. }
  63. formatDate(date) {
  64. return this.dashboard.formatDate(date);
  65. }
  66. formatBasicDate(date) {
  67. const now = this.dashboard.timezone === 'browser' ? moment() : moment.utc();
  68. const then = this.dashboard.timezone === 'browser' ? moment(date) : moment.utc(date);
  69. return then.from(now);
  70. }
  71. getDiff(diff: string) {
  72. this.diff = diff;
  73. this.mode = 'compare';
  74. // have it already been fetched?
  75. if (this.delta[this.diff]) {
  76. return this.$q.when(this.delta[this.diff]);
  77. }
  78. const selected = _.filter(this.revisions, { checked: true });
  79. this.newInfo = selected[0];
  80. this.baseInfo = selected[1];
  81. this.isNewLatest = this.newInfo.version === this.dashboard.version;
  82. this.loading = true;
  83. const options: CalculateDiffOptions = {
  84. new: {
  85. dashboardId: this.dashboard.id,
  86. version: this.newInfo.version,
  87. },
  88. base: {
  89. dashboardId: this.dashboard.id,
  90. version: this.baseInfo.version,
  91. },
  92. diffType: diff,
  93. };
  94. return this.historySrv
  95. .calculateDiff(options)
  96. .then(response => {
  97. this.delta[this.diff] = response;
  98. })
  99. .catch(() => {
  100. this.mode = 'list';
  101. })
  102. .finally(() => {
  103. this.loading = false;
  104. });
  105. }
  106. getLog(append = false) {
  107. this.loading = !append;
  108. this.appending = append;
  109. const options: HistoryListOpts = {
  110. limit: this.limit,
  111. start: this.start,
  112. };
  113. return this.historySrv
  114. .getHistoryList(this.dashboard, options)
  115. .then(revisions => {
  116. // set formatted dates & default values
  117. for (let rev of revisions) {
  118. rev.createdDateString = this.formatDate(rev.created);
  119. rev.ageString = this.formatBasicDate(rev.created);
  120. rev.checked = false;
  121. }
  122. this.revisions = append ? this.revisions.concat(revisions) : revisions;
  123. })
  124. .catch(err => {
  125. this.loading = false;
  126. })
  127. .finally(() => {
  128. this.loading = false;
  129. this.appending = false;
  130. });
  131. }
  132. isLastPage() {
  133. return _.find(this.revisions, rev => rev.version === 1);
  134. }
  135. reset() {
  136. this.delta = { basic: '', json: '' };
  137. this.diff = 'basic';
  138. this.mode = 'list';
  139. this.revisions = _.map(this.revisions, rev => _.extend({}, rev, { checked: false }));
  140. this.canCompare = false;
  141. this.start = 0;
  142. this.isNewLatest = false;
  143. }
  144. resetFromSource() {
  145. this.revisions = [];
  146. return this.getLog().then(this.reset.bind(this));
  147. }
  148. restore(version: number) {
  149. this.$rootScope.appEvent('confirm-modal', {
  150. title: 'Restore version',
  151. text: '',
  152. text2: `Are you sure you want to restore the dashboard to version ${version}? All unsaved changes will be lost.`,
  153. icon: 'fa-history',
  154. yesText: `Yes, restore to version ${version}`,
  155. onConfirm: this.restoreConfirm.bind(this, version),
  156. });
  157. }
  158. restoreConfirm(version: number) {
  159. this.loading = true;
  160. return this.historySrv
  161. .restoreDashboard(this.dashboard, version)
  162. .then(response => {
  163. this.$location.url(locationUtil.stripBaseFromUrl(response.url)).replace();
  164. this.$route.reload();
  165. this.$rootScope.appEvent('alert-success', ['Dashboard restored', 'Restored from version ' + version]);
  166. })
  167. .catch(() => {
  168. this.mode = 'list';
  169. this.loading = false;
  170. });
  171. }
  172. }
  173. export function dashboardHistoryDirective() {
  174. return {
  175. restrict: 'E',
  176. templateUrl: 'public/app/features/dashboard/history/history.html',
  177. controller: HistoryListCtrl,
  178. bindToController: true,
  179. controllerAs: 'ctrl',
  180. scope: {
  181. dashboard: '=',
  182. },
  183. };
  184. }
  185. angular.module('grafana.directives').directive('gfDashboardHistory', dashboardHistoryDirective);