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
6ea99540
Commit
6ea99540
authored
Apr 21, 2017
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of github.com:grafana/grafana
parents
b22b3e5b
61609780
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
248 additions
and
37 deletions
+248
-37
public/app/plugins/panel/singlestat/editor.html
+9
-1
public/app/plugins/panel/singlestat/module.ts
+90
-16
public/app/plugins/panel/singlestat/specs/singlestat_specs.ts
+149
-20
No files found.
public/app/plugins/panel/singlestat/editor.html
View file @
6ea99540
...
...
@@ -3,11 +3,19 @@
<h5
class=
"section-heading"
>
Value
</h5>
<div
class=
"gf-form-inline"
>
<div
class=
"gf-form"
>
<div
class=
"gf-form"
ng-show=
"ctrl.dataType === 'timeseries'"
>
<label
class=
"gf-form-label width-6"
>
Stat
</label>
<div
class=
"gf-form-select-wrapper width-7"
>
<select
class=
"gf-form-input"
ng-model=
"ctrl.panel.valueName"
ng-options=
"f for f in ctrl.valueNameOptions"
ng-change=
"ctrl.render()"
></select>
</div>
</div>
<div
class=
"gf-form"
ng-show=
"ctrl.dataType === 'table'"
>
<label
class=
"gf-form-label width-6"
>
Column
</label>
<div
class=
"gf-form-select-wrapper width-7"
>
<select
class=
"gf-form-input"
ng-model=
"ctrl.panel.tableColumn"
ng-options=
"f for f in ctrl.tableColumnOptions"
ng-change=
"ctrl.refresh()"
></select>
</div>
</div>
<div
class=
"gf-form"
>
<label
class=
"gf-form-label width-6"
>
Font size
</label>
<div
class=
"gf-form-select-wrapper"
>
<select
class=
"gf-form-input"
ng-model=
"ctrl.panel.valueFontSize"
ng-options=
"f for f in ctrl.fontSizes"
ng-change=
"ctrl.render()"
></select>
...
...
public/app/plugins/panel/singlestat/module.ts
View file @
6ea99540
...
...
@@ -14,6 +14,7 @@ import {MetricsPanelCtrl} from 'app/plugins/sdk';
class
SingleStatCtrl
extends
MetricsPanelCtrl
{
static
templateUrl
=
'module.html'
;
dataType
=
'timeseries'
;
series
:
any
[];
data
:
any
;
fontSizes
:
any
[];
...
...
@@ -22,6 +23,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
panel
:
any
;
events
:
any
;
valueNameOptions
:
any
[]
=
[
'min'
,
'max'
,
'avg'
,
'current'
,
'total'
,
'name'
,
'first'
,
'delta'
,
'diff'
,
'range'
];
tableColumnOptions
:
any
;
// Set and populate defaults
panelDefaults
=
{
...
...
@@ -67,7 +69,8 @@ class SingleStatCtrl extends MetricsPanelCtrl {
maxValue
:
100
,
thresholdMarkers
:
true
,
thresholdLabels
:
false
}
},
tableColumn
:
''
};
/** @ngInject */
...
...
@@ -98,11 +101,16 @@ class SingleStatCtrl extends MetricsPanelCtrl {
}
onDataReceived
(
dataList
)
{
this
.
series
=
dataList
.
map
(
this
.
seriesHandler
.
bind
(
this
));
var
data
:
any
=
{};
this
.
setValues
(
data
);
const
data
:
any
=
{};
if
(
dataList
.
length
>
0
&&
dataList
[
0
].
type
===
'table'
){
this
.
dataType
=
'table'
;
const
tableData
=
dataList
.
map
(
this
.
tableHandler
.
bind
(
this
));
this
.
setTableValues
(
tableData
,
data
);
}
else
{
this
.
dataType
=
'timeseries'
;
this
.
series
=
dataList
.
map
(
this
.
seriesHandler
.
bind
(
this
));
this
.
setValues
(
data
);
}
this
.
data
=
data
;
this
.
render
();
}
...
...
@@ -117,6 +125,69 @@ class SingleStatCtrl extends MetricsPanelCtrl {
return
series
;
}
tableHandler
(
tableData
)
{
const
datapoints
=
[];
const
columnNames
=
{};
tableData
.
columns
.
forEach
((
column
,
columnIndex
)
=>
{
columnNames
[
columnIndex
]
=
column
.
text
;
});
this
.
tableColumnOptions
=
columnNames
;
if
(
!
_
.
find
(
tableData
.
columns
,
[
'text'
,
this
.
panel
.
tableColumn
]))
{
this
.
setTableColumnToSensibleDefault
(
tableData
);
}
tableData
.
rows
.
forEach
((
row
)
=>
{
const
datapoint
=
{};
row
.
forEach
((
value
,
columnIndex
)
=>
{
const
key
=
columnNames
[
columnIndex
];
datapoint
[
key
]
=
value
;
});
datapoints
.
push
(
datapoint
);
});
return
datapoints
;
}
setTableColumnToSensibleDefault
(
tableData
)
{
if
(
this
.
tableColumnOptions
.
length
===
1
)
{
this
.
panel
.
tableColumn
=
this
.
tableColumnOptions
[
0
];
}
else
{
this
.
panel
.
tableColumn
=
_
.
find
(
tableData
.
columns
,
(
col
)
=>
{
return
col
.
type
!==
'time'
;
}).
text
;
}
}
setTableValues
(
tableData
,
data
)
{
if
(
!
tableData
||
tableData
.
length
===
0
)
{
return
;
}
if
(
tableData
[
0
].
length
===
0
||
!
tableData
[
0
][
0
][
this
.
panel
.
tableColumn
])
{
return
;
}
let
highestValue
=
0
;
let
lowestValue
=
Number
.
MAX_VALUE
;
const
datapoint
=
tableData
[
0
][
0
];
data
.
value
=
datapoint
[
this
.
panel
.
tableColumn
];
if
(
_
.
isString
(
data
.
value
))
{
data
.
valueFormatted
=
_
.
escape
(
data
.
value
);
data
.
value
=
0
;
data
.
valueRounded
=
0
;
}
else
{
const
decimalInfo
=
this
.
getDecimalsForValue
(
data
.
value
);
const
formatFunc
=
kbn
.
valueFormats
[
this
.
panel
.
format
];
data
.
valueFormatted
=
formatFunc
(
datapoint
[
this
.
panel
.
tableColumn
],
decimalInfo
.
decimals
,
decimalInfo
.
scaledDecimals
);
data
.
valueRounded
=
kbn
.
roundValue
(
data
.
value
,
this
.
panel
.
decimals
||
0
);
}
this
.
setValueMapping
(
data
);
}
setColoring
(
options
)
{
if
(
options
.
background
)
{
this
.
panel
.
colorValue
=
false
;
...
...
@@ -192,10 +263,10 @@ class SingleStatCtrl extends MetricsPanelCtrl {
if
(
this
.
panel
.
valueName
===
'name'
)
{
data
.
value
=
0
;
data
.
valueRounded
=
0
;
data
.
valueFormated
=
this
.
series
[
0
].
alias
;
data
.
valueFormat
t
ed
=
this
.
series
[
0
].
alias
;
}
else
if
(
_
.
isString
(
lastValue
))
{
data
.
value
=
0
;
data
.
valueFormated
=
_
.
escape
(
lastValue
);
data
.
valueFormat
t
ed
=
_
.
escape
(
lastValue
);
data
.
valueRounded
=
0
;
}
else
{
data
.
value
=
this
.
series
[
0
].
stats
[
this
.
panel
.
valueName
];
...
...
@@ -203,7 +274,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
var
decimalInfo
=
this
.
getDecimalsForValue
(
data
.
value
);
var
formatFunc
=
kbn
.
valueFormats
[
this
.
panel
.
format
];
data
.
valueFormated
=
formatFunc
(
data
.
value
,
decimalInfo
.
decimals
,
decimalInfo
.
scaledDecimals
);
data
.
valueFormat
t
ed
=
formatFunc
(
data
.
value
,
decimalInfo
.
decimals
,
decimalInfo
.
scaledDecimals
);
data
.
valueRounded
=
kbn
.
roundValue
(
data
.
value
,
decimalInfo
.
decimals
);
}
...
...
@@ -211,7 +282,10 @@ class SingleStatCtrl extends MetricsPanelCtrl {
data
.
scopedVars
=
_
.
extend
({},
this
.
panel
.
scopedVars
);
data
.
scopedVars
[
"__name"
]
=
{
value
:
this
.
series
[
0
].
label
};
}
this
.
setValueMapping
(
data
);
}
setValueMapping
(
data
)
{
// check value to text mappings if its enabled
if
(
this
.
panel
.
mappingType
===
1
)
{
for
(
let
i
=
0
;
i
<
this
.
panel
.
valueMaps
.
length
;
i
++
)
{
...
...
@@ -219,7 +293,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
// special null case
if
(
map
.
value
===
'null'
)
{
if
(
data
.
value
===
null
||
data
.
value
===
void
0
)
{
data
.
valueFormated
=
map
.
text
;
data
.
valueFormat
t
ed
=
map
.
text
;
return
;
}
continue
;
...
...
@@ -228,7 +302,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
// value/number to text mapping
var
value
=
parseFloat
(
map
.
value
);
if
(
value
===
data
.
valueRounded
)
{
data
.
valueFormated
=
map
.
text
;
data
.
valueFormat
t
ed
=
map
.
text
;
return
;
}
}
...
...
@@ -238,7 +312,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
// special null case
if
(
map
.
from
===
'null'
&&
map
.
to
===
'null'
)
{
if
(
data
.
value
===
null
||
data
.
value
===
void
0
)
{
data
.
valueFormated
=
map
.
text
;
data
.
valueFormat
t
ed
=
map
.
text
;
return
;
}
continue
;
...
...
@@ -248,14 +322,14 @@ class SingleStatCtrl extends MetricsPanelCtrl {
var
from
=
parseFloat
(
map
.
from
);
var
to
=
parseFloat
(
map
.
to
);
if
(
to
>=
data
.
valueRounded
&&
from
<=
data
.
valueRounded
)
{
data
.
valueFormated
=
map
.
text
;
data
.
valueFormat
t
ed
=
map
.
text
;
return
;
}
}
}
if
(
data
.
value
===
null
||
data
.
value
===
void
0
)
{
data
.
valueFormated
=
"no value"
;
data
.
valueFormat
t
ed
=
"no value"
;
}
}
...
...
@@ -317,7 +391,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
if
(
panel
.
prefix
)
{
body
+=
getSpan
(
'singlestat-panel-prefix'
,
panel
.
prefixFontSize
,
panel
.
prefix
);
}
var
value
=
applyColoringThresholds
(
data
.
value
,
data
.
valueFormated
);
var
value
=
applyColoringThresholds
(
data
.
value
,
data
.
valueFormat
t
ed
);
body
+=
getSpan
(
'singlestat-panel-value'
,
panel
.
valueFontSize
,
value
);
if
(
panel
.
postfix
)
{
body
+=
getSpan
(
'singlestat-panel-postfix'
,
panel
.
postfixFontSize
,
panel
.
postfix
);
}
...
...
@@ -329,7 +403,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
function
getValueText
()
{
var
result
=
panel
.
prefix
?
panel
.
prefix
:
''
;
result
+=
data
.
valueFormated
;
result
+=
data
.
valueFormat
t
ed
;
result
+=
panel
.
postfix
?
panel
.
postfix
:
''
;
return
result
;
...
...
public/app/plugins/panel/singlestat/specs/singlestat
-
specs.ts
→
public/app/plugins/panel/singlestat/specs/singlestat
_
specs.ts
View file @
6ea99540
...
...
@@ -26,11 +26,7 @@ describe('SingleStatCtrl', function() {
beforeEach
(
function
()
{
setupFunc
();
var
data
=
[
{
target
:
'test.cpu1'
,
datapoints
:
ctx
.
datapoints
}
];
ctx
.
ctrl
.
onDataReceived
(
data
);
ctx
.
ctrl
.
onDataReceived
(
ctx
.
data
);
ctx
.
data
=
ctx
.
ctrl
.
data
;
});
};
...
...
@@ -41,7 +37,9 @@ describe('SingleStatCtrl', function() {
singleStatScenario
(
'with defaults'
,
function
(
ctx
)
{
ctx
.
setup
(
function
()
{
ctx
.
datapoints
=
[[
10
,
1
],
[
20
,
2
]];
ctx
.
data
=
[
{
target
:
'test.cpu1'
,
datapoints
:
[[
10
,
1
],
[
20
,
2
]]}
];
});
it
(
'Should use series avg as default main value'
,
function
()
{
...
...
@@ -49,14 +47,16 @@ describe('SingleStatCtrl', function() {
expect
(
ctx
.
data
.
valueRounded
).
to
.
be
(
15
);
});
it
(
'should set formated falue'
,
function
()
{
expect
(
ctx
.
data
.
valueFormated
).
to
.
be
(
'15'
);
it
(
'should set format
t
ed falue'
,
function
()
{
expect
(
ctx
.
data
.
valueFormat
t
ed
).
to
.
be
(
'15'
);
});
});
singleStatScenario
(
'showing serie name instead of value'
,
function
(
ctx
)
{
ctx
.
setup
(
function
()
{
ctx
.
datapoints
=
[[
10
,
1
],
[
20
,
2
]];
ctx
.
data
=
[
{
target
:
'test.cpu1'
,
datapoints
:
[[
10
,
1
],
[
20
,
2
]]}
];
ctx
.
ctrl
.
panel
.
valueName
=
'name'
;
});
...
...
@@ -65,14 +65,16 @@ describe('SingleStatCtrl', function() {
expect
(
ctx
.
data
.
valueRounded
).
to
.
be
(
0
);
});
it
(
'should set formated falue'
,
function
()
{
expect
(
ctx
.
data
.
valueFormated
).
to
.
be
(
'test.cpu1'
);
it
(
'should set format
t
ed falue'
,
function
()
{
expect
(
ctx
.
data
.
valueFormat
t
ed
).
to
.
be
(
'test.cpu1'
);
});
});
singleStatScenario
(
'MainValue should use same number for decimals as displayed when checking thresholds'
,
function
(
ctx
)
{
ctx
.
setup
(
function
()
{
ctx
.
datapoints
=
[[
99.999
,
1
],
[
99.99999
,
2
]];
ctx
.
data
=
[
{
target
:
'test.cpu1'
,
datapoints
:
[[
99.999
,
1
],
[
99.99999
,
2
]]}
];
});
it
(
'Should be rounded'
,
function
()
{
...
...
@@ -80,14 +82,16 @@ describe('SingleStatCtrl', function() {
expect
(
ctx
.
data
.
valueRounded
).
to
.
be
(
100
);
});
it
(
'should set formated falue'
,
function
()
{
expect
(
ctx
.
data
.
valueFormated
).
to
.
be
(
'100'
);
it
(
'should set format
t
ed falue'
,
function
()
{
expect
(
ctx
.
data
.
valueFormat
t
ed
).
to
.
be
(
'100'
);
});
});
singleStatScenario
(
'When value to text mapping is specified'
,
function
(
ctx
)
{
ctx
.
setup
(
function
()
{
ctx
.
datapoints
=
[[
9.9
,
1
]];
ctx
.
data
=
[
{
target
:
'test.cpu1'
,
datapoints
:
[[
9.9
,
1
]]}
];
ctx
.
ctrl
.
panel
.
valueMaps
=
[{
value
:
'10'
,
text
:
'OK'
}];
});
...
...
@@ -100,32 +104,157 @@ describe('SingleStatCtrl', function() {
});
it
(
'Should replace value with text'
,
function
()
{
expect
(
ctx
.
data
.
valueFormated
).
to
.
be
(
'OK'
);
expect
(
ctx
.
data
.
valueFormat
t
ed
).
to
.
be
(
'OK'
);
});
});
singleStatScenario
(
'When range to text mapping is specifiedfor first range'
,
function
(
ctx
)
{
ctx
.
setup
(
function
()
{
ctx
.
datapoints
=
[[
41
,
50
]];
ctx
.
data
=
[
{
target
:
'test.cpu1'
,
datapoints
:
[[
41
,
50
]]}
];
ctx
.
ctrl
.
panel
.
mappingType
=
2
;
ctx
.
ctrl
.
panel
.
rangeMaps
=
[{
from
:
'10'
,
to
:
'50'
,
text
:
'OK'
},{
from
:
'51'
,
to
:
'100'
,
text
:
'NOT OK'
}];
});
it
(
'Should replace value with text OK'
,
function
()
{
expect
(
ctx
.
data
.
valueFormated
).
to
.
be
(
'OK'
);
expect
(
ctx
.
data
.
valueFormat
t
ed
).
to
.
be
(
'OK'
);
});
});
singleStatScenario
(
'When range to text mapping is specified for other ranges'
,
function
(
ctx
)
{
ctx
.
setup
(
function
()
{
ctx
.
datapoints
=
[[
65
,
75
]];
ctx
.
data
=
[
{
target
:
'test.cpu1'
,
datapoints
:
[[
65
,
75
]]}
];
ctx
.
ctrl
.
panel
.
mappingType
=
2
;
ctx
.
ctrl
.
panel
.
rangeMaps
=
[{
from
:
'10'
,
to
:
'50'
,
text
:
'OK'
},{
from
:
'51'
,
to
:
'100'
,
text
:
'NOT OK'
}];
});
it
(
'Should replace value with text NOT OK'
,
function
()
{
expect
(
ctx
.
data
.
valueFormated
).
to
.
be
(
'NOT OK'
);
expect
(
ctx
.
data
.
valueFormat
t
ed
).
to
.
be
(
'NOT OK'
);
});
});
describe
(
'When table data'
,
function
()
{
const
tableData
=
[{
"columns"
:
[
{
"text"
:
"Time"
,
"type"
:
"time"
},
{
"text"
:
"test1"
},
{
"text"
:
"mean"
},
{
"text"
:
"test2"
}
],
"rows"
:
[
[
1492759673649
,
'ignore1'
,
15
,
'ignore2'
]
],
"type"
:
"table"
}];
singleStatScenario
(
'with default values'
,
function
(
ctx
)
{
ctx
.
setup
(
function
()
{
ctx
.
data
=
tableData
;
ctx
.
ctrl
.
panel
.
tableColumn
=
'mean'
;
});
it
(
'Should use first rows value as default main value'
,
function
()
{
expect
(
ctx
.
data
.
value
).
to
.
be
(
15
);
expect
(
ctx
.
data
.
valueRounded
).
to
.
be
(
15
);
});
it
(
'should set formatted value'
,
function
()
{
expect
(
ctx
.
data
.
valueFormatted
).
to
.
be
(
'15'
);
});
});
singleStatScenario
(
'When table data has multiple columns'
,
function
(
ctx
)
{
ctx
.
setup
(
function
()
{
ctx
.
data
=
tableData
;
ctx
.
ctrl
.
panel
.
tableColumn
=
''
;
});
it
(
'Should set column to first column that is not time'
,
function
()
{
expect
(
ctx
.
ctrl
.
panel
.
tableColumn
).
to
.
be
(
'test1'
);
});
});
singleStatScenario
(
'MainValue should use same number for decimals as displayed when checking thresholds'
,
function
(
ctx
)
{
ctx
.
setup
(
function
()
{
ctx
.
data
=
tableData
;
ctx
.
data
[
0
].
rows
[
0
]
=
[
1492759673649
,
'ignore1'
,
99.99999
,
'ignore2'
];
ctx
.
ctrl
.
panel
.
tableColumn
=
'mean'
;
});
it
(
'Should be rounded'
,
function
()
{
expect
(
ctx
.
data
.
value
).
to
.
be
(
99.99999
);
expect
(
ctx
.
data
.
valueRounded
).
to
.
be
(
100
);
});
it
(
'should set formatted falue'
,
function
()
{
expect
(
ctx
.
data
.
valueFormatted
).
to
.
be
(
'100'
);
});
});
singleStatScenario
(
'When value to text mapping is specified'
,
function
(
ctx
)
{
ctx
.
setup
(
function
()
{
ctx
.
data
=
tableData
;
ctx
.
data
[
0
].
rows
[
0
]
=
[
1492759673649
,
'ignore1'
,
9.9
,
'ignore2'
];
ctx
.
ctrl
.
panel
.
tableColumn
=
'mean'
;
ctx
.
ctrl
.
panel
.
valueMaps
=
[{
value
:
'10'
,
text
:
'OK'
}];
});
it
(
'value should remain'
,
function
()
{
expect
(
ctx
.
data
.
value
).
to
.
be
(
9.9
);
});
it
(
'round should be rounded up'
,
function
()
{
expect
(
ctx
.
data
.
valueRounded
).
to
.
be
(
10
);
});
it
(
'Should replace value with text'
,
function
()
{
expect
(
ctx
.
data
.
valueFormatted
).
to
.
be
(
'OK'
);
});
});
singleStatScenario
(
'When range to text mapping is specified for first range'
,
function
(
ctx
)
{
ctx
.
setup
(
function
()
{
ctx
.
data
=
tableData
;
ctx
.
data
[
0
].
rows
[
0
]
=
[
1492759673649
,
'ignore1'
,
41
,
'ignore2'
];
ctx
.
ctrl
.
panel
.
tableColumn
=
'mean'
;
ctx
.
ctrl
.
panel
.
mappingType
=
2
;
ctx
.
ctrl
.
panel
.
rangeMaps
=
[{
from
:
'10'
,
to
:
'50'
,
text
:
'OK'
},{
from
:
'51'
,
to
:
'100'
,
text
:
'NOT OK'
}];
});
it
(
'Should replace value with text OK'
,
function
()
{
expect
(
ctx
.
data
.
valueFormatted
).
to
.
be
(
'OK'
);
});
});
singleStatScenario
(
'When range to text mapping is specified for other ranges'
,
function
(
ctx
)
{
ctx
.
setup
(
function
()
{
ctx
.
data
=
tableData
;
ctx
.
data
[
0
].
rows
[
0
]
=
[
1492759673649
,
'ignore1'
,
65
,
'ignore2'
];
ctx
.
ctrl
.
panel
.
tableColumn
=
'mean'
;
ctx
.
ctrl
.
panel
.
mappingType
=
2
;
ctx
.
ctrl
.
panel
.
rangeMaps
=
[{
from
:
'10'
,
to
:
'50'
,
text
:
'OK'
},{
from
:
'51'
,
to
:
'100'
,
text
:
'NOT OK'
}];
});
it
(
'Should replace value with text NOT OK'
,
function
()
{
expect
(
ctx
.
data
.
valueFormatted
).
to
.
be
(
'NOT OK'
);
});
});
singleStatScenario
(
'When value is string'
,
function
(
ctx
)
{
ctx
.
setup
(
function
()
{
ctx
.
data
=
tableData
;
ctx
.
data
[
0
].
rows
[
0
]
=
[
1492759673649
,
'ignore1'
,
65
,
'ignore2'
];
ctx
.
ctrl
.
panel
.
tableColumn
=
'test1'
;
});
it
(
'Should replace value with text NOT OK'
,
function
()
{
expect
(
ctx
.
data
.
valueFormatted
).
to
.
be
(
'ignore1'
);
});
});
});
});
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