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
71e93e52
Unverified
Commit
71e93e52
authored
Jan 07, 2021
by
Ryan McKinley
Committed by
GitHub
Jan 07, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
GraphNG: support dashes (#30070)
parent
dba4942e
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
523 additions
and
7 deletions
+523
-7
devenv/dev-dashboards/panel-graph/graph-ng.json
+311
-5
packages/grafana-ui/src/components/GraphNG/GraphNG.tsx
+1
-0
packages/grafana-ui/src/components/uPlot/config.ts
+9
-1
packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts
+7
-0
public/app/plugins/panel/graph3/LineStyleEditor.tsx
+123
-0
public/app/plugins/panel/graph3/__snapshots__/migrations.test.ts.snap
+17
-0
public/app/plugins/panel/graph3/migrations.test.ts
+4
-1
public/app/plugins/panel/graph3/migrations.ts
+39
-0
public/app/plugins/panel/graph3/module.tsx
+12
-0
No files found.
devenv/dev-dashboards/panel-graph/graph-ng.json
View file @
71e93e52
...
...
@@ -2093,10 +2093,7 @@
"y"
:
34
},
"id"
:
11
,
"panels"
:
[],
"title"
:
"Show gaps & Connected"
,
"type"
:
"row"
},
"panels"
:
[
{
"datasource"
:
"gdev-testdata"
,
"fieldConfig"
:
{
...
...
@@ -2557,6 +2554,315 @@
"title"
:
"Null values & show connected"
,
"transformations"
:
[],
"type"
:
"graph3"
}
],
"title"
:
"Show gaps & Connected"
,
"type"
:
"row"
},
{
"collapsed"
:
false
,
"datasource"
:
null
,
"gridPos"
:
{
"h"
:
1
,
"w"
:
24
,
"x"
:
0
,
"y"
:
35
},
"id"
:
62
,
"panels"
:
[],
"title"
:
"Line Styles"
,
"type"
:
"row"
},
{
"datasource"
:
null
,
"fieldConfig"
:
{
"defaults"
:
{
"color"
:
{
"mode"
:
"palette-classic"
},
"custom"
:
{
"align"
:
null
,
"axis"
:
{
"grid"
:
true
,
"label"
:
""
,
"side"
:
3
,
"width"
:
60
},
"axisLabel"
:
""
,
"axisPlacement"
:
"auto"
,
"bars"
:
{
"show"
:
false
},
"drawStyle"
:
"line"
,
"fill"
:
{
"alpha"
:
0
},
"fillGradient"
:
{
"label"
:
"None"
},
"fillOpacity"
:
0
,
"hideFrom"
:
{
"graph"
:
false
,
"legend"
:
false
,
"tooltip"
:
false
},
"line"
:
{
"color"
:
{
"mode"
:
"palette-classic"
},
"show"
:
true
,
"width"
:
1
},
"lineInterpolation"
:
"linear"
,
"lineStyle"
:
{
"dash"
:
[
10
,
10
],
"fill"
:
"dash"
},
"lineWidth"
:
2
,
"nullValues"
:
"null"
,
"pointSize"
:
5
,
"points"
:
{
"radius"
:
5
,
"show"
:
false
},
"scaleDistribution"
:
{
"type"
:
"linear"
},
"showPoints"
:
"auto"
,
"spanNulls"
:
false
},
"mappings"
:
[],
"thresholds"
:
{
"mode"
:
"absolute"
,
"steps"
:
[
{
"color"
:
"green"
,
"value"
:
null
},
{
"color"
:
"red"
,
"value"
:
80
}
]
}
},
"overrides"
:
[
{
"matcher"
:
{
"id"
:
"byName"
,
"options"
:
"B-series"
},
"properties"
:
[
{
"id"
:
"custom.lineStyle"
,
"value"
:
{
"dash"
:
[
10
,
20
],
"fill"
:
"dash"
}
}
]
},
{
"matcher"
:
{
"id"
:
"byName"
,
"options"
:
"C-series"
},
"properties"
:
[
{
"id"
:
"custom.lineStyle"
,
"value"
:
{
"dash"
:
[
10
,
30
],
"fill"
:
"dash"
}
}
]
},
{
"matcher"
:
{
"id"
:
"byName"
,
"options"
:
"D-series"
},
"properties"
:
[
{
"id"
:
"custom.lineStyle"
,
"value"
:
{
"dash"
:
[
30
,
3
,
3
],
"fill"
:
"dash"
}
}
]
},
{
"matcher"
:
{
"id"
:
"byName"
,
"options"
:
"E-series"
},
"properties"
:
[
{
"id"
:
"custom.lineStyle"
}
]
}
]
},
"gridPos"
:
{
"h"
:
7
,
"w"
:
6
,
"x"
:
0
,
"y"
:
36
},
"id"
:
60
,
"options"
:
{
"graph"
:
{
"realTimeUpdates"
:
false
},
"legend"
:
{
"asTable"
:
false
,
"displayMode"
:
"hidden"
,
"isVisible"
:
true
,
"placement"
:
"bottom"
},
"tooltipOptions"
:
{
"mode"
:
"single"
}
},
"pluginVersion"
:
"7.2.0-pre"
,
"targets"
:
[
{
"alias"
:
""
,
"csvWave"
:
{
"timeStep"
:
60
,
"valuesCSV"
:
"0,0,2,2,1,1"
},
"lines"
:
10
,
"points"
:
[],
"pulseWave"
:
{
"offCount"
:
3
,
"offValue"
:
1
,
"onCount"
:
3
,
"onValue"
:
2
,
"timeStep"
:
60
},
"refId"
:
"A"
,
"scenarioId"
:
"csv_metric_values"
,
"stream"
:
{
"bands"
:
1
,
"noise"
:
2.2
,
"speed"
:
250
,
"spread"
:
3.5
,
"type"
:
"signal"
},
"stringInput"
:
"10,10"
},
{
"alias"
:
""
,
"csvWave"
:
{
"timeStep"
:
60
,
"valuesCSV"
:
"0,0,2,2,1,1"
},
"lines"
:
10
,
"points"
:
[],
"pulseWave"
:
{
"offCount"
:
3
,
"offValue"
:
1
,
"onCount"
:
3
,
"onValue"
:
2
,
"timeStep"
:
60
},
"refId"
:
"B"
,
"scenarioId"
:
"csv_metric_values"
,
"stream"
:
{
"bands"
:
1
,
"noise"
:
2.2
,
"speed"
:
250
,
"spread"
:
3.5
,
"type"
:
"signal"
},
"stringInput"
:
"9,9"
},
{
"alias"
:
""
,
"csvWave"
:
{
"timeStep"
:
60
,
"valuesCSV"
:
"0,0,2,2,1,1"
},
"lines"
:
10
,
"points"
:
[],
"pulseWave"
:
{
"offCount"
:
3
,
"offValue"
:
1
,
"onCount"
:
3
,
"onValue"
:
2
,
"timeStep"
:
60
},
"refId"
:
"C"
,
"scenarioId"
:
"csv_metric_values"
,
"stream"
:
{
"bands"
:
1
,
"noise"
:
2.2
,
"speed"
:
250
,
"spread"
:
3.5
,
"type"
:
"signal"
},
"stringInput"
:
"8,8"
},
{
"alias"
:
""
,
"csvWave"
:
{
"timeStep"
:
60
,
"valuesCSV"
:
"0,0,2,2,1,1"
},
"lines"
:
10
,
"points"
:
[],
"pulseWave"
:
{
"offCount"
:
3
,
"offValue"
:
1
,
"onCount"
:
3
,
"onValue"
:
2
,
"timeStep"
:
60
},
"refId"
:
"D"
,
"scenarioId"
:
"csv_metric_values"
,
"stream"
:
{
"bands"
:
1
,
"noise"
:
2.2
,
"speed"
:
250
,
"spread"
:
3.5
,
"type"
:
"signal"
},
"stringInput"
:
"7,7"
},
{
"alias"
:
""
,
"csvWave"
:
{
"timeStep"
:
60
,
"valuesCSV"
:
"0,0,2,2,1,1"
},
"lines"
:
10
,
"points"
:
[],
"pulseWave"
:
{
"offCount"
:
3
,
"offValue"
:
1
,
"onCount"
:
3
,
"onValue"
:
2
,
"timeStep"
:
60
},
"refId"
:
"E"
,
"scenarioId"
:
"csv_metric_values"
,
"stream"
:
{
"bands"
:
1
,
"noise"
:
2.2
,
"speed"
:
250
,
"spread"
:
3.5
,
"type"
:
"signal"
},
"stringInput"
:
"6,6"
}
],
"timeFrom"
:
null
,
"timeShift"
:
null
,
"title"
:
"Dashed lines"
,
"type"
:
"graph3"
},
{
"collapsed"
:
false
,
...
...
@@ -2714,5 +3020,5 @@
"timezone"
:
""
,
"title"
:
"Panel Tests - Graph NG"
,
"uid"
:
"TkZXxlNG3"
,
"version"
:
2
"version"
:
1
}
packages/grafana-ui/src/components/GraphNG/GraphNG.tsx
View file @
71e93e52
...
...
@@ -175,6 +175,7 @@ export const GraphNG: React.FC<GraphNGProps> = ({
lineColor
:
customConfig
.
lineColor
??
seriesColor
,
lineWidth
:
customConfig
.
lineWidth
,
lineInterpolation
:
customConfig
.
lineInterpolation
,
lineStyle
:
customConfig
.
lineStyle
,
showPoints
,
pointSize
:
customConfig
.
pointSize
,
pointColor
:
customConfig
.
pointColor
??
seriesColor
,
...
...
packages/grafana-ui/src/components/uPlot/config.ts
View file @
71e93e52
...
...
@@ -51,11 +51,19 @@ export enum ScaleDistribution {
/**
* @alpha
*/
export
interface
LineStyle
{
fill
?:
'solid'
|
'dash'
|
'dot'
|
'square'
;
// cap = 'butt' | 'round' | 'square'
dash
?:
number
[];
}
/**
* @alpha
*/
export
interface
LineConfig
{
lineColor
?:
string
;
lineWidth
?:
number
;
lineInterpolation
?:
LineInterpolation
;
line
Dash
?:
number
[]
;
line
Style
?:
LineStyle
;
spanNulls
?:
boolean
;
}
...
...
packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts
View file @
71e93e52
...
...
@@ -25,6 +25,7 @@ export class UPlotSeriesBuilder extends PlotConfigBuilder<SeriesProps, Series> {
lineInterpolation
,
lineColor
,
lineWidth
,
lineStyle
,
showPoints
,
pointColor
,
pointSize
,
...
...
@@ -40,6 +41,12 @@ export class UPlotSeriesBuilder extends PlotConfigBuilder<SeriesProps, Series> {
}
else
{
lineConfig
.
stroke
=
lineColor
;
lineConfig
.
width
=
lineWidth
;
if
(
lineStyle
&&
lineStyle
.
fill
!==
'solid'
)
{
if
(
lineStyle
.
fill
===
'dot'
)
{
// lineConfig.dashCap = 'round'; // square or butt
}
lineConfig
.
dash
=
lineStyle
.
dash
??
[
10
,
10
];
}
lineConfig
.
paths
=
(
self
:
uPlot
,
seriesIdx
:
number
,
idx0
:
number
,
idx1
:
number
)
=>
{
let
pathsBuilder
=
mapDrawStyleToPathBuilder
(
drawStyle
,
lineInterpolation
);
return
pathsBuilder
(
self
,
seriesIdx
,
idx0
,
idx1
);
...
...
public/app/plugins/panel/graph3/LineStyleEditor.tsx
0 → 100644
View file @
71e93e52
import
React
,
{
useMemo
}
from
'react'
;
import
{
FieldOverrideEditorProps
,
SelectableValue
}
from
'@grafana/data'
;
import
{
HorizontalGroup
,
IconButton
,
LineStyle
,
RadioButtonGroup
,
Select
}
from
'@grafana/ui'
;
type
LineFill
=
'solid'
|
'dash'
|
'dot'
;
const
lineFillOptions
:
Array
<
SelectableValue
<
LineFill
>>
=
[
{
label
:
'Solid'
,
value
:
'solid'
,
},
{
label
:
'Dash'
,
value
:
'dash'
,
},
// {
// label: 'Dots',
// value: 'dot',
// },
];
const
dashOptions
:
Array
<
SelectableValue
<
string
>>
=
[
'10, 10'
,
// default
'10, 15'
,
'10, 20'
,
'10, 25'
,
'10, 30'
,
'10, 40'
,
'15, 10'
,
'20, 10'
,
'25, 10'
,
'30, 10'
,
'40, 10'
,
'50, 10'
,
'5, 10'
,
'30, 3, 3'
,
].
map
(
txt
=>
({
label
:
txt
,
value
:
txt
,
}));
const
dotOptions
:
Array
<
SelectableValue
<
string
>>
=
[
'0, 10'
,
// default
'0, 20'
,
'0, 30'
,
'0, 40'
,
'0, 3, 3'
,
].
map
(
txt
=>
({
label
:
txt
,
value
:
txt
,
}));
export
const
LineStyleEditor
:
React
.
FC
<
FieldOverrideEditorProps
<
LineStyle
,
any
>>
=
({
value
,
onChange
})
=>
{
const
options
=
useMemo
(()
=>
(
value
?.
fill
===
'dash'
?
dashOptions
:
dotOptions
),
[
value
]);
const
current
=
useMemo
(()
=>
{
if
(
!
value
?.
dash
?.
length
)
{
return
options
[
0
];
}
const
str
=
value
.
dash
?.
join
(
', '
);
const
val
=
options
.
find
(
o
=>
o
.
value
===
str
);
if
(
!
val
)
{
return
{
label
:
str
,
value
:
str
,
};
}
return
val
;
},
[
value
,
options
]);
return
(
<
HorizontalGroup
>
<
RadioButtonGroup
value=
{
value
?.
fill
||
'solid'
}
options=
{
lineFillOptions
}
onChange=
{
v
=>
{
onChange
({
...
value
,
fill
:
v
!
,
});
}
}
/>
{
value
?.
fill
&&
value
?.
fill
!==
'solid'
&&
(
<>
<
Select
allowCustomValue=
{
true
}
options=
{
options
}
value=
{
current
}
width=
{
20
}
onChange=
{
v
=>
{
onChange
({
...
value
,
dash
:
parseText
(
v
.
value
??
''
),
});
}
}
formatCreateLabel=
{
t
=>
`Segments: ${parseText(t).join(', ')}`
}
/>
<
div
>
<
a
title=
"The input expects a segment list"
href=
"https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash#Parameters"
target=
"_blank"
rel=
"noreferrer"
>
<
IconButton
name=
"question-circle"
/>
</
a
>
</
div
>
</>
)
}
</
HorizontalGroup
>
);
};
function
parseText
(
txt
:
string
):
number
[]
{
const
segments
:
number
[]
=
[];
for
(
const
s
of
txt
.
split
(
/
(?:
,|
)
+/
))
{
const
num
=
Number
.
parseInt
(
s
,
10
);
if
(
!
isNaN
(
num
))
{
segments
.
push
(
num
);
}
}
return
segments
;
}
public/app/plugins/panel/graph3/__snapshots__/migrations.test.ts.snap
View file @
71e93e52
...
...
@@ -117,6 +117,13 @@ Object {
"axisPlacement": "auto",
"drawStyle": "line",
"fillOpacity": 10,
"lineStyle": Object {
"dash": Array [
10,
10,
],
"fill": "dash",
},
"lineWidth": 1,
"pointSize": 6,
"showPoints": "never",
...
...
@@ -155,6 +162,16 @@ Object {
"id": "custom.axisLabel",
"value": "Y222",
},
Object {
"id": "custom.lineStyle",
"value": Object {
"dash": Array [
5,
8,
],
"fill": "dash",
},
},
],
},
],
...
...
public/app/plugins/panel/graph3/migrations.test.ts
View file @
71e93e52
...
...
@@ -186,6 +186,9 @@ const twoYAxis = {
{
alias
:
'B-series'
,
yaxis
:
2
,
dashLength
:
5
,
dashes
:
true
,
spaceLength
:
8
,
},
],
thresholds
:
[],
...
...
@@ -199,7 +202,7 @@ const twoYAxis = {
},
],
fillGradient
:
0
,
dashes
:
fals
e
,
dashes
:
tru
e
,
hiddenSeries
:
false
,
points
:
false
,
bars
:
false
,
...
...
public/app/plugins/panel/graph3/migrations.ts
View file @
71e93e52
...
...
@@ -16,6 +16,7 @@ import {
AxisPlacement
,
DrawStyle
,
LineInterpolation
,
LineStyle
,
PointVisibility
,
}
from
'@grafana/ui/src/components/uPlot/config'
;
import
{
Options
}
from
'./types'
;
...
...
@@ -52,6 +53,12 @@ export function flotToGraphOptions(angular: any): { fieldConfig: FieldConfigSour
};
}
// Dashes
const
dash
:
LineStyle
=
{
fill
:
angular
.
dashes
?
'dash'
:
'solid'
,
dash
:
[
angular
.
dashLength
??
10
,
angular
.
spaceLength
??
10
],
};
// "seriesOverrides": [
// {
// "$$hashKey": "object:183",
...
...
@@ -98,6 +105,8 @@ export function flotToGraphOptions(angular: any): { fieldConfig: FieldConfigSour
},
properties
:
[],
};
let
dashOverride
:
LineStyle
|
undefined
=
undefined
;
for
(
const
p
of
Object
.
keys
(
seriesOverride
))
{
const
v
=
seriesOverride
[
p
];
switch
(
p
)
{
...
...
@@ -165,10 +174,37 @@ export function flotToGraphOptions(angular: any): { fieldConfig: FieldConfigSour
value
:
2
+
v
*
2
,
});
break
;
case
'dashLength'
:
case
'spaceLength'
:
case
'dashes'
:
if
(
!
dashOverride
)
{
dashOverride
=
{
fill
:
dash
.
fill
,
dash
:
[...
dash
.
dash
!
],
};
}
switch
(
p
)
{
case
'dashLength'
:
dashOverride
.
dash
!
[
0
]
=
v
;
break
;
case
'spaceLength'
:
dashOverride
.
dash
!
[
1
]
=
v
;
break
;
case
'dashes'
:
dashOverride
.
fill
=
v
?
'dash'
:
'solid'
;
break
;
}
break
;
default
:
console
.
log
(
'Ignore override migration:'
,
seriesOverride
.
alias
,
p
,
v
);
}
}
if
(
dashOverride
)
{
rule
.
properties
.
push
({
id
:
'custom.lineStyle'
,
value
:
dashOverride
,
});
}
if
(
rule
.
properties
.
length
)
{
overrides
.
push
(
rule
);
}
...
...
@@ -185,6 +221,9 @@ export function flotToGraphOptions(angular: any): { fieldConfig: FieldConfigSour
}
graph
.
lineWidth
=
angular
.
linewidth
;
if
(
dash
.
fill
!==
'solid'
)
{
graph
.
lineStyle
=
dash
;
}
if
(
isNumber
(
angular
.
pointradius
))
{
graph
.
pointSize
=
2
+
angular
.
pointradius
*
2
;
...
...
public/app/plugins/panel/graph3/module.tsx
View file @
71e93e52
...
...
@@ -11,6 +11,7 @@ import {
GraphFieldConfig
,
graphFieldOptions
,
LegendDisplayMode
,
LineStyle
,
PointVisibility
,
ScaleDistribution
,
ScaleDistributionConfig
,
...
...
@@ -20,6 +21,7 @@ import { GraphPanel } from './GraphPanel';
import
{
graphPanelChangedHandler
}
from
'./migrations'
;
import
{
Options
}
from
'./types'
;
import
{
ScaleDistributionEditor
}
from
'./ScaleDistributionEditor'
;
import
{
LineStyleEditor
}
from
'./LineStyleEditor'
;
export
const
plugin
=
new
PanelPlugin
<
Options
,
GraphFieldConfig
>
(
GraphPanel
)
.
setPanelChangeHandler
(
graphPanelChangedHandler
)
...
...
@@ -75,6 +77,16 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(GraphPanel)
},
showIf
:
c
=>
c
.
drawStyle
!==
DrawStyle
.
Points
,
})
.
addCustomEditor
<
void
,
LineStyle
>
({
id
:
'lineStyle'
,
path
:
'lineStyle'
,
name
:
'Line style'
,
showIf
:
c
=>
c
.
drawStyle
===
DrawStyle
.
Line
,
editor
:
LineStyleEditor
,
override
:
LineStyleEditor
,
process
:
identityOverrideProcessor
,
shouldApply
:
f
=>
f
.
type
===
FieldType
.
number
,
})
.
addRadio
({
path
:
'fillGradient'
,
name
:
'Fill gradient'
,
...
...
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