diff --git a/x-pack/plugins/ml/public/application/components/data_grid/common.ts b/x-pack/plugins/ml/public/application/components/data_grid/common.ts index 7d0559c215114..33fc3516d5f3f 100644 --- a/x-pack/plugins/ml/public/application/components/data_grid/common.ts +++ b/x-pack/plugins/ml/public/application/components/data_grid/common.ts @@ -102,6 +102,8 @@ export const getDataGridSchemasFromFieldTypes = (fieldTypes: FieldTypes, results case 'boolean': schema = 'boolean'; break; + case 'text': + schema = NON_AGGREGATABLE; } if ( @@ -122,7 +124,10 @@ export const getDataGridSchemasFromFieldTypes = (fieldTypes: FieldTypes, results }); }; -export const getDataGridSchemaFromKibanaFieldType = (field: IFieldType | undefined) => { +export const NON_AGGREGATABLE = 'non-aggregatable'; +export const getDataGridSchemaFromKibanaFieldType = ( + field: IFieldType | undefined +): string | undefined => { // Built-in values are ['boolean', 'currency', 'datetime', 'numeric', 'json'] // To fall back to the default string schema it needs to be undefined. let schema; @@ -143,6 +148,10 @@ export const getDataGridSchemaFromKibanaFieldType = (field: IFieldType | undefin break; } + if (schema === undefined && field?.aggregatable === false) { + return NON_AGGREGATABLE; + } + return schema; }; diff --git a/x-pack/plugins/ml/public/application/components/data_grid/use_column_chart.ts b/x-pack/plugins/ml/public/application/components/data_grid/use_column_chart.ts index 31f0168a948bc..1a1a51edcc45e 100644 --- a/x-pack/plugins/ml/public/application/components/data_grid/use_column_chart.ts +++ b/x-pack/plugins/ml/public/application/components/data_grid/use_column_chart.ts @@ -13,6 +13,8 @@ import { euiPaletteColorBlind, EuiDataGridColumn } from '@elastic/eui'; import { KBN_FIELD_TYPES } from '../../../../../../../src/plugins/data/public'; +import { NON_AGGREGATABLE } from './common'; + export const hoveredRow$ = new BehaviorSubject(null); const BAR_COLOR = euiPaletteColorBlind()[0]; @@ -34,7 +36,11 @@ const getXScaleType = ( } }; -const getFieldType = (schema: EuiDataGridColumn['schema']) => { +const getFieldType = (schema: EuiDataGridColumn['schema']): KBN_FIELD_TYPES | undefined => { + if (schema === NON_AGGREGATABLE) { + return undefined; + } + let fieldType: KBN_FIELD_TYPES; switch (schema) { @@ -190,7 +196,7 @@ export const fetchChartData = async ( data: await fetchChartTermsData(), id: columnType.id, } as OrdinalChartData; - } else if (fieldType === KBN_FIELD_TYPES.OBJECT) { + } else if (fieldType === KBN_FIELD_TYPES.OBJECT || fieldType === undefined) { return { cardinality: 0, data: [], @@ -248,6 +254,10 @@ export const useColumnChart = (chartData: ChartData, columnType: EuiDataGridColu const hoveredRow = useObservable(hoveredRow$); + if (fieldType === undefined) { + throw new Error('Invalid fieldType'); + } + const xScaleType = getXScaleType(fieldType); const getColor = (d: ChartDataItem) => { diff --git a/x-pack/plugins/ml/public/application/components/data_grid/use_column_charts.tsx b/x-pack/plugins/ml/public/application/components/data_grid/use_column_charts.tsx index 802195f50a3cf..56df1a592f228 100644 --- a/x-pack/plugins/ml/public/application/components/data_grid/use_column_charts.tsx +++ b/x-pack/plugins/ml/public/application/components/data_grid/use_column_charts.tsx @@ -74,7 +74,7 @@ export function useColumnCharts( )}`} style={{ width: `${columnWidth}px` }} > - {!d.isExpandable && chartData !== undefined && ( + {chartData !== undefined && chartData.data.length > 0 && ( )} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts index e8f25584201e3..3bd48739e89e3 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts @@ -6,12 +6,16 @@ import { useEffect } from 'react'; +import { EuiDataGridColumn } from '@elastic/eui'; + import { IndexPattern } from '../../../../../../../../../src/plugins/data/public'; import { + fetchChartData, getDataGridSchemaFromKibanaFieldType, getFieldsFromKibanaIndexPattern, useDataGrid, useRenderCellValue, + ChartData, EsSorting, SearchResponse7, UseIndexDataReturnType, @@ -26,11 +30,11 @@ export const useIndexData = (indexPattern: IndexPattern, query: any): UseIndexDa const indexPatternFields = getFieldsFromKibanaIndexPattern(indexPattern); // EuiDataGrid State - const columns = [ + const columns: EuiDataGridColumn[] = [ ...indexPatternFields.map((id) => { const field = indexPattern.fields.getByName(id); const schema = getDataGridSchemaFromKibanaFieldType(field); - return { id, schema }; + return { id, schema, isExpandable: schema !== 'boolean' }; }), ]; @@ -93,6 +97,32 @@ export const useIndexData = (indexPattern: IndexPattern, query: any): UseIndexDa // eslint-disable-next-line react-hooks/exhaustive-deps }, [indexPattern.title, JSON.stringify([query, pagination, sortingColumns])]); + const fetchColumnChartsData = async function () { + const fetchers = dataGrid.visibleColumns.map((vc) => { + const columnType = columns.find((c) => c.id === vc); + + if (columnType === undefined) { + return Promise.resolve(undefined); + } + return fetchChartData(indexPattern.title, ml, query, columnType); + }); + + const data = (await Promise.all(fetchers)) as ChartData[]; + dataGrid.setColumnCharts(data.filter((d) => d !== undefined)); + }; + + useEffect(() => { + if (dataGrid.chartsVisible) { + fetchColumnChartsData(); + } + // custom comparison + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ + dataGrid.chartsVisible, + indexPattern.title, + JSON.stringify([query, dataGrid.visibleColumns]), + ]); + const renderCellValue = useRenderCellValue(indexPattern, pagination, tableItems); return { diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts index b8b5a16c84e85..9b7027da60fe8 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts @@ -11,12 +11,15 @@ import { EuiDataGridColumn } from '@elastic/eui'; import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public'; import { + fetchChartData, getDataGridSchemasFromFieldTypes, useDataGrid, useRenderCellValue, + ChartData, UseIndexDataReturnType, } from '../../../../../components/data_grid'; import { SavedSearchQuery } from '../../../../../contexts/ml'; +import { ml } from '../../../../../services/ml_api_service'; import { getIndexData, getIndexFields, DataFrameAnalyticsConfig } from '../../../../common'; import { @@ -66,6 +69,28 @@ export const useExplorationResults = ( // eslint-disable-next-line react-hooks/exhaustive-deps }, [jobConfig && jobConfig.id, dataGrid.pagination, searchQuery, dataGrid.sortingColumns]); + const fetchColumnChartsData = async function () { + const fetchers = dataGrid.visibleColumns.map((vc) => { + const columnType = columns.find((c) => c.id === vc); + + if (columnType === undefined || jobConfig === undefined) { + return Promise.resolve(undefined); + } + return fetchChartData(jobConfig.dest.index, ml, { match_all: {} }, columnType); + }); + + const data = (await Promise.all(fetchers)) as ChartData[]; + dataGrid.setColumnCharts(data.filter((d) => d !== undefined)); + }; + + useEffect(() => { + if (dataGrid.chartsVisible) { + fetchColumnChartsData(); + } + // custom comparison + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [dataGrid.chartsVisible, jobConfig?.dest.index, JSON.stringify([dataGrid.visibleColumns])]); + const renderCellValue = useRenderCellValue( indexPattern, dataGrid.pagination, diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts index ebac6ccb2298e..2fa74aa7bf22f 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts @@ -16,12 +16,15 @@ import { COLOR_RANGE_SCALE, } from '../../../../../components/color_range_legend'; import { + fetchChartData, getDataGridSchemasFromFieldTypes, useDataGrid, useRenderCellValue, + ChartData, UseIndexDataReturnType, } from '../../../../../components/data_grid'; import { SavedSearchQuery } from '../../../../../contexts/ml'; +import { ml } from '../../../../../services/ml_api_service'; import { getIndexData, getIndexFields, DataFrameAnalyticsConfig } from '../../../../common'; import { DEFAULT_RESULTS_FIELD, FEATURE_INFLUENCE } from '../../../../common/constants'; @@ -75,6 +78,28 @@ export const useOutlierData = ( // eslint-disable-next-line react-hooks/exhaustive-deps }, [jobConfig && jobConfig.id, dataGrid.pagination, searchQuery, dataGrid.sortingColumns]); + const fetchColumnChartsData = async function () { + const fetchers = dataGrid.visibleColumns.map((vc) => { + const columnType = columns.find((c) => c.id === vc); + + if (columnType === undefined || jobConfig === undefined) { + return Promise.resolve(undefined); + } + return fetchChartData(jobConfig.dest.index, ml, { match_all: {} }, columnType); + }); + + const data = (await Promise.all(fetchers)) as ChartData[]; + dataGrid.setColumnCharts(data.filter((d) => d !== undefined)); + }; + + useEffect(() => { + if (dataGrid.chartsVisible) { + fetchColumnChartsData(); + } + // custom comparison + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [dataGrid.chartsVisible, jobConfig?.dest.index, JSON.stringify([dataGrid.visibleColumns])]); + const colorRange = useColorRange( COLOR_RANGE.BLUE, COLOR_RANGE_SCALE.INFLUENCER,