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

[Textbased languages] Render Lens suggestions in Discover #151581

Merged
merged 61 commits into from
Mar 27, 2023
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
de1ff64
Export lens suggestions
stratoula Feb 20, 2023
00cb8b8
Display Lens suggestion in Discover
stratoula Feb 20, 2023
bffa8ac
fix checks
stratoula Feb 20, 2023
234f0df
Fix translations
stratoula Feb 20, 2023
30298e7
Fix jest tests
stratoula Feb 20, 2023
be41a2a
Update jest tests
stratoula Feb 20, 2023
8fb6c45
Fix functional tests
stratoula Feb 21, 2023
40f338d
Fix metric dimensions
stratoula Feb 21, 2023
65a1e4d
Add suggestions selector
stratoula Feb 21, 2023
315fa50
Merge branch 'main' into textbased-discover-lens
stratoula Feb 21, 2023
f184264
Fix functional test
stratoula Feb 21, 2023
6f4b9b2
Fixes suggestions problem
stratoula Feb 21, 2023
42089ae
backup of results
stratoula Feb 22, 2023
ec81464
Add number of results
stratoula Feb 23, 2023
33779f5
Use the enum for the textBased status
stratoula Feb 23, 2023
2c5ec62
Change the implementation for hits
stratoula Feb 23, 2023
08030da
Fix FTs
stratoula Feb 23, 2023
32869b8
Fix FT test
stratoula Feb 23, 2023
6f68bb1
Display the chart icon on the dropdown
stratoula Feb 23, 2023
d41e767
Fix Lens FT
stratoula Feb 23, 2023
ab9020c
Merge branch 'main' into textbased-discover-lens
stratoula Feb 23, 2023
5c25035
Add unit tests
stratoula Feb 24, 2023
de2a97d
Add Lens unit tests
stratoula Feb 24, 2023
7c7cf8e
Merge branch 'main' into textbased-discover-lens
stratoula Feb 28, 2023
03bd2a7
Add jest test for chart
stratoula Feb 28, 2023
d3916f0
Adds more unit tests
stratoula Feb 28, 2023
201f5af
Write some FTs
stratoula Mar 1, 2023
747670e
Fix a bug on the dropdown
stratoula Mar 1, 2023
55f75c5
Merge branch 'main' into textbased-discover-lens
stratoula Mar 1, 2023
226cf5b
Merge branch 'main' into textbased-discover-lens
stratoula Mar 6, 2023
c9cb194
Jest test refactor
stratoula Mar 7, 2023
4e91bb3
Fetch is PlainRecord from the discover layout
stratoula Mar 7, 2023
a7732f5
Further fixes
stratoula Mar 7, 2023
82919cd
Remove unecessary code
stratoula Mar 7, 2023
59fc4b6
Merge branch 'main' into textbased-discover-lens
stratoula Mar 7, 2023
483698c
Clearing the suggestion combobox will default to the activeSuggestion
stratoula Mar 8, 2023
ff9de56
Fix bug with selected fields
stratoula Mar 8, 2023
793121a
Fix rotating number title
stratoula Mar 8, 2023
a5ab5ed
Merge branch 'main' into textbased-discover-lens
stratoula Mar 9, 2023
83c4c74
Apply PR comments
stratoula Mar 10, 2023
2e3c7b0
Merge with main and resolve conflicts
stratoula Mar 21, 2023
886475b
Merge branch 'main' into textbased-discover-lens
stratoula Mar 23, 2023
d0d2175
Merge branch 'main' into textbased-discover-lens
stratoula Mar 24, 2023
951eb39
Merge branch 'main' into textbased-discover-lens
davismcphee Mar 24, 2023
f510e8c
Make text based total hits state internal to Unified Histogram
davismcphee Mar 7, 2023
15b8f8b
Revert changes to use_lens_props to respect refetch$
davismcphee Mar 7, 2023
df9b6a7
Add total hits support for text based queries to Unified Histogram
davismcphee Mar 8, 2023
d72d016
Add auto refetch support for currentSuggestion
davismcphee Mar 8, 2023
2778344
Move Lens suggestions out of the state container and into the main Un…
davismcphee Mar 8, 2023
ef2d9c5
Refetch when current suggestion is changed
davismcphee Mar 9, 2023
a18cd30
Add columns comment
davismcphee Mar 22, 2023
3588bd5
Show horizontal rule above table in text based mode
davismcphee Mar 22, 2023
3bdb2eb
Fix issues with text based total hits behaviour, and update how text …
davismcphee Mar 22, 2023
89ea7b9
Manage extra Unified Histogram refetches when using text based languages
davismcphee Mar 24, 2023
c7ec599
Fix Jest tests
davismcphee Mar 24, 2023
59fde5b
Merge pull request #25 from davismcphee/textbased-discover-lens-cleanup
stratoula Mar 24, 2023
4fef6cb
Merge branch 'main' into textbased-discover-lens
stratoula Mar 27, 2023
7603649
Apply PR comments
stratoula Mar 27, 2023
344530a
Fix jest tests
stratoula Mar 27, 2023
8bf34d4
Nit
stratoula Mar 27, 2023
32e212b
Revert
stratoula Mar 27, 2023
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
1 change: 1 addition & 0 deletions src/plugins/discover/public/__mocks__/data_view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export const buildDataViewMock = ({
getFormatterForField: jest.fn(() => ({ convert: (value: unknown) => value })),
isTimeNanosBased: () => false,
isPersisted: () => true,
toSpec: () => ({}),
getTimeField: () => {
return dataViewFields.find((field) => field.name === timeFieldName);
},
Expand Down
9 changes: 8 additions & 1 deletion src/plugins/discover/public/__mocks__/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,14 @@ export function createDiscoverServicesMock(): DiscoverServices {
savedObjectsTagging: {},
dataViews: dataPlugin.dataViews,
timefilter: dataPlugin.query.timefilter.timefilter,
lens: { EmbeddableComponent: jest.fn(() => null) },
lens: {
EmbeddableComponent: jest.fn(() => null),
stateHelperApi: jest.fn(() => {
return {
suggestionsApi: jest.fn(),
};
}),
},
locator: {
useUrl: jest.fn(() => ''),
navigate: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const DiscoverHistogramLayout = ({
inspectorAdapters,
savedSearchFetch$: stateContainer.dataState.fetch$,
searchSessionId,
isPlainRecord,
...commonProps,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import React, { ReactElement } from 'react';
import { AggregateQuery, Query } from '@kbn/es-query';
import { buildDataTableRecord } from '../../../../utils/build_data_record';
import { esHits } from '../../../../__mocks__/es_hits';
import { act, renderHook, WrapperComponent } from '@testing-library/react-hooks';
Expand Down Expand Up @@ -38,11 +39,11 @@ import { checkHitCount, sendErrorTo } from '../../hooks/use_saved_search_message
import type { InspectorAdapters } from '../../hooks/use_inspector';

const mockData = dataPluginMock.createStartContract();
const mockQueryState = {
let mockQueryState = {
query: {
query: 'query',
language: 'kuery',
},
} as Query | AggregateQuery,
filters: [],
time: {
from: 'now-15m',
Expand Down Expand Up @@ -112,19 +113,21 @@ describe('useDiscoverHistogram', () => {
foundDocuments: true,
}) as DataMain$,
savedSearchFetch$ = new Subject() as DataFetch$,
documents$ = new BehaviorSubject({
fetchStatus: FetchStatus.COMPLETE,
result: esHits.map((esHit) => buildDataTableRecord(esHit, dataViewWithTimefieldMock)),
}) as DataDocuments$,
isPlainRecord = false,
}: {
stateContainer?: DiscoverStateContainer;
searchSessionId?: string;
inspectorAdapters?: InspectorAdapters;
totalHits$?: DataTotalHits$;
main$?: DataMain$;
savedSearchFetch$?: DataFetch$;
documents$?: DataDocuments$;
isPlainRecord?: boolean;
} = {}) => {
const documents$ = new BehaviorSubject({
fetchStatus: FetchStatus.COMPLETE,
result: esHits.map((esHit) => buildDataTableRecord(esHit, dataViewWithTimefieldMock)),
}) as DataDocuments$;

const availableFields$ = new BehaviorSubject({
fetchStatus: FetchStatus.COMPLETE,
fields: [] as string[],
Expand All @@ -144,6 +147,7 @@ describe('useDiscoverHistogram', () => {
dataView: dataViewWithTimefieldMock,
inspectorAdapters,
searchSessionId,
isPlainRecord,
};

const Wrapper: WrapperComponent<UseDiscoverHistogramProps> = ({ children }) => (
Expand Down Expand Up @@ -186,6 +190,7 @@ describe('useDiscoverHistogram', () => {
'timeRange',
'chartHidden',
'timeInterval',
'columns',
'breakdownField',
'searchSessionId',
'totalHitsStatus',
Expand All @@ -196,6 +201,9 @@ describe('useDiscoverHistogram', () => {
});

describe('state', () => {
beforeEach(() => {
mockCheckHitCount.mockClear();
});
it('should subscribe to state changes', async () => {
const { hook } = await renderUseDiscoverHistogram();
const api = createMockUnifiedHistogramApi({ initialized: true });
Expand Down Expand Up @@ -347,7 +355,6 @@ describe('useDiscoverHistogram', () => {
});

it('should update total hits when the total hits state changes', async () => {
mockCheckHitCount.mockClear();
const totalHits$ = new BehaviorSubject({
fetchStatus: FetchStatus.LOADING,
result: undefined,
Expand Down Expand Up @@ -383,8 +390,66 @@ describe('useDiscoverHistogram', () => {
expect(mockCheckHitCount).toHaveBeenCalledWith(main$, 100);
});

it('should fetch total hits for text based', async () => {
mockQueryState = {
query: { sql: 'select * from index' },
filters: [],
time: {
from: 'now-15m',
to: 'now',
},
};

mockData.query.getState = () => mockQueryState;
const documents$ = new BehaviorSubject({
fetchStatus: FetchStatus.COMPLETE,
result: [{ raw: {}, flattened: {}, id: '1' }],
}) as unknown as DataDocuments$;
const main$ = new BehaviorSubject({
fetchStatus: FetchStatus.COMPLETE,
recordRawType: RecordRawType.DOCUMENT,
foundDocuments: true,
}) as DataMain$;
const stateContainer = getStateContainer();
const { hook } = await renderUseDiscoverHistogram({
stateContainer,
documents$,
main$,
isPlainRecord: true,
});
const api = createMockUnifiedHistogramApi({ initialized: true });
let params: Partial<UnifiedHistogramState> = {};
api.setTotalHits = jest.fn((p) => {
params = { ...params, ...p };
});
act(() => {
hook.result.current.setUnifiedHistogramApi(api);
});
expect(api.setTotalHits).toHaveBeenCalledWith({
totalHitsResult: 1,
totalHitsStatus: FetchStatus.COMPLETE,
});
expect(documents$.value).toEqual({
fetchStatus: FetchStatus.COMPLETE,
result: [{ raw: {}, flattened: {}, id: '1' }],
});
expect(mockCheckHitCount).not.toHaveBeenCalled();
});

it('should not update total hits when the total hits state changes to an error', async () => {
mockCheckHitCount.mockClear();
mockQueryState = {
stratoula marked this conversation as resolved.
Show resolved Hide resolved
query: {
query: 'query',
language: 'kuery',
} as Query | AggregateQuery,
filters: [],
time: {
from: 'now-15m',
to: 'now',
},
};

mockData.query.getState = () => mockQueryState;
const totalHits$ = new BehaviorSubject({
fetchStatus: FetchStatus.UNINITIALIZED,
result: undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
UnifiedHistogramState,
} from '@kbn/unified-histogram-plugin/public';
import { isEqual } from 'lodash';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { AggregateQuery, Query, isOfAggregateQueryType } from '@kbn/es-query';
import { useCallback, useEffect, useRef, useState } from 'react';
import { distinctUntilChanged, map, Observable } from 'rxjs';
import { useDiscoverServices } from '../../../../hooks/use_discover_services';
import { getUiActions } from '../../../../kibana_services';
Expand All @@ -34,6 +35,7 @@ export interface UseDiscoverHistogramProps {
inspectorAdapters: InspectorAdapters;
savedSearchFetch$: DataFetch$;
searchSessionId: string | undefined;
isPlainRecord: boolean;
}

export const useDiscoverHistogram = ({
Expand All @@ -43,6 +45,7 @@ export const useDiscoverHistogram = ({
inspectorAdapters,
savedSearchFetch$,
searchSessionId,
isPlainRecord,
}: UseDiscoverHistogramProps) => {
const services = useDiscoverServices();
const timefilter = services.data.query.timefilter.timefilter;
Expand All @@ -52,6 +55,12 @@ export const useDiscoverHistogram = ({
*/

const [unifiedHistogram, setUnifiedHistogram] = useState<UnifiedHistogramInitializedApi>();
const prev = useRef<{ query: AggregateQuery | Query | undefined; columns: string[] | undefined }>(
{
columns: [],
query: undefined,
}
);

const setUnifiedHistogramApi = useCallback(
(api: UnifiedHistogramApi | null) => {
Expand All @@ -66,12 +75,15 @@ export const useDiscoverHistogram = ({
hideChart: chartHidden,
interval: timeInterval,
breakdownField,
columns,
} = stateContainer.appState.getState();

const { fetchStatus: totalHitsStatus, result: totalHitsResult } =
savedSearchData$.totalHits$.getValue();

const { query, filters, time: timeRange } = services.data.query.getState();
prev.current.query = query;
prev.current.columns = columns;

api.initialize({
services: { ...services, uiActions: getUiActions() },
Expand All @@ -85,6 +97,7 @@ export const useDiscoverHistogram = ({
timeRange,
chartHidden,
timeInterval,
columns,
breakdownField,
searchSessionId,
totalHitsStatus: totalHitsStatus.toString() as UnifiedHistogramFetchStatus,
Expand Down Expand Up @@ -134,18 +147,8 @@ export const useDiscoverHistogram = ({
/**
* Update Unified Histgoram request params
*/

const {
query,
filters,
fromDate: from,
toDate: to,
} = useQuerySubscriber({ data: services.data });

const timeRange = useMemo(
() => (from && to ? { from, to } : timefilter.getTimeDefaults()),
[timefilter, from, to]
);
const { query, filters } = useQuerySubscriber({ data: services.data });
const timeRange = timefilter.getAbsoluteTime();

useEffect(() => {
unifiedHistogram?.setRequestParams({
Expand Down Expand Up @@ -180,13 +183,13 @@ export const useDiscoverHistogram = ({
// We only want to show the partial results on the first load,
// or there will be a flickering effect as the loading spinner
// is quickly shown and hidden again on fetches
if (!firstLoadComplete.current) {
if (!firstLoadComplete.current && !isPlainRecord) {
unifiedHistogram?.setTotalHits({
totalHitsStatus: totalHitsStatus.toString() as UnifiedHistogramFetchStatus,
totalHitsResult,
});
}
}, [totalHitsResult, totalHitsStatus, unifiedHistogram]);
}, [isPlainRecord, totalHitsResult, totalHitsStatus, unifiedHistogram]);

/**
* Sync URL query params with Unified Histogram
Expand Down Expand Up @@ -214,6 +217,35 @@ export const useDiscoverHistogram = ({
unifiedHistogram?.setBreakdownField(breakdownField);
}, [breakdownField, unifiedHistogram]);

const columns = useAppStateSelector((state) => state.columns);
const documentState = useDataState(savedSearchData$.documents$);

useEffect(() => {
const currentQueryIsTextBased = query && isOfAggregateQueryType(query);
const initialQueryIsTextBased =
prev.current.query && isOfAggregateQueryType(prev.current.query);
// Update the columns only when the query changes
stratoula marked this conversation as resolved.
Show resolved Hide resolved
if (!isEqual(columns, prev.current.columns) && !isEqual(query, prev.current.query)) {
// transitioning from dataview mode to text based mode should set the columns to []
if (currentQueryIsTextBased && !initialQueryIsTextBased) {
unifiedHistogram?.setColumns([]);
} else {
unifiedHistogram?.setColumns(columns);
}
prev.current.query = query;
prev.current.columns = columns;
}
}, [columns, query, unifiedHistogram]);

useEffect(() => {
davismcphee marked this conversation as resolved.
Show resolved Hide resolved
if (isPlainRecord) {
unifiedHistogram?.setTotalHits({
totalHitsResult: documentState.result?.length,
totalHitsStatus: documentState.fetchStatus.toString() as UnifiedHistogramFetchStatus,
});
}
}, [documentState.fetchStatus, documentState.result, isPlainRecord, unifiedHistogram]);

/**
* Total hits
*/
Expand All @@ -227,6 +259,10 @@ export const useDiscoverHistogram = ({
return;
}

if (isPlainRecord) {
return;
}

const { recordRawType } = savedSearchData$.totalHits$.getValue();

// Sync the totalHits$ observable with the unified histogram state
Expand All @@ -252,7 +288,13 @@ export const useDiscoverHistogram = ({
return () => {
subscription?.unsubscribe();
};
}, [savedSearchData$.main$, savedSearchData$.totalHits$, services.data, unifiedHistogram]);
}, [
isPlainRecord,
savedSearchData$.main$,
savedSearchData$.totalHits$,
services.data,
unifiedHistogram,
]);

/**
* Data fetching
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,12 +262,4 @@ describe('discover sidebar', function () {
const createDataViewButton = findTestSubject(compWithPickerInViewerMode, 'dataview-create-new');
expect(createDataViewButton.length).toBe(0);
});

it('should render the Visualize in Lens button in text based languages mode', async () => {
const compInViewerMode = await mountComponent(getCompProps(), {
query: { sql: 'SELECT * FROM test' },
});
const visualizeField = findTestSubject(compInViewerMode, 'textBased-visualize');
expect(visualizeField.length).toBe(1);
});
});
Loading