mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Dashboards: Implement natural sort for query variables (#78024)
This commit is contained in:
@@ -648,7 +648,7 @@ A variable is a placeholder for a value. You can use variables in metric queries
|
|||||||
| `query` | | No | | Query used to fetch values for a variable |
|
| `query` | | No | | Query used to fetch values for a variable |
|
||||||
| `refresh` | integer | No | | Options to config when to refresh a variable<br/>`0`: Never refresh the variable<br/>`1`: Queries the data source every time the dashboard loads.<br/>`2`: Queries the data source when the dashboard time range changes.<br/>Possible values are: `0`, `1`, `2`. |
|
| `refresh` | integer | No | | Options to config when to refresh a variable<br/>`0`: Never refresh the variable<br/>`1`: Queries the data source every time the dashboard loads.<br/>`2`: Queries the data source when the dashboard time range changes.<br/>Possible values are: `0`, `1`, `2`. |
|
||||||
| `skipUrlSync` | boolean | No | `false` | Whether the variable value should be managed by URL query params or not |
|
| `skipUrlSync` | boolean | No | `false` | Whether the variable value should be managed by URL query params or not |
|
||||||
| `sort` | integer | No | | Sort variable options<br/>Accepted values are:<br/>`0`: No sorting<br/>`1`: Alphabetical ASC<br/>`2`: Alphabetical DESC<br/>`3`: Numerical ASC<br/>`4`: Numerical DESC<br/>`5`: Alphabetical Case Insensitive ASC<br/>`6`: Alphabetical Case Insensitive DESC<br/>Possible values are: `0`, `1`, `2`, `3`, `4`, `5`, `6`. |
|
| `sort` | integer | No | | Sort variable options<br/>Accepted values are:<br/>`0`: No sorting<br/>`1`: Alphabetical ASC<br/>`2`: Alphabetical DESC<br/>`3`: Numerical ASC<br/>`4`: Numerical DESC<br/>`5`: Alphabetical Case Insensitive ASC<br/>`6`: Alphabetical Case Insensitive DESC<br/>`7`: Natural ASC<br/>`8`: Natural DESC<br/>Possible values are: `0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`. |
|
||||||
|
|
||||||
### VariableOption
|
### VariableOption
|
||||||
|
|
||||||
|
@@ -243,7 +243,9 @@ lineage: schemas: [{
|
|||||||
// `4`: Numerical DESC
|
// `4`: Numerical DESC
|
||||||
// `5`: Alphabetical Case Insensitive ASC
|
// `5`: Alphabetical Case Insensitive ASC
|
||||||
// `6`: Alphabetical Case Insensitive DESC
|
// `6`: Alphabetical Case Insensitive DESC
|
||||||
#VariableSort: 0 | 1 | 2 | 3 | 4 | 5 | 6 @cuetsy(kind="enum",memberNames="disabled|alphabeticalAsc|alphabeticalDesc|numericalAsc|numericalDesc|alphabeticalCaseInsensitiveAsc|alphabeticalCaseInsensitiveDesc")
|
// `7`: Natural ASC
|
||||||
|
// `8`: Natural DESC
|
||||||
|
#VariableSort: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 @cuetsy(kind="enum",memberNames="disabled|alphabeticalAsc|alphabeticalDesc|numericalAsc|numericalDesc|alphabeticalCaseInsensitiveAsc|alphabeticalCaseInsensitiveDesc|naturalAsc|naturalDesc")
|
||||||
|
|
||||||
// Ref to a DataSource instance
|
// Ref to a DataSource instance
|
||||||
#DataSourceRef: {
|
#DataSourceRef: {
|
||||||
|
@@ -36,6 +36,8 @@ export enum VariableSort {
|
|||||||
numericalDesc,
|
numericalDesc,
|
||||||
alphabeticalCaseInsensitiveAsc,
|
alphabeticalCaseInsensitiveAsc,
|
||||||
alphabeticalCaseInsensitiveDesc,
|
alphabeticalCaseInsensitiveDesc,
|
||||||
|
naturalAsc,
|
||||||
|
naturalDesc,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum VariableHide {
|
export enum VariableHide {
|
||||||
|
@@ -233,6 +233,8 @@ export enum VariableHide {
|
|||||||
* `4`: Numerical DESC
|
* `4`: Numerical DESC
|
||||||
* `5`: Alphabetical Case Insensitive ASC
|
* `5`: Alphabetical Case Insensitive ASC
|
||||||
* `6`: Alphabetical Case Insensitive DESC
|
* `6`: Alphabetical Case Insensitive DESC
|
||||||
|
* `7`: Natural ASC
|
||||||
|
* `8`: Natural DESC
|
||||||
*/
|
*/
|
||||||
export enum VariableSort {
|
export enum VariableSort {
|
||||||
alphabeticalAsc = 1,
|
alphabeticalAsc = 1,
|
||||||
@@ -240,6 +242,8 @@ export enum VariableSort {
|
|||||||
alphabeticalCaseInsensitiveDesc = 6,
|
alphabeticalCaseInsensitiveDesc = 6,
|
||||||
alphabeticalDesc = 2,
|
alphabeticalDesc = 2,
|
||||||
disabled = 0,
|
disabled = 0,
|
||||||
|
naturalAsc = 7,
|
||||||
|
naturalDesc = 8,
|
||||||
numericalAsc = 3,
|
numericalAsc = 3,
|
||||||
numericalDesc = 4,
|
numericalDesc = 4,
|
||||||
}
|
}
|
||||||
|
@@ -152,6 +152,8 @@ const (
|
|||||||
VariableSortN4 VariableSort = 4
|
VariableSortN4 VariableSort = 4
|
||||||
VariableSortN5 VariableSort = 5
|
VariableSortN5 VariableSort = 5
|
||||||
VariableSortN6 VariableSort = 6
|
VariableSortN6 VariableSort = 6
|
||||||
|
VariableSortN7 VariableSort = 7
|
||||||
|
VariableSortN8 VariableSort = 8
|
||||||
)
|
)
|
||||||
|
|
||||||
// Defines values for VariableType.
|
// Defines values for VariableType.
|
||||||
@@ -960,6 +962,8 @@ type VariableModel struct {
|
|||||||
// `4`: Numerical DESC
|
// `4`: Numerical DESC
|
||||||
// `5`: Alphabetical Case Insensitive ASC
|
// `5`: Alphabetical Case Insensitive ASC
|
||||||
// `6`: Alphabetical Case Insensitive DESC
|
// `6`: Alphabetical Case Insensitive DESC
|
||||||
|
// `7`: Natural ASC
|
||||||
|
// `8`: Natural DESC
|
||||||
Sort *VariableSort `json:"sort,omitempty"`
|
Sort *VariableSort `json:"sort,omitempty"`
|
||||||
|
|
||||||
// Dashboard variable type
|
// Dashboard variable type
|
||||||
@@ -1001,6 +1005,8 @@ type VariableRefresh int
|
|||||||
// `4`: Numerical DESC
|
// `4`: Numerical DESC
|
||||||
// `5`: Alphabetical Case Insensitive ASC
|
// `5`: Alphabetical Case Insensitive ASC
|
||||||
// `6`: Alphabetical Case Insensitive DESC
|
// `6`: Alphabetical Case Insensitive DESC
|
||||||
|
// `7`: Natural ASC
|
||||||
|
// `8`: Natural DESC
|
||||||
type VariableSort int
|
type VariableSort int
|
||||||
|
|
||||||
// Dashboard variable type
|
// Dashboard variable type
|
||||||
|
@@ -19,6 +19,8 @@ const SORT_OPTIONS = [
|
|||||||
{ label: 'Numerical (desc)', value: VariableSort.numericalDesc },
|
{ label: 'Numerical (desc)', value: VariableSort.numericalDesc },
|
||||||
{ label: 'Alphabetical (case-insensitive, asc)', value: VariableSort.alphabeticalCaseInsensitiveAsc },
|
{ label: 'Alphabetical (case-insensitive, asc)', value: VariableSort.alphabeticalCaseInsensitiveAsc },
|
||||||
{ label: 'Alphabetical (case-insensitive, desc)', value: VariableSort.alphabeticalCaseInsensitiveDesc },
|
{ label: 'Alphabetical (case-insensitive, desc)', value: VariableSort.alphabeticalCaseInsensitiveDesc },
|
||||||
|
{ label: 'Natural (asc)', value: VariableSort.naturalAsc },
|
||||||
|
{ label: 'Natural (desc)', value: VariableSort.naturalDesc },
|
||||||
];
|
];
|
||||||
|
|
||||||
export function QueryVariableSortSelect({ onChange, sort }: PropsWithChildren<Props>) {
|
export function QueryVariableSortSelect({ onChange, sort }: PropsWithChildren<Props>) {
|
||||||
|
@@ -277,6 +277,8 @@ describe('sortVariableValues', () => {
|
|||||||
${[{ text: '1' }, { text: null }, { text: '2' }]} | ${VariableSort.numericalDesc} | ${[{ text: '2' }, { text: '1' }, { text: null }]}
|
${[{ text: '1' }, { text: null }, { text: '2' }]} | ${VariableSort.numericalDesc} | ${[{ text: '2' }, { text: '1' }, { text: null }]}
|
||||||
${[{ text: 'a' }, { text: null }, { text: 'b' }]} | ${VariableSort.alphabeticalCaseInsensitiveAsc} | ${[{ text: null }, { text: 'a' }, { text: 'b' }]}
|
${[{ text: 'a' }, { text: null }, { text: 'b' }]} | ${VariableSort.alphabeticalCaseInsensitiveAsc} | ${[{ text: null }, { text: 'a' }, { text: 'b' }]}
|
||||||
${[{ text: 'a' }, { text: null }, { text: 'b' }]} | ${VariableSort.alphabeticalCaseInsensitiveDesc} | ${[{ text: 'b' }, { text: 'a' }, { text: null }]}
|
${[{ text: 'a' }, { text: null }, { text: 'b' }]} | ${VariableSort.alphabeticalCaseInsensitiveDesc} | ${[{ text: 'b' }, { text: 'a' }, { text: null }]}
|
||||||
|
${[{ text: '1' }, { text: null }, { text: '2' }]} | ${VariableSort.naturalAsc} | ${[{ text: null }, { text: '1' }, { text: '2' }]}
|
||||||
|
${[{ text: '1' }, { text: null }, { text: '2' }]} | ${VariableSort.naturalDesc} | ${[{ text: '2' }, { text: '1' }, { text: null }]}
|
||||||
`(
|
`(
|
||||||
'then it should sort the options correctly without throwing (sortOrder:$sortOrder)',
|
'then it should sort the options correctly without throwing (sortOrder:$sortOrder)',
|
||||||
({ options, sortOrder, expected }) => {
|
({ options, sortOrder, expected }) => {
|
||||||
@@ -286,6 +288,19 @@ describe('sortVariableValues', () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when using natural sort', () => {
|
||||||
|
it.each`
|
||||||
|
options | sortOrder | expected
|
||||||
|
${[{ text: '12-lax01' }, { text: '4-sjc01' }, { text: '21-lhr01' }]} | ${VariableSort.naturalAsc} | ${[{ text: '4-sjc01' }, { text: '12-lax01' }, { text: '21-lhr01' }]}
|
||||||
|
${[{ text: 'lax01' }, { text: 'sjc01' }, { text: 'sjc02' }, { text: 'lhr01' }]} | ${VariableSort.naturalAsc} | ${[{ text: 'lax01' }, { text: 'lhr01' }, { text: 'sjc01' }, { text: 'sjc02' }]}
|
||||||
|
${[{ text: '4m10' }, { text: '4m2' }, { text: '4m1' }, { text: '4m4' }]} | ${VariableSort.naturalAsc} | ${[{ text: '4m1' }, { text: '4m2' }, { text: '4m4' }, { text: '4m10' }]}
|
||||||
|
`('then it should sort like humans would naturally sort', ({ options, sortOrder, expected }) => {
|
||||||
|
const result = sortVariableValues(options, sortOrder);
|
||||||
|
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('metricNamesToVariableValues', () => {
|
describe('metricNamesToVariableValues', () => {
|
||||||
|
@@ -56,6 +56,18 @@ export const sortVariableValues = (options: any[], sortOrder: VariableSort) => {
|
|||||||
options = sortBy(options, (opt) => {
|
options = sortBy(options, (opt) => {
|
||||||
return toLower(opt.text);
|
return toLower(opt.text);
|
||||||
});
|
});
|
||||||
|
} else if (sortType === 4) {
|
||||||
|
options.sort((a, b) => {
|
||||||
|
if (!a.text) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!b.text) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.text.localeCompare(b.text, undefined, { numeric: true });
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reverseSort) {
|
if (reverseSort) {
|
||||||
|
Reference in New Issue
Block a user