mirror of
https://github.com/grafana/grafana.git
synced 2025-09-22 14:43:51 +08:00
Variables: Limit rendering of options in dropdown to improve search performance (#27525)
* fixed: bigdata dropdown first limit 1000 * fixed: change to use function of applylimit * fixed: remove both applyLimit callers * feat: test for new logic with applimit * feat: test showOptions with the applyLimit logic * fixed: test equal fixed
This commit is contained in:
@ -861,4 +861,85 @@ describe('optionsPickerReducer', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when large data for updateOptionsAndFilter', () => {
|
||||||
|
it('then state should be correct', () => {
|
||||||
|
const searchQuery = 'option:11256';
|
||||||
|
|
||||||
|
const options: VariableOption[] = [];
|
||||||
|
for (let index = 0; index <= OPTIONS_LIMIT + 11256; index++) {
|
||||||
|
options.push({ text: `option:${index}`, value: `option:${index}`, selected: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { initialState } = getVariableTestContext({
|
||||||
|
queryValue: searchQuery,
|
||||||
|
});
|
||||||
|
|
||||||
|
reducerTester<OptionsPickerState>()
|
||||||
|
.givenReducer(optionsPickerReducer, cloneDeep(initialState))
|
||||||
|
.whenActionIsDispatched(updateOptionsAndFilter(options))
|
||||||
|
.thenStateShouldEqual({
|
||||||
|
...cloneDeep(initialState),
|
||||||
|
options: [{ text: 'option:11256', value: 'option:11256', selected: false }],
|
||||||
|
selectedValues: [],
|
||||||
|
queryValue: 'option:11256',
|
||||||
|
highlightIndex: 0,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when large data for updateOptionsFromSearch is dispatched and variable has searchFilter', () => {
|
||||||
|
it('then state should be correct', () => {
|
||||||
|
const searchQuery = '__searchFilter';
|
||||||
|
const options = [{ text: 'All', value: '$__all', selected: true }];
|
||||||
|
|
||||||
|
for (let i = 0; i <= OPTIONS_LIMIT + 137; i++) {
|
||||||
|
options.push({ text: `option${i}`, value: `option${i}`, selected: false });
|
||||||
|
}
|
||||||
|
const { initialState } = getVariableTestContext({
|
||||||
|
queryValue: searchQuery,
|
||||||
|
});
|
||||||
|
|
||||||
|
reducerTester<OptionsPickerState>()
|
||||||
|
.givenReducer(optionsPickerReducer, cloneDeep(initialState))
|
||||||
|
.whenActionIsDispatched(updateOptionsFromSearch(options))
|
||||||
|
.thenStateShouldEqual({
|
||||||
|
...initialState,
|
||||||
|
options: options.slice(0, OPTIONS_LIMIT),
|
||||||
|
selectedValues: [{ text: 'All', value: '$__all', selected: true }],
|
||||||
|
highlightIndex: 0,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when large data for showOptions', () => {
|
||||||
|
it('then state should be correct', () => {
|
||||||
|
const { initialState } = getVariableTestContext({});
|
||||||
|
const payload = {
|
||||||
|
type: 'query',
|
||||||
|
query: '',
|
||||||
|
options: [{ text: 'option0', value: 'option0', selected: false }],
|
||||||
|
multi: false,
|
||||||
|
id: '0',
|
||||||
|
} as QueryVariableModel;
|
||||||
|
const checkOptions = [];
|
||||||
|
for (let index = 0; index < OPTIONS_LIMIT; index++) {
|
||||||
|
checkOptions.push({ text: `option${index}`, value: `option${index}`, selected: false });
|
||||||
|
}
|
||||||
|
for (let i = 1; i <= OPTIONS_LIMIT + 137; i++) {
|
||||||
|
payload.options.push({ text: `option${i}`, value: `option${i}`, selected: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
reducerTester<OptionsPickerState>()
|
||||||
|
.givenReducer(optionsPickerReducer, cloneDeep(initialState))
|
||||||
|
.whenActionIsDispatched(showOptions(payload))
|
||||||
|
.thenStateShouldEqual({
|
||||||
|
...initialState,
|
||||||
|
options: checkOptions,
|
||||||
|
id: '0',
|
||||||
|
multi: false,
|
||||||
|
queryValue: '',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -78,6 +78,7 @@ const updateOptions = (state: OptionsPickerState): OptionsPickerState => {
|
|||||||
|
|
||||||
return { ...option, selected };
|
return { ...option, selected };
|
||||||
});
|
});
|
||||||
|
state.options = applyLimit(state.options);
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -234,18 +235,17 @@ const optionsPickerSlice = createSlice({
|
|||||||
updateOptionsAndFilter: (state, action: PayloadAction<VariableOption[]>): OptionsPickerState => {
|
updateOptionsAndFilter: (state, action: PayloadAction<VariableOption[]>): OptionsPickerState => {
|
||||||
const searchQuery = trim((state.queryValue ?? '').toLowerCase());
|
const searchQuery = trim((state.queryValue ?? '').toLowerCase());
|
||||||
|
|
||||||
const filteredOptions = action.payload.filter(option => {
|
state.options = action.payload.filter(option => {
|
||||||
const text = Array.isArray(option.text) ? option.text.toString() : option.text;
|
const text = Array.isArray(option.text) ? option.text.toString() : option.text;
|
||||||
return text.toLowerCase().indexOf(searchQuery) !== -1;
|
return text.toLowerCase().indexOf(searchQuery) !== -1;
|
||||||
});
|
});
|
||||||
|
|
||||||
state.options = applyLimit(filteredOptions);
|
|
||||||
state.highlightIndex = 0;
|
state.highlightIndex = 0;
|
||||||
|
|
||||||
return applyStateChanges(state, updateDefaultSelection, updateOptions);
|
return applyStateChanges(state, updateDefaultSelection, updateOptions);
|
||||||
},
|
},
|
||||||
updateOptionsFromSearch: (state, action: PayloadAction<VariableOption[]>): OptionsPickerState => {
|
updateOptionsFromSearch: (state, action: PayloadAction<VariableOption[]>): OptionsPickerState => {
|
||||||
state.options = applyLimit(action.payload);
|
state.options = action.payload;
|
||||||
state.highlightIndex = 0;
|
state.highlightIndex = 0;
|
||||||
|
|
||||||
return applyStateChanges(state, updateDefaultSelection, updateOptions);
|
return applyStateChanges(state, updateDefaultSelection, updateOptions);
|
||||||
|
Reference in New Issue
Block a user