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
0de9c038
Commit
0de9c038
authored
Feb 19, 2019
by
Peter Holmberg
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'gauge-multi-series' into bar-gauge-poc
parents
5f56a07a
c7bb563c
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
408 additions
and
49 deletions
+408
-49
devenv/dev-dashboards/panel_tests_multiseries_gauge.json
+296
-0
packages/grafana-ui/src/components/Gauge/Gauge.tsx
+9
-11
public/app/core/utils/ConfigProvider.tsx
+1
-0
public/app/plugins/panel/gauge/GaugeOptionsBox.tsx
+6
-4
public/app/plugins/panel/gauge/GaugePanel.tsx
+96
-34
No files found.
devenv/dev-dashboards/panel_tests_multiseries_gauge.json
0 → 100644
View file @
0de9c038
{
"annotations"
:
{
"list"
:
[
{
"builtIn"
:
1
,
"datasource"
:
"-- Grafana --"
,
"enable"
:
true
,
"hide"
:
true
,
"iconColor"
:
"rgba(0, 211, 255, 1)"
,
"name"
:
"Annotations & Alerts"
,
"type"
:
"dashboard"
}
]
},
"editable"
:
true
,
"gnetId"
:
null
,
"graphTooltip"
:
0
,
"links"
:
[],
"panels"
:
[
{
"datasource"
:
"gdev-testdata"
,
"gridPos"
:
{
"h"
:
8
,
"w"
:
24
,
"x"
:
0
,
"y"
:
0
},
"id"
:
6
,
"links"
:
[],
"options-gauge"
:
{
"decimals"
:
0
,
"maxValue"
:
100
,
"minValue"
:
0
,
"options"
:
{
"decimals"
:
0
,
"maxValue"
:
100
,
"minValue"
:
0
,
"prefix"
:
""
,
"showThresholdLabels"
:
false
,
"showThresholdMarkers"
:
true
,
"stat"
:
"avg"
,
"suffix"
:
""
,
"thresholds"
:
[],
"unit"
:
"none"
,
"valueMappings"
:
[]
},
"prefix"
:
""
,
"showThresholdLabels"
:
false
,
"showThresholdMarkers"
:
true
,
"stat"
:
"avg"
,
"suffix"
:
""
,
"thresholds"
:
[
{
"color"
:
"#1F78C1"
,
"index"
:
5
,
"value"
:
96.875
},
{
"color"
:
"#E24D42"
,
"index"
:
4
,
"value"
:
93.75
},
{
"color"
:
"#EF843C"
,
"index"
:
3
,
"value"
:
87.5
},
{
"color"
:
"#6ED0E0"
,
"index"
:
2
,
"value"
:
75
},
{
"color"
:
"#EAB839"
,
"index"
:
1
,
"value"
:
50
},
{
"color"
:
"#7EB26D"
,
"index"
:
0
,
"value"
:
null
}
],
"unit"
:
"none"
,
"valueMappings"
:
[
{
"from"
:
"50"
,
"id"
:
1
,
"operator"
:
""
,
"text"
:
"Hello :) "
,
"to"
:
"90"
,
"type"
:
2
,
"value"
:
""
}
]
},
"targets"
:
[
{
"refId"
:
"A"
,
"scenarioId"
:
"random_walk"
},
{
"refId"
:
"B"
,
"scenarioId"
:
"random_walk"
},
{
"refId"
:
"C"
,
"scenarioId"
:
"random_walk"
},
{
"refId"
:
"D"
,
"scenarioId"
:
"random_walk"
},
{
"refId"
:
"E"
,
"scenarioId"
:
"random_walk"
}
],
"timeFrom"
:
null
,
"timeShift"
:
null
,
"title"
:
"Horizontal with range variable"
,
"type"
:
"gauge"
},
{
"datasource"
:
"gdev-testdata"
,
"gridPos"
:
{
"h"
:
8
,
"w"
:
24
,
"x"
:
0
,
"y"
:
8
},
"id"
:
2
,
"links"
:
[],
"options-gauge"
:
{
"decimals"
:
0
,
"maxValue"
:
100
,
"minValue"
:
0
,
"options"
:
{
"decimals"
:
0
,
"maxValue"
:
100
,
"minValue"
:
0
,
"prefix"
:
""
,
"showThresholdLabels"
:
false
,
"showThresholdMarkers"
:
true
,
"stat"
:
"avg"
,
"suffix"
:
""
,
"thresholds"
:
[],
"unit"
:
"none"
,
"valueMappings"
:
[]
},
"prefix"
:
""
,
"showThresholdLabels"
:
false
,
"showThresholdMarkers"
:
true
,
"stat"
:
"avg"
,
"suffix"
:
""
,
"thresholds"
:
[
{
"color"
:
"#EAB839"
,
"index"
:
1
,
"value"
:
50
},
{
"color"
:
"#7EB26D"
,
"index"
:
0
,
"value"
:
null
}
],
"unit"
:
"none"
,
"valueMappings"
:
[]
},
"targets"
:
[
{
"refId"
:
"A"
,
"scenarioId"
:
"random_walk"
},
{
"refId"
:
"B"
,
"scenarioId"
:
"random_walk"
},
{
"refId"
:
"C"
,
"scenarioId"
:
"random_walk"
},
{
"refId"
:
"D"
,
"scenarioId"
:
"random_walk"
},
{
"refId"
:
"E"
,
"scenarioId"
:
"random_walk"
}
],
"timeFrom"
:
null
,
"timeShift"
:
null
,
"title"
:
"Repeat horizontal"
,
"type"
:
"gauge"
},
{
"datasource"
:
"gdev-testdata"
,
"gridPos"
:
{
"h"
:
14
,
"w"
:
5
,
"x"
:
0
,
"y"
:
16
},
"id"
:
4
,
"links"
:
[],
"options-gauge"
:
{
"decimals"
:
0
,
"maxValue"
:
"200"
,
"minValue"
:
0
,
"options"
:
{
"decimals"
:
0
,
"maxValue"
:
100
,
"minValue"
:
0
,
"prefix"
:
""
,
"showThresholdLabels"
:
false
,
"showThresholdMarkers"
:
true
,
"stat"
:
"avg"
,
"suffix"
:
""
,
"thresholds"
:
[],
"unit"
:
"none"
,
"valueMappings"
:
[]
},
"prefix"
:
""
,
"showThresholdLabels"
:
false
,
"showThresholdMarkers"
:
true
,
"stat"
:
"max"
,
"suffix"
:
""
,
"thresholds"
:
[
{
"color"
:
"#6ED0E0"
,
"index"
:
2
,
"value"
:
75
},
{
"color"
:
"#EAB839"
,
"index"
:
1
,
"value"
:
50
},
{
"color"
:
"#7EB26D"
,
"index"
:
0
,
"value"
:
null
}
],
"unit"
:
"none"
,
"valueMappings"
:
[]
},
"targets"
:
[
{
"refId"
:
"A"
,
"scenarioId"
:
"random_walk"
},
{
"refId"
:
"B"
,
"scenarioId"
:
"random_walk"
},
{
"refId"
:
"C"
,
"scenarioId"
:
"random_walk"
},
{
"refId"
:
"D"
,
"scenarioId"
:
"random_walk"
},
{
"refId"
:
"E"
,
"scenarioId"
:
"random_walk"
}
],
"timeFrom"
:
null
,
"timeShift"
:
null
,
"title"
:
"Vertical"
,
"type"
:
"gauge"
}
],
"schemaVersion"
:
17
,
"style"
:
"dark"
,
"tags"
:
[],
"templating"
:
{
"list"
:
[]
},
"time"
:
{
"from"
:
"now-6h"
,
"to"
:
"now"
},
"timepicker"
:
{
"refresh_intervals"
:
[
"5s"
,
"10s"
,
"30s"
,
"1m"
,
"5m"
,
"15m"
,
"30m"
,
"1h"
,
"2h"
,
"1d"
],
"time_options"
:
[
"5m"
,
"15m"
,
"1h"
,
"6h"
,
"12h"
,
"24h"
,
"2d"
,
"7d"
,
"30d"
]
},
"timezone"
:
""
,
"title"
:
"Multi series gauges"
,
"uid"
:
"szkuR1umk"
,
"version"
:
7
}
packages/grafana-ui/src/components/Gauge/Gauge.tsx
View file @
0de9c038
...
...
@@ -173,17 +173,15 @@ export class Gauge extends PureComponent<Props> {
const
{
height
,
width
}
=
this
.
props
;
return
(
<
div
className=
"singlestat-panel"
>
<
div
style=
{
{
height
:
`${height * 0.9}px`
,
width
:
`${Math.min(width, height * 1.3)}px`
,
top
:
'10px'
,
margin
:
'auto'
,
}
}
ref=
{
element
=>
(
this
.
canvasElement
=
element
)
}
/>
</
div
>
<
div
style=
{
{
height
:
`${height * 0.9}px`
,
width
:
`${Math.min(width, height * 1.3)}px`
,
top
:
'10px'
,
margin
:
'auto'
,
}
}
ref=
{
element
=>
(
this
.
canvasElement
=
element
)
}
/>
);
}
}
public/app/core/utils/ConfigProvider.tsx
View file @
0de9c038
...
...
@@ -15,6 +15,7 @@ export const provideConfig = (component: React.ComponentType<any>) => {
export
const
getCurrentThemeName
=
()
=>
config
.
bootData
.
user
.
lightTheme
?
GrafanaThemeType
.
Light
:
GrafanaThemeType
.
Dark
;
export
const
getCurrentTheme
=
()
=>
getTheme
(
getCurrentThemeName
());
export
const
ThemeProvider
=
({
children
}:
{
children
:
React
.
ReactNode
})
=>
{
...
...
public/app/plugins/panel/gauge/GaugeOptionsBox.tsx
View file @
0de9c038
...
...
@@ -9,6 +9,8 @@ import { FormField, PanelEditorProps } from '@grafana/ui';
import
{
GaugeOptions
}
from
'./types'
;
export
class
GaugeOptionsBox
extends
PureComponent
<
PanelEditorProps
<
GaugeOptions
>>
{
labelWidth
=
8
;
onToggleThresholdLabels
=
()
=>
this
.
props
.
onChange
({
...
this
.
props
.
options
,
showThresholdLabels
:
!
this
.
props
.
options
.
showThresholdLabels
});
...
...
@@ -25,17 +27,17 @@ export class GaugeOptionsBox extends PureComponent<PanelEditorProps<GaugeOptions
return
(
<
PanelOptionsGroup
title=
"Gauge"
>
<
FormField
label=
"Min value"
labelWidth=
{
8
}
onChange=
{
this
.
onMinValueChange
}
value=
{
minValue
}
/>
<
FormField
label=
"Max value"
labelWidth=
{
8
}
onChange=
{
this
.
onMaxValueChange
}
value=
{
maxValue
}
/>
<
FormField
label=
"Min value"
labelWidth=
{
this
.
labelWidth
}
onChange=
{
this
.
onMinValueChange
}
value=
{
minValue
}
/>
<
FormField
label=
"Max value"
labelWidth=
{
this
.
labelWidth
}
onChange=
{
this
.
onMaxValueChange
}
value=
{
maxValue
}
/>
<
Switch
label=
"Show labels"
labelClass=
"width-8"
labelClass=
{
`width-${this.labelWidth}`
}
checked=
{
showThresholdLabels
}
onChange=
{
this
.
onToggleThresholdLabels
}
/>
<
Switch
label=
"Show markers"
labelClass=
"width-8"
labelClass=
{
`width-${this.labelWidth}`
}
checked=
{
showThresholdMarkers
}
onChange=
{
this
.
onToggleThresholdMarkers
}
/>
...
...
public/app/plugins/panel/gauge/GaugePanel.tsx
View file @
0de9c038
...
...
@@ -2,62 +2,124 @@
import
React
,
{
PureComponent
}
from
'react'
;
// Services & Utils
import
{
processTimeSeries
,
ThemeContext
}
from
'@grafana/ui'
;
import
{
processTimeSeries
}
from
'@grafana/ui'
;
import
{
config
}
from
'app/core/config'
;
// Components
import
{
Gauge
}
from
'@grafana/ui'
;
// Types
import
{
GaugeOptions
}
from
'./types'
;
import
{
PanelProps
,
NullValueMode
,
TimeSeriesValue
}
from
'@grafana/ui/src/types'
;
import
{
PanelProps
,
NullValueMode
}
from
'@grafana/ui/src/types'
;
interface
Props
extends
PanelProps
<
GaugeOptions
>
{}
export
class
GaugePanel
extends
PureComponent
<
Props
>
{
render
()
{
const
{
panelData
,
width
,
height
,
onInterpolate
,
options
}
=
this
.
props
;
const
{
valueOptions
}
=
options
;
renderMultipleGauge
(
timeSeries
)
{
const
{
options
,
height
,
width
}
=
this
.
props
;
const
{
stat
}
=
options
.
valueOptions
;
return
timeSeries
.
map
((
series
,
index
)
=>
{
const
singleStatWidth
=
1
/
timeSeries
.
length
*
100
;
const
singleStatHeight
=
1
/
timeSeries
.
length
*
100
;
const
repeatingGaugeWidth
=
Math
.
floor
(
width
/
timeSeries
.
length
)
-
10
;
// make Gauge slightly smaller than panel.
const
repeatingGaugeHeight
=
Math
.
floor
(
height
/
timeSeries
.
length
)
-
10
;
const
horizontalPanels
=
{
display
:
'inline-block'
,
height
:
height
,
width
:
`
${
singleStatWidth
}
%`
,
};
const
verticalPanels
=
{
display
:
'block'
,
width
:
width
,
height
:
`
${
singleStatHeight
}
%`
,
};
let
style
=
{};
let
gaugeWidth
=
width
;
let
gaugeHeight
=
height
;
if
(
width
>
height
)
{
style
=
horizontalPanels
;
gaugeWidth
=
repeatingGaugeWidth
;
}
else
if
(
height
>
width
)
{
style
=
verticalPanels
;
gaugeHeight
=
repeatingGaugeHeight
;
}
const
value
=
stat
!==
'name'
?
series
.
stats
[
stat
]
:
series
.
label
;
return
(
<
div
className=
"singlestat-panel"
key=
{
`${timeSeries.label}-${index}`
}
style=
{
style
}
>
{
this
.
renderGauge
(
value
,
gaugeWidth
,
gaugeHeight
)
}
<
div
style=
{
{
textAlign
:
'center'
}
}
>
{
series
.
label
}
</
div
>
</
div
>
);
});
}
renderGauge
(
value
,
width
,
height
)
{
const
{
onInterpolate
,
options
}
=
this
.
props
;
const
{
valueOptions
}
=
options
;
const
prefix
=
onInterpolate
(
valueOptions
.
prefix
);
const
suffix
=
onInterpolate
(
valueOptions
.
suffix
);
let
value
:
TimeSeriesValue
;
return
(
<
Gauge
value=
{
value
}
width=
{
width
}
height=
{
height
}
prefix=
{
prefix
}
suffix=
{
suffix
}
unit=
{
valueOptions
.
unit
}
decimals=
{
valueOptions
.
decimals
}
thresholds=
{
options
.
thresholds
}
valueMappings=
{
options
.
valueMappings
}
showThresholdLabels=
{
options
.
showThresholdLabels
}
showThresholdMarkers=
{
options
.
showThresholdMarkers
}
minValue=
{
options
.
minValue
}
maxValue=
{
options
.
maxValue
}
theme=
{
config
.
theme
}
/>
);
}
renderSingleGauge
(
timeSeries
)
{
const
{
options
,
width
,
height
}
=
this
.
props
;
const
value
=
timeSeries
[
0
].
stats
[
options
.
valueOptions
.
stat
];
return
<
div
className=
"singlestat-panel"
>
{
this
.
renderGauge
(
value
,
width
,
height
)
}
</
div
>;
}
renderGaugeWithTableData
(
panelData
)
{
const
{
width
,
height
}
=
this
.
props
;
const
firstTableDataValue
=
panelData
.
tableData
.
rows
[
0
].
find
(
prop
=>
prop
>
0
);
return
<
div
className=
"singlestat-panel"
>
{
this
.
renderGauge
(
firstTableDataValue
,
width
,
height
)
}
</
div
>;
}
render
()
{
const
{
panelData
}
=
this
.
props
;
if
(
panelData
.
timeSeries
)
{
const
vm
Series
=
processTimeSeries
({
const
time
Series
=
processTimeSeries
({
timeSeries
:
panelData
.
timeSeries
,
nullValueMode
:
NullValueMode
.
Null
,
});
if
(
vmSeries
[
0
])
{
value
=
vmSeries
[
0
].
stats
[
valueOptions
.
stat
];
if
(
timeSeries
.
length
>
1
)
{
return
this
.
renderMultipleGauge
(
timeSeries
);
}
else
if
(
timeSeries
.
length
>
0
)
{
return
this
.
renderSingleGauge
(
timeSeries
);
}
else
{
value
=
null
;
return
null
;
}
}
else
if
(
panelData
.
tableData
)
{
value
=
panelData
.
tableData
.
rows
[
0
].
find
(
prop
=>
prop
>
0
);
return
this
.
renderGaugeWithTableData
(
panelData
);
}
else
{
return
<
div
className=
"singlestat-panel"
>
No time series data available
</
div
>;
}
return
(
<
ThemeContext
.
Consumer
>
{
theme
=>
(
<
Gauge
value=
{
value
}
width=
{
width
}
height=
{
height
}
prefix=
{
prefix
}
suffix=
{
suffix
}
unit=
{
valueOptions
.
unit
}
decimals=
{
valueOptions
.
decimals
}
thresholds=
{
options
.
thresholds
}
valueMappings=
{
options
.
valueMappings
}
showThresholdLabels=
{
options
.
showThresholdLabels
}
showThresholdMarkers=
{
options
.
showThresholdMarkers
}
minValue=
{
options
.
minValue
}
maxValue=
{
options
.
maxValue
}
theme=
{
theme
}
/>
)
}
</
ThemeContext
.
Consumer
>
);
}
}
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