Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.7] [Controls] Fix sorting of numeric keyword fields (#155207) #155934

Merged
merged 1 commit into from
Apr 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/plugins/controls/common/options_list/mocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ const mockOptionsListComponentState = {
...getDefaultComponentState(),
field: undefined,
totalCardinality: 0,
availableOptions: {
woof: { doc_count: 100 },
bark: { doc_count: 75 },
meow: { doc_count: 50 },
quack: { doc_count: 25 },
moo: { doc_count: 5 },
},
availableOptions: [
{ value: 'woof', docCount: 100 },
{ value: 'bark', docCount: 75 },
{ value: 'meow', docCount: 50 },
{ value: 'quack', docCount: 25 },
{ value: 'moo', docCount: 5 },
],
invalidSelections: [],
validSelections: [],
} as OptionsListComponentState;
Expand Down
4 changes: 1 addition & 3 deletions src/plugins/controls/common/options_list/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ export interface OptionsListEmbeddableInput extends DataControlInput {
placeholder?: string;
}

export interface OptionsListSuggestions {
[key: string]: { doc_count: number };
}
export type OptionsListSuggestions = Array<{ value: string; docCount?: number }>;

/**
* The Options list response is returned from the serverside Options List route.
Expand Down
10 changes: 7 additions & 3 deletions src/plugins/controls/public/__stories__/controls.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ import { injectStorybookDataView } from '../services/data_views/data_views.story
import { replaceOptionsListMethod } from '../services/options_list/options_list.story';
import { populateStorybookControlFactories } from './storybook_control_factories';
import { replaceValueSuggestionMethod } from '../services/unified_search/unified_search.story';
import { OptionsListResponse, OptionsListRequest } from '../../common/options_list/types';
import {
OptionsListResponse,
OptionsListRequest,
OptionsListSuggestions,
} from '../../common/options_list/types';

export default {
title: 'Controls',
Expand All @@ -56,9 +60,9 @@ const storybookStubOptionsListRequest = async (
r({
suggestions: getFlightSearchOptions(request.field.name, request.searchString).reduce(
(o, current, index) => {
return { ...o, [current]: { doc_count: index } };
return [...o, { value: current, docCount: index }];
},
{}
[] as OptionsListSuggestions
),
totalCardinality: 100,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ describe('Options list popover', () => {
});

test('no available options', async () => {
const popover = await mountComponent({ componentState: { availableOptions: {} } });
const popover = await mountComponent({ componentState: { availableOptions: [] } });
const availableOptionsDiv = findTestSubject(popover, 'optionsList-control-available-options');
const noOptionsDiv = findTestSubject(
availableOptionsDiv,
Expand Down Expand Up @@ -125,9 +125,7 @@ describe('Options list popover', () => {
selectedOptions: ['bark', 'woof'],
},
componentState: {
availableOptions: {
bark: { doc_count: 75 },
},
availableOptions: [{ value: 'bark', docCount: 75 }],
validSelections: ['bark'],
invalidSelections: ['woof'],
},
Expand All @@ -152,9 +150,7 @@ describe('Options list popover', () => {
const popover = await mountComponent({
explicitInput: { selectedOptions: ['bark', 'woof', 'meow'] },
componentState: {
availableOptions: {
bark: { doc_count: 75 },
},
availableOptions: [{ value: 'bark', docCount: 75 }],
validSelections: ['bark'],
invalidSelections: ['woof', 'meow'],
},
Expand Down Expand Up @@ -217,7 +213,7 @@ describe('Options list popover', () => {

test('if existsSelected = false and no suggestions, then "Exists" does not show up', async () => {
const popover = await mountComponent({
componentState: { availableOptions: {} },
componentState: { availableOptions: [] },
explicitInput: { existsSelected: false },
});
const existsOption = findTestSubject(popover, 'optionsList-control-selection-exists');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const OptionsListPopoverSuggestions = ({
const canLoadMoreSuggestions = useMemo(
() =>
totalCardinality
? Object.keys(availableOptions ?? {}).length <
? (availableOptions ?? []).length <
Math.min(totalCardinality, MAX_OPTIONS_LIST_REQUEST_SIZE)
: false,
[availableOptions, totalCardinality]
Expand All @@ -68,7 +68,7 @@ export const OptionsListPopoverSuggestions = ({
[invalidSelections]
);
const suggestions = useMemo(() => {
return showOnlySelected ? selectedOptions : Object.keys(availableOptions ?? {});
return showOnlySelected ? selectedOptions : availableOptions ?? [];
}, [availableOptions, selectedOptions, showOnlySelected]);

const existsSelectableOption = useMemo<EuiSelectableOption | undefined>(() => {
Expand All @@ -86,19 +86,23 @@ export const OptionsListPopoverSuggestions = ({
const [selectableOptions, setSelectableOptions] = useState<EuiSelectableOption[]>([]); // will be set in following useEffect
useEffect(() => {
/* This useEffect makes selectableOptions responsive to search, show only selected, and clear selections */
const options: EuiSelectableOption[] = (suggestions ?? []).map((key) => {
const options: EuiSelectableOption[] = (suggestions ?? []).map((suggestion) => {
if (typeof suggestion === 'string') {
// this means that `showOnlySelected` is true, and doc count is not known when this is the case
suggestion = { value: suggestion };
}
return {
key,
label: key,
checked: selectedOptionsSet?.has(key) ? 'on' : undefined,
'data-test-subj': `optionsList-control-selection-${key}`,
key: suggestion.value,
label: suggestion.value,
checked: selectedOptionsSet?.has(suggestion.value) ? 'on' : undefined,
'data-test-subj': `optionsList-control-selection-${suggestion.value}`,
className:
showOnlySelected && invalidSelectionsSet.has(key)
showOnlySelected && invalidSelectionsSet.has(suggestion.value)
? 'optionsList__selectionInvalid'
: 'optionsList__validSuggestion',
append:
!showOnlySelected && availableOptions?.[key] ? (
<OptionsListPopoverSuggestionBadge documentCount={availableOptions[key].doc_count} />
!showOnlySelected && suggestion?.docCount ? (
<OptionsListPopoverSuggestionBadge documentCount={suggestion.docCount} />
) : undefined,
};
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ export class OptionsListEmbeddable extends Embeddable<OptionsListEmbeddableInput
batch(() => {
dispatch(
updateQueryResults({
availableOptions: {},
availableOptions: [],
})
);
dispatch(setLoading(false));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ let optionsListRequestMethod = async (request: OptionsListRequest, abortSignal:
setTimeout(
() =>
r({
suggestions: {},
suggestions: [],
totalCardinality: 100,
}),
120
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,17 +388,20 @@ describe('options list cheap queries', () => {
expect(
suggestionAggBuilder.parse(rawSearchResponseMock, optionsListRequestBodyMock).suggestions
).toMatchInlineSnapshot(`
Object {
"cool1": Object {
"doc_count": 5,
Array [
Object {
"docCount": 5,
"value": "cool1",
},
"cool2": Object {
"doc_count": 15,
Object {
"docCount": 15,
"value": "cool2",
},
"cool3": Object {
"doc_count": 10,
Object {
"docCount": 10,
"value": "cool3",
},
}
]
`);
});

Expand All @@ -421,14 +424,16 @@ describe('options list cheap queries', () => {
expect(
suggestionAggBuilder.parse(rawSearchResponseMock, optionsListRequestBodyMock).suggestions
).toMatchInlineSnapshot(`
Object {
"false": Object {
"doc_count": 55,
Array [
Object {
"docCount": 55,
"value": "false",
},
"true": Object {
"doc_count": 155,
Object {
"docCount": 155,
"value": "true",
},
}
]
`);
});

Expand All @@ -455,17 +460,20 @@ describe('options list cheap queries', () => {
expect(
suggestionAggBuilder.parse(rawSearchResponseMock, optionsListRequestBodyMock).suggestions
).toMatchInlineSnapshot(`
Object {
"cool1": Object {
"doc_count": 5,
Array [
Object {
"docCount": 5,
"value": "cool1",
},
"cool2": Object {
"doc_count": 15,
Object {
"docCount": 15,
"value": "cool2",
},
"cool3": Object {
"doc_count": 10,
Object {
"docCount": 10,
"value": "cool3",
},
}
]
`);
});

Expand All @@ -490,17 +498,20 @@ describe('options list cheap queries', () => {
expect(
suggestionAggBuilder.parse(rawSearchResponseMock, optionsListRequestBodyMock).suggestions
).toMatchInlineSnapshot(`
Object {
"cool1": Object {
"doc_count": 5,
Array [
Object {
"docCount": 5,
"value": "cool1",
},
"cool2": Object {
"doc_count": 15,
Object {
"docCount": 15,
"value": "cool2",
},
"cool3": Object {
"doc_count": 10,
Object {
"docCount": 10,
"value": "cool3",
},
}
]
`);
});
});
Expand Down Expand Up @@ -552,55 +563,50 @@ describe('options list cheap queries', () => {
rawSearchResponseMock,
optionsListRequestBodyMock
).suggestions;
/** first, verify that the sorting worked as expected */
expect(Object.keys(parsed)).toMatchInlineSnapshot(`
Array [
"52:ae76:5947:5e2a:551:fe6a:712a:c72",
"111.52.174.2",
"196.162.13.39",
"f7a9:640b:b5a0:1219:8d75:ed94:3c3e:2e63",
"23.216.241.120",
"28c7:c9a4:42fd:16b0:4de5:e41e:28d9:9172",
"21.35.91.62",
"21.35.91.61",
"203.88.33.151",
"1ec:aa98:b0a6:d07c:590:18a0:8a33:2eb8",
]
`);
/** then, make sure the object is structured properly */

expect(parsed).toMatchInlineSnapshot(`
Object {
"111.52.174.2": Object {
"doc_count": 11,
Array [
Object {
"docCount": 12,
"value": "52:ae76:5947:5e2a:551:fe6a:712a:c72",
},
"196.162.13.39": Object {
"doc_count": 10,
Object {
"docCount": 11,
"value": "111.52.174.2",
},
"1ec:aa98:b0a6:d07c:590:18a0:8a33:2eb8": Object {
"doc_count": 6,
Object {
"docCount": 10,
"value": "196.162.13.39",
},
"203.88.33.151": Object {
"doc_count": 7,
Object {
"docCount": 10,
"value": "f7a9:640b:b5a0:1219:8d75:ed94:3c3e:2e63",
},
"21.35.91.61": Object {
"doc_count": 8,
Object {
"docCount": 9,
"value": "23.216.241.120",
},
"21.35.91.62": Object {
"doc_count": 8,
Object {
"docCount": 9,
"value": "28c7:c9a4:42fd:16b0:4de5:e41e:28d9:9172",
},
"23.216.241.120": Object {
"doc_count": 9,
Object {
"docCount": 8,
"value": "21.35.91.62",
},
"28c7:c9a4:42fd:16b0:4de5:e41e:28d9:9172": Object {
"doc_count": 9,
Object {
"docCount": 8,
"value": "21.35.91.61",
},
"52:ae76:5947:5e2a:551:fe6a:712a:c72": Object {
"doc_count": 12,
Object {
"docCount": 7,
"value": "203.88.33.151",
},
"f7a9:640b:b5a0:1219:8d75:ed94:3c3e:2e63": Object {
"doc_count": 10,
Object {
"docCount": 6,
"value": "1ec:aa98:b0a6:d07c:590:18a0:8a33:2eb8",
},
}
]
`);
});
});
Loading