mirror of
https://github.com/grafana/grafana.git
synced 2025-08-02 16:12:27 +08:00
OptionsPicker: Allow storing raw input even when matches exist (#84790)
This commit is contained in:
@ -569,8 +569,11 @@ describe('optionsPickerReducer', () => {
|
|||||||
.whenActionIsDispatched(updateOptionsAndFilter(options))
|
.whenActionIsDispatched(updateOptionsAndFilter(options))
|
||||||
.thenStateShouldEqual({
|
.thenStateShouldEqual({
|
||||||
...initialState,
|
...initialState,
|
||||||
options: [{ text: 'All', value: '$__all', selected: true }],
|
options: [
|
||||||
selectedValues: [{ text: 'All', value: '$__all', selected: true }],
|
{ text: '> A', value: 'A', selected: false },
|
||||||
|
{ text: 'All', value: '$__all', selected: false },
|
||||||
|
],
|
||||||
|
selectedValues: [],
|
||||||
queryValue: 'A',
|
queryValue: 'A',
|
||||||
highlightIndex: 0,
|
highlightIndex: 0,
|
||||||
});
|
});
|
||||||
@ -815,6 +818,45 @@ describe('optionsPickerReducer', () => {
|
|||||||
highlightIndex: 0,
|
highlightIndex: 0,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should offer as-typed option even when matches exist', () => {
|
||||||
|
const searchQuery = 'a.*';
|
||||||
|
|
||||||
|
const options: VariableOption[] = 'A AA AB C'.split(' ').map((v) => ({
|
||||||
|
selected: false,
|
||||||
|
text: v,
|
||||||
|
value: v,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const expect: VariableOption[] = [
|
||||||
|
{
|
||||||
|
selected: false,
|
||||||
|
text: '> ' + searchQuery,
|
||||||
|
value: searchQuery,
|
||||||
|
},
|
||||||
|
].concat(
|
||||||
|
'A AA AB'.split(' ').map((v) => ({
|
||||||
|
selected: false,
|
||||||
|
text: v,
|
||||||
|
value: v,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
const { initialState } = getVariableTestContext({
|
||||||
|
queryValue: searchQuery,
|
||||||
|
});
|
||||||
|
|
||||||
|
reducerTester<OptionsPickerState>()
|
||||||
|
.givenReducer(optionsPickerReducer, cloneDeep(initialState))
|
||||||
|
.whenActionIsDispatched(updateOptionsAndFilter(options))
|
||||||
|
.thenStateShouldEqual({
|
||||||
|
...cloneDeep(initialState),
|
||||||
|
options: expect,
|
||||||
|
selectedValues: [],
|
||||||
|
queryValue: searchQuery,
|
||||||
|
highlightIndex: 1,
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when large data for updateOptionsFromSearch is dispatched and variable has searchFilter', () => {
|
describe('when large data for updateOptionsFromSearch is dispatched and variable has searchFilter', () => {
|
||||||
|
@ -267,12 +267,30 @@ const optionsPickerSlice = createSlice({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// always sort $__all to the top, even if exact match exists?
|
// always sort $__all to the top, even if exact match exists?
|
||||||
opts.sort((a, b) => (a.value === '$__all' ? -1 : 0) - (b.value === '$__all' ? -1 : 0));
|
opts.sort((a, b) => (a.value === ALL_VARIABLE_VALUE ? -1 : 0) - (b.value === ALL_VARIABLE_VALUE ? -1 : 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state.highlightIndex = 0;
|
||||||
|
|
||||||
|
if (needle !== '') {
|
||||||
|
// top ranked match index
|
||||||
|
let firstMatchIdx = opts.findIndex((o) => o.value !== ALL_VARIABLE_VALUE);
|
||||||
|
|
||||||
|
// if there's no match or no exact match, prepend as-typed option
|
||||||
|
if (firstMatchIdx === -1 || opts[firstMatchIdx].value !== needle) {
|
||||||
|
opts.unshift({
|
||||||
|
selected: false,
|
||||||
|
text: '> ' + needle,
|
||||||
|
value: needle,
|
||||||
|
});
|
||||||
|
|
||||||
|
// if no match at all, select as-typed, else select best match
|
||||||
|
state.highlightIndex = firstMatchIdx === -1 ? 0 : firstMatchIdx + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.options = opts;
|
state.options = opts;
|
||||||
state.highlightIndex = 0;
|
|
||||||
|
|
||||||
return applyStateChanges(state, updateDefaultSelection, updateOptions);
|
return applyStateChanges(state, updateDefaultSelection, updateOptions);
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user