mirror of
https://github.com/grafana/grafana.git
synced 2025-09-22 05:23:50 +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 };
|
||||
});
|
||||
state.options = applyLimit(state.options);
|
||||
return state;
|
||||
};
|
||||
|
||||
@ -234,18 +235,17 @@ const optionsPickerSlice = createSlice({
|
||||
updateOptionsAndFilter: (state, action: PayloadAction<VariableOption[]>): OptionsPickerState => {
|
||||
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;
|
||||
return text.toLowerCase().indexOf(searchQuery) !== -1;
|
||||
});
|
||||
|
||||
state.options = applyLimit(filteredOptions);
|
||||
state.highlightIndex = 0;
|
||||
|
||||
return applyStateChanges(state, updateDefaultSelection, updateOptions);
|
||||
},
|
||||
updateOptionsFromSearch: (state, action: PayloadAction<VariableOption[]>): OptionsPickerState => {
|
||||
state.options = applyLimit(action.payload);
|
||||
state.options = action.payload;
|
||||
state.highlightIndex = 0;
|
||||
|
||||
return applyStateChanges(state, updateDefaultSelection, updateOptions);
|
||||
|
Reference in New Issue
Block a user