diff --git a/pkg/api/dashboard.go b/pkg/api/dashboard.go index eb1df4785ac..94e47b9b85d 100644 --- a/pkg/api/dashboard.go +++ b/pkg/api/dashboard.go @@ -276,6 +276,22 @@ func GetDashboardVersions(c *middleware.Context) Response { return ApiError(404, fmt.Sprintf("No versions found for dashboardId %d", dashboardId), err) } + for _, version := range query.Result { + if version.RestoredFrom == version.Version { + version.Message = "Initial save (created migration)" + continue + } + + if version.RestoredFrom > 0 { + version.Message = fmt.Sprintf("Restored from version %d", version.RestoredFrom) + continue + } + + if version.ParentVersion == 0 { + version.Message = "Initial save" + } + } + return Json(200, query.Result) } @@ -417,11 +433,12 @@ func RestoreDashboardVersion(c *middleware.Context, apiCmd dtos.RestoreDashboard version := versionQuery.Result saveCmd := m.SaveDashboardCommand{} + saveCmd.RestoredFrom = version.Version saveCmd.OrgId = c.OrgId saveCmd.UserId = c.UserId saveCmd.Dashboard = version.Data saveCmd.Dashboard.Set("version", dashboard.Version) - saveCmd.Message = fmt.Sprintf("Dashboard restored from version %d", version.Version) + saveCmd.Message = fmt.Sprintf("Restored from version %d", version.Version) return PostDashboard(c, saveCmd) } diff --git a/pkg/models/dashboards.go b/pkg/models/dashboards.go index eb0e442ad9a..0463e9c209b 100644 --- a/pkg/models/dashboards.go +++ b/pkg/models/dashboards.go @@ -131,12 +131,13 @@ func (dash *Dashboard) UpdateSlug() { // type SaveDashboardCommand struct { - Dashboard *simplejson.Json `json:"dashboard" binding:"Required"` - UserId int64 `json:"userId"` - OrgId int64 `json:"-"` - Overwrite bool `json:"overwrite"` - PluginId string `json:"-"` - Message string `json:"message"` + Dashboard *simplejson.Json `json:"dashboard" binding:"Required"` + UserId int64 `json:"userId"` + Overwrite bool `json:"overwrite"` + Message string `json:"message"` + OrgId int64 `json:"-"` + RestoredFrom int `json:"-"` + PluginId string `json:"-"` Result *Dashboard } diff --git a/pkg/services/sqlstore/dashboard.go b/pkg/services/sqlstore/dashboard.go index d3f3c115ca3..b46d1961305 100644 --- a/pkg/services/sqlstore/dashboard.go +++ b/pkg/services/sqlstore/dashboard.go @@ -93,7 +93,7 @@ func SaveDashboard(cmd *m.SaveDashboardCommand) error { dashVersion := &m.DashboardVersion{ DashboardId: dash.Id, ParentVersion: parentVersion, - RestoredFrom: -1, + RestoredFrom: cmd.RestoredFrom, Version: dash.Version, Created: time.Now(), CreatedBy: dash.UpdatedBy, diff --git a/pkg/services/sqlstore/migrations/dashboard_version_mig.go b/pkg/services/sqlstore/migrations/dashboard_version_mig.go index dbc3dc46007..01bced00dea 100644 --- a/pkg/services/sqlstore/migrations/dashboard_version_mig.go +++ b/pkg/services/sqlstore/migrations/dashboard_version_mig.go @@ -39,7 +39,7 @@ func addDashboardVersionMigration(mg *Migrator) { ) SELECT dashboard.id, - dashboard.version + 1, + dashboard.version, dashboard.version, dashboard.version, dashboard.updated, diff --git a/public/app/features/dashboard/history/history.html b/public/app/features/dashboard/history/history.html index 696265667dd..a739871b144 100644 --- a/public/app/features/dashboard/history/history.html +++ b/public/app/features/dashboard/history/history.html @@ -60,7 +60,7 @@ {{revision.message}} -   Restore +   Restore   Current diff --git a/public/app/features/dashboard/history/history.ts b/public/app/features/dashboard/history/history.ts index c1fb78a0e30..11091c6010f 100644 --- a/public/app/features/dashboard/history/history.ts +++ b/public/app/features/dashboard/history/history.ts @@ -125,31 +125,9 @@ export class HistoryListCtrl { limit: this.limit, start: this.start, }; + return this.historySrv.getHistoryList(this.dashboard, options).then(revisions => { - const formattedRevisions = _.flow( - _.partialRight(_.map, rev => _.extend({}, rev, { - checked: false, - message: (revision => { - if (revision.message === '') { - if (revision.version === 1) { - return 'Dashboard\'s initial save'; - } - - if (revision.restoredFrom > 0) { - return `Restored from version ${revision.restoredFrom}`; - } - - if (revision.parentVersion === 0) { - return 'Dashboard overwritten'; - } - - return 'Dashboard saved'; - } - return revision.message; - })(rev), - })))(revisions); - - this.revisions = append ? this.revisions.concat(formattedRevisions) : formattedRevisions; + this.revisions = append ? this.revisions.concat(revisions) : revisions; }).catch(err => { this.$rootScope.appEvent('alert-error', ['There was an error fetching the history list', (err.message || err)]); }).finally(() => { diff --git a/public/app/features/dashboard/specs/history_ctrl_specs.ts b/public/app/features/dashboard/specs/history_ctrl_specs.ts index e4fe847c4cc..fe64da04755 100644 --- a/public/app/features/dashboard/specs/history_ctrl_specs.ts +++ b/public/app/features/dashboard/specs/history_ctrl_specs.ts @@ -89,21 +89,6 @@ describe('HistoryListCtrl', function() { expect(ctx.ctrl.selected).to.eql([]); }); - it('should add a default message to versions without a message', function() { - expect(ctx.ctrl.revisions[0].message).to.be('Dashboard saved'); - }); - - it('should add a message to revisions restored from another version', function() { - expect(ctx.ctrl.revisions[1].message).to.be('Restored from version 1'); - }); - - it('should add a message to entries that overwrote version history', function() { - expect(ctx.ctrl.revisions[2].message).to.be('Dashboard overwritten'); - }); - - it('should add a message to the initial dashboard save', function() { - expect(ctx.ctrl.revisions[3].message).to.be('Dashboard\'s initial save'); - }); }); describe('and fetching the history list fails', function() { @@ -307,7 +292,6 @@ describe('HistoryListCtrl', function() { $rootScope, $scope: ctx.scope, }); - ctx.ctrl.$scope.setupDashboard = sinon.stub(); ctx.ctrl.dashboard = { id: 1 }; ctx.ctrl.restore(); ctx.ctrl.$scope.$apply(); @@ -318,99 +302,20 @@ describe('HistoryListCtrl', function() { expect($rootScope.appEvent.calledWith('confirm-modal')).to.be(true); }); - describe('from the diff view', function() { - it('should return to the list view on restore', function() { - ctx.ctrl.mode = 'compare'; - deferred.resolve(restoreResponse); - ctx.ctrl.restoreConfirm(RESTORE_ID); - ctx.ctrl.$scope.$apply(); - expect(ctx.ctrl.mode).to.be('list'); - }); - }); - - describe('and restore is selected and successful', function() { - beforeEach(function() { - deferred.resolve(restoreResponse); - ctx.ctrl.restoreConfirm(RESTORE_ID); - ctx.ctrl.$scope.$apply(); - }); - - it('should indicate loading has finished', function() { - expect(ctx.ctrl.loading).to.be(false); - }); - - it('should add an entry for the restored revision to the history list', function() { - expect(ctx.ctrl.revisions.length).to.be(5); - }); - - describe('the restored revision', function() { - var first; - beforeEach(function() { first = ctx.ctrl.revisions[0]; }); - - it('should have its `id` and `version` numbers incremented', function() { - expect(first.id).to.be(5); - expect(first.version).to.be(5); - }); - - it('should set `parentVersion` to the reverted version', function() { - expect(first.parentVersion).to.be(RESTORE_ID); - }); - - it('should set `dashboardId` to the dashboard\'s id', function() { - expect(first.dashboardId).to.be(1); - }); - - it('should set `created` to date to the current time', function() { - expect(_.isDate(first.created)).to.be(true); - }); - - it('should set `createdBy` to the username of the user who reverted', function() { - expect(first.createdBy).to.be('Carlos'); - }); - - it('should set `message` to the user\'s commit message', function() { - expect(first.message).to.be('Restored from version 4'); - }); - }); - - it('should reset the controller\'s state', function() { - expect(ctx.ctrl.mode).to.be('list'); - expect(ctx.ctrl.delta).to.eql({ basic: '', html: '' }); - expect(ctx.ctrl.selected.length).to.be(0); - expect(ctx.ctrl.selected).to.eql([]); - expect(_.find(ctx.ctrl.revisions, rev => rev.checked)).to.be.undefined; - }); - - it('should set the dashboard object to the response dashboard data', function() { - expect(ctx.ctrl.dashboard).to.eql(restoreResponse.dashboard.dashboard); - expect(ctx.ctrl.dashboard.meta).to.eql(restoreResponse.dashboard.meta); - }); - - it('should call setupDashboard to render new revision', function() { - expect(ctx.ctrl.$scope.setupDashboard.calledOnce).to.be(true); - expect(ctx.ctrl.$scope.setupDashboard.getCall(0).args[0]).to.eql(restoreResponse.dashboard); - }); - }); - describe('and restore fails to fetch', function() { beforeEach(function() { deferred.reject(new Error('RestoreError')); ctx.ctrl.restoreConfirm(RESTORE_ID); - ctx.ctrl.$scope.$apply(); + try { + // this throws error, due to promise rejection + ctx.ctrl.$scope.$apply(); + } catch (e) {} }); it('should indicate loading has finished', function() { expect(ctx.ctrl.loading).to.be(false); }); - it('should broadcast an event indicating the failure', function() { - expect($rootScope.appEvent.callCount).to.be(2); - expect($rootScope.appEvent.getCall(0).calledWith('confirm-modal')).to.be(true); - expect($rootScope.appEvent.getCall(1).args[0]).to.be('alert-error'); - expect($rootScope.appEvent.getCall(1).args[1][0]).to.be('There was an error restoring the dashboard'); - }); - - // TODO: test state after failure i.e. do we hide the modal or keep it visible }); }); });