mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Implement review feedback
This commit is contained in:
committed by
Ben Tranter
parent
a927b893ae
commit
77c046aac6
@@ -224,11 +224,11 @@ func (hs *HttpServer) registerRoutes() {
|
||||
r.Group("/dashboards", func() {
|
||||
r.Combo("/db/:slug").Get(GetDashboard).Delete(DeleteDashboard)
|
||||
|
||||
r.Get("/db/:dashboardId/versions", GetDashboardVersions)
|
||||
r.Get("/db/:dashboardId/versions/:id", GetDashboardVersion)
|
||||
r.Get("/db/:dashboardId/compare/:versions", CompareDashboardVersions)
|
||||
r.Get("/db/:dashboardId/compare/:versions/html", CompareDashboardVersionsJSON)
|
||||
r.Get("/db/:dashboardId/compare/:versions/basic", CompareDashboardVersionsBasic)
|
||||
r.Get("/db/:dashboardId/versions", wrap(GetDashboardVersions))
|
||||
r.Get("/db/:dashboardId/versions/:id", wrap(GetDashboardVersion))
|
||||
r.Get("/db/:dashboardId/compare/:versions", wrap(CompareDashboardVersions))
|
||||
r.Get("/db/:dashboardId/compare/:versions/html", wrap(CompareDashboardVersionsJSON))
|
||||
r.Get("/db/:dashboardId/compare/:versions/basic", wrap(CompareDashboardVersionsBasic))
|
||||
r.Post("/db/:dashboardId/restore", reqEditorRole, bind(m.RestoreDashboardVersionCommand{}), wrap(RestoreDashboardVersion))
|
||||
|
||||
r.Post("/db", reqEditorRole, bind(m.SaveDashboardCommand{}), wrap(PostDashboard))
|
||||
|
||||
@@ -258,16 +258,9 @@ func GetDashboardFromJsonFile(c *middleware.Context) {
|
||||
c.JSON(200, &dash)
|
||||
}
|
||||
|
||||
// GetDashboardVersions returns all dashboardversions as JSON
|
||||
func GetDashboardVersions(c *middleware.Context) {
|
||||
dashboardIdStr := c.Params(":dashboardId")
|
||||
dashboardId, err := strconv.Atoi(dashboardIdStr)
|
||||
if err != nil {
|
||||
c.JsonApiErr(400, err.Error(), err)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO(ben) the orderBy arg should be split into snake_case?
|
||||
// GetDashboardVersions returns all dashboard versions as JSON
|
||||
func GetDashboardVersions(c *middleware.Context) Response {
|
||||
dashboardId := c.ParamsInt64(":dashboardId")
|
||||
orderBy := c.Query("orderBy")
|
||||
limit := c.QueryInt("limit")
|
||||
start := c.QueryInt("start")
|
||||
@@ -279,62 +272,54 @@ func GetDashboardVersions(c *middleware.Context) {
|
||||
}
|
||||
|
||||
query := m.GetDashboardVersionsCommand{
|
||||
DashboardId: int64(dashboardId),
|
||||
DashboardId: dashboardId,
|
||||
OrderBy: orderBy,
|
||||
Limit: limit,
|
||||
Start: start,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
c.JsonApiErr(404, fmt.Sprintf("No versions found for dashboardId %d", dashboardId), err)
|
||||
return
|
||||
return ApiError(404, fmt.Sprintf("No versions found for dashboardId %d", dashboardId), err)
|
||||
}
|
||||
|
||||
dashboardVersions := make([]*m.DashboardVersionDTO, len(query.Result))
|
||||
for i, dashboardVersion := range query.Result {
|
||||
creator := "Anonymous"
|
||||
if dashboardVersion.CreatedBy > 0 {
|
||||
creator = getUserLogin(dashboardVersion.CreatedBy)
|
||||
}
|
||||
// // TODO(ben) use inner join with DTO
|
||||
// dashboardVersions := make([]*m.DashboardVersionDTO, len(query.Result))
|
||||
// for i, dashboardVersion := range query.Result {
|
||||
// creator := "Anonymous"
|
||||
// if dashboardVersion.CreatedBy > 0 {
|
||||
// creator = getUserLogin(dashboardVersion.CreatedBy)
|
||||
// }
|
||||
|
||||
dashboardVersions[i] = &m.DashboardVersionDTO{
|
||||
Id: dashboardVersion.Id,
|
||||
DashboardId: dashboardVersion.DashboardId,
|
||||
ParentVersion: dashboardVersion.ParentVersion,
|
||||
RestoredFrom: dashboardVersion.RestoredFrom,
|
||||
Version: dashboardVersion.Version,
|
||||
Created: dashboardVersion.Created,
|
||||
CreatedBy: creator,
|
||||
Message: dashboardVersion.Message,
|
||||
}
|
||||
}
|
||||
// dashboardVersions[i] = &m.DashboardVersionDTO{
|
||||
// Id: dashboardVersion.Id,
|
||||
// DashboardId: dashboardVersion.DashboardId,
|
||||
// ParentVersion: dashboardVersion.ParentVersion,
|
||||
// RestoredFrom: dashboardVersion.RestoredFrom,
|
||||
// Version: dashboardVersion.Version,
|
||||
// Created: dashboardVersion.Created,
|
||||
// CreatedBy: creator,
|
||||
// Message: dashboardVersion.Message,
|
||||
// }
|
||||
// }
|
||||
|
||||
c.JSON(200, dashboardVersions)
|
||||
return Json(200, query.Result)
|
||||
}
|
||||
|
||||
// GetDashboardVersion returns the dashboard version with the given ID.
|
||||
func GetDashboardVersion(c *middleware.Context) {
|
||||
dashboardIdStr := c.Params(":dashboardId")
|
||||
dashboardId, err := strconv.Atoi(dashboardIdStr)
|
||||
if err != nil {
|
||||
c.JsonApiErr(400, err.Error(), err)
|
||||
return
|
||||
}
|
||||
|
||||
versionStr := c.Params(":id")
|
||||
version, err := strconv.Atoi(versionStr)
|
||||
if err != nil {
|
||||
c.JsonApiErr(400, err.Error(), err)
|
||||
return
|
||||
}
|
||||
func GetDashboardVersion(c *middleware.Context) Response {
|
||||
dashboardId := c.ParamsInt64(":dashboardId")
|
||||
version := c.ParamsInt(":id")
|
||||
|
||||
query := m.GetDashboardVersionCommand{
|
||||
DashboardId: int64(dashboardId),
|
||||
DashboardId: dashboardId,
|
||||
Version: version,
|
||||
}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
c.JsonApiErr(500, err.Error(), err)
|
||||
return
|
||||
return ApiError(
|
||||
500,
|
||||
fmt.Sprintf("Dashboard version %d not found for dashboardId %d", version, dashboardId),
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
creator := "Anonymous"
|
||||
@@ -347,10 +332,10 @@ func GetDashboardVersion(c *middleware.Context) {
|
||||
CreatedBy: creator,
|
||||
}
|
||||
|
||||
c.JSON(200, dashVersionMeta)
|
||||
return Json(200, dashVersionMeta)
|
||||
}
|
||||
|
||||
func dashCmd(c *middleware.Context) (m.CompareDashboardVersionsCommand, error) {
|
||||
func createCompareDashboardVersionCommand(c *middleware.Context) (m.CompareDashboardVersionsCommand, error) {
|
||||
cmd := m.CompareDashboardVersionsCommand{}
|
||||
|
||||
dashboardIdStr := c.Params(":dashboardId")
|
||||
@@ -381,106 +366,82 @@ func dashCmd(c *middleware.Context) (m.CompareDashboardVersionsCommand, error) {
|
||||
}
|
||||
|
||||
// CompareDashboardVersions compares dashboards the way the GitHub API does.
|
||||
func CompareDashboardVersions(c *middleware.Context) {
|
||||
cmd, err := dashCmd(c)
|
||||
func CompareDashboardVersions(c *middleware.Context) Response {
|
||||
cmd, err := createCompareDashboardVersionCommand(c)
|
||||
if err != nil {
|
||||
c.JsonApiErr(500, err.Error(), err)
|
||||
return ApiError(500, err.Error(), err)
|
||||
}
|
||||
cmd.DiffType = m.DiffDelta
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "cannot-compute-diff", err)
|
||||
return
|
||||
return ApiError(500, "Unable to compute diff", err)
|
||||
}
|
||||
|
||||
// here the output is already JSON, so we need to unmarshal it into a
|
||||
// map before marshaling the entire response
|
||||
deltaMap := make(map[string]interface{})
|
||||
err = json.Unmarshal(cmd.Delta, &deltaMap)
|
||||
if err != nil {
|
||||
c.JsonApiErr(500, err.Error(), err)
|
||||
return
|
||||
return ApiError(500, err.Error(), err)
|
||||
}
|
||||
|
||||
c.JSON(200, simplejson.NewFromAny(util.DynMap{
|
||||
return Json(200, util.DynMap{
|
||||
"meta": util.DynMap{
|
||||
"original": cmd.Original,
|
||||
"new": cmd.New,
|
||||
},
|
||||
"delta": deltaMap,
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
// CompareDashboardVersionsJSON compares dashboards the way the GitHub API does,
|
||||
// returning a human-readable JSON diff.
|
||||
func CompareDashboardVersionsJSON(c *middleware.Context) {
|
||||
cmd, err := dashCmd(c)
|
||||
func CompareDashboardVersionsJSON(c *middleware.Context) Response {
|
||||
cmd, err := createCompareDashboardVersionCommand(c)
|
||||
if err != nil {
|
||||
c.JsonApiErr(500, err.Error(), err)
|
||||
return ApiError(500, err.Error(), err)
|
||||
}
|
||||
cmd.DiffType = m.DiffJSON
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, err.Error(), err)
|
||||
return
|
||||
return ApiError(500, err.Error(), err)
|
||||
}
|
||||
|
||||
c.Header().Set("Content-Type", "text/html")
|
||||
c.WriteHeader(200)
|
||||
c.Write(cmd.Delta)
|
||||
return Respond(200, cmd.Delta).Header("Content-Type", "text/html")
|
||||
}
|
||||
|
||||
// CompareDashboardVersionsBasic compares dashboards the way the GitHub API does,
|
||||
// returning a human-readable diff.
|
||||
func CompareDashboardVersionsBasic(c *middleware.Context) {
|
||||
cmd, err := dashCmd(c)
|
||||
func CompareDashboardVersionsBasic(c *middleware.Context) Response {
|
||||
cmd, err := createCompareDashboardVersionCommand(c)
|
||||
if err != nil {
|
||||
c.JsonApiErr(500, err.Error(), err)
|
||||
return ApiError(500, err.Error(), err)
|
||||
}
|
||||
cmd.DiffType = m.DiffBasic
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, err.Error(), err)
|
||||
return
|
||||
return ApiError(500, err.Error(), err)
|
||||
}
|
||||
|
||||
c.Header().Set("Content-Type", "text/html")
|
||||
c.WriteHeader(200)
|
||||
c.Write(cmd.Delta)
|
||||
return Respond(200, cmd.Delta).Header("Content-Type", "text/html")
|
||||
}
|
||||
|
||||
// RestoreDashboardVersion restores a dashboard to the given version.
|
||||
func RestoreDashboardVersion(c *middleware.Context, cmd m.RestoreDashboardVersionCommand) Response {
|
||||
if !c.IsSignedIn {
|
||||
return Json(401, util.DynMap{
|
||||
"message": "Must be signed in to restore a version",
|
||||
"status": "unauthorized",
|
||||
})
|
||||
return ApiError(401, "Must be signed in to restore a version", nil)
|
||||
}
|
||||
|
||||
cmd.UserId = c.UserId
|
||||
dashboardIdStr := c.Params(":dashboardId")
|
||||
dashboardId, err := strconv.Atoi(dashboardIdStr)
|
||||
if err != nil {
|
||||
return Json(404, util.DynMap{
|
||||
"message": err.Error(),
|
||||
"status": "cannot-find-dashboard",
|
||||
})
|
||||
}
|
||||
cmd.DashboardId = int64(dashboardId)
|
||||
cmd.DashboardId = c.ParamsInt64(":dashboardId")
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Json(500, util.DynMap{
|
||||
"message": err.Error(),
|
||||
"status": "cannot-restore-version",
|
||||
})
|
||||
return ApiError(500, "Cannot restore version", err)
|
||||
}
|
||||
|
||||
isStarred, err := isDashboardStarredByUser(c, cmd.Result.Id)
|
||||
if err != nil {
|
||||
return Json(500, util.DynMap{
|
||||
"message": "Error while checking if dashboard was starred by user",
|
||||
"status": err.Error(),
|
||||
})
|
||||
return ApiError(500, "Error checking if dashboard is starred by user", err)
|
||||
}
|
||||
|
||||
// Finding creator and last updater of the dashboard
|
||||
|
||||
@@ -80,7 +80,7 @@ type GetDashboardVersionsCommand struct {
|
||||
Limit int `json:"limit"`
|
||||
Start int `json:"start"`
|
||||
|
||||
Result []*DashboardVersion
|
||||
Result []*DashboardVersionDTO
|
||||
}
|
||||
|
||||
// RestoreDashboardVersionCommand creates a new dashboard version.
|
||||
|
||||
@@ -91,15 +91,25 @@ func GetDashboardVersion(query *m.GetDashboardVersionCommand) error {
|
||||
|
||||
// GetDashboardVersions gets all dashboard versions for the given dashboard ID.
|
||||
func GetDashboardVersions(query *m.GetDashboardVersionsCommand) error {
|
||||
order := ""
|
||||
|
||||
// the query builder in xorm doesn't provide a way to set
|
||||
// a default order, so we perform this check
|
||||
if query.OrderBy != "" {
|
||||
order = " desc"
|
||||
if query.OrderBy == "" {
|
||||
query.OrderBy = "version"
|
||||
}
|
||||
err := x.In("dashboard_id", query.DashboardId).
|
||||
OrderBy(query.OrderBy+order).
|
||||
query.OrderBy += " desc"
|
||||
|
||||
err := x.Table("dashboard_version").
|
||||
Select(`dashboard_version.id,
|
||||
dashboard_version.dashboard_id,
|
||||
dashboard_version.parent_version,
|
||||
dashboard_version.restored_from,
|
||||
dashboard_version.version,
|
||||
dashboard_version.created,
|
||||
dashboard_version.created_by as created_by_id,
|
||||
dashboard_version.message,
|
||||
dashboard_version.data,
|
||||
"user".login as created_by`).
|
||||
Join("LEFT", "user", `dashboard_version.created_by = "user".id`).
|
||||
Where("dashboard_version.dashboard_id=?", query.DashboardId).
|
||||
OrderBy("dashboard_version."+query.OrderBy).
|
||||
Limit(query.Limit, query.Start).
|
||||
Find(&query.Result)
|
||||
if err != nil {
|
||||
|
||||
@@ -8,7 +8,7 @@ function ($, coreModule) {
|
||||
var editViewMap = {
|
||||
'settings': { src: 'public/app/features/dashboard/partials/settings.html'},
|
||||
'annotations': { src: 'public/app/features/annotations/partials/editor.html'},
|
||||
'audit': { src: 'public/app/features/dashboard/audit/partials/audit.html'},
|
||||
'history': { src: 'public/app/features/dashboard/history/partials/history.html'},
|
||||
'templating': { src: 'public/app/features/templating/partials/editor.html'},
|
||||
'import': { src: '<dash-import></dash-import>' }
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@ import coreModule from '../core_module';
|
||||
export class DeltaCtrl {
|
||||
observer: any;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private $rootScope) {
|
||||
const waitForCompile = function(mutations) {
|
||||
if (mutations.length === 1) {
|
||||
@@ -70,7 +71,7 @@ export function linkJson() {
|
||||
link: '@lineLink',
|
||||
switchView: '&',
|
||||
},
|
||||
templateUrl: 'public/app/features/dashboard/audit/partials/link-json.html',
|
||||
templateUrl: 'public/app/features/dashboard/history/partials/link-json.html',
|
||||
};
|
||||
}
|
||||
coreModule.directive('diffLinkJson', linkJson);
|
||||
|
||||
@@ -2,7 +2,6 @@ define([
|
||||
'./panellinks/module',
|
||||
'./dashlinks/module',
|
||||
'./annotations/all',
|
||||
'./annotations/annotations_srv',
|
||||
'./templating/all',
|
||||
'./dashboard/all',
|
||||
'./playlist/all',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
define([
|
||||
'./dashboard_ctrl',
|
||||
'./alerting_srv',
|
||||
'./audit/audit_srv',
|
||||
'./history/history',
|
||||
'./dashboardLoaderSrv',
|
||||
'./dashnav/dashnav',
|
||||
'./submenu/submenu',
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
<ul class="dropdown-menu">
|
||||
<li ng-if="dashboardMeta.canEdit"><a class="pointer" ng-click="openEditView('settings');">Settings</a></li>
|
||||
<li ng-if="dashboardMeta.canEdit"><a class="pointer" ng-click="openEditView('annotations');">Annotations</a></li>
|
||||
<li ng-if="dashboardMeta.canEdit && dashboard.version > 0 && !dashboardMeta.isHome"><a class="pointer" ng-click="openEditView('audit');">Changelog</a></li>
|
||||
<li ng-if="dashboardMeta.canEdit && dashboard.version > 0 && !dashboardMeta.isHome"><a class="pointer" ng-click="openEditView('history');">Changelog</a></li>
|
||||
<li ng-if="dashboardMeta.canEdit"><a class="pointer" ng-click="openEditView('templating');">Templating</a></li>
|
||||
<li ng-if="dashboardMeta.canEdit"><a class="pointer" ng-click="viewJson();">View JSON</a></li>
|
||||
<li ng-if="contextSrv.isEditor && !dashboard.editable"><a class="pointer" ng-click="makeEditable();">Make Editable</a></li>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div ng-controller="AuditLogCtrl">
|
||||
<div>
|
||||
<div class="tabbed-view-header">
|
||||
<h2 class="tabbed-view-title">
|
||||
Changelog
|
||||
@@ -12,10 +12,10 @@
|
||||
</li>
|
||||
<li class="gf-tabs-item" ng-show="ctrl.mode === 'compare'">
|
||||
<span ng-if="ctrl.isOriginalCurrent()" class="active gf-tabs-link">
|
||||
Version {{ctrl.selected[0]}} <i class="fa fa-arrows-h" /> Current
|
||||
Version {{ctrl.selected[0]}} <i class="fa fa-arrows-h"></i> Current
|
||||
</span>
|
||||
<span ng-if="!ctrl.isOriginalCurrent()" class="active gf-tabs-link">
|
||||
Version {{ctrl.selected[0]}} <i class="fa fa-arrows-h" /> Version {{ctrl.selected[1]}}
|
||||
Version {{ctrl.selected[0]}} <i class="fa fa-arrows-h"></i> Version {{ctrl.selected[1]}}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -30,11 +30,11 @@
|
||||
<div ng-if="ctrl.mode === 'list'">
|
||||
<div ng-if="ctrl.loading">
|
||||
<i class="fa fa-spinner fa-spin"></i>
|
||||
<em>Fetching audit log…</em>
|
||||
<em>Fetching history list…</em>
|
||||
</div>
|
||||
|
||||
<div ng-if="!ctrl.loading">
|
||||
<div class="audit-table gf-form">
|
||||
<div class="history-table gf-form">
|
||||
<div class="gf-form-group">
|
||||
<table class="filter-table">
|
||||
<thead>
|
||||
@@ -102,7 +102,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="audit-log" ng-if="ctrl.mode === 'compare'">
|
||||
<div class="history-list" ng-if="ctrl.mode === 'compare'">
|
||||
<div class="page-container">
|
||||
<div class="page-body">
|
||||
<aside class="page-sidebar">
|
||||
@@ -129,7 +129,7 @@
|
||||
</a>
|
||||
<h4>
|
||||
Comparing Version {{ctrl.selected[0]}}
|
||||
<i class="fa fa-arrows-h" />
|
||||
<i class="fa fa-arrows-h"></i>
|
||||
Version {{ctrl.selected[1]}}
|
||||
<cite class="muted" ng-if="ctrl.isOriginalCurrent()">(Current)</cite>
|
||||
</h4>
|
||||
@@ -148,8 +148,8 @@
|
||||
</p>
|
||||
</section>
|
||||
<div id="delta" diff-delta>
|
||||
<div class="delta-basic" ng-show="ctrl.diff === 'basic'" compile="ctrl.delta.basic" />
|
||||
<div class="delta-html" ng-show="ctrl.diff === 'html'" compile="ctrl.delta.html" />
|
||||
<div class="delta-basic" ng-show="ctrl.diff === 'basic'" compile="ctrl.delta.basic"></div>
|
||||
<div class="delta-html" ng-show="ctrl.diff === 'html'" compile="ctrl.delta.html"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,15 +1,15 @@
|
||||
///<reference path="../../../headers/common.d.ts" />
|
||||
|
||||
import './history_srv';
|
||||
|
||||
import _ from 'lodash';
|
||||
import angular from 'angular';
|
||||
import moment from 'moment';
|
||||
|
||||
import coreModule from 'app/core/core_module';
|
||||
|
||||
import {DashboardModel} from '../model';
|
||||
import {AuditLogOpts, RevisionsModel} from './models';
|
||||
import {HistoryListOpts, RevisionsModel} from './models';
|
||||
|
||||
export class AuditLogCtrl {
|
||||
export class HistoryListCtrl {
|
||||
appending: boolean;
|
||||
dashboard: DashboardModel;
|
||||
delta: { basic: string; html: string; };
|
||||
@@ -29,11 +29,10 @@ export class AuditLogCtrl {
|
||||
private $window,
|
||||
private $q,
|
||||
private contextSrv,
|
||||
private auditSrv) {
|
||||
private historySrv) {
|
||||
$scope.ctrl = this;
|
||||
|
||||
this.appending = false;
|
||||
this.dashboard = $scope.dashboard;
|
||||
this.diff = 'basic';
|
||||
this.limit = 10;
|
||||
this.loading = false;
|
||||
@@ -106,7 +105,7 @@ export class AuditLogCtrl {
|
||||
this.loading = false;
|
||||
return this.$q.when(this.delta[this.diff]);
|
||||
} else {
|
||||
return this.auditSrv.compareVersions(this.dashboard, compare, diff).then(response => {
|
||||
return this.historySrv.compareVersions(this.dashboard, compare, diff).then(response => {
|
||||
this.delta[this.diff] = response;
|
||||
}).catch(err => {
|
||||
this.mode = 'list';
|
||||
@@ -118,12 +117,12 @@ export class AuditLogCtrl {
|
||||
getLog(append = false) {
|
||||
this.loading = !append;
|
||||
this.appending = append;
|
||||
const options: AuditLogOpts = {
|
||||
const options: HistoryListOpts = {
|
||||
limit: this.limit,
|
||||
start: this.start,
|
||||
orderBy: this.orderBy,
|
||||
};
|
||||
return this.auditSrv.getAuditLog(this.dashboard, options).then(revisions => {
|
||||
return this.historySrv.getHistoryList(this.dashboard, options).then(revisions => {
|
||||
const formattedRevisions = _.flow(
|
||||
_.partialRight(_.map, rev => _.extend({}, rev, {
|
||||
checked: false,
|
||||
@@ -149,7 +148,7 @@ export class AuditLogCtrl {
|
||||
|
||||
this.revisions = append ? this.revisions.concat(formattedRevisions) : formattedRevisions;
|
||||
}).catch(err => {
|
||||
this.$rootScope.appEvent('alert-error', ['There was an error fetching the audit log', (err.message || err)]);
|
||||
this.$rootScope.appEvent('alert-error', ['There was an error fetching the history list', (err.message || err)]);
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
this.appending = false;
|
||||
@@ -209,7 +208,7 @@ export class AuditLogCtrl {
|
||||
|
||||
restoreConfirm(version: number) {
|
||||
this.loading = true;
|
||||
return this.auditSrv.restoreDashboard(this.dashboard, version).then(response => {
|
||||
return this.historySrv.restoreDashboard(this.dashboard, version).then(response => {
|
||||
this.revisions.unshift({
|
||||
id: this.revisions[0].id + 1,
|
||||
checked: false,
|
||||
@@ -232,4 +231,17 @@ export class AuditLogCtrl {
|
||||
}
|
||||
}
|
||||
|
||||
coreModule.controller('AuditLogCtrl', AuditLogCtrl);
|
||||
export function dashboardHistoryDirective() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
templateUrl: 'public/app/features/dashboard/history/history.html',
|
||||
controller: HistoryListCtrl,
|
||||
bindToController: true,
|
||||
controllerAs: 'ctrl',
|
||||
scope: {
|
||||
dashboard: "="
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
angular.module('grafana.directives').directive('gfDashboardHistory', dashboardHistoryDirective);
|
||||
@@ -1,17 +1,15 @@
|
||||
///<reference path="../../../headers/common.d.ts" />
|
||||
|
||||
import './audit_ctrl';
|
||||
|
||||
import _ from 'lodash';
|
||||
import coreModule from 'app/core/core_module';
|
||||
import {DashboardModel} from '../model';
|
||||
import {AuditLogOpts} from './models';
|
||||
import {HistoryListOpts} from './models';
|
||||
|
||||
export class AuditSrv {
|
||||
export class HistorySrv {
|
||||
/** @ngInject */
|
||||
constructor(private backendSrv, private $q) {}
|
||||
|
||||
getAuditLog(dashboard: DashboardModel, options: AuditLogOpts) {
|
||||
getHistoryList(dashboard: DashboardModel, options: HistoryListOpts) {
|
||||
const id = dashboard && dashboard.id ? dashboard.id : void 0;
|
||||
return id ? this.backendSrv.get(`api/dashboards/db/${id}/versions`, options) : this.$q.when([]);
|
||||
}
|
||||
@@ -29,4 +27,4 @@ export class AuditSrv {
|
||||
}
|
||||
}
|
||||
|
||||
coreModule.service('auditSrv', AuditSrv);
|
||||
coreModule.service('historySrv', HistorySrv);
|
||||
@@ -1,4 +1,4 @@
|
||||
export interface AuditLogOpts {
|
||||
export interface HistoryListOpts {
|
||||
limit: number;
|
||||
start: number;
|
||||
orderBy: string;
|
||||
@@ -0,0 +1 @@
|
||||
<gf-dashboard-history dashboard="dashboard"></gf-dashboard-history>
|
||||
@@ -1,11 +1,11 @@
|
||||
import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/common';
|
||||
|
||||
import _ from 'lodash';
|
||||
import {AuditLogCtrl} from 'app/features/dashboard/audit/audit_ctrl';
|
||||
import { versions, compare, restore } from 'test/mocks/audit-mocks';
|
||||
import {HistoryListCtrl} from 'app/features/dashboard/history/history';
|
||||
import { versions, compare, restore } from 'test/mocks/history-mocks';
|
||||
import config from 'app/core/config';
|
||||
|
||||
describe('AuditLogCtrl', function() {
|
||||
describe('HistoryListCtrl', function() {
|
||||
var RESTORE_ID = 4;
|
||||
|
||||
var ctx: any = {};
|
||||
@@ -18,11 +18,11 @@ describe('AuditLogCtrl', function() {
|
||||
ctx.scope = $rootScope.$new();
|
||||
}));
|
||||
|
||||
var auditSrv;
|
||||
var historySrv;
|
||||
var $rootScope;
|
||||
beforeEach(function() {
|
||||
auditSrv = {
|
||||
getAuditLog: sinon.stub(),
|
||||
historySrv = {
|
||||
getHistoryList: sinon.stub(),
|
||||
compareVersions: sinon.stub(),
|
||||
restoreDashboard: sinon.stub(),
|
||||
};
|
||||
@@ -32,24 +32,24 @@ describe('AuditLogCtrl', function() {
|
||||
};
|
||||
});
|
||||
|
||||
describe('when the audit log component is loaded', function() {
|
||||
describe('when the history list component is loaded', function() {
|
||||
var deferred;
|
||||
|
||||
beforeEach(angularMocks.inject(($controller, $q) => {
|
||||
deferred = $q.defer();
|
||||
auditSrv.getAuditLog.returns(deferred.promise);
|
||||
ctx.ctrl = $controller(AuditLogCtrl, {
|
||||
auditSrv,
|
||||
historySrv.getHistoryList.returns(deferred.promise);
|
||||
ctx.ctrl = $controller(HistoryListCtrl, {
|
||||
historySrv,
|
||||
$rootScope,
|
||||
$scope: ctx.scope,
|
||||
});
|
||||
}));
|
||||
|
||||
it('should immediately attempt to fetch the audit log', function() {
|
||||
expect(auditSrv.getAuditLog.calledOnce).to.be(true);
|
||||
it('should immediately attempt to fetch the history list', function() {
|
||||
expect(historySrv.getHistoryList.calledOnce).to.be(true);
|
||||
});
|
||||
|
||||
describe('and the audit log is successfully fetched', function() {
|
||||
describe('and the history list is successfully fetched', function() {
|
||||
beforeEach(function() {
|
||||
deferred.resolve(versionsResponse);
|
||||
ctx.ctrl.$scope.$apply();
|
||||
@@ -106,9 +106,9 @@ describe('AuditLogCtrl', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('and fetching the audit log fails', function() {
|
||||
describe('and fetching the history list fails', function() {
|
||||
beforeEach(function() {
|
||||
deferred.reject(new Error('AuditLogError'));
|
||||
deferred.reject(new Error('HistoryListError'));
|
||||
ctx.ctrl.$scope.$apply();
|
||||
});
|
||||
|
||||
@@ -134,7 +134,7 @@ describe('AuditLogCtrl', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('should update the audit log when the dashboard is saved', function() {
|
||||
describe('should update the history list when the dashboard is saved', function() {
|
||||
beforeEach(function() {
|
||||
ctx.ctrl.dashboard = { version: 3 };
|
||||
ctx.ctrl.resetFromSource = sinon.spy();
|
||||
@@ -163,10 +163,10 @@ describe('AuditLogCtrl', function() {
|
||||
|
||||
beforeEach(angularMocks.inject(($controller, $q) => {
|
||||
deferred = $q.defer();
|
||||
auditSrv.getAuditLog.returns($q.when(versionsResponse));
|
||||
auditSrv.compareVersions.returns(deferred.promise);
|
||||
ctx.ctrl = $controller(AuditLogCtrl, {
|
||||
auditSrv,
|
||||
historySrv.getHistoryList.returns($q.when(versionsResponse));
|
||||
historySrv.compareVersions.returns(deferred.promise);
|
||||
ctx.ctrl = $controller(HistoryListCtrl, {
|
||||
historySrv,
|
||||
$rootScope,
|
||||
$scope: ctx.scope,
|
||||
});
|
||||
@@ -174,8 +174,8 @@ describe('AuditLogCtrl', function() {
|
||||
ctx.ctrl.$scope.$apply();
|
||||
}));
|
||||
|
||||
it('should have already fetched the audit log', function() {
|
||||
expect(auditSrv.getAuditLog.calledOnce).to.be(true);
|
||||
it('should have already fetched the history list', function() {
|
||||
expect(historySrv.getHistoryList.calledOnce).to.be(true);
|
||||
expect(ctx.ctrl.revisions.length).to.be.above(0);
|
||||
});
|
||||
|
||||
@@ -205,7 +205,7 @@ describe('AuditLogCtrl', function() {
|
||||
});
|
||||
|
||||
it('should fetch the basic diff if two valid versions are selected', function() {
|
||||
expect(auditSrv.compareVersions.calledOnce).to.be(true);
|
||||
expect(historySrv.compareVersions.calledOnce).to.be(true);
|
||||
expect(ctx.ctrl.delta.basic).to.be('<div></div>');
|
||||
expect(ctx.ctrl.delta.html).to.be('');
|
||||
});
|
||||
@@ -229,7 +229,7 @@ describe('AuditLogCtrl', function() {
|
||||
});
|
||||
|
||||
it('should fetch the json diff if two valid versions are selected', function() {
|
||||
expect(auditSrv.compareVersions.calledOnce).to.be(true);
|
||||
expect(historySrv.compareVersions.calledOnce).to.be(true);
|
||||
expect(ctx.ctrl.delta.basic).to.be('');
|
||||
expect(ctx.ctrl.delta.html).to.be('<pre><code></code></pre>');
|
||||
});
|
||||
@@ -254,7 +254,7 @@ describe('AuditLogCtrl', function() {
|
||||
});
|
||||
|
||||
it('should use the cached diffs instead of fetching', function() {
|
||||
expect(auditSrv.compareVersions.calledOnce).to.be(false);
|
||||
expect(historySrv.compareVersions.calledOnce).to.be(false);
|
||||
expect(ctx.ctrl.delta.basic).to.be('cached basic');
|
||||
});
|
||||
|
||||
@@ -272,10 +272,10 @@ describe('AuditLogCtrl', function() {
|
||||
});
|
||||
|
||||
it('should fetch the diff if two valid versions are selected', function() {
|
||||
expect(auditSrv.compareVersions.calledOnce).to.be(true);
|
||||
expect(historySrv.compareVersions.calledOnce).to.be(true);
|
||||
});
|
||||
|
||||
it('should return to the audit log view', function() {
|
||||
it('should return to the history list view', function() {
|
||||
expect(ctx.ctrl.mode).to.be('list');
|
||||
});
|
||||
|
||||
@@ -299,10 +299,10 @@ describe('AuditLogCtrl', function() {
|
||||
|
||||
beforeEach(angularMocks.inject(($controller, $q) => {
|
||||
deferred = $q.defer();
|
||||
auditSrv.getAuditLog.returns($q.when(versionsResponse));
|
||||
auditSrv.restoreDashboard.returns(deferred.promise);
|
||||
ctx.ctrl = $controller(AuditLogCtrl, {
|
||||
auditSrv,
|
||||
historySrv.getHistoryList.returns($q.when(versionsResponse));
|
||||
historySrv.restoreDashboard.returns(deferred.promise);
|
||||
ctx.ctrl = $controller(HistoryListCtrl, {
|
||||
historySrv,
|
||||
contextSrv: { user: { name: 'Carlos' }},
|
||||
$rootScope,
|
||||
$scope: ctx.scope,
|
||||
@@ -339,7 +339,7 @@ describe('AuditLogCtrl', function() {
|
||||
expect(ctx.ctrl.loading).to.be(false);
|
||||
});
|
||||
|
||||
it('should add an entry for the restored revision to the audit log', function() {
|
||||
it('should add an entry for the restored revision to the history list', function() {
|
||||
expect(ctx.ctrl.revisions.length).to.be(5);
|
||||
});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/common';
|
||||
|
||||
import helpers from 'test/specs/helpers';
|
||||
import AuditSrv from '../audit/audit_srv';
|
||||
import { versions, compare, restore } from 'test/mocks/audit-mocks';
|
||||
import HistorySrv from '../history/history_srv';
|
||||
import { versions, compare, restore } from 'test/mocks/history-mocks';
|
||||
|
||||
describe('auditSrv', function() {
|
||||
describe('historySrv', function() {
|
||||
var ctx = new helpers.ServiceTestContext();
|
||||
|
||||
var versionsResponse = versions();
|
||||
@@ -23,11 +23,11 @@ describe('auditSrv', function() {
|
||||
return [200, restoreResponse(parsedData.version)];
|
||||
});
|
||||
}));
|
||||
beforeEach(ctx.createService('auditSrv'));
|
||||
beforeEach(ctx.createService('historySrv'));
|
||||
|
||||
describe('getAuditLog', function() {
|
||||
describe('getHistoryList', function() {
|
||||
it('should return a versions array for the given dashboard id', function(done) {
|
||||
ctx.service.getAuditLog({ id: 1 }).then(function(versions) {
|
||||
ctx.service.getHistoryList({ id: 1 }).then(function(versions) {
|
||||
expect(versions).to.eql(versionsResponse);
|
||||
done();
|
||||
});
|
||||
@@ -35,7 +35,7 @@ describe('auditSrv', function() {
|
||||
});
|
||||
|
||||
it('should return an empty array when not given an id', function(done) {
|
||||
ctx.service.getAuditLog({ }).then(function(versions) {
|
||||
ctx.service.getHistoryList({ }).then(function(versions) {
|
||||
expect(versions).to.eql([]);
|
||||
done();
|
||||
});
|
||||
@@ -43,7 +43,7 @@ describe('auditSrv', function() {
|
||||
});
|
||||
|
||||
it('should return an empty array when not given a dashboard', function(done) {
|
||||
ctx.service.getAuditLog().then(function(versions) {
|
||||
ctx.service.getHistoryList().then(function(versions) {
|
||||
expect(versions).to.eql([]);
|
||||
done();
|
||||
});
|
||||
@@ -82,7 +82,7 @@
|
||||
@import "pages/playlist";
|
||||
@import "pages/admin";
|
||||
@import "pages/alerting";
|
||||
@import "pages/audit";
|
||||
@import "pages/history";
|
||||
@import "pages/plugins";
|
||||
@import "pages/signup";
|
||||
@import "pages/styleguide";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Audit Table
|
||||
.audit-table {
|
||||
// History Table
|
||||
.history-table {
|
||||
// .gf-form overrides
|
||||
.gf-form-label { display: none; }
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
}
|
||||
|
||||
// Diff View
|
||||
.audit-log {
|
||||
.history-list {
|
||||
h4 {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
@@ -39,7 +39,7 @@ define([],
|
||||
dashboardId: 1,
|
||||
parentVersion: 0,
|
||||
restoredFrom: -1,
|
||||
slug: 'audit-dashboard',
|
||||
slug: 'history-dashboard',
|
||||
version: 1,
|
||||
created: '2017-02-22T17:06:37-08:00',
|
||||
createdBy: 'admin',
|
||||
@@ -57,7 +57,7 @@ define([],
|
||||
canSave: true,
|
||||
canEdit: true,
|
||||
canStar: true,
|
||||
slug: 'audit-dashboard',
|
||||
slug: 'history-dashboard',
|
||||
expires: '0001-01-01T00:00:00Z',
|
||||
created: '2017-02-21T18:40:45-08:00',
|
||||
updated: '2017-04-11T21:31:22.59219665-07:00',
|
||||
@@ -69,7 +69,7 @@ define([],
|
||||
annotations: {
|
||||
list: []
|
||||
},
|
||||
description: 'A random dashboard for implementing the audit log',
|
||||
description: 'A random dashboard for implementing the history list',
|
||||
editable: true,
|
||||
gnetId: null,
|
||||
graphTooltip: 0,
|
||||
@@ -185,7 +185,7 @@ define([],
|
||||
]
|
||||
},
|
||||
timezone: 'utc',
|
||||
title: 'Audit Dashboard',
|
||||
title: 'History Dashboard',
|
||||
version: version,
|
||||
}
|
||||
},
|
||||
Reference in New Issue
Block a user