[unified search] allowing to pass additional filters used for suggestions (#154522)

This commit is contained in:
Peter Pisljar 2023-04-11 15:43:58 +02:00 committed by GitHub
parent ed4d49b59c
commit 2459819c62
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 67 additions and 2 deletions

View file

@ -8,11 +8,12 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
import type { Query } from '@kbn/es-query';
import type { DataViewBase, Query } from '@kbn/es-query';
import { storiesOf } from '@storybook/react';
import { I18nProvider } from '@kbn/i18n-react';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/public';
import { buildExistsFilter } from '@kbn/es-query';
import { SearchBar, SearchBarProps } from '../search_bar';
import { setIndexPatterns } from '../services';
@ -260,6 +261,15 @@ storiesOf('SearchBar', module)
showQueryInput: false,
} as SearchBarProps)
)
.add('with additional filters used for suggestions', () =>
wrapSearchBarInContext({
filtersForSuggestions: [
buildExistsFilter({ type: 'keyword', name: 'geo.src' }, {
id: undefined,
} as unknown as DataViewBase),
],
} as unknown as SearchBarProps)
)
.add('with only the filter bar on', () =>
wrapSearchBarInContext({
showDatePicker: false,

View file

@ -22,6 +22,7 @@ export interface Props {
indexPatterns: DataView[];
intl: InjectedIntl;
timeRangeForSuggestionsOverride?: boolean;
filtersForSuggestions?: Filter[];
hiddenPanelOptions?: FilterItemsProps['hiddenPanelOptions'];
/**
* Applies extra styles necessary when coupled with the query bar
@ -54,6 +55,7 @@ const FilterBarUI = React.memo(function FilterBarUI(props: Props) {
onFiltersUpdated={props.onFiltersUpdated}
indexPatterns={props.indexPatterns!}
timeRangeForSuggestionsOverride={props.timeRangeForSuggestionsOverride}
filtersForSuggestions={props.filtersForSuggestions}
hiddenPanelOptions={props.hiddenPanelOptions}
readOnly={props.isDisabled}
/>

View file

@ -126,6 +126,7 @@ export interface FilterEditorComponentProps {
onLocalFilterCreate?: (initialState: { filter: Filter; queryDslFilter: QueryDslFilter }) => void;
onLocalFilterUpdate?: (filter: Filter | QueryDslFilter) => void;
timeRangeForSuggestionsOverride?: boolean;
filtersForSuggestions?: Filter[];
mode?: 'edit' | 'add';
}
@ -334,6 +335,7 @@ class FilterEditorComponent extends Component<FilterEditorProps, State> {
<FiltersBuilder
filters={[localFilter]}
timeRangeForSuggestionsOverride={this.props.timeRangeForSuggestionsOverride}
filtersForSuggestions={this.props.filtersForSuggestions}
dataView={selectedDataView!}
onChange={this.onLocalFilterChange}
disabled={!selectedDataView}

View file

@ -12,6 +12,7 @@ import { UI_SETTINGS } from '@kbn/data-plugin/common';
import { DataView, DataViewField } from '@kbn/data-views-plugin/common';
import { debounce } from 'lodash';
import { buildQueryFromFilters, Filter } from '@kbn/es-query';
import { IUnifiedSearchPluginServices } from '../../types';
export interface PhraseSuggestorProps {
@ -19,6 +20,7 @@ export interface PhraseSuggestorProps {
indexPattern: DataView;
field: DataViewField;
timeRangeForSuggestionsOverride?: boolean;
filtersForSuggestions?: Filter[];
}
export interface PhraseSuggestorState {
@ -73,7 +75,7 @@ export class PhraseSuggestorUI<T extends PhraseSuggestorProps> extends React.Com
protected updateSuggestions = debounce(async (query: string = '') => {
if (this.abortController) this.abortController.abort();
this.abortController = new AbortController();
const { indexPattern, field, timeRangeForSuggestionsOverride } = this
const { indexPattern, field, timeRangeForSuggestionsOverride, filtersForSuggestions } = this
.props as PhraseSuggestorProps;
if (!field || !this.isSuggestingValues()) {
return;
@ -85,6 +87,8 @@ export class PhraseSuggestorUI<T extends PhraseSuggestorProps> extends React.Com
query,
signal: this.abortController.signal,
useTimeRange: timeRangeForSuggestionsOverride,
boolFilter: buildQueryFromFilters(filtersForSuggestions, undefined).filter,
method: filtersForSuggestions?.length ? 'terms_agg' : 'terms_enum',
});
this.setState({ suggestions, isLoading: false });

View file

@ -56,6 +56,7 @@ export interface FilterItemProps extends WithCloseFilterEditorConfirmModalProps
uiSettings: IUiSettingsClient;
hiddenPanelOptions?: FilterPanelOption[];
timeRangeForSuggestionsOverride?: boolean;
filtersForSuggestions?: Filter[];
readOnly?: boolean;
}
@ -391,6 +392,7 @@ function FilterItemComponent(props: FilterItemProps) {
onLocalFilterCreate={onLocalFilterCreate}
onCancel={() => setIsPopoverOpen(false)}
timeRangeForSuggestionsOverride={props.timeRangeForSuggestionsOverride}
filtersForSuggestions={props.filtersForSuggestions}
/>
</div>,
]}

View file

@ -35,6 +35,8 @@ export interface FilterItemsProps {
intl: InjectedIntl;
/** Controls whether or not filter suggestions are influenced by the global time */
timeRangeForSuggestionsOverride?: boolean;
/** adds additional filters to be used for suggestions */
filtersForSuggestions?: Filter[];
/** Array of panel options that controls the styling of each filter pill */
hiddenPanelOptions?: FilterItemProps['hiddenPanelOptions'];
}
@ -74,6 +76,7 @@ const FilterItemsUI = React.memo(function FilterItemsUI(props: FilterItemsProps)
uiSettings={uiSettings!}
hiddenPanelOptions={props.hiddenPanelOptions}
timeRangeForSuggestionsOverride={props.timeRangeForSuggestionsOverride}
filtersForSuggestions={props.filtersForSuggestions}
readOnly={readOnly}
/>
</EuiFlexItem>

View file

@ -8,6 +8,7 @@
import React, { Dispatch } from 'react';
import type { DataView } from '@kbn/data-views-plugin/common';
import { Filter } from '@kbn/es-query';
import type { FiltersBuilderActions } from './reducer';
interface FiltersBuilderContextType {
@ -19,6 +20,7 @@ interface FiltersBuilderContextType {
};
dropTarget: string;
timeRangeForSuggestionsOverride?: boolean;
filtersForSuggestions?: Filter[];
disabled: boolean;
}

View file

@ -96,6 +96,7 @@ export function FilterItem({
dropTarget,
globalParams: { hideOr },
timeRangeForSuggestionsOverride,
filtersForSuggestions,
disabled,
} = useContext(FiltersBuilderContextType);
const conditionalOperationType = getBooleanRelationType(filter);
@ -309,6 +310,7 @@ export function FilterItem({
onHandleParamsChange={onHandleParamsChange}
onHandleParamsUpdate={onHandleParamsUpdate}
timeRangeForSuggestionsOverride={timeRangeForSuggestionsOverride}
filtersForSuggestions={filtersForSuggestions}
/>
</div>
</EuiFormRow>

View file

@ -21,6 +21,7 @@ interface ParamsEditorProps {
onHandleParamsChange: (params: Filter['meta']['params']) => void;
onHandleParamsUpdate: (value: string) => void;
timeRangeForSuggestionsOverride?: boolean;
filtersForSuggestions?: Filter[];
field?: DataViewField;
operator?: Operator;
}
@ -33,6 +34,7 @@ export function ParamsEditor({
onHandleParamsChange,
onHandleParamsUpdate,
timeRangeForSuggestionsOverride,
filtersForSuggestions,
}: ParamsEditorProps) {
const { disabled } = useContext(FiltersBuilderContextType);
const onParamsChange = useCallback(
@ -67,6 +69,7 @@ export function ParamsEditor({
onParamsChange={onParamsChange}
onParamsUpdate={onParamsUpdate}
timeRangeForSuggestionsOverride={timeRangeForSuggestionsOverride}
filtersForSuggestions={filtersForSuggestions}
/>
</EuiToolTip>
</EuiFormRow>

View file

@ -10,6 +10,7 @@ import React from 'react';
import { i18n } from '@kbn/i18n';
import { DataView, DataViewField } from '@kbn/data-views-plugin/common';
import { EuiFieldText } from '@elastic/eui';
import { Filter } from '@kbn/es-query';
import {
PhraseValueInput,
PhrasesValuesInput,
@ -35,6 +36,7 @@ interface ParamsEditorInputProps {
onParamsChange: (params: unknown) => void;
onParamsUpdate: (value: unknown) => void;
timeRangeForSuggestionsOverride?: boolean;
filtersForSuggestions?: Filter[];
field?: DataViewField;
operator?: Operator;
invalid: boolean;
@ -63,6 +65,7 @@ export function ParamsEditorInput({
onParamsChange,
onParamsUpdate,
timeRangeForSuggestionsOverride,
filtersForSuggestions,
}: ParamsEditorInputProps) {
switch (operator?.type) {
case 'exists':
@ -76,6 +79,7 @@ export function ParamsEditorInput({
value={params !== undefined ? `${params}` : undefined}
onChange={onParamsChange}
timeRangeForSuggestionsOverride={timeRangeForSuggestionsOverride}
filtersForSuggestions={filtersForSuggestions}
fullWidth
invalid={invalid}
disabled={disabled}
@ -91,6 +95,7 @@ export function ParamsEditorInput({
onChange={onParamsChange}
onParamsUpdate={onParamsUpdate}
timeRangeForSuggestionsOverride={timeRangeForSuggestionsOverride}
filtersForSuggestions={filtersForSuggestions}
fullWidth
disabled={disabled}
/>

View file

@ -22,6 +22,7 @@ export interface FiltersBuilderProps {
dataView: DataView;
onChange: (filters: Filter[]) => void;
timeRangeForSuggestionsOverride?: boolean;
filtersForSuggestions?: Filter[];
maxDepth?: number;
hideOr?: boolean;
disabled?: boolean;
@ -35,6 +36,7 @@ function FiltersBuilder({
dataView,
filters,
timeRangeForSuggestionsOverride,
filtersForSuggestions,
maxDepth = DEFAULT_MAX_DEPTH,
hideOr = false,
disabled = false,
@ -124,6 +126,7 @@ function FiltersBuilder({
dispatch,
dropTarget,
timeRangeForSuggestionsOverride,
filtersForSuggestions,
disabled,
}}
>

View file

@ -36,6 +36,7 @@ interface AddFilterPopoverProps extends WithCloseFilterEditorConfirmModalProps {
indexPatterns?: Array<DataView | string>;
filters: Filter[];
timeRangeForSuggestionsOverride?: boolean;
filtersForSuggestions?: Filter[];
onFiltersUpdated?: (filters: Filter[]) => void;
isDisabled?: boolean;
buttonProps?: Partial<EuiButtonIconProps>;
@ -45,6 +46,7 @@ const AddFilterPopoverComponent = React.memo(function AddFilterPopover({
indexPatterns,
filters,
timeRangeForSuggestionsOverride,
filtersForSuggestions,
onFiltersUpdated,
buttonProps,
isDisabled,
@ -96,6 +98,7 @@ const AddFilterPopoverComponent = React.memo(function AddFilterPopover({
indexPatterns={indexPatterns}
filters={filters}
timeRangeForSuggestionsOverride={timeRangeForSuggestionsOverride}
filtersForSuggestions={filtersForSuggestions}
onFiltersUpdated={onFiltersUpdated}
onLocalFilterUpdate={onLocalFilterUpdate}
onLocalFilterCreate={onLocalFilterCreate}

View file

@ -26,6 +26,7 @@ interface FilterEditorWrapperProps {
indexPatterns?: Array<DataView | string>;
filters: Filter[];
timeRangeForSuggestionsOverride?: boolean;
filtersForSuggestions?: Filter[];
closePopoverOnAdd?: () => void;
closePopoverOnCancel?: () => void;
onFiltersUpdated?: (filters: Filter[]) => void;
@ -37,6 +38,7 @@ export const FilterEditorWrapper = React.memo(function FilterEditorWrapper({
indexPatterns,
filters,
timeRangeForSuggestionsOverride,
filtersForSuggestions,
closePopoverOnAdd,
closePopoverOnCancel,
onFiltersUpdated,
@ -111,6 +113,7 @@ export const FilterEditorWrapper = React.memo(function FilterEditorWrapper({
onLocalFilterUpdate={onLocalFilterUpdate}
onLocalFilterCreate={onLocalFilterCreate}
timeRangeForSuggestionsOverride={timeRangeForSuggestionsOverride}
filtersForSuggestions={filtersForSuggestions}
/>
)}
</div>

View file

@ -59,6 +59,7 @@ export interface QueryBarMenuProps extends WithCloseFilterEditorConfirmModalProp
showFilterBar?: boolean;
showSaveQuery?: boolean;
timeRangeForSuggestionsOverride?: boolean;
filtersForSuggestions?: Filter[];
indexPatterns?: Array<DataView | string>;
buttonProps?: Partial<EuiButtonIconProps>;
isDisabled?: boolean;
@ -88,6 +89,7 @@ function QueryBarMenuComponent({
showSaveQuery,
indexPatterns,
timeRangeForSuggestionsOverride,
filtersForSuggestions,
buttonProps,
isDisabled,
onCloseFilterPopover,
@ -186,6 +188,7 @@ function QueryBarMenuComponent({
indexPatterns={indexPatterns}
filters={filters!}
timeRangeForSuggestionsOverride={timeRangeForSuggestionsOverride}
filtersForSuggestions={filtersForSuggestions}
onFiltersUpdated={onFiltersUpdated}
onLocalFilterUpdate={onLocalFilterUpdate}
onLocalFilterCreate={onLocalFilterCreate}

View file

@ -100,6 +100,7 @@ export interface QueryBarTopRowProps<QT extends Query | AggregateQuery = Query>
showAutoRefreshOnly?: boolean;
timeHistory?: TimeHistoryContract;
timeRangeForSuggestionsOverride?: boolean;
filtersForSuggestions?: Filter[];
filters: Filter[];
onFiltersUpdated?: (filters: Filter[]) => void;
dataViewPickerComponentProps?: DataViewPickerProps;
@ -501,6 +502,7 @@ export const QueryBarTopRow = React.memo(
indexPatterns={props.indexPatterns}
filters={props.filters}
timeRangeForSuggestionsOverride={props.timeRangeForSuggestionsOverride}
filtersForSuggestions={props.filtersForSuggestions}
onFiltersUpdated={props.onFiltersUpdated}
buttonProps={{ size: shouldShowDatePickerAsBadge() ? 's' : 'm', display: 'empty' }}
isDisabled={props.isDisabled}
@ -545,6 +547,7 @@ export const QueryBarTopRow = React.memo(
iconType={props.iconType}
nonKqlMode={props.nonKqlMode}
timeRangeForSuggestionsOverride={props.timeRangeForSuggestionsOverride}
filtersForSuggestions={props.filtersForSuggestions}
disableLanguageSwitcher={true}
prepend={renderFilterMenuOnly() && renderFilterButtonGroup()}
size={props.suggestionsSize}

View file

@ -36,6 +36,7 @@ import { getFieldSubtypeNested, KIBANA_USER_QUERY_LANGUAGE_KEY } from '@kbn/data
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
import type { IStorageWrapper } from '@kbn/kibana-utils-plugin/public';
import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
import { buildQueryFromFilters, Filter } from '@kbn/es-query';
import { matchPairs } from './match_pairs';
import { toUser } from './to_user';
import { fromUser } from './from_user';
@ -137,6 +138,11 @@ export interface QueryStringInputProps {
* Override whether autocomplete suggestions are restricted by time range.
*/
timeRangeForSuggestionsOverride?: boolean;
/**
* Add additional filters used for suggestions
*/
filtersForSuggestions?: Filter[];
}
interface State {
@ -279,6 +285,8 @@ export default class QueryStringInputUI extends PureComponent<QueryStringInputPr
selectionEnd,
signal: this.abortController.signal,
useTimeRange: this.props.timeRangeForSuggestionsOverride,
boolFilter: buildQueryFromFilters(this.props.filtersForSuggestions, undefined).filter,
method: this.props.filtersForSuggestions?.length ? 'terms_agg' : 'terms_enum',
})) || [];
return [...suggestions, ...recentSearchSuggestions];
} catch (e) {

View file

@ -236,6 +236,7 @@ export function createSearchBar({
displayStyle={props.displayStyle}
isScreenshotMode={isScreenshotMode}
dataTestSubj={props.dataTestSubj}
filtersForSuggestions={props.filtersForSuggestions}
/>
</core.i18n.Context>
</KibanaContextProvider>

View file

@ -54,6 +54,7 @@ export interface SearchBarOwnProps<QT extends AggregateQuery | Query = Query> {
showDatePicker?: boolean;
showAutoRefreshOnly?: boolean;
filters?: Filter[];
filtersForSuggestions?: Filter[];
hiddenFilterPanelOptions?: QueryBarMenuProps['hiddenPanelOptions'];
// Date picker
isRefreshPaused?: boolean;
@ -127,6 +128,7 @@ class SearchBarUI<QT extends (Query | AggregateQuery) | Query = Query> extends C
showDatePicker: true,
showSubmitButton: true,
showAutoRefreshOnly: false,
filtersForSuggestions: [],
};
private services = this.props.kibana.services;
@ -480,6 +482,7 @@ class SearchBarUI<QT extends (Query | AggregateQuery) | Query = Query> extends C
buttonProps={{ size: this.shouldShowDatePickerAsBadge() ? 's' : 'm' }}
indexPatterns={this.props.indexPatterns}
timeRangeForSuggestionsOverride={timeRangeForSuggestionsOverride}
filtersForSuggestions={this.props.filtersForSuggestions}
manageFilterSetComponent={
this.props.showFilterBar && this.state.query
? this.renderSavedQueryManagement(
@ -500,6 +503,7 @@ class SearchBarUI<QT extends (Query | AggregateQuery) | Query = Query> extends C
onFiltersUpdated={this.props.onFiltersUpdated}
indexPatterns={this.props.indexPatterns!}
timeRangeForSuggestionsOverride={timeRangeForSuggestionsOverride}
filtersForSuggestions={this.props.filtersForSuggestions}
hiddenPanelOptions={this.props.hiddenFilterPanelOptions}
readOnly={this.props.isDisabled}
/>
@ -510,6 +514,7 @@ class SearchBarUI<QT extends (Query | AggregateQuery) | Query = Query> extends C
onFiltersUpdated={this.props.onFiltersUpdated}
indexPatterns={this.props.indexPatterns!}
timeRangeForSuggestionsOverride={timeRangeForSuggestionsOverride}
filtersForSuggestions={this.props.filtersForSuggestions}
hiddenPanelOptions={this.props.hiddenFilterPanelOptions}
isDisabled={this.props.isDisabled}
data-test-subj="unifiedFilterBar"
@ -553,6 +558,7 @@ class SearchBarUI<QT extends (Query | AggregateQuery) | Query = Query> extends C
iconType={this.props.iconType}
nonKqlMode={this.props.nonKqlMode}
timeRangeForSuggestionsOverride={timeRangeForSuggestionsOverride}
filtersForSuggestions={this.props.filtersForSuggestions}
filters={this.props.filters!}
onFiltersUpdated={this.props.onFiltersUpdated}
dataViewPickerComponentProps={this.props.dataViewPickerComponentProps}