Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
77c046aa
Commit
77c046aa
authored
Jun 01, 2017
by
sanchitraizada
Committed by
Ben Tranter
Jun 01, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement review feedback
parent
a927b893
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
177 additions
and
195 deletions
+177
-195
pkg/api/api.go
+5
-5
pkg/api/dashboard.go
+61
-100
pkg/models/dashboard_version.go
+1
-1
pkg/services/sqlstore/dashboard_version.go
+18
-8
public/app/core/directives/dash_edit_link.js
+1
-1
public/app/core/directives/diff-view.ts
+2
-1
public/app/features/all.js
+0
-1
public/app/features/dashboard/all.js
+1
-1
public/app/features/dashboard/dashnav/dashnav.html
+1
-1
public/app/features/dashboard/history/history.html
+9
-9
public/app/features/dashboard/history/history.ts
+24
-12
public/app/features/dashboard/history/history_srv.ts
+4
-6
public/app/features/dashboard/history/models.ts
+1
-1
public/app/features/dashboard/history/partials/history.html
+1
-0
public/app/features/dashboard/history/partials/link-json.html
+0
-0
public/app/features/dashboard/specs/history_ctrl_specs.ts
+32
-32
public/app/features/dashboard/specs/history_srv_specs.ts
+8
-8
public/sass/_grafana.scss
+1
-1
public/sass/pages/_history.scss
+3
-3
public/test/mocks/history-mocks.js
+4
-4
No files found.
pkg/api/api.go
View file @
77c046aa
...
...
@@ -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
))
...
...
pkg/api/dashboard.go
View file @
77c046aa
...
...
@@ -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
.
JsonApiEr
r
(
404
,
fmt
.
Sprintf
(
"No versions found for dashboardId %d"
,
dashboardId
),
err
)
return
}
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
,
}
}
c
.
JSON
(
200
,
dashboardVersions
)
return
ApiErro
r
(
404
,
fmt
.
Sprintf
(
"No versions found for dashboardId %d"
,
dashboardId
),
err
)
}
// // 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,
//
}
//
}
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
dashCm
d
(
c
*
middleware
.
Context
)
(
m
.
CompareDashboardVersionsCommand
,
error
)
{
func
createCompareDashboardVersionComman
d
(
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
:=
dashCm
d
(
c
)
func
CompareDashboardVersions
(
c
*
middleware
.
Context
)
Response
{
cmd
,
err
:=
createCompareDashboardVersionComman
d
(
c
)
if
err
!=
nil
{
c
.
JsonApiEr
r
(
500
,
err
.
Error
(),
err
)
return
ApiErro
r
(
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
:=
dashCm
d
(
c
)
func
CompareDashboardVersionsJSON
(
c
*
middleware
.
Context
)
Response
{
cmd
,
err
:=
createCompareDashboardVersionComman
d
(
c
)
if
err
!=
nil
{
c
.
JsonApiEr
r
(
500
,
err
.
Error
(),
err
)
return
ApiErro
r
(
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
:=
dashCm
d
(
c
)
func
CompareDashboardVersionsBasic
(
c
*
middleware
.
Context
)
Response
{
cmd
,
err
:=
createCompareDashboardVersionComman
d
(
c
)
if
err
!=
nil
{
c
.
JsonApiEr
r
(
500
,
err
.
Error
(),
err
)
return
ApiErro
r
(
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
...
...
pkg/models/dashboard_version.go
View file @
77c046aa
...
...
@@ -80,7 +80,7 @@ type GetDashboardVersionsCommand struct {
Limit
int
`json:"limit"`
Start
int
`json:"start"`
Result
[]
*
DashboardVersion
Result
[]
*
DashboardVersion
DTO
}
// RestoreDashboardVersionCommand creates a new dashboard version.
...
...
pkg/services/sqlstore/dashboard_version.go
View file @
77c046aa
...
...
@@ -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
{
...
...
public/app/core/directives/dash_edit_link.js
View file @
77c046aa
...
...
@@ -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>'
}
};
...
...
public/app/core/directives/diff-view.ts
View file @
77c046aa
...
...
@@ -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
);
public/app/features/all.js
View file @
77c046aa
...
...
@@ -2,7 +2,6 @@ define([
'./panellinks/module'
,
'./dashlinks/module'
,
'./annotations/all'
,
'./annotations/annotations_srv'
,
'./templating/all'
,
'./dashboard/all'
,
'./playlist/all'
,
...
...
public/app/features/dashboard/all.js
View file @
77c046aa
define
([
'./dashboard_ctrl'
,
'./alerting_srv'
,
'./
audit/audit_srv
'
,
'./
history/history
'
,
'./dashboardLoaderSrv'
,
'./dashnav/dashnav'
,
'./submenu/submenu'
,
...
...
public/app/features/dashboard/dashnav/dashnav.html
View file @
77c046aa
...
...
@@ -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>
...
...
public/app/features/dashboard/
audit/partials/audit
.html
→
public/app/features/dashboard/
history/history
.html
View file @
77c046aa
<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>
...
...
public/app/features/dashboard/
audit/audit_ctrl
.ts
→
public/app/features/dashboard/
history/history
.ts
View file @
77c046aa
///<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
{
AuditLog
Opts
,
RevisionsModel
}
from
'./models'
;
import
{
HistoryList
Opts
,
RevisionsModel
}
from
'./models'
;
export
class
AuditLog
Ctrl
{
export
class
HistoryList
Ctrl
{
appending
:
boolean
;
dashboard
:
DashboardModel
;
delta
:
{
basic
:
string
;
html
:
string
;
};
...
...
@@ -29,11 +29,10 @@ export class AuditLogCtrl {
private
$window
,
private
$q
,
private
contextSrv
,
private
audit
Srv
)
{
private
history
Srv
)
{
$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
.
audit
Srv
.
compareVersions
(
this
.
dashboard
,
compare
,
diff
).
then
(
response
=>
{
return
this
.
history
Srv
.
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
:
AuditLog
Opts
=
{
const
options
:
HistoryList
Opts
=
{
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
.
audit
Srv
.
restoreDashboard
(
this
.
dashboard
,
version
).
then
(
response
=>
{
return
this
.
history
Srv
.
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
);
public/app/features/dashboard/
audit/audit
_srv.ts
→
public/app/features/dashboard/
history/history
_srv.ts
View file @
77c046aa
///<reference path="../../../headers/common.d.ts" />
import
'./audit_ctrl'
;
import
_
from
'lodash'
;
import
coreModule
from
'app/core/core_module'
;
import
{
DashboardModel
}
from
'../model'
;
import
{
AuditLog
Opts
}
from
'./models'
;
import
{
HistoryList
Opts
}
from
'./models'
;
export
class
Audit
Srv
{
export
class
History
Srv
{
/** @ngInject */
constructor
(
private
backendSrv
,
private
$q
)
{}
get
AuditLog
(
dashboard
:
DashboardModel
,
options
:
AuditLog
Opts
)
{
get
HistoryList
(
dashboard
:
DashboardModel
,
options
:
HistoryList
Opts
)
{
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'
,
Audit
Srv
);
coreModule
.
service
(
'
historySrv'
,
History
Srv
);
public/app/features/dashboard/
audit
/models.ts
→
public/app/features/dashboard/
history
/models.ts
View file @
77c046aa
export
interface
AuditLog
Opts
{
export
interface
HistoryList
Opts
{
limit
:
number
;
start
:
number
;
orderBy
:
string
;
...
...
public/app/features/dashboard/history/partials/history.html
0 → 100644
View file @
77c046aa
<gf-dashboard-history
dashboard=
"dashboard"
></gf-dashboard-history>
public/app/features/dashboard/
audit
/partials/link-json.html
→
public/app/features/dashboard/
history
/partials/link-json.html
View file @
77c046aa
File moved
public/app/features/dashboard/specs/
audit
_ctrl_specs.ts
→
public/app/features/dashboard/specs/
history
_ctrl_specs.ts
View file @
77c046aa
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
(
'
AuditLog
Ctrl'
,
function
()
{
describe
(
'
HistoryList
Ctrl'
,
function
()
{
var
RESTORE_ID
=
4
;
var
ctx
:
any
=
{};
...
...
@@ -18,11 +18,11 @@ describe('AuditLogCtrl', function() {
ctx
.
scope
=
$rootScope
.
$new
();
}));
var
audit
Srv
;
var
history
Srv
;
var
$rootScope
;
beforeEach
(
function
()
{
audit
Srv
=
{
get
AuditLog
:
sinon
.
stub
(),
history
Srv
=
{
get
HistoryList
:
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
(
AuditLog
Ctrl
,
{
audit
Srv
,
historySrv
.
getHistoryList
.
returns
(
deferred
.
promise
);
ctx
.
ctrl
=
$controller
(
HistoryList
Ctrl
,
{
history
Srv
,
$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
(
'
AuditLog
Error'
));
deferred
.
reject
(
new
Error
(
'
HistoryList
Error'
));
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
));
audit
Srv
.
compareVersions
.
returns
(
deferred
.
promise
);
ctx
.
ctrl
=
$controller
(
AuditLog
Ctrl
,
{
audit
Srv
,
historySrv
.
getHistoryList
.
returns
(
$q
.
when
(
versionsResponse
));
history
Srv
.
compareVersions
.
returns
(
deferred
.
promise
);
ctx
.
ctrl
=
$controller
(
HistoryList
Ctrl
,
{
history
Srv
,
$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
(
audit
Srv
.
compareVersions
.
calledOnce
).
to
.
be
(
true
);
expect
(
history
Srv
.
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
(
audit
Srv
.
compareVersions
.
calledOnce
).
to
.
be
(
true
);
expect
(
history
Srv
.
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
(
audit
Srv
.
compareVersions
.
calledOnce
).
to
.
be
(
false
);
expect
(
history
Srv
.
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
(
audit
Srv
.
compareVersions
.
calledOnce
).
to
.
be
(
true
);
expect
(
history
Srv
.
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
));
audit
Srv
.
restoreDashboard
.
returns
(
deferred
.
promise
);
ctx
.
ctrl
=
$controller
(
AuditLog
Ctrl
,
{
audit
Srv
,
historySrv
.
getHistoryList
.
returns
(
$q
.
when
(
versionsResponse
));
history
Srv
.
restoreDashboard
.
returns
(
deferred
.
promise
);
ctx
.
ctrl
=
$controller
(
HistoryList
Ctrl
,
{
history
Srv
,
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
);
});
...
...
public/app/features/dashboard/specs/
audit
_srv_specs.ts
→
public/app/features/dashboard/specs/
history
_srv_specs.ts
View file @
77c046aa
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
(
'
audit
Srv'
,
function
()
{
describe
(
'
history
Srv'
,
function
()
{
var
ctx
=
new
helpers
.
ServiceTestContext
();
var
versionsResponse
=
versions
();
...
...
@@ -23,11 +23,11 @@ describe('auditSrv', function() {
return
[
200
,
restoreResponse
(
parsedData
.
version
)];
});
}));
beforeEach
(
ctx
.
createService
(
'
audit
Srv'
));
beforeEach
(
ctx
.
createService
(
'
history
Srv'
));
describe
(
'get
AuditLog
'
,
function
()
{
describe
(
'get
HistoryList
'
,
function
()
{
it
(
'should return a versions array for the given dashboard id'
,
function
(
done
)
{
ctx
.
service
.
get
AuditLog
({
id
:
1
}).
then
(
function
(
versions
)
{
ctx
.
service
.
get
HistoryList
({
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
.
get
AuditLog
({
}).
then
(
function
(
versions
)
{
ctx
.
service
.
get
HistoryList
({
}).
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
.
get
AuditLog
().
then
(
function
(
versions
)
{
ctx
.
service
.
get
HistoryList
().
then
(
function
(
versions
)
{
expect
(
versions
).
to
.
eql
([]);
done
();
});
...
...
public/sass/_grafana.scss
View file @
77c046aa
...
...
@@ -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"
;
...
...
public/sass/pages/_
audit
.scss
→
public/sass/pages/_
history
.scss
View file @
77c046aa
//
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
;
}
...
...
public/test/mocks/
audit
-mocks.js
→
public/test/mocks/
history
-mocks.js
View file @
77c046aa
...
...
@@ -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
,
}
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment