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
bb65113c
Unverified
Commit
bb65113c
authored
Jan 18, 2021
by
Ryan McKinley
Committed by
GitHub
Jan 18, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Transforms: add sort by transformer (#30370)
parent
8c31e259
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
246 additions
and
0 deletions
+246
-0
docs/sources/panels/transformations/types-options.md
+9
-0
packages/grafana-data/src/transformations/transformers.ts
+2
-0
packages/grafana-data/src/transformations/transformers/ids.ts
+1
-0
packages/grafana-data/src/transformations/transformers/sortBy.test.ts
+99
-0
packages/grafana-data/src/transformations/transformers/sortBy.ts
+65
-0
public/app/core/components/TransformersUI/SortByTransformerEditor.tsx
+68
-0
public/app/core/utils/standardTransformers.ts
+2
-0
No files found.
docs/sources/panels/transformations/types-options.md
View file @
bb65113c
...
@@ -17,6 +17,7 @@ Grafana comes with the following transformations:
...
@@ -17,6 +17,7 @@ Grafana comes with the following transformations:
-
[
Add field from calculation
](
#add-field-from-calculation
)
-
[
Add field from calculation
](
#add-field-from-calculation
)
-
[
Labels to fields
](
#labels-to-fields
)
-
[
Labels to fields
](
#labels-to-fields
)
-
[
Concatenate fields
](
#concatenate-fields
)
-
[
Concatenate fields
](
#concatenate-fields
)
-
[
Sort by
](
#sort-by
)
-
[
Group by
](
#group-by
)
-
[
Group by
](
#group-by
)
-
[
Merge
](
#merge
)
-
[
Merge
](
#merge
)
-
[
Rename by regex
](
#rename-by-regex
)
-
[
Rename by regex
](
#rename-by-regex
)
...
@@ -236,6 +237,14 @@ After merge:
...
@@ -236,6 +237,14 @@ After merge:
| 2020-07-07 11:34:20 | ServerA | 10 | |
| 2020-07-07 11:34:20 | ServerA | 10 | |
| 2020-07-07 11:34:20 | | 20 | EU |
| 2020-07-07 11:34:20 | | 20 | EU |
## Sort by
> **Note:** This transformation is available in Grafana 7.4+.
This transformation will sort each frame by the configured field, When
`reverse`
is checked, the values will return in
the opposite order.
## Group by
## Group by
> **Note:** This transformation is available in Grafana 7.2+.
> **Note:** This transformation is available in Grafana 7.2+.
...
...
packages/grafana-data/src/transformations/transformers.ts
View file @
bb65113c
...
@@ -13,6 +13,7 @@ import { renameFieldsTransformer } from './transformers/rename';
...
@@ -13,6 +13,7 @@ import { renameFieldsTransformer } from './transformers/rename';
import
{
labelsToFieldsTransformer
}
from
'./transformers/labelsToFields'
;
import
{
labelsToFieldsTransformer
}
from
'./transformers/labelsToFields'
;
import
{
ensureColumnsTransformer
}
from
'./transformers/ensureColumns'
;
import
{
ensureColumnsTransformer
}
from
'./transformers/ensureColumns'
;
import
{
groupByTransformer
}
from
'./transformers/groupBy'
;
import
{
groupByTransformer
}
from
'./transformers/groupBy'
;
import
{
sortByTransformer
}
from
'./transformers/sortBy'
;
import
{
mergeTransformer
}
from
'./transformers/merge'
;
import
{
mergeTransformer
}
from
'./transformers/merge'
;
import
{
renameByRegexTransformer
}
from
'./transformers/renameByRegex'
;
import
{
renameByRegexTransformer
}
from
'./transformers/renameByRegex'
;
import
{
filterByValueTransformer
}
from
'./transformers/filterByValue'
;
import
{
filterByValueTransformer
}
from
'./transformers/filterByValue'
;
...
@@ -35,6 +36,7 @@ export const standardTransformers = {
...
@@ -35,6 +36,7 @@ export const standardTransformers = {
labelsToFieldsTransformer
,
labelsToFieldsTransformer
,
ensureColumnsTransformer
,
ensureColumnsTransformer
,
groupByTransformer
,
groupByTransformer
,
sortByTransformer
,
mergeTransformer
,
mergeTransformer
,
renameByRegexTransformer
,
renameByRegexTransformer
,
};
};
packages/grafana-data/src/transformations/transformers/ids.ts
View file @
bb65113c
...
@@ -21,4 +21,5 @@ export enum DataTransformerID {
...
@@ -21,4 +21,5 @@ export enum DataTransformerID {
noop
=
'noop'
,
noop
=
'noop'
,
ensureColumns
=
'ensureColumns'
,
ensureColumns
=
'ensureColumns'
,
groupBy
=
'groupBy'
,
groupBy
=
'groupBy'
,
sortBy
=
'sortBy'
,
}
}
packages/grafana-data/src/transformations/transformers/sortBy.test.ts
0 → 100644
View file @
bb65113c
import
{
toDataFrame
}
from
'../../dataframe/processDataFrame'
;
import
{
sortByTransformer
,
SortByTransformerOptions
}
from
'./sortBy'
;
import
{
mockTransformationsRegistry
}
from
'../../utils/tests/mockTransformationsRegistry'
;
import
{
transformDataFrame
}
from
'../transformDataFrame'
;
import
{
Field
,
FieldType
}
from
'../../types'
;
import
{
DataTransformerID
}
from
'./ids'
;
import
{
DataTransformerConfig
}
from
'@grafana/data'
;
const
testFrame
=
toDataFrame
({
name
:
'A'
,
fields
:
[
{
name
:
'time'
,
type
:
FieldType
.
time
,
values
:
[
10
,
9
,
8
,
7
,
6
,
5
]
},
// desc
{
name
:
'text'
,
type
:
FieldType
.
string
,
values
:
[
'a'
,
'z'
,
'b'
,
'x'
,
'c'
]
},
{
name
:
'count'
,
type
:
FieldType
.
string
,
values
:
[
1
,
2
,
3
,
4
,
5
]
},
// asc
],
});
describe
(
'SortBy transformer'
,
()
=>
{
beforeAll
(()
=>
{
mockTransformationsRegistry
([
sortByTransformer
]);
});
it
(
'should not apply transformation if config is missing sort fields'
,
async
()
=>
{
const
cfg
:
DataTransformerConfig
<
SortByTransformerOptions
>
=
{
id
:
DataTransformerID
.
sortBy
,
options
:
{
sort
:
[],
// nothing
},
};
await
expect
(
transformDataFrame
([
cfg
],
[
testFrame
])).
toEmitValuesWith
(
received
=>
{
const
result
=
received
[
0
];
expect
(
result
[
0
]).
toBe
(
testFrame
);
});
});
it
(
'should sort time asc'
,
async
()
=>
{
const
cfg
:
DataTransformerConfig
<
SortByTransformerOptions
>
=
{
id
:
DataTransformerID
.
sortBy
,
options
:
{
sort
:
[
{
field
:
'time'
,
},
],
},
};
await
expect
(
transformDataFrame
([
cfg
],
[
testFrame
])).
toEmitValuesWith
(
received
=>
{
expect
(
getFieldSnapshot
(
received
[
0
][
0
].
fields
[
0
])).
toMatchInlineSnapshot
(
`
Object {
"name": "time",
"values": Array [
5,
6,
7,
8,
9,
10,
],
}
`
);
});
});
it
(
'should sort time (desc)'
,
async
()
=>
{
const
cfg
:
DataTransformerConfig
<
SortByTransformerOptions
>
=
{
id
:
DataTransformerID
.
sortBy
,
options
:
{
sort
:
[
{
field
:
'time'
,
desc
:
true
,
},
],
},
};
await
expect
(
transformDataFrame
([
cfg
],
[
testFrame
])).
toEmitValuesWith
(
received
=>
{
expect
(
getFieldSnapshot
(
received
[
0
][
0
].
fields
[
0
])).
toMatchInlineSnapshot
(
`
Object {
"name": "time",
"values": Array [
10,
9,
8,
7,
6,
5,
],
}
`
);
});
});
});
function
getFieldSnapshot
(
f
:
Field
):
Object
{
return
{
name
:
f
.
name
,
values
:
f
.
values
.
toArray
()
};
}
packages/grafana-data/src/transformations/transformers/sortBy.ts
0 → 100644
View file @
bb65113c
import
{
map
}
from
'rxjs/operators'
;
import
{
DataTransformerID
}
from
'./ids'
;
import
{
DataTransformerInfo
}
from
'../../types/transformations'
;
import
{
DataFrame
}
from
'../../types'
;
import
{
getFieldDisplayName
}
from
'../../field'
;
import
{
sortDataFrame
}
from
'../../dataframe'
;
export
interface
SortByField
{
field
:
string
;
desc
?:
boolean
;
index
?:
number
;
}
export
interface
SortByTransformerOptions
{
// NOTE: this structure supports an array, however only the first entry is used
// future versions may support multi-sort options
sort
:
SortByField
[];
}
export
const
sortByTransformer
:
DataTransformerInfo
<
SortByTransformerOptions
>
=
{
id
:
DataTransformerID
.
sortBy
,
name
:
'Sort by'
,
description
:
'Sort fields in a frame'
,
defaultOptions
:
{
fields
:
{},
},
/**
* Return a modified copy of the series. If the transform is not or should not
* be applied, just return the input series
*/
operator
:
options
=>
source
=>
source
.
pipe
(
map
(
data
=>
{
if
(
!
Array
.
isArray
(
data
)
||
data
.
length
===
0
||
!
options
?.
sort
?.
length
)
{
return
data
;
}
return
sortDataFrames
(
data
,
options
.
sort
);
})
),
};
export
function
sortDataFrames
(
data
:
DataFrame
[],
sort
:
SortByField
[]):
DataFrame
[]
{
return
data
.
map
(
frame
=>
{
const
s
=
attachFieldIndex
(
frame
,
sort
);
if
(
s
.
length
&&
s
[
0
].
index
!=
null
)
{
return
sortDataFrame
(
frame
,
s
[
0
].
index
,
s
[
0
].
desc
);
}
return
frame
;
});
}
function
attachFieldIndex
(
frame
:
DataFrame
,
sort
:
SortByField
[]):
SortByField
[]
{
return
sort
.
map
(
s
=>
{
if
(
s
.
index
!=
null
)
{
// null or undefined
return
s
;
}
return
{
...
s
,
index
:
frame
.
fields
.
findIndex
(
f
=>
s
.
field
===
getFieldDisplayName
(
f
,
frame
)),
};
});
}
public/app/core/components/TransformersUI/SortByTransformerEditor.tsx
0 → 100644
View file @
bb65113c
import
React
,
{
useCallback
,
useMemo
}
from
'react'
;
import
{
DataTransformerID
,
standardTransformers
,
TransformerRegistyItem
,
TransformerUIProps
}
from
'@grafana/data'
;
import
{
getAllFieldNamesFromDataFrames
}
from
'./OrganizeFieldsTransformerEditor'
;
import
{
InlineField
,
InlineSwitch
,
InlineFieldRow
,
Select
}
from
'@grafana/ui'
;
import
{
SortByField
,
SortByTransformerOptions
}
from
'@grafana/data/src/transformations/transformers/sortBy'
;
export
const
SortByTransformerEditor
:
React
.
FC
<
TransformerUIProps
<
SortByTransformerOptions
>>
=
({
input
,
options
,
onChange
,
})
=>
{
const
fieldNames
=
useMemo
(
()
=>
getAllFieldNamesFromDataFrames
(
input
).
map
(
n
=>
({
value
:
n
,
label
:
n
,
})),
[
input
]
);
// Only supports single sort for now
const
onSortChange
=
useCallback
(
(
idx
:
number
,
cfg
:
SortByField
)
=>
{
onChange
({
...
options
,
sort
:
[
cfg
]
});
},
[
options
]
);
const
sorts
=
options
.
sort
?.
length
?
options
.
sort
:
[{}
as
SortByField
];
return
(
<
div
>
{
sorts
.
map
((
s
,
index
)
=>
{
return
(
<
InlineFieldRow
key=
{
`${s.field}/${index}`
}
>
<
InlineField
label=
"Field"
labelWidth=
{
10
}
grow=
{
true
}
>
<
Select
options=
{
fieldNames
}
value=
{
fieldNames
.
find
(
v
=>
v
.
value
===
s
.
field
)
}
placeholder=
"Select field"
onChange=
{
v
=>
{
onSortChange
(
index
,
{
...
s
,
field
:
v
.
value
!
});
}
}
/>
</
InlineField
>
<
InlineField
label=
"Reverse"
>
<
InlineSwitch
value=
{
!!
s
.
desc
}
onChange=
{
()
=>
{
onSortChange
(
index
,
{
...
s
,
desc
:
!!!
s
.
desc
});
}
}
/>
</
InlineField
>
</
InlineFieldRow
>
);
})
}
</
div
>
);
};
export
const
sortByTransformRegistryItem
:
TransformerRegistyItem
<
SortByTransformerOptions
>
=
{
id
:
DataTransformerID
.
sortBy
,
editor
:
SortByTransformerEditor
,
transformation
:
standardTransformers
.
sortByTransformer
,
name
:
standardTransformers
.
sortByTransformer
.
name
,
description
:
standardTransformers
.
sortByTransformer
.
description
,
};
public/app/core/utils/standardTransformers.ts
View file @
bb65113c
...
@@ -8,6 +8,7 @@ import { seriesToFieldsTransformerRegistryItem } from '../components/Transformer
...
@@ -8,6 +8,7 @@ import { seriesToFieldsTransformerRegistryItem } from '../components/Transformer
import
{
calculateFieldTransformRegistryItem
}
from
'../components/TransformersUI/CalculateFieldTransformerEditor'
;
import
{
calculateFieldTransformRegistryItem
}
from
'../components/TransformersUI/CalculateFieldTransformerEditor'
;
import
{
labelsToFieldsTransformerRegistryItem
}
from
'../components/TransformersUI/LabelsToFieldsTransformerEditor'
;
import
{
labelsToFieldsTransformerRegistryItem
}
from
'../components/TransformersUI/LabelsToFieldsTransformerEditor'
;
import
{
groupByTransformRegistryItem
}
from
'../components/TransformersUI/GroupByTransformerEditor'
;
import
{
groupByTransformRegistryItem
}
from
'../components/TransformersUI/GroupByTransformerEditor'
;
import
{
sortByTransformRegistryItem
}
from
'../components/TransformersUI/SortByTransformerEditor'
;
import
{
mergeTransformerRegistryItem
}
from
'../components/TransformersUI/MergeTransformerEditor'
;
import
{
mergeTransformerRegistryItem
}
from
'../components/TransformersUI/MergeTransformerEditor'
;
import
{
seriesToRowsTransformerRegistryItem
}
from
'../components/TransformersUI/SeriesToRowsTransformerEditor'
;
import
{
seriesToRowsTransformerRegistryItem
}
from
'../components/TransformersUI/SeriesToRowsTransformerEditor'
;
import
{
concatenateTransformRegistryItem
}
from
'../components/TransformersUI/ConcatenateTransformerEditor'
;
import
{
concatenateTransformRegistryItem
}
from
'../components/TransformersUI/ConcatenateTransformerEditor'
;
...
@@ -27,6 +28,7 @@ export const getStandardTransformers = (): Array<TransformerRegistyItem<any>> =>
...
@@ -27,6 +28,7 @@ export const getStandardTransformers = (): Array<TransformerRegistyItem<any>> =>
calculateFieldTransformRegistryItem
,
calculateFieldTransformRegistryItem
,
labelsToFieldsTransformerRegistryItem
,
labelsToFieldsTransformerRegistryItem
,
groupByTransformRegistryItem
,
groupByTransformRegistryItem
,
sortByTransformRegistryItem
,
mergeTransformerRegistryItem
,
mergeTransformerRegistryItem
,
];
];
};
};
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