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
9b63a817
Commit
9b63a817
authored
Dec 21, 2017
by
Patrick O'Carroll
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
migrated files to ts + fixed specfile
parent
af34f997
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
476 additions
and
361 deletions
+476
-361
public/app/features/dashboard/all.ts
+3
-3
public/app/features/dashboard/dashboardLoaderSrv.js
+0
-109
public/app/features/dashboard/dashboard_loader_srv.ts
+158
-0
public/app/features/dashboard/share_snapshot_ctrl.ts
+58
-55
public/app/features/dashboard/specs/unsaved_changes_srv_specs.ts
+21
-5
public/app/features/dashboard/unsavedChangesSrv.js
+0
-189
public/app/features/dashboard/unsaved_changes_srv.ts
+236
-0
No files found.
public/app/features/dashboard/all.ts
View file @
9b63a817
import
'./dashboard_ctrl'
;
import
'./alerting_srv'
;
import
'./history/history'
;
import
'./dashboard
LoaderS
rv'
;
import
'./dashboard
_loader_s
rv'
;
import
'./dashnav/dashnav'
;
import
'./submenu/submenu'
;
import
'./save_as_modal'
;
import
'./save_modal'
;
import
'./shareModalCtrl'
;
import
'./share
SnapshotC
trl'
;
import
'./share
_snapshot_c
trl'
;
import
'./dashboard_srv'
;
import
'./view_state_srv'
;
import
'./validation_srv'
;
import
'./time_srv'
;
import
'./unsaved
ChangesS
rv'
;
import
'./unsaved
_changes_s
rv'
;
import
'./unsaved_changes_modal'
;
import
'./timepicker/timepicker'
;
import
'./upload'
;
...
...
public/app/features/dashboard/dashboardLoaderSrv.js
deleted
100644 → 0
View file @
af34f997
define
([
'angular'
,
'moment'
,
'lodash'
,
'jquery'
,
'app/core/utils/kbn'
,
'app/core/utils/datemath'
,
'app/core/services/impression_srv'
],
function
(
angular
,
moment
,
_
,
$
,
kbn
,
dateMath
,
impressionSrv
)
{
'use strict'
;
kbn
=
kbn
.
default
;
impressionSrv
=
impressionSrv
.
default
;
var
module
=
angular
.
module
(
'grafana.services'
);
module
.
service
(
'dashboardLoaderSrv'
,
function
(
backendSrv
,
dashboardSrv
,
datasourceSrv
,
$http
,
$q
,
$timeout
,
contextSrv
,
$routeParams
,
$rootScope
)
{
var
self
=
this
;
this
.
_dashboardLoadFailed
=
function
(
title
,
snapshot
)
{
snapshot
=
snapshot
||
false
;
return
{
meta
:
{
canStar
:
false
,
isSnapshot
:
snapshot
,
canDelete
:
false
,
canSave
:
false
,
canEdit
:
false
,
dashboardNotFound
:
true
},
dashboard
:
{
title
:
title
}
};
};
this
.
loadDashboard
=
function
(
type
,
slug
)
{
var
promise
;
if
(
type
===
'script'
)
{
promise
=
this
.
_loadScriptedDashboard
(
slug
);
}
else
if
(
type
===
'snapshot'
)
{
promise
=
backendSrv
.
get
(
'/api/snapshots/'
+
$routeParams
.
slug
)
.
catch
(
function
()
{
return
self
.
_dashboardLoadFailed
(
"Snapshot not found"
,
true
);
});
}
else
{
promise
=
backendSrv
.
getDashboard
(
$routeParams
.
type
,
$routeParams
.
slug
)
.
then
(
function
(
result
)
{
if
(
result
.
meta
.
isFolder
)
{
$rootScope
.
appEvent
(
"alert-error"
,
[
'Dashboard not found'
]);
throw
new
Error
(
"Dashboard not found"
);
}
return
result
;
})
.
catch
(
function
()
{
return
self
.
_dashboardLoadFailed
(
"Not found"
);
});
}
promise
.
then
(
function
(
result
)
{
if
(
result
.
meta
.
dashboardNotFound
!==
true
)
{
impressionSrv
.
addDashboardImpression
(
result
.
dashboard
.
id
);
}
return
result
;
});
return
promise
;
};
this
.
_loadScriptedDashboard
=
function
(
file
)
{
var
url
=
'public/dashboards/'
+
file
.
replace
(
/
\.(?!
js
)
/
,
"/"
)
+
'?'
+
new
Date
().
getTime
();
return
$http
({
url
:
url
,
method
:
"GET"
})
.
then
(
this
.
_executeScript
).
then
(
function
(
result
)
{
return
{
meta
:
{
fromScript
:
true
,
canDelete
:
false
,
canSave
:
false
,
canStar
:
false
},
dashboard
:
result
.
data
};
},
function
(
err
)
{
console
.
log
(
'Script dashboard error '
+
err
);
$rootScope
.
appEvent
(
'alert-error'
,
[
"Script Error"
,
"Please make sure it exists and returns a valid dashboard"
]);
return
self
.
_dashboardLoadFailed
(
'Scripted dashboard'
);
});
};
this
.
_executeScript
=
function
(
result
)
{
var
services
=
{
dashboardSrv
:
dashboardSrv
,
datasourceSrv
:
datasourceSrv
,
$q
:
$q
,
};
/*jshint -W054 */
var
script_func
=
new
Function
(
'ARGS'
,
'kbn'
,
'dateMath'
,
'_'
,
'moment'
,
'window'
,
'document'
,
'$'
,
'jQuery'
,
'services'
,
result
.
data
);
var
script_result
=
script_func
(
$routeParams
,
kbn
,
dateMath
,
_
,
moment
,
window
,
document
,
$
,
$
,
services
);
// Handle async dashboard scripts
if
(
_
.
isFunction
(
script_result
))
{
var
deferred
=
$q
.
defer
();
script_result
(
function
(
dashboard
)
{
$timeout
(
function
()
{
deferred
.
resolve
({
data
:
dashboard
});
});
});
return
deferred
.
promise
;
}
return
{
data
:
script_result
};
};
});
});
public/app/features/dashboard/dashboard_loader_srv.ts
0 → 100644
View file @
9b63a817
import
angular
from
'angular'
;
import
moment
from
'moment'
;
import
_
from
'lodash'
;
import
$
from
'jquery'
;
import
kbn
from
'app/core/utils/kbn'
;
import
*
as
dateMath
from
'app/core/utils/datemath'
;
import
impressionSrv
from
'app/core/services/impression_srv'
;
export
class
DashboardLoaderSrv
{
/** @ngInject */
constructor
(
private
backendSrv
,
private
dashboardSrv
,
private
datasourceSrv
,
private
$http
,
private
$q
,
private
$timeout
,
contextSrv
,
private
$routeParams
,
private
$rootScope
)
{}
_dashboardLoadFailed
(
title
,
snapshot
)
{
snapshot
=
snapshot
||
false
;
return
{
meta
:
{
canStar
:
false
,
isSnapshot
:
snapshot
,
canDelete
:
false
,
canSave
:
false
,
canEdit
:
false
,
dashboardNotFound
:
true
,
},
dashboard
:
{
title
:
title
},
};
}
loadDashboard
(
type
,
slug
)
{
var
promise
;
if
(
type
===
'script'
)
{
promise
=
this
.
_loadScriptedDashboard
(
slug
);
}
else
if
(
type
===
'snapshot'
)
{
promise
=
this
.
backendSrv
.
get
(
'/api/snapshots/'
+
this
.
$routeParams
.
slug
)
.
catch
(()
=>
{
return
this
.
_dashboardLoadFailed
(
'Snapshot not found'
,
true
);
});
}
else
{
promise
=
this
.
backendSrv
.
getDashboard
(
this
.
$routeParams
.
type
,
this
.
$routeParams
.
slug
)
.
then
(
result
=>
{
if
(
result
.
meta
.
isFolder
)
{
this
.
$rootScope
.
appEvent
(
'alert-error'
,
[
'Dashboard not found'
]);
throw
new
Error
(
'Dashboard not found'
);
}
return
result
;
})
.
catch
(()
=>
{
return
this
.
_dashboardLoadFailed
(
'Not found'
,
true
);
});
}
promise
.
then
(
function
(
result
)
{
if
(
result
.
meta
.
dashboardNotFound
!==
true
)
{
impressionSrv
.
addDashboardImpression
(
result
.
dashboard
.
id
);
}
return
result
;
});
return
promise
;
}
_loadScriptedDashboard
(
file
)
{
var
url
=
'public/dashboards/'
+
file
.
replace
(
/
\.(?!
js
)
/
,
'/'
)
+
'?'
+
new
Date
().
getTime
();
return
this
.
$http
({
url
:
url
,
method
:
'GET'
})
.
then
(
this
.
_executeScript
)
.
then
(
function
(
result
)
{
return
{
meta
:
{
fromScript
:
true
,
canDelete
:
false
,
canSave
:
false
,
canStar
:
false
,
},
dashboard
:
result
.
data
,
};
},
function
(
err
)
{
console
.
log
(
'Script dashboard error '
+
err
);
this
.
$rootScope
.
appEvent
(
'alert-error'
,
[
'Script Error'
,
'Please make sure it exists and returns a valid dashboard'
,
]);
return
this
.
_dashboardLoadFailed
(
'Scripted dashboard'
);
}
);
}
_executeScript
(
result
)
{
var
services
=
{
dashboardSrv
:
this
.
dashboardSrv
,
datasourceSrv
:
this
.
datasourceSrv
,
$q
:
this
.
$q
,
};
/*jshint -W054 */
var
script_func
=
new
Function
(
'ARGS'
,
'kbn'
,
'dateMath'
,
'_'
,
'moment'
,
'window'
,
'document'
,
'$'
,
'jQuery'
,
'services'
,
result
.
data
);
var
script_result
=
script_func
(
this
.
$routeParams
,
kbn
,
dateMath
,
_
,
moment
,
window
,
document
,
$
,
$
,
services
);
// Handle async dashboard scripts
if
(
_
.
isFunction
(
script_result
))
{
var
deferred
=
this
.
$q
.
defer
();
script_result
(
dashboard
=>
{
this
.
$timeout
(()
=>
{
deferred
.
resolve
({
data
:
dashboard
});
});
});
return
deferred
.
promise
;
}
return
{
data
:
script_result
};
}
}
angular
.
module
(
'grafana.services'
)
.
service
(
'dashboardLoaderSrv'
,
DashboardLoaderSrv
);
public/app/features/dashboard/share
SnapshotCtrl.j
s
→
public/app/features/dashboard/share
_snapshot_ctrl.t
s
View file @
9b63a817
define
([
'angular'
,
'lodash'
,
],
function
(
angular
,
_
)
{
'use strict'
;
var
module
=
angular
.
module
(
'grafana.controllers'
);
module
.
controller
(
'ShareSnapshotCtrl'
,
function
(
$scope
,
$rootScope
,
$location
,
backendSrv
,
$timeout
,
timeSrv
)
{
import
angular
from
'angular'
;
import
_
from
'lodash'
;
export
class
ShareSnapshotCtrl
{
constructor
(
$scope
,
$rootScope
,
$location
,
backendSrv
,
$timeout
,
timeSrv
)
{
$scope
.
snapshot
=
{
name
:
$scope
.
dashboard
.
title
,
expires
:
0
,
...
...
@@ -18,16 +12,16 @@ function (angular, _) {
$scope
.
step
=
1
;
$scope
.
expireOptions
=
[
{
text
:
'1 Hour'
,
value
:
60
*
60
},
{
text
:
'1 Day'
,
value
:
60
*
60
*
24
},
{
text
:
'7 Days'
,
value
:
60
*
60
*
24
*
7
},
{
text
:
'Never'
,
value
:
0
},
{
text
:
'1 Hour'
,
value
:
60
*
60
},
{
text
:
'1 Day'
,
value
:
60
*
60
*
24
},
{
text
:
'7 Days'
,
value
:
60
*
60
*
24
*
7
},
{
text
:
'Never'
,
value
:
0
},
];
$scope
.
accessOptions
=
[
{
text
:
'Anyone with the link'
,
value
:
1
},
{
text
:
'Organization users'
,
value
:
2
},
{
text
:
'Public on the web'
,
value
:
3
},
{
text
:
'Anyone with the link'
,
value
:
1
},
{
text
:
'Organization users'
,
value
:
2
},
{
text
:
'Public on the web'
,
value
:
3
},
];
$scope
.
init
=
function
()
{
...
...
@@ -42,7 +36,7 @@ function (angular, _) {
$scope
.
createSnapshot
=
function
(
external
)
{
$scope
.
dashboard
.
snapshot
=
{
timestamp
:
new
Date
()
timestamp
:
new
Date
()
,
};
if
(
!
external
)
{
...
...
@@ -69,31 +63,37 @@ function (angular, _) {
expires
:
$scope
.
snapshot
.
expires
,
};
var
postUrl
=
external
?
$scope
.
externalUrl
+
$scope
.
apiUrl
:
$scope
.
apiUrl
;
backendSrv
.
post
(
postUrl
,
cmdData
).
then
(
function
(
results
)
{
$scope
.
loading
=
false
;
if
(
external
)
{
$scope
.
deleteUrl
=
results
.
deleteUrl
;
$scope
.
snapshotUrl
=
results
.
url
;
$scope
.
saveExternalSnapshotRef
(
cmdData
,
results
);
}
else
{
var
url
=
$location
.
url
();
var
baseUrl
=
$location
.
absUrl
();
if
(
url
!==
'/'
)
{
baseUrl
=
baseUrl
.
replace
(
url
,
''
)
+
'/'
;
var
postUrl
=
external
?
$scope
.
externalUrl
+
$scope
.
apiUrl
:
$scope
.
apiUrl
;
backendSrv
.
post
(
postUrl
,
cmdData
).
then
(
function
(
results
)
{
$scope
.
loading
=
false
;
if
(
external
)
{
$scope
.
deleteUrl
=
results
.
deleteUrl
;
$scope
.
snapshotUrl
=
results
.
url
;
$scope
.
saveExternalSnapshotRef
(
cmdData
,
results
);
}
else
{
var
url
=
$location
.
url
();
var
baseUrl
=
$location
.
absUrl
();
if
(
url
!==
'/'
)
{
baseUrl
=
baseUrl
.
replace
(
url
,
''
)
+
'/'
;
}
$scope
.
snapshotUrl
=
baseUrl
+
'dashboard/snapshot/'
+
results
.
key
;
$scope
.
deleteUrl
=
baseUrl
+
'api/snapshots-delete/'
+
results
.
deleteKey
;
}
$scope
.
snapshotUrl
=
baseUrl
+
'dashboard/snapshot/'
+
results
.
key
;
$scope
.
deleteUrl
=
baseUrl
+
'api/snapshots-delete/'
+
results
.
deleteKey
;
$scope
.
step
=
2
;
},
function
()
{
$scope
.
loading
=
false
;
}
$scope
.
step
=
2
;
},
function
()
{
$scope
.
loading
=
false
;
});
);
};
$scope
.
getSnapshotUrl
=
function
()
{
...
...
@@ -116,21 +116,22 @@ function (angular, _) {
// remove annotation queries
dash
.
annotations
.
list
=
_
.
chain
(
dash
.
annotations
.
list
)
.
filter
(
function
(
annotation
)
{
return
annotation
.
enable
;
})
.
map
(
function
(
annotation
)
{
return
{
name
:
annotation
.
name
,
enable
:
annotation
.
enable
,
iconColor
:
annotation
.
iconColor
,
snapshotData
:
annotation
.
snapshotData
};
}).
value
();
.
filter
(
function
(
annotation
)
{
return
annotation
.
enable
;
})
.
map
(
function
(
annotation
)
{
return
{
name
:
annotation
.
name
,
enable
:
annotation
.
enable
,
iconColor
:
annotation
.
iconColor
,
snapshotData
:
annotation
.
snapshotData
,
};
})
.
value
();
// remove template queries
_
.
each
(
dash
.
templating
.
list
,
function
(
variable
)
{
variable
.
query
=
""
;
variable
.
query
=
''
;
variable
.
options
=
variable
.
current
;
variable
.
refresh
=
false
;
});
...
...
@@ -168,7 +169,9 @@ function (angular, _) {
cmdData
.
deleteKey
=
results
.
deleteKey
;
backendSrv
.
post
(
'/api/snapshots/'
,
cmdData
);
};
}
}
});
}
);
angular
.
module
(
'grafana.controllers'
)
.
controller
(
'ShareSnapshotCtrl'
,
ShareSnapshotCtrl
);
public/app/features/dashboard/specs/unsaved_changes_srv_specs.ts
View file @
9b63a817
...
...
@@ -6,14 +6,17 @@ import {
sinon
,
angularMocks
,
}
from
'test/lib/common'
;
import
'app/features/dashboard/unsavedChangesS
rv'
;
import
{
Tracker
}
from
'app/features/dashboard/unsaved_changes_s
rv'
;
import
'app/features/dashboard/dashboard_srv'
;
import
{
contextSrv
}
from
'app/core/core'
;
describe
(
'unsavedChangesSrv'
,
function
()
{
var
_unsavedChangesSrv
;
var
_dashboardSrv
;
var
_contextSrvStub
=
{
isEditor
:
true
};
var
_rootScope
;
var
_location
;
var
_timeout
;
var
_window
;
var
tracker
;
var
dash
;
var
scope
;
...
...
@@ -32,11 +35,15 @@ describe('unsavedChangesSrv', function() {
unsavedChangesSrv
,
$location
,
$rootScope
,
dashboardSrv
dashboardSrv
,
$timeout
,
$window
)
{
_unsavedChangesSrv
=
unsavedChangesSrv
;
_dashboardSrv
=
dashboardSrv
;
_rootScope
=
$rootScope
;
_location
=
$location
;
_timeout
=
$timeout
;
_window
=
$window
;
})
);
...
...
@@ -54,7 +61,16 @@ describe('unsavedChangesSrv', function() {
scope
.
appEvent
=
sinon
.
spy
();
scope
.
onAppEvent
=
sinon
.
spy
();
tracker
=
new
_unsavedChangesSrv
.
Tracker
(
dash
,
scope
);
tracker
=
new
Tracker
(
dash
,
scope
,
undefined
,
_location
,
_window
,
_timeout
,
contextSrv
,
_rootScope
);
});
it
(
'No changes should not have changes'
,
function
()
{
...
...
public/app/features/dashboard/unsavedChangesSrv.js
deleted
100644 → 0
View file @
af34f997
define
([
'angular'
,
'lodash'
,
],
function
(
angular
,
_
)
{
'use strict'
;
var
module
=
angular
.
module
(
'grafana.services'
);
module
.
service
(
'unsavedChangesSrv'
,
function
(
$rootScope
,
$q
,
$location
,
$timeout
,
contextSrv
,
dashboardSrv
,
$window
)
{
function
Tracker
(
dashboard
,
scope
,
originalCopyDelay
)
{
var
self
=
this
;
this
.
current
=
dashboard
;
this
.
originalPath
=
$location
.
path
();
this
.
scope
=
scope
;
// register events
scope
.
onAppEvent
(
'dashboard-saved'
,
function
()
{
this
.
original
=
this
.
current
.
getSaveModelClone
();
this
.
originalPath
=
$location
.
path
();
}.
bind
(
this
));
$window
.
onbeforeunload
=
function
()
{
if
(
self
.
ignoreChanges
())
{
return
;
}
if
(
self
.
hasChanges
())
{
return
"There are unsaved changes to this dashboard"
;
}
};
scope
.
$on
(
"$locationChangeStart"
,
function
(
event
,
next
)
{
// check if we should look for changes
if
(
self
.
originalPath
===
$location
.
path
())
{
return
true
;
}
if
(
self
.
ignoreChanges
())
{
return
true
;
}
if
(
self
.
hasChanges
())
{
event
.
preventDefault
();
self
.
next
=
next
;
$timeout
(
function
()
{
self
.
open_modal
();
});
}
});
if
(
originalCopyDelay
)
{
$timeout
(
function
()
{
// wait for different services to patch the dashboard (missing properties)
self
.
original
=
dashboard
.
getSaveModelClone
();
},
originalCopyDelay
);
}
else
{
self
.
original
=
dashboard
.
getSaveModelClone
();
}
}
var
p
=
Tracker
.
prototype
;
// for some dashboards and users
// changes should be ignored
p
.
ignoreChanges
=
function
()
{
if
(
!
this
.
original
)
{
return
true
;
}
if
(
!
contextSrv
.
isEditor
)
{
return
true
;
}
if
(
!
this
.
current
||
!
this
.
current
.
meta
)
{
return
true
;
}
var
meta
=
this
.
current
.
meta
;
return
!
meta
.
canSave
||
meta
.
fromScript
||
meta
.
fromFile
;
};
// remove stuff that should not count in diff
p
.
cleanDashboardFromIgnoredChanges
=
function
(
dash
)
{
// ignore time and refresh
dash
.
time
=
0
;
dash
.
refresh
=
0
;
dash
.
schemaVersion
=
0
;
// filter row and panels properties that should be ignored
dash
.
rows
=
_
.
filter
(
dash
.
rows
,
function
(
row
)
{
if
(
row
.
repeatRowId
)
{
return
false
;
}
row
.
panels
=
_
.
filter
(
row
.
panels
,
function
(
panel
)
{
if
(
panel
.
repeatPanelId
)
{
return
false
;
}
// remove scopedVars
panel
.
scopedVars
=
null
;
// ignore span changes
panel
.
span
=
null
;
// ignore panel legend sort
if
(
panel
.
legend
)
{
delete
panel
.
legend
.
sort
;
delete
panel
.
legend
.
sortDesc
;
}
return
true
;
});
// ignore collapse state
row
.
collapse
=
false
;
return
true
;
});
dash
.
panels
=
_
.
filter
(
dash
.
panels
,
function
(
panel
)
{
if
(
panel
.
repeatPanelId
)
{
return
false
;
}
// remove scopedVars
panel
.
scopedVars
=
null
;
// ignore panel legend sort
if
(
panel
.
legend
)
{
delete
panel
.
legend
.
sort
;
delete
panel
.
legend
.
sortDesc
;
}
return
true
;
});
// ignore template variable values
_
.
each
(
dash
.
templating
.
list
,
function
(
value
)
{
value
.
current
=
null
;
value
.
options
=
null
;
value
.
filters
=
null
;
});
};
p
.
hasChanges
=
function
()
{
var
current
=
this
.
current
.
getSaveModelClone
();
var
original
=
this
.
original
;
this
.
cleanDashboardFromIgnoredChanges
(
current
);
this
.
cleanDashboardFromIgnoredChanges
(
original
);
var
currentTimepicker
=
_
.
find
(
current
.
nav
,
{
type
:
'timepicker'
});
var
originalTimepicker
=
_
.
find
(
original
.
nav
,
{
type
:
'timepicker'
});
if
(
currentTimepicker
&&
originalTimepicker
)
{
currentTimepicker
.
now
=
originalTimepicker
.
now
;
}
var
currentJson
=
angular
.
toJson
(
current
);
var
originalJson
=
angular
.
toJson
(
original
);
return
currentJson
!==
originalJson
;
};
p
.
discardChanges
=
function
()
{
this
.
original
=
null
;
this
.
gotoNext
();
};
p
.
open_modal
=
function
()
{
$rootScope
.
appEvent
(
'show-modal'
,
{
templateHtml
:
'<unsaved-changes-modal dismiss="dismiss()"></unsaved-changes-modal>'
,
modalClass
:
'modal--narrow confirm-modal'
});
};
p
.
saveChanges
=
function
()
{
var
self
=
this
;
var
cancel
=
$rootScope
.
$on
(
'dashboard-saved'
,
function
()
{
cancel
();
$timeout
(
function
()
{
self
.
gotoNext
();
});
});
$rootScope
.
appEvent
(
'save-dashboard'
);
};
p
.
gotoNext
=
function
()
{
var
baseLen
=
$location
.
absUrl
().
length
-
$location
.
url
().
length
;
var
nextUrl
=
this
.
next
.
substring
(
baseLen
);
$location
.
url
(
nextUrl
);
};
this
.
Tracker
=
Tracker
;
this
.
init
=
function
(
dashboard
,
scope
)
{
this
.
tracker
=
new
Tracker
(
dashboard
,
scope
,
1000
);
return
this
.
tracker
;
};
});
});
public/app/features/dashboard/unsaved_changes_srv.ts
0 → 100644
View file @
9b63a817
import
angular
from
'angular'
;
import
_
from
'lodash'
;
export
class
Tracker
{
current
:
any
;
originalPath
:
any
;
scope
:
any
;
original
:
any
;
next
:
any
;
$window
:
any
;
/** @ngInject */
constructor
(
dashboard
,
scope
,
originalCopyDelay
,
private
$location
,
$window
,
private
$timeout
,
private
contextSrv
,
private
$rootScope
)
{
this
.
$location
=
$location
;
this
.
$window
=
$window
;
this
.
current
=
dashboard
;
this
.
originalPath
=
$location
.
path
();
this
.
scope
=
scope
;
// register events
scope
.
onAppEvent
(
'dashboard-saved'
,
()
=>
{
this
.
original
=
this
.
current
.
getSaveModelClone
();
this
.
originalPath
=
$location
.
path
();
});
$window
.
onbeforeunload
=
()
=>
{
if
(
this
.
ignoreChanges
())
{
return
''
;
}
if
(
this
.
hasChanges
())
{
return
'There are unsaved changes to this dashboard'
;
}
return
''
;
};
scope
.
$on
(
'$locationChangeStart'
,
(
event
,
next
)
=>
{
// check if we should look for changes
if
(
this
.
originalPath
===
$location
.
path
())
{
return
true
;
}
if
(
this
.
ignoreChanges
())
{
return
true
;
}
if
(
this
.
hasChanges
())
{
event
.
preventDefault
();
this
.
next
=
next
;
this
.
$timeout
(()
=>
{
this
.
open_modal
();
});
}
return
false
;
});
if
(
originalCopyDelay
)
{
this
.
$timeout
(()
=>
{
// wait for different services to patch the dashboard (missing properties)
this
.
original
=
dashboard
.
getSaveModelClone
();
},
originalCopyDelay
);
}
else
{
this
.
original
=
dashboard
.
getSaveModelClone
();
}
}
// for some dashboards and users
// changes should be ignored
ignoreChanges
()
{
if
(
!
this
.
original
)
{
return
true
;
}
if
(
!
this
.
contextSrv
.
isEditor
)
{
return
true
;
}
if
(
!
this
.
current
||
!
this
.
current
.
meta
)
{
return
true
;
}
var
meta
=
this
.
current
.
meta
;
return
!
meta
.
canSave
||
meta
.
fromScript
||
meta
.
fromFile
;
}
// remove stuff that should not count in diff
cleanDashboardFromIgnoredChanges
(
dash
)
{
// ignore time and refresh
dash
.
time
=
0
;
dash
.
refresh
=
0
;
dash
.
schemaVersion
=
0
;
// filter row and panels properties that should be ignored
dash
.
rows
=
_
.
filter
(
dash
.
rows
,
function
(
row
)
{
if
(
row
.
repeatRowId
)
{
return
false
;
}
row
.
panels
=
_
.
filter
(
row
.
panels
,
function
(
panel
)
{
if
(
panel
.
repeatPanelId
)
{
return
false
;
}
// remove scopedVars
panel
.
scopedVars
=
null
;
// ignore span changes
panel
.
span
=
null
;
// ignore panel legend sort
if
(
panel
.
legend
)
{
delete
panel
.
legend
.
sort
;
delete
panel
.
legend
.
sortDesc
;
}
return
true
;
});
// ignore collapse state
row
.
collapse
=
false
;
return
true
;
});
dash
.
panels
=
_
.
filter
(
dash
.
panels
,
panel
=>
{
if
(
panel
.
repeatPanelId
)
{
return
false
;
}
// remove scopedVars
panel
.
scopedVars
=
null
;
// ignore panel legend sort
if
(
panel
.
legend
)
{
delete
panel
.
legend
.
sort
;
delete
panel
.
legend
.
sortDesc
;
}
return
true
;
});
// ignore template variable values
_
.
each
(
dash
.
templating
.
list
,
function
(
value
)
{
value
.
current
=
null
;
value
.
options
=
null
;
value
.
filters
=
null
;
});
}
hasChanges
()
{
var
current
=
this
.
current
.
getSaveModelClone
();
var
original
=
this
.
original
;
this
.
cleanDashboardFromIgnoredChanges
(
current
);
this
.
cleanDashboardFromIgnoredChanges
(
original
);
var
currentTimepicker
=
_
.
find
(
current
.
nav
,
{
type
:
'timepicker'
});
var
originalTimepicker
=
_
.
find
(
original
.
nav
,
{
type
:
'timepicker'
});
if
(
currentTimepicker
&&
originalTimepicker
)
{
currentTimepicker
.
now
=
originalTimepicker
.
now
;
}
var
currentJson
=
angular
.
toJson
(
current
);
var
originalJson
=
angular
.
toJson
(
original
);
return
currentJson
!==
originalJson
;
}
discardChanges
()
{
this
.
original
=
null
;
this
.
gotoNext
();
}
open_modal
()
{
this
.
$rootScope
.
appEvent
(
'show-modal'
,
{
templateHtml
:
'<unsaved-changes-modal dismiss="dismiss()"></unsaved-changes-modal>'
,
modalClass
:
'modal--narrow confirm-modal'
,
});
}
saveChanges
()
{
var
self
=
this
;
var
cancel
=
this
.
$rootScope
.
$on
(
'dashboard-saved'
,
()
=>
{
cancel
();
this
.
$timeout
(()
=>
{
self
.
gotoNext
();
});
});
this
.
$rootScope
.
appEvent
(
'save-dashboard'
);
}
gotoNext
()
{
var
baseLen
=
this
.
$location
.
absUrl
().
length
-
this
.
$location
.
url
().
length
;
var
nextUrl
=
this
.
next
.
substring
(
baseLen
);
this
.
$location
.
url
(
nextUrl
);
}
}
/** @ngInject */
export
function
unsavedChangesSrv
(
$rootScope
,
$q
,
$location
,
$timeout
,
contextSrv
,
dashboardSrv
,
$window
)
{
this
.
Tracker
=
Tracker
;
this
.
init
=
function
(
dashboard
,
scope
)
{
this
.
tracker
=
new
Tracker
(
dashboard
,
scope
,
1000
,
$location
,
$window
,
$timeout
,
contextSrv
,
$rootScope
);
return
this
.
tracker
;
};
}
angular
.
module
(
'grafana.services'
)
.
service
(
'unsavedChangesSrv'
,
unsavedChangesSrv
);
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