From d06310dab0b8ad42b03996cb70125e23b4486e4a Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Wed, 22 Apr 2020 10:09:55 +0200 Subject: [PATCH] [ML] ExplorationResultsPage. --- .../data_frame_analytics/common/fields.ts | 8 +- .../classification_exploration.tsx | 2 - .../exploration_page_wrapper.tsx | 23 +-- .../exploration_page_wrapper/index.ts | 2 +- .../exploration_results_table.tsx} | 6 +- .../exploration_results_table/index.ts | 7 + .../use_exploration_results.ts} | 6 +- .../regression_exploration.tsx | 2 - .../regression_exploration/results_table.tsx | 169 ------------------ .../use_regression_data.ts | 72 -------- 10 files changed, 31 insertions(+), 266 deletions(-) rename x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/{classification_exploration/results_table.tsx => exploration_results_table/exploration_results_table.tsx} (97%) create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/index.ts rename x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/{classification_exploration/use_classification_data.ts => exploration_results_table/use_exploration_results.ts} (92%) delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/results_table.tsx delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/use_regression_data.ts diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts index 55fa6267e407d..f03ae61482a40 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts @@ -112,7 +112,7 @@ export const sortColumns = (obj: EsDocSource, resultsField: string) => (a: strin return a.localeCompare(b); }; -export const sortRegressionResultsFields = ( +export const sortExplorationResultsFields = ( a: string, b: string, jobConfig: DataFrameAnalyticsConfig @@ -298,7 +298,7 @@ export const getDefaultFieldsFromJobCaps = ( allFields.push(...fields, ...featureImportanceFields); allFields.sort(({ name: a }: { name: string }, { name: b }: { name: string }) => - sortRegressionResultsFields(a, b, jobConfig) + sortExplorationResultsFields(a, b, jobConfig) ); let selectedFields = allFields.filter( @@ -349,7 +349,7 @@ export const getDefaultClassificationFields = ( return docs.some(row => row._source[k] !== null); }) - .sort((a, b) => sortRegressionResultsFields(a, b, jobConfig)) + .sort((a, b) => sortExplorationResultsFields(a, b, jobConfig)) .slice(0, DEFAULT_REGRESSION_COLUMNS); }; @@ -382,7 +382,7 @@ export const getDefaultRegressionFields = ( return docs.some(row => row._source[k] !== null); }) - .sort((a, b) => sortRegressionResultsFields(a, b, jobConfig)) + .sort((a, b) => sortExplorationResultsFields(a, b, jobConfig)) .slice(0, DEFAULT_REGRESSION_COLUMNS); }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/classification_exploration.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/classification_exploration.tsx index c3c1bdf05ec48..ccac9a697210b 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/classification_exploration.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/classification_exploration.tsx @@ -11,7 +11,6 @@ import { i18n } from '@kbn/i18n'; import { ExplorationPageWrapper } from '../exploration_page_wrapper'; import { EvaluatePanel } from './evaluate_panel'; -import { ResultsTable } from './results_table'; interface Props { jobId: string; @@ -29,7 +28,6 @@ export const ClassificationExploration: FC = ({ jobId }) => { } )} EvaluatePanel={EvaluatePanel} - ResultsTable={ResultsTable} /> ); }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_page_wrapper/exploration_page_wrapper.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_page_wrapper/exploration_page_wrapper.tsx index 0d6ddc99db400..1986c486974c9 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_page_wrapper/exploration_page_wrapper.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_page_wrapper/exploration_page_wrapper.tsx @@ -8,25 +8,28 @@ import React, { FC, useState } from 'react'; import { EuiSpacer } from '@elastic/eui'; -import { useResultsViewConfig } from '../../../../common'; +import { useResultsViewConfig, DataFrameAnalyticsConfig } from '../../../../common'; import { ResultsSearchQuery, defaultSearchQuery } from '../../../../common/analytics'; +import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common'; + +import { ExplorationResultsTable } from '../exploration_results_table'; import { JobConfigErrorCallout } from '../job_config_error_callout'; import { LoadingPanel } from '../loading_panel'; +export interface EvaluatePanelProps { + jobConfig: DataFrameAnalyticsConfig; + jobStatus?: DATA_FRAME_TASK_STATE; + searchQuery: ResultsSearchQuery; +} + interface Props { jobId: string; title: string; - EvaluatePanel: any; - ResultsTable: any; + EvaluatePanel: FC; } -export const ExplorationPageWrapper: FC = ({ - jobId, - title, - EvaluatePanel, - ResultsTable, -}) => { +export const ExplorationPageWrapper: FC = ({ jobId, title, EvaluatePanel }) => { const { indexPattern, isInitialized, @@ -60,7 +63,7 @@ export const ExplorationPageWrapper: FC = ({ jobConfig !== undefined && indexPattern !== undefined && isInitialized === true && ( - = React.memo( +export const ExplorationResultsTable: FC = React.memo( ({ indexPattern, jobConfig, jobStatus, setEvaluateSearchQuery, title }) => { const [searchQuery, setSearchQuery] = useState(defaultSearchQuery); @@ -67,7 +67,7 @@ export const ResultsTable: FC = React.memo( setEvaluateSearchQuery(searchQuery); }, [JSON.stringify(searchQuery)]); - const classificationData = useClassificationData(indexPattern, jobConfig, searchQuery); + const classificationData = useExplorationResults(indexPattern, jobConfig, searchQuery); const docFieldsCount = classificationData.columns.length; const { columns, errorMessage, status, tableItems, visibleColumns } = classificationData; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/index.ts new file mode 100644 index 0000000000000..19308640c8b02 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { ExplorationResultsTable } from './exploration_results_table'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/use_classification_data.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts similarity index 92% rename from x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/use_classification_data.ts rename to x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts index 339b672861847..0850e5298d74e 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/use_classification_data.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts @@ -19,11 +19,11 @@ import { import { SavedSearchQuery } from '../../../../../contexts/ml'; import { getIndexData, getIndexFields, DataFrameAnalyticsConfig } from '../../../../common'; -import { sortRegressionResultsFields } from '../../../../common/fields'; +import { sortExplorationResultsFields } from '../../../../common/fields'; const FEATURE_IMPORTANCE = 'feature_importance'; -export const useClassificationData = ( +export const useExplorationResults = ( indexPattern: IndexPattern | undefined, jobConfig: DataFrameAnalyticsConfig | undefined, searchQuery: SavedSearchQuery @@ -38,7 +38,7 @@ export const useClassificationData = ( const { fieldTypes } = getIndexFields(jobConfig, needsDestIndexFields); columns.push( ...getDataGridSchemasFromFieldTypes(fieldTypes, resultsField).sort((a: any, b: any) => - sortRegressionResultsFields(a.id, b.id, jobConfig) + sortExplorationResultsFields(a.id, b.id, jobConfig) ) ); } diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/regression_exploration.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/regression_exploration.tsx index 59db5e1eb583f..36d91f6f41d44 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/regression_exploration.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/regression_exploration.tsx @@ -11,7 +11,6 @@ import { i18n } from '@kbn/i18n'; import { ExplorationPageWrapper } from '../exploration_page_wrapper'; import { EvaluatePanel } from './evaluate_panel'; -import { ResultsTable } from './results_table'; interface Props { jobId: string; @@ -26,7 +25,6 @@ export const RegressionExploration: FC = ({ jobId }) => { values: { jobId }, })} EvaluatePanel={EvaluatePanel} - ResultsTable={ResultsTable} /> ); }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/results_table.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/results_table.tsx deleted file mode 100644 index bef354befe4ef..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/results_table.tsx +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { Fragment, FC, useEffect, useState } from 'react'; - -import { i18n } from '@kbn/i18n'; -import { - EuiCallOut, - EuiFlexGroup, - EuiFlexItem, - EuiFormRow, - EuiPanel, - EuiSpacer, - EuiText, -} from '@elastic/eui'; - -import { - DataFrameAnalyticsConfig, - MAX_COLUMNS, - INDEX_STATUS, - SEARCH_SIZE, - defaultSearchQuery, -} from '../../../../common'; -import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns'; -import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common'; -import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public'; - -import { DataGrid } from '../../../../../components/data_grid'; -import { SavedSearchQuery } from '../../../../../contexts/ml'; -import { getToastNotifications } from '../../../../../util/dependency_cache'; - -import { ExplorationQueryBar } from '../exploration_query_bar'; -import { ExplorationTitle } from '../exploration_title'; - -import { useRegressionData } from './use_regression_data'; - -const showingDocs = i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.documentsShownHelpText', - { - defaultMessage: 'Showing documents for which predictions exist', - } -); - -const showingFirstDocs = i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.firstDocumentsShownHelpText', - { - defaultMessage: 'Showing first {searchSize} documents for which predictions exist', - values: { searchSize: SEARCH_SIZE }, - } -); - -interface Props { - indexPattern: IndexPattern; - jobConfig: DataFrameAnalyticsConfig; - jobStatus?: DATA_FRAME_TASK_STATE; - setEvaluateSearchQuery: React.Dispatch>; - title: string; -} - -export const ResultsTable: FC = React.memo( - ({ indexPattern, jobConfig, jobStatus, setEvaluateSearchQuery, title }) => { - const [searchQuery, setSearchQuery] = useState(defaultSearchQuery); - - useEffect(() => { - setEvaluateSearchQuery(searchQuery); - }, [JSON.stringify(searchQuery)]); - - const regressionData = useRegressionData(indexPattern, jobConfig, searchQuery); - const docFieldsCount = regressionData.columns.length; - const { columns, errorMessage, status, tableItems, visibleColumns } = regressionData; - - if (jobConfig === undefined || regressionData === undefined) { - return null; - } - // if it's a searchBar syntax error leave the table visible so they can try again - if (status === INDEX_STATUS.ERROR && !errorMessage.includes('parsing_exception')) { - return ( - - - - - - {jobStatus !== undefined && ( - - {getTaskStateBadge(jobStatus)} - - )} - - -

{errorMessage}

-
-
- ); - } - - return ( - - - - - - - - {jobStatus !== undefined && ( - - {getTaskStateBadge(jobStatus)} - - )} - - - - - - {docFieldsCount > MAX_COLUMNS && ( - - {i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.fieldSelection', - { - defaultMessage: - '{selectedFieldsLength, number} of {docFieldsCount, number} {docFieldsCount, plural, one {field} other {fields}} selected', - values: { selectedFieldsLength: visibleColumns.length, docFieldsCount }, - } - )} - - )} - - - - - {(columns.length > 0 || searchQuery !== defaultSearchQuery) && ( - - - - - - - - - - - - - - - - - )} - - ); - } -); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/use_regression_data.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/use_regression_data.ts deleted file mode 100644 index bd3d41cf4b161..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/use_regression_data.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { useEffect } from 'react'; - -import { EuiDataGridColumn } from '@elastic/eui'; - -import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public'; - -import { - getDataGridSchemasFromFieldTypes, - useDataGrid, - useRenderCellValue, - UseIndexDataReturnType, -} from '../../../../../components/data_grid'; -import { SavedSearchQuery } from '../../../../../contexts/ml'; - -import { getIndexData, getIndexFields, DataFrameAnalyticsConfig } from '../../../../common'; -import { sortRegressionResultsFields } from '../../../../common/fields'; - -const FEATURE_IMPORTANCE = 'feature_importance'; - -export const useRegressionData = ( - indexPattern: IndexPattern | undefined, - jobConfig: DataFrameAnalyticsConfig | undefined, - searchQuery: SavedSearchQuery -): UseIndexDataReturnType => { - const needsDestIndexFields = - indexPattern !== undefined && indexPattern.title === jobConfig?.source.index[0]; - - const columns: EuiDataGridColumn[] = []; - - if (jobConfig !== undefined) { - const resultsField = jobConfig.dest.results_field; - const { fieldTypes } = getIndexFields(jobConfig, needsDestIndexFields); - columns.push( - ...getDataGridSchemasFromFieldTypes(fieldTypes, resultsField).sort((a: any, b: any) => - sortRegressionResultsFields(a.id, b.id, jobConfig) - ) - ); - } - - const dataGrid = useDataGrid( - columns, - 25, - // reduce default selected rows from 20 to 8 for performance reasons. - 8, - // by default, hide feature-importance columns and the doc id copy - d => !d.includes(`.${FEATURE_IMPORTANCE}.`) && d !== 'ml__id_copy' - ); - - useEffect(() => { - getIndexData(jobConfig, dataGrid, searchQuery); - // custom comparison - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [jobConfig && jobConfig.id, dataGrid.pagination, searchQuery, dataGrid.sortingColumns]); - - const renderCellValue = useRenderCellValue( - indexPattern, - dataGrid.pagination, - dataGrid.tableItems - ); - - return { - ...dataGrid, - columns, - renderCellValue, - }; -};