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
830c307b
Commit
830c307b
authored
Nov 21, 2017
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
progress on scrollable panels work
parent
741e5a38
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
46 additions
and
53 deletions
+46
-53
public/app/core/components/scroll/scroll.ts
+0
-2
public/app/features/dashboard/dashgrid/DashboardPanel.tsx
+1
-1
public/app/features/dashboard/dashgrid/PanelLoader.ts
+1
-1
public/app/features/panel/panel_ctrl.ts
+4
-15
public/app/features/panel/panel_directive.ts
+21
-26
public/app/features/plugins/plugin_component.ts
+2
-2
public/app/plugins/panel/alertlist/module.ts
+1
-1
public/app/plugins/panel/dashlist/module.ts
+1
-1
public/app/plugins/panel/singlestat/module.ts
+6
-1
public/app/plugins/panel/text/module.ts
+2
-1
public/sass/components/_panel_singlestat.scss
+1
-0
public/sass/pages/_dashboard.scss
+6
-2
No files found.
public/app/core/components/scroll/scroll.ts
View file @
830c307b
///<reference path="../../../headers/common.d.ts" />
import
GeminiScrollbar
from
'gemini-scrollbar'
;
import
GeminiScrollbar
from
'gemini-scrollbar'
;
import
coreModule
from
'app/core/core_module'
;
import
coreModule
from
'app/core/core_module'
;
...
...
public/app/features/dashboard/dashgrid/DashboardPanel.tsx
View file @
830c307b
...
@@ -47,7 +47,7 @@ export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
...
@@ -47,7 +47,7 @@ export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
}
}
return
(
return
(
<
div
ref=
{
element
=>
this
.
element
=
element
}
/>
<
div
ref=
{
element
=>
this
.
element
=
element
}
className=
"panel-height-helper"
/>
);
);
}
}
}
}
...
...
public/app/features/dashboard/dashgrid/PanelLoader.ts
View file @
830c307b
...
@@ -12,7 +12,7 @@ export class PanelLoader {
...
@@ -12,7 +12,7 @@ export class PanelLoader {
}
}
load
(
elem
,
panel
,
dashboard
):
AttachedPanel
{
load
(
elem
,
panel
,
dashboard
):
AttachedPanel
{
var
template
=
'<plugin-component type="panel"></plugin-component>'
;
var
template
=
'<plugin-component type="panel"
class="panel-height-helper"
></plugin-component>'
;
var
panelScope
=
this
.
$rootScope
.
$new
();
var
panelScope
=
this
.
$rootScope
.
$new
();
panelScope
.
panel
=
panel
;
panelScope
.
panel
=
panel
;
panelScope
.
dashboard
=
dashboard
;
panelScope
.
dashboard
=
dashboard
;
...
...
public/app/features/panel/panel_ctrl.ts
View file @
830c307b
...
@@ -5,9 +5,7 @@ import {appEvents, profiler} from 'app/core/core';
...
@@ -5,9 +5,7 @@ import {appEvents, profiler} from 'app/core/core';
import
Remarkable
from
'remarkable'
;
import
Remarkable
from
'remarkable'
;
import
{
GRID_CELL_HEIGHT
,
GRID_CELL_VMARGIN
}
from
'app/core/constants'
;
import
{
GRID_CELL_HEIGHT
,
GRID_CELL_VMARGIN
}
from
'app/core/constants'
;
const
TITLE_HEIGHT
=
25
;
const
TITLE_HEIGHT
=
27
;
const
EMPTY_TITLE_HEIGHT
=
9
;
const
PANEL_PADDING
=
5
;
const
PANEL_BORDER
=
2
;
const
PANEL_BORDER
=
2
;
import
{
Emitter
}
from
'app/core/core'
;
import
{
Emitter
}
from
'app/core/core'
;
...
@@ -31,7 +29,6 @@ export class PanelCtrl {
...
@@ -31,7 +29,6 @@ export class PanelCtrl {
containerHeight
:
any
;
containerHeight
:
any
;
events
:
Emitter
;
events
:
Emitter
;
timing
:
any
;
timing
:
any
;
scrollable
:
boolean
;
constructor
(
$scope
,
$injector
)
{
constructor
(
$scope
,
$injector
)
{
this
.
$injector
=
$injector
;
this
.
$injector
=
$injector
;
...
@@ -40,7 +37,6 @@ export class PanelCtrl {
...
@@ -40,7 +37,6 @@ export class PanelCtrl {
this
.
editorTabIndex
=
0
;
this
.
editorTabIndex
=
0
;
this
.
events
=
this
.
panel
.
events
;
this
.
events
=
this
.
panel
.
events
;
this
.
timing
=
{};
this
.
timing
=
{};
this
.
scrollable
=
false
;
var
plugin
=
config
.
panels
[
this
.
panel
.
type
];
var
plugin
=
config
.
panels
[
this
.
panel
.
type
];
if
(
plugin
)
{
if
(
plugin
)
{
...
@@ -66,7 +62,6 @@ export class PanelCtrl {
...
@@ -66,7 +62,6 @@ export class PanelCtrl {
}
}
refresh
()
{
refresh
()
{
this
.
setPanelHeight
();
this
.
events
.
emit
(
'refresh'
,
null
);
this
.
events
.
emit
(
'refresh'
,
null
);
}
}
...
@@ -75,7 +70,6 @@ export class PanelCtrl {
...
@@ -75,7 +70,6 @@ export class PanelCtrl {
}
}
changeView
(
fullscreen
,
edit
)
{
changeView
(
fullscreen
,
edit
)
{
this
.
setPanelHeight
();
this
.
publishAppEvent
(
'panel-change-view'
,
{
this
.
publishAppEvent
(
'panel-change-view'
,
{
fullscreen
:
fullscreen
,
edit
:
edit
,
panelId
:
this
.
panel
.
id
fullscreen
:
fullscreen
,
edit
:
edit
,
panelId
:
this
.
panel
.
id
});
});
...
@@ -169,18 +163,13 @@ export class PanelCtrl {
...
@@ -169,18 +163,13 @@ export class PanelCtrl {
this
.
containerHeight
=
this
.
panel
.
gridPos
.
h
*
GRID_CELL_HEIGHT
+
((
this
.
panel
.
gridPos
.
h
-
1
)
*
GRID_CELL_VMARGIN
);
this
.
containerHeight
=
this
.
panel
.
gridPos
.
h
*
GRID_CELL_HEIGHT
+
((
this
.
panel
.
gridPos
.
h
-
1
)
*
GRID_CELL_VMARGIN
);
}
}
this
.
height
=
this
.
containerHeight
-
(
PANEL_BORDER
+
PANEL_PADDING
+
(
this
.
panel
.
title
?
TITLE_HEIGHT
:
EMPTY_TITLE_HEIGHT
));
console
.
log
(
this
.
containerHeight
);
}
this
.
height
=
this
.
containerHeight
-
(
PANEL_BORDER
+
TITLE_HEIGHT
);
console
.
log
(
PANEL_BORDER
+
TITLE_HEIGHT
);
setPanelHeight
()
{
if
(
this
.
scrollable
)
{
this
.
$scope
.
setPanelHeight
();
}
}
}
render
(
payload
?)
{
render
(
payload
?)
{
this
.
timing
.
renderStart
=
new
Date
().
getTime
();
this
.
timing
.
renderStart
=
new
Date
().
getTime
();
this
.
setPanelHeight
();
this
.
events
.
emit
(
'render'
,
payload
);
this
.
events
.
emit
(
'render'
,
payload
);
}
}
...
...
public/app/features/panel/panel_directive.ts
View file @
830c307b
///<reference path="../../headers/common.d.ts" />
import
angular
from
'angular'
;
import
angular
from
'angular'
;
import
Drop
from
'tether-drop'
;
import
Drop
from
'tether-drop'
;
import
GeminiScrollbar
from
'gemini-scrollbar'
;
var
module
=
angular
.
module
(
'grafana.directives'
);
var
module
=
angular
.
module
(
'grafana.directives'
);
...
@@ -21,12 +20,7 @@ var panelTemplate = `
...
@@ -21,12 +20,7 @@ var panelTemplate = `
</div>
</div>
<div class="panel-content">
<div class="panel-content">
<div gemini-scrollbar ng-if="ctrl.scrollable">
<ng-transclude></ng-transclude>
<div class="panel-content--scrollable">
<ng-transclude></ng-transclude>
</div>
</div>
<ng-transclude ng-if="!ctrl.scrollable"></ng-transclude>
</div>
</div>
</div>
</div>
...
@@ -78,7 +72,7 @@ module.directive('grafanaPanel', function($rootScope, $document) {
...
@@ -78,7 +72,7 @@ module.directive('grafanaPanel', function($rootScope, $document) {
var
lastHasAlertRule
=
false
;
var
lastHasAlertRule
=
false
;
var
lastAlertState
;
var
lastAlertState
;
var
hasAlertRule
;
var
hasAlertRule
;
var
lastHeight
=
0
;
//
var lastHeight = 0;
function
mouseEnter
()
{
function
mouseEnter
()
{
panelContainer
.
toggleClass
(
'panel-hover-highlight'
,
true
);
panelContainer
.
toggleClass
(
'panel-hover-highlight'
,
true
);
...
@@ -90,16 +84,17 @@ module.directive('grafanaPanel', function($rootScope, $document) {
...
@@ -90,16 +84,17 @@ module.directive('grafanaPanel', function($rootScope, $document) {
ctrl
.
dashboard
.
setPanelFocus
(
0
);
ctrl
.
dashboard
.
setPanelFocus
(
0
);
}
}
function
setPanelHeight
()
{
panelContent
.
height
(
ctrl
.
height
);
}
ctrl
.
$scope
.
setPanelHeight
=
setPanelHeight
;
// set initial height
// set initial height
if
(
!
ctrl
.
containerH
eight
)
{
if
(
!
ctrl
.
h
eight
)
{
ctrl
.
calculatePanelHeight
();
ctrl
.
calculatePanelHeight
();
panelContainer
.
css
({
minHeight
:
ctrl
.
containerHeight
});
if
(
ctrl
.
__proto__
.
constructor
.
scrollable
)
{
lastHeight
=
ctrl
.
containerHeight
;
panelContent
.
addClass
(
'panel-content--scrollable'
);
var
myScrollbar
=
new
GeminiScrollbar
({
autoshow
:
false
,
element
:
panelContent
[
0
]
}).
create
();
}
}
}
// set initial transparency
// set initial transparency
...
@@ -109,10 +104,10 @@ module.directive('grafanaPanel', function($rootScope, $document) {
...
@@ -109,10 +104,10 @@ module.directive('grafanaPanel', function($rootScope, $document) {
}
}
ctrl
.
events
.
on
(
'render'
,
()
=>
{
ctrl
.
events
.
on
(
'render'
,
()
=>
{
if
(
lastHeight
!==
ctrl
.
containerH
eight
)
{
// if (lastHeight !== ctrl.h
eight) {
panelContainer
.
css
({
minHeight
:
ctrl
.
containerHeight
});
// panelContent.css({'height': ctrl.height + 'px'
});
lastHeight
=
ctrl
.
containerH
eight
;
// lastHeight = ctrl.h
eight;
}
//
}
if
(
transparentLastState
!==
ctrl
.
panel
.
transparent
)
{
if
(
transparentLastState
!==
ctrl
.
panel
.
transparent
)
{
panelContainer
.
toggleClass
(
'panel-transparent'
,
ctrl
.
panel
.
transparent
===
true
);
panelContainer
.
toggleClass
(
'panel-transparent'
,
ctrl
.
panel
.
transparent
===
true
);
...
@@ -201,11 +196,11 @@ module.directive('panelHelpCorner', function($rootScope) {
...
@@ -201,11 +196,11 @@ module.directive('panelHelpCorner', function($rootScope) {
return
{
return
{
restrict
:
'E'
,
restrict
:
'E'
,
template
:
`
template
:
`
<span class="alert-error panel-error small pointer" ng-if="ctrl.error" ng-click="ctrl.openInspector()">
<span class="alert-error panel-error small pointer" ng-if="ctrl.error" ng-click="ctrl.openInspector()">
<span data-placement="top" bs-tooltip="ctrl.error">
<span data-placement="top" bs-tooltip="ctrl.error">
<i class="fa fa-exclamation"></i><span class="panel-error-arrow"></span>
<i class="fa fa-exclamation"></i><span class="panel-error-arrow"></span>
</span>
</span>
</span>
</span>
`
,
`
,
link
:
function
(
scope
,
elem
)
{
link
:
function
(
scope
,
elem
)
{
}
}
...
...
public/app/features/plugins/plugin_component.ts
View file @
830c307b
...
@@ -68,7 +68,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
...
@@ -68,7 +68,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
var
componentInfo
:
any
=
{
var
componentInfo
:
any
=
{
name
:
'panel-plugin-'
+
scope
.
panel
.
type
,
name
:
'panel-plugin-'
+
scope
.
panel
.
type
,
bindings
:
{
dashboard
:
"="
,
panel
:
"="
,
row
:
"="
},
bindings
:
{
dashboard
:
"="
,
panel
:
"="
,
row
:
"="
},
attrs
:
{
dashboard
:
"dashboard"
,
panel
:
"panel"
},
attrs
:
{
dashboard
:
"dashboard"
,
panel
:
"panel"
,
class
:
"panel-height-helper"
},
};
};
let
panelInfo
=
config
.
panels
[
scope
.
panel
.
type
];
let
panelInfo
=
config
.
panels
[
scope
.
panel
.
type
];
...
@@ -98,7 +98,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
...
@@ -98,7 +98,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
PanelCtrl
.
templatePromise
=
getTemplate
(
PanelCtrl
).
then
(
template
=>
{
PanelCtrl
.
templatePromise
=
getTemplate
(
PanelCtrl
).
then
(
template
=>
{
PanelCtrl
.
templateUrl
=
null
;
PanelCtrl
.
templateUrl
=
null
;
PanelCtrl
.
template
=
`<grafana-panel ctrl="ctrl">
${
template
}
</grafana-panel>`
;
PanelCtrl
.
template
=
`<grafana-panel ctrl="ctrl"
class="panel-height-helper"
>
${
template
}
</grafana-panel>`
;
return
componentInfo
;
return
componentInfo
;
});
});
...
...
public/app/plugins/panel/alertlist/module.ts
View file @
830c307b
...
@@ -9,6 +9,7 @@ import * as dateMath from 'app/core/utils/datemath';
...
@@ -9,6 +9,7 @@ import * as dateMath from 'app/core/utils/datemath';
class
AlertListPanel
extends
PanelCtrl
{
class
AlertListPanel
extends
PanelCtrl
{
static
templateUrl
=
'module.html'
;
static
templateUrl
=
'module.html'
;
static
scrollable
=
true
;
showOptions
=
[
showOptions
=
[
{
text
:
'Current state'
,
value
:
'current'
},
{
text
:
'Current state'
,
value
:
'current'
},
...
@@ -38,7 +39,6 @@ class AlertListPanel extends PanelCtrl {
...
@@ -38,7 +39,6 @@ class AlertListPanel extends PanelCtrl {
constructor
(
$scope
,
$injector
,
private
backendSrv
)
{
constructor
(
$scope
,
$injector
,
private
backendSrv
)
{
super
(
$scope
,
$injector
);
super
(
$scope
,
$injector
);
_
.
defaults
(
this
.
panel
,
this
.
panelDefaults
);
_
.
defaults
(
this
.
panel
,
this
.
panelDefaults
);
this
.
scrollable
=
true
;
this
.
events
.
on
(
'init-edit-mode'
,
this
.
onInitEditMode
.
bind
(
this
));
this
.
events
.
on
(
'init-edit-mode'
,
this
.
onInitEditMode
.
bind
(
this
));
this
.
events
.
on
(
'refresh'
,
this
.
onRefresh
.
bind
(
this
));
this
.
events
.
on
(
'refresh'
,
this
.
onRefresh
.
bind
(
this
));
...
...
public/app/plugins/panel/dashlist/module.ts
View file @
830c307b
...
@@ -6,6 +6,7 @@ import {impressions} from 'app/features/dashboard/impression_store';
...
@@ -6,6 +6,7 @@ import {impressions} from 'app/features/dashboard/impression_store';
class
DashListCtrl
extends
PanelCtrl
{
class
DashListCtrl
extends
PanelCtrl
{
static
templateUrl
=
'module.html'
;
static
templateUrl
=
'module.html'
;
static
scrollable
=
true
;
groups
:
any
[];
groups
:
any
[];
modes
:
any
[];
modes
:
any
[];
...
@@ -25,7 +26,6 @@ class DashListCtrl extends PanelCtrl {
...
@@ -25,7 +26,6 @@ class DashListCtrl extends PanelCtrl {
constructor
(
$scope
,
$injector
,
private
backendSrv
,
private
dashboardSrv
)
{
constructor
(
$scope
,
$injector
,
private
backendSrv
,
private
dashboardSrv
)
{
super
(
$scope
,
$injector
);
super
(
$scope
,
$injector
);
_
.
defaults
(
this
.
panel
,
this
.
panelDefaults
);
_
.
defaults
(
this
.
panel
,
this
.
panelDefaults
);
this
.
scrollable
=
true
;
if
(
this
.
panel
.
tag
)
{
if
(
this
.
panel
.
tag
)
{
this
.
panel
.
tags
=
[
this
.
panel
.
tag
];
this
.
panel
.
tags
=
[
this
.
panel
.
tag
];
...
...
public/app/plugins/panel/singlestat/module.ts
View file @
830c307b
...
@@ -395,9 +395,10 @@ class SingleStatCtrl extends MetricsPanelCtrl {
...
@@ -395,9 +395,10 @@ class SingleStatCtrl extends MetricsPanelCtrl {
var
data
,
linkInfo
;
var
data
,
linkInfo
;
var
$panelContainer
=
elem
.
find
(
'.panel-container'
);
var
$panelContainer
=
elem
.
find
(
'.panel-container'
);
elem
=
elem
.
find
(
'.singlestat-panel'
);
elem
=
elem
.
find
(
'.singlestat-panel'
);
console
.
log
(
'singlestat element'
,
elem
.
length
);
function
setElementHeight
()
{
function
setElementHeight
()
{
elem
.
css
(
'height'
,
ctrl
.
height
+
'px'
);
///
elem.css('height', ctrl.height + 'px');
}
}
function
applyColoringThresholds
(
value
,
valueString
)
{
function
applyColoringThresholds
(
value
,
valueString
)
{
...
@@ -560,6 +561,8 @@ class SingleStatCtrl extends MetricsPanelCtrl {
...
@@ -560,6 +561,8 @@ class SingleStatCtrl extends MetricsPanelCtrl {
plotCss
.
height
=
Math
.
floor
(
height
*
0.25
)
+
"px"
;
plotCss
.
height
=
Math
.
floor
(
height
*
0.25
)
+
"px"
;
}
}
console
.
log
(
'singlestat height'
,
ctrl
.
height
);
console
.
log
(
'singlestat plotCss'
,
plotCss
.
height
);
plotCanvas
.
css
(
plotCss
);
plotCanvas
.
css
(
plotCss
);
var
options
=
{
var
options
=
{
...
@@ -596,6 +599,8 @@ class SingleStatCtrl extends MetricsPanelCtrl {
...
@@ -596,6 +599,8 @@ class SingleStatCtrl extends MetricsPanelCtrl {
if
(
!
ctrl
.
data
)
{
return
;
}
if
(
!
ctrl
.
data
)
{
return
;
}
data
=
ctrl
.
data
;
data
=
ctrl
.
data
;
console
.
log
(
'singlestat'
,
elem
.
html
());
// get thresholds
// get thresholds
data
.
thresholds
=
panel
.
thresholds
.
split
(
','
).
map
(
function
(
strVale
)
{
data
.
thresholds
=
panel
.
thresholds
.
split
(
','
).
map
(
function
(
strVale
)
{
return
Number
(
strVale
.
trim
());
return
Number
(
strVale
.
trim
());
...
...
public/app/plugins/panel/text/module.ts
View file @
830c307b
...
@@ -5,6 +5,7 @@ import {PanelCtrl} from 'app/plugins/sdk';
...
@@ -5,6 +5,7 @@ import {PanelCtrl} from 'app/plugins/sdk';
export
class
TextPanelCtrl
extends
PanelCtrl
{
export
class
TextPanelCtrl
extends
PanelCtrl
{
static
templateUrl
=
`public/app/plugins/panel/text/module.html`
;
static
templateUrl
=
`public/app/plugins/panel/text/module.html`
;
static
scrollable
=
true
;
remarkable
:
any
;
remarkable
:
any
;
content
:
string
;
content
:
string
;
...
@@ -19,11 +20,11 @@ export class TextPanelCtrl extends PanelCtrl {
...
@@ -19,11 +20,11 @@ export class TextPanelCtrl extends PanelCtrl {
super
(
$scope
,
$injector
);
super
(
$scope
,
$injector
);
_
.
defaults
(
this
.
panel
,
this
.
panelDefaults
);
_
.
defaults
(
this
.
panel
,
this
.
panelDefaults
);
this
.
scrollable
=
true
;
this
.
events
.
on
(
'init-edit-mode'
,
this
.
onInitEditMode
.
bind
(
this
));
this
.
events
.
on
(
'init-edit-mode'
,
this
.
onInitEditMode
.
bind
(
this
));
this
.
events
.
on
(
'refresh'
,
this
.
onRefresh
.
bind
(
this
));
this
.
events
.
on
(
'refresh'
,
this
.
onRefresh
.
bind
(
this
));
this
.
events
.
on
(
'render'
,
this
.
onRender
.
bind
(
this
));
this
.
events
.
on
(
'render'
,
this
.
onRender
.
bind
(
this
));
$scope
.
$watch
(
'ctrl.panel.content'
,
$scope
.
$watch
(
'ctrl.panel.content'
,
_
.
throttle
(()
=>
{
_
.
throttle
(()
=>
{
this
.
render
();
this
.
render
();
...
...
public/sass/components/_panel_singlestat.scss
View file @
830c307b
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
position
:
relative
;
position
:
relative
;
display
:
table
;
display
:
table
;
width
:
100%
;
width
:
100%
;
height
:
100%
;
}
}
.singlestat-panel-value-container
{
.singlestat-panel-value-container
{
...
...
public/sass/pages/_dashboard.scss
View file @
830c307b
...
@@ -23,6 +23,11 @@ div.flot-text {
...
@@ -23,6 +23,11 @@ div.flot-text {
}
}
}
}
.panel-height-helper
{
display
:
block
;
height
:
100%
;
}
.panel-container
{
.panel-container
{
background-color
:
$panel-bg
;
background-color
:
$panel-bg
;
border
:
$panel-border
;
border
:
$panel-border
;
...
@@ -38,12 +43,11 @@ div.flot-text {
...
@@ -38,12 +43,11 @@ div.flot-text {
.panel-content
{
.panel-content
{
padding
:
0px
10px
5px
10px
;
padding
:
0px
10px
5px
10px
;
height
:
100%
;
height
:
calc
(
100%
-
27px
)
;
&
--scrollable
{
&
--scrollable
{
// Add space for scrollbar
// Add space for scrollbar
padding-right
:
10px
;
padding-right
:
10px
;
padding-left
:
6px
;
}
}
}
}
...
...
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