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:
parent
b2d94f3d85
commit
860b3bbce7
@ -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 |
|
||||
| `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 |
|
||||
| `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
|
||||
|
||||
|
@ -243,7 +243,9 @@ lineage: schemas: [{
|
||||
// `4`: Numerical DESC
|
||||
// `5`: Alphabetical Case Insensitive ASC
|
||||
// `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
|
||||
#DataSourceRef: {
|
||||
|
@ -36,6 +36,8 @@ export enum VariableSort {
|
||||
numericalDesc,
|
||||
alphabeticalCaseInsensitiveAsc,
|
||||
alphabeticalCaseInsensitiveDesc,
|
||||
naturalAsc,
|
||||
naturalDesc,
|
||||
}
|
||||
|
||||
export enum VariableHide {
|
||||
|
@ -233,6 +233,8 @@ export enum VariableHide {
|
||||
* `4`: Numerical DESC
|
||||
* `5`: Alphabetical Case Insensitive ASC
|
||||
* `6`: Alphabetical Case Insensitive DESC
|
||||
* `7`: Natural ASC
|
||||
* `8`: Natural DESC
|
||||
*/
|
||||
export enum VariableSort {
|
||||
alphabeticalAsc = 1,
|
||||
@ -240,6 +242,8 @@ export enum VariableSort {
|
||||
alphabeticalCaseInsensitiveDesc = 6,
|
||||
alphabeticalDesc = 2,
|
||||
disabled = 0,
|
||||
naturalAsc = 7,
|
||||
naturalDesc = 8,
|
||||
numericalAsc = 3,
|
||||
numericalDesc = 4,
|
||||
}
|
||||
|
@ -152,6 +152,8 @@ const (
|
||||
VariableSortN4 VariableSort = 4
|
||||
VariableSortN5 VariableSort = 5
|
||||
VariableSortN6 VariableSort = 6
|
||||
VariableSortN7 VariableSort = 7
|
||||
VariableSortN8 VariableSort = 8
|
||||
)
|
||||
|
||||
// Defines values for VariableType.
|
||||
@ -960,6 +962,8 @@ type VariableModel struct {
|
||||
// `4`: Numerical DESC
|
||||
// `5`: Alphabetical Case Insensitive ASC
|
||||
// `6`: Alphabetical Case Insensitive DESC
|
||||
// `7`: Natural ASC
|
||||
// `8`: Natural DESC
|
||||
Sort *VariableSort `json:"sort,omitempty"`
|
||||
|
||||
// Dashboard variable type
|
||||
@ -1001,6 +1005,8 @@ type VariableRefresh int
|
||||
// `4`: Numerical DESC
|
||||
// `5`: Alphabetical Case Insensitive ASC
|
||||
// `6`: Alphabetical Case Insensitive DESC
|
||||
// `7`: Natural ASC
|
||||
// `8`: Natural DESC
|
||||
type VariableSort int
|
||||
|
||||
// Dashboard variable type
|
||||
|
@ -19,6 +19,8 @@ const SORT_OPTIONS = [
|
||||
{ label: 'Numerical (desc)', value: VariableSort.numericalDesc },
|
||||
{ label: 'Alphabetical (case-insensitive, asc)', value: VariableSort.alphabeticalCaseInsensitiveAsc },
|
||||
{ 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>) {
|
||||
|
@ -277,6 +277,8 @@ describe('sortVariableValues', () => {
|
||||
${[{ 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.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)',
|
||||
({ 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', () => {
|
||||
|
@ -56,6 +56,18 @@ export const sortVariableValues = (options: any[], sortOrder: VariableSort) => {
|
||||
options = sortBy(options, (opt) => {
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user