/* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0 and the Server Side Public License, v 1; you may not use this file except * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ import React, { useEffect, useState } from 'react'; import { v4 as uuidv4 } from 'uuid'; import { lastValueFrom } from 'rxjs'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { NavigationPublicPluginStart } from '@kbn/navigation-plugin/public'; import type { Filter, Query, TimeRange } from '@kbn/es-query'; import { ViewMode } from '@kbn/embeddable-plugin/public'; import { EuiCallOut, EuiLoadingSpinner, EuiPanel, EuiSpacer, EuiText, EuiTitle, } from '@elastic/eui'; import { AwaitingControlGroupAPI, ControlGroupRenderer } from '@kbn/controls-plugin/public'; import { PLUGIN_ID } from './constants'; interface Props { data: DataPublicPluginStart; dataView: DataView; navigation: NavigationPublicPluginStart; } export const SearchExample = ({ data, dataView, navigation }: Props) => { const [controlFilters, setControlFilters] = useState([]); const [controlGroupAPI, setControlGroupAPI] = useState(); const [hits, setHits] = useState(0); const [filters, setFilters] = useState([]); const [isSearching, setIsSearching] = useState(false); const [query, setQuery] = useState({ language: 'kuery', query: '', }); const [timeRange, setTimeRange] = useState({ from: 'now-7d', to: 'now' }); useEffect(() => { if (!controlGroupAPI) { return; } const subscription = controlGroupAPI.onFiltersPublished$.subscribe((newFilters) => { setControlFilters([...newFilters]); }); return () => { subscription.unsubscribe(); }; }, [controlGroupAPI]); useEffect(() => { const abortController = new AbortController(); const search = async () => { setIsSearching(true); const searchSource = await data.search.searchSource.create(); searchSource.setField('index', dataView); searchSource.setField('size', 0); searchSource.setField('filter', [ ...filters, ...controlFilters, data.query.timefilter.timefilter.createFilter(dataView, timeRange), ] as Filter[]); searchSource.setField('query', query); const { rawResponse: resp } = await lastValueFrom( searchSource.fetch$({ abortSignal: abortController.signal, sessionId: uuidv4(), legacyHitsTotal: false, }) ); const total = resp.hits?.total as undefined | { relation: string; value: number }; if (total !== undefined) { setHits(total.value); } setIsSearching(false); }; search().catch((error) => { setIsSearching(false); if (error.name === 'AbortError') { // ignore abort errors } else { // eslint-disable-next-line no-console console.error(error); } }); return () => { abortController.abort(); }; }, [controlFilters, data, dataView, filters, query, timeRange]); return ( <>

Search example

Pass filters, query, and time range to narrow controls. Combine search bar filters with controls filters to narrow results.

{ // filterManager.setFilters populates filter.meta so filter pill has pretty title data.query.filterManager.setFilters(newFilters); setFilters(newFilters); }} onQuerySubmit={({ dateRange, query: newQuery }) => { setQuery(newQuery); setTimeRange(dateRange); }} query={query} showSearchBar={true} /> { await builder.addDataControlFromField(initialInput, { dataViewId: dataView.id!, title: 'Destintion country', fieldName: 'geo.dest', width: 'medium', grow: false, }); await builder.addDataControlFromField(initialInput, { dataViewId: dataView.id!, fieldName: 'bytes', width: 'medium', grow: true, title: 'Bytes', }); return { initialInput: { ...initialInput, viewMode: ViewMode.VIEW, }, }; }} query={query} ref={setControlGroupAPI} timeRange={timeRange} /> {isSearching ? :

Hits: {hits}

}
); };