From 9cb47743cce57a715ec18c0e42887c08cf921cc2 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Tue, 6 Oct 2020 08:39:44 +0200 Subject: [PATCH] [ML] Data Frame Analytics: Expandable sections for classification and regression (#79414) (#79517) Applies the expandable section based layout to the results pages of classification and regression analytics jobs. --- .../_classification_exploration.scss | 2 +- .../classification_exploration.tsx | 28 +- .../evaluate_panel.tsx | 292 +++++++------ .../expandable_section.scss | 4 + .../expandable_section/expandable_section.tsx | 43 +- .../expandable_section_analytics.tsx | 146 +++++++ .../expandable_section_results.tsx | 161 +++++++ .../components/expandable_section/index.ts | 8 +- .../exploration_page_wrapper.tsx | 98 ++++- .../exploration_results_table.tsx | 180 +------- .../exploration_title/exploration_title.tsx | 15 - .../components/exploration_title/index.ts | 7 - .../index_pattern_prompt.tsx | 3 +- .../job_config_error_callout.tsx | 2 - .../loading_panel/loading_panel.tsx | 11 +- .../outlier_exploration.tsx | 229 +--------- .../regression_exploration/evaluate_panel.tsx | 394 +++++++++--------- .../feature_importance_summary.tsx | 141 +++---- .../pages/analytics_exploration/page.tsx | 2 - .../translations/translations/ja-JP.json | 3 - .../translations/translations/zh-CN.json | 3 - .../ml/data_frame_analytics_results.ts | 4 +- 22 files changed, 919 insertions(+), 857 deletions(-) create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section_analytics.tsx create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section_results.tsx delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_title/exploration_title.tsx delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_title/index.ts diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/_classification_exploration.scss b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/_classification_exploration.scss index 102f6630f2ee2..00463affa0d03 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/_classification_exploration.scss +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/_classification_exploration.scss @@ -23,7 +23,7 @@ .mlDataFrameAnalyticsClassification__actualLabel { float: left; width: 80px; - padding-top: $euiSize * 4 + $euiSizeXS; + padding-top: $euiSize * 4; } /* 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 833b4a78178d4..f03fe2dae778c 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 @@ -17,17 +17,19 @@ interface Props { } export const ClassificationExploration: FC = ({ jobId, defaultIsTraining }) => ( - +
+ +
); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx index 86e2c5fd2fb94..f37f649ac2595 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx @@ -6,7 +6,7 @@ import './_classification_exploration.scss'; -import React, { FC, useState, useEffect, Fragment } from 'react'; +import React, { FC, useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { @@ -15,7 +15,6 @@ import { EuiFlexGroup, EuiFlexItem, EuiIconTip, - EuiPanel, EuiSpacer, EuiText, EuiTitle, @@ -30,7 +29,6 @@ import { DataFrameAnalyticsConfig, } from '../../../../common'; import { isKeywordAndTextType } from '../../../../common/fields'; -import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/use_columns'; import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common'; import { isResultsSearchBoolQuery, @@ -39,7 +37,9 @@ import { ResultsSearchQuery, ANALYSIS_CONFIG_TYPE, } from '../../../../common/analytics'; -import { LoadingPanel } from '../loading_panel'; + +import { ExpandableSection, HEADER_ITEMS_LOADING } from '../expandable_section'; + import { getColumnData, ACTUAL_CLASS_ID, @@ -47,7 +47,7 @@ import { getTrailingControlColumns, } from './column_data'; -interface Props { +export interface EvaluatePanelProps { jobConfig: DataFrameAnalyticsConfig; jobStatus?: DATA_FRAME_TASK_STATE; searchQuery: ResultsSearchQuery; @@ -90,7 +90,7 @@ function getHelpText(dataSubsetTitle: string) { return helpText; } -export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) => { +export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) => { const { services: { docLinks }, } = useMlKibana(); @@ -272,10 +272,6 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) return {columnId === ACTUAL_CLASS_ID ? cellValue : accuracy}; }; - if (isLoading === true) { - return ; - } - const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = docLinks; const showTrailingColumns = columnsData.length > MAX_COLUMNS; @@ -288,137 +284,159 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) showTrailingColumns === true && showFullColumns === false ? MAX_COLUMNS : columnsData.length; return ( - -
- - - - - {i18n.translate( - 'xpack.ml.dataframe.analytics.classificationExploration.evaluateJobIdTitle', - { - defaultMessage: 'Evaluation of classification job ID {jobId}', - values: { jobId: jobConfig.id }, - } - )} - - - - {jobStatus !== undefined && ( - - {getTaskStateBadge(jobStatus)} - - )} - - - - {i18n.translate( - 'xpack.ml.dataframe.analytics.classificationExploration.classificationDocsLink', - { - defaultMessage: 'Classification evaluation docs ', - } - )} - - - -
- {error !== null && } - {error === null && ( - -
- - - {getHelpText(dataSubsetTitle)} - - - - - -
- {docsCount !== null && ( - - - - )} - {/* BEGIN TABLE ELEMENTS */} - -
-
- - - -
-
- {columns.length > 0 && columnsData.length > 0 && ( + <> + + } + docsLink={ + + {i18n.translate( + 'xpack.ml.dataframe.analytics.classificationExploration.classificationDocsLink', + { + defaultMessage: 'Classification evaluation docs ', + } + )} + + } + headerItems={ + !isLoading + ? [ + ...(jobStatus !== undefined + ? [ + { + id: 'jobStatus', + label: i18n.translate( + 'xpack.ml.dataframe.analytics.classificationExploration.evaluateJobStatusLabel', + { + defaultMessage: 'Job status', + } + ), + value: jobStatus, + }, + ] + : []), + ...(docsCount !== null + ? [ + { + id: 'docsEvaluated', + label: i18n.translate( + 'xpack.ml.dataframe.analytics.classificationExploration.generalizationDocsCount', + { + defaultMessage: '{docsCount, plural, one {doc} other {docs}} evaluated', + values: { docsCount }, + } + ), + value: docsCount, + }, + ] + : []), + ] + : HEADER_ITEMS_LOADING + } + contentPadding={true} + content={ + !isLoading ? ( + <> + {error !== null && } + {error === null && ( <> -
- - + + {getHelpText(dataSubsetTitle)} + + + - + + + {/* BEGIN TABLE ELEMENTS */} + +
+
+ + + +
+
+ {columns.length > 0 && columnsData.length > 0 && ( + <> +
+ + + +
+ + + + )} +
- - )} -
-
- - )} - {/* END TABLE ELEMENTS */} - + {/* END TABLE ELEMENTS */} + + ) : null + } + /> + + ); }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section.scss b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section.scss index e296744b2737d..c1c80e8dbd2c4 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section.scss +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section.scss @@ -1,3 +1,7 @@ .mlExpandableSection { padding: 0 $euiSizeS $euiSizeS $euiSizeS; } + +.mlExpandableSection-contentPadding { + padding: $euiSizeS; +} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section.tsx index 97fb8fd29e5a7..fa7538b580334 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section.tsx @@ -29,9 +29,13 @@ const isHeaderItems = (arg: any): arg is HeaderItem[] => { return Array.isArray(arg); }; +export const HEADER_ITEMS_LOADING = 'header_items_loading'; + export interface ExpandableSectionProps { content: ReactNode; - headerItems?: HeaderItem[] | 'loading'; + contentPadding?: boolean; + docsLink?: ReactNode; + headerItems?: HeaderItem[] | typeof HEADER_ITEMS_LOADING; isExpanded?: boolean; dataTestId: string; title: ReactNode; @@ -45,8 +49,10 @@ export const ExpandableSection: FC = ({ // callback. isExpanded: isExpandedDefault = true, content, + contentPadding = false, dataTestId, title, + docsLink, }) => { const [isExpanded, setIsExpanded] = useState(isExpandedDefault); const toggleExpanded = () => { @@ -56,16 +62,21 @@ export const ExpandableSection: FC = ({ return (
- - {title} - - {headerItems === 'loading' && } + + + + {title} + + + {docsLink !== undefined && {docsLink}} + + {headerItems === HEADER_ITEMS_LOADING && } {isHeaderItems(headerItems) && ( {headerItems.map(({ label, value, id }) => ( @@ -82,13 +93,19 @@ export const ExpandableSection: FC = ({ {value} )} - {label === undefined && value} + {label === undefined && ( + + {value} + + )} ))} )}
- {isExpanded && content} + {isExpanded && ( +
{content}
+ )}
); }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section_analytics.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section_analytics.tsx new file mode 100644 index 0000000000000..0d8a0df30b4e0 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section_analytics.tsx @@ -0,0 +1,146 @@ +/* + * 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, { useEffect, useState, FC } from 'react'; + +import { FormattedMessage } from '@kbn/i18n/react'; + +import { EuiHorizontalRule, EuiLoadingSpinner, EuiSpacer, EuiText } from '@elastic/eui'; + +import type { DataFrameAnalysisConfigType } from '../../../../../../../common/types/data_frame_analytics'; + +import { ml } from '../../../../../services/ml_api_service'; + +import { getAnalysisType } from '../../../../common'; + +import { isGetDataFrameAnalyticsStatsResponseOk } from '../../../analytics_management/services/analytics_service/get_analytics'; +import { + DataFrameAnalyticsListRow, + DATA_FRAME_MODE, +} from '../../../analytics_management/components/analytics_list/common'; +import { ExpandedRow } from '../../../analytics_management/components/analytics_list/expanded_row'; + +import { + ExpandableSection, + ExpandableSectionProps, + HEADER_ITEMS_LOADING, +} from './expandable_section'; + +const getAnalyticsSectionHeaderItems = ( + expandedRowItem: DataFrameAnalyticsListRow | undefined +): ExpandableSectionProps['headerItems'] => { + if (expandedRowItem === undefined) { + return HEADER_ITEMS_LOADING; + } + + const sourceIndex = Array.isArray(expandedRowItem.config.source.index) + ? expandedRowItem.config.source.index.join() + : expandedRowItem.config.source.index; + + return [ + { + id: 'analysisTypeLabel', + label: ( + + ), + value: expandedRowItem.job_type, + }, + { + id: 'analysisSourceIndexLabel', + label: ( + + ), + value: sourceIndex, + }, + { + id: 'analysisDestinationIndexLabel', + label: ( + + ), + value: expandedRowItem.config.dest.index, + }, + ]; +}; + +interface ExpandableSectionAnalyticsProps { + jobId: string; +} + +export const ExpandableSectionAnalytics: FC = ({ jobId }) => { + const [expandedRowItem, setExpandedRowItem] = useState(); + + const fetchStats = async () => { + const analyticsConfigs = await ml.dataFrameAnalytics.getDataFrameAnalytics(jobId); + const analyticsStats = await ml.dataFrameAnalytics.getDataFrameAnalyticsStats(jobId); + + const config = analyticsConfigs.data_frame_analytics[0]; + const stats = isGetDataFrameAnalyticsStatsResponseOk(analyticsStats) + ? analyticsStats.data_frame_analytics[0] + : undefined; + + if (stats === undefined) { + return; + } + + const newExpandedRowItem: DataFrameAnalyticsListRow = { + checkpointing: {}, + config, + id: config.id, + job_type: getAnalysisType(config.analysis) as DataFrameAnalysisConfigType, + mode: DATA_FRAME_MODE.BATCH, + state: stats.state, + stats, + }; + + setExpandedRowItem(newExpandedRowItem); + }; + + useEffect(() => { + fetchStats(); + }, [jobId]); + + const analyticsSectionHeaderItems = getAnalyticsSectionHeaderItems(expandedRowItem); + const analyticsSectionContent = ( + <> + + {expandedRowItem === undefined && ( + + + + + + )} + {expandedRowItem !== undefined && } + + ); + + return ( + <> + + } + /> + + + ); +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section_results.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section_results.tsx new file mode 100644 index 0000000000000..e01a291b27385 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section_results.tsx @@ -0,0 +1,161 @@ +/* + * 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, { FC } from 'react'; + +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { EuiDataGridColumn, EuiSpacer, EuiText } from '@elastic/eui'; + +import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public'; + +import { + isClassificationAnalysis, + isRegressionAnalysis, +} from '../../../../../../../common/util/analytics_utils'; + +import { getToastNotifications } from '../../../../../util/dependency_cache'; +import { useColorRange, ColorRangeLegend } from '../../../../../components/color_range_legend'; +import { DataGrid, UseIndexDataReturnType } from '../../../../../components/data_grid'; +import { SavedSearchQuery } from '../../../../../contexts/ml'; + +import { defaultSearchQuery, DataFrameAnalyticsConfig, SEARCH_SIZE } from '../../../../common'; + +import { + ExpandableSection, + ExpandableSectionProps, + HEADER_ITEMS_LOADING, +} from '../expandable_section'; +import { IndexPatternPrompt } from '../index_pattern_prompt'; + +const showingDocs = i18n.translate( + 'xpack.ml.dataframe.analytics.explorationResults.documentsShownHelpText', + { + defaultMessage: 'Showing documents for which predictions exist', + } +); + +const showingFirstDocs = i18n.translate( + 'xpack.ml.dataframe.analytics.explorationResults.firstDocumentsShownHelpText', + { + defaultMessage: 'Showing first {searchSize} documents for which predictions exist', + values: { searchSize: SEARCH_SIZE }, + } +); + +const getResultsSectionHeaderItems = ( + columnsWithCharts: EuiDataGridColumn[], + tableItems: Array>, + rowCount: number, + colorRange?: ReturnType +): ExpandableSectionProps['headerItems'] => { + return columnsWithCharts.length > 0 && tableItems.length > 0 + ? [ + { + id: 'explorationTableTotalDocs', + label: ( + + ), + value: rowCount, + }, + ...(colorRange !== undefined + ? [ + { + id: 'colorRangeLegend', + value: ( + + ), + }, + ] + : []), + ] + : HEADER_ITEMS_LOADING; +}; + +interface ExpandableSectionResultsProps { + colorRange?: ReturnType; + indexData: UseIndexDataReturnType; + indexPattern?: IndexPattern; + jobConfig?: DataFrameAnalyticsConfig; + needsDestIndexPattern: boolean; + searchQuery: SavedSearchQuery; +} + +export const ExpandableSectionResults: FC = ({ + colorRange, + indexData, + indexPattern, + jobConfig, + needsDestIndexPattern, + searchQuery, +}) => { + const { columnsWithCharts, tableItems } = indexData; + + // Results section header items and content + const resultsSectionHeaderItems = getResultsSectionHeaderItems( + columnsWithCharts, + tableItems, + indexData.rowCount, + colorRange + ); + const resultsSectionContent = ( + <> + {jobConfig !== undefined && needsDestIndexPattern && ( +
+ +
+ )} + {jobConfig !== undefined && + (isRegressionAnalysis(jobConfig.analysis) || + isClassificationAnalysis(jobConfig.analysis)) && ( + + {tableItems.length === SEARCH_SIZE ? showingFirstDocs : showingDocs} + + )} + {(columnsWithCharts.length > 0 || searchQuery !== defaultSearchQuery) && + indexPattern !== undefined && ( + <> + {columnsWithCharts.length > 0 && tableItems.length > 0 && ( + + )} + + )} + + ); + + return ( + <> + + } + /> + + + ); +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/index.ts index ad7ce84902e87..3d9237922e19d 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/index.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/index.ts @@ -4,4 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -export { ExpandableSection, ExpandableSectionProps } from './expandable_section'; +export { + ExpandableSection, + ExpandableSectionProps, + HEADER_ITEMS_LOADING, +} from './expandable_section'; +export { ExpandableSectionAnalytics } from './expandable_section_analytics'; +export { ExpandableSectionResults } from './expandable_section_results'; 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 6b1b3fc1bb47f..b03777fef6bd4 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 @@ -4,20 +4,49 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { FC, useState } from 'react'; +import React, { FC, useEffect, useState } from 'react'; -import { EuiSpacer } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; -import { useResultsViewConfig, DataFrameAnalyticsConfig } from '../../../../common'; -import { ResultsSearchQuery, defaultSearchQuery } from '../../../../common/analytics'; +import { useUrlState } from '../../../../../util/url_state'; + +import { + defaultSearchQuery, + getDefaultTrainingFilterQuery, + useResultsViewConfig, + DataFrameAnalyticsConfig, +} from '../../../../common'; +import { ResultsSearchQuery } from '../../../../common/analytics'; import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common'; +import { ExpandableSectionAnalytics } from '../expandable_section'; import { ExplorationResultsTable } from '../exploration_results_table'; +import { ExplorationQueryBar } from '../exploration_query_bar'; import { JobConfigErrorCallout } from '../job_config_error_callout'; import { LoadingPanel } from '../loading_panel'; import { FeatureImportanceSummaryPanelProps } from '../total_feature_importance_summary/feature_importance_summary'; +const filters = { + options: [ + { + id: 'training', + label: i18n.translate('xpack.ml.dataframe.analytics.explorationResults.trainingSubsetLabel', { + defaultMessage: 'Training', + }), + }, + { + id: 'testing', + label: i18n.translate('xpack.ml.dataframe.analytics.explorationResults.testingSubsetLabel', { + defaultMessage: 'Testing', + }), + }, + ], + columnId: 'ml.is_training', + key: { training: true, testing: false }, +}; + export interface EvaluatePanelProps { jobConfig: DataFrameAnalyticsConfig; jobStatus?: DATA_FRAME_TASK_STATE; @@ -50,7 +79,25 @@ export const ExplorationPageWrapper: FC = ({ needsDestIndexPattern, totalFeatureImportance, } = useResultsViewConfig(jobId); + const [searchQuery, setSearchQuery] = useState(defaultSearchQuery); + const [globalState, setGlobalState] = useUrlState('_g'); + const [defaultQueryString, setDefaultQueryString] = useState(); + + useEffect(() => { + if (defaultIsTraining !== undefined && jobConfig !== undefined) { + // Apply defaultIsTraining filter + setSearchQuery( + getDefaultTrainingFilterQuery(jobConfig.dest.results_field, defaultIsTraining) + ); + setDefaultQueryString(`${jobConfig.dest.results_field}.is_training : ${defaultIsTraining}`); + // Clear defaultIsTraining from url + setGlobalState('ml', { + analysisType: globalState.ml.analysisType, + jobId: globalState.ml.jobId, + }); + } + }, [jobConfig?.dest.results_field]); if (jobConfigErrorMessage !== undefined || jobCapsServiceErrorMessage !== undefined) { return ( @@ -61,21 +108,54 @@ export const ExplorationPageWrapper: FC = ({ /> ); } + return ( <> + {typeof jobConfig?.description !== 'undefined' && ( + <> + {jobConfig?.description} + + + )} + + {indexPattern !== undefined && ( + <> + + + + + + + + + + + + + )} + {isLoadingJobConfig === true && jobConfig === undefined && } {isLoadingJobConfig === false && jobConfig !== undefined && isInitialized === true && ( - + )} + {isLoadingJobConfig === true && totalFeatureImportance === undefined && } {isLoadingJobConfig === false && totalFeatureImportance !== undefined && ( <> - )} - + {isLoadingJobConfig === true && jobConfig === undefined && } + {isLoadingJobConfig === false && jobConfig !== undefined && isInitialized === true && ( + + )} + {isLoadingJobConfig === true && jobConfig === undefined && } {isLoadingJobConfig === false && jobConfig !== undefined && @@ -86,9 +166,7 @@ export const ExplorationPageWrapper: FC = ({ jobConfig={jobConfig} jobStatus={jobStatus} needsDestIndexPattern={needsDestIndexPattern} - setEvaluateSearchQuery={setSearchQuery} - title={title} - defaultIsTraining={defaultIsTraining} + searchQuery={searchQuery} /> )} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx index bd4079272c56e..a6e95269b3633 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx @@ -4,118 +4,37 @@ * 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 { EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiPanel, EuiSpacer, EuiText } from '@elastic/eui'; +import React, { FC } from 'react'; 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 { - DataFrameAnalyticsConfig, - MAX_COLUMNS, - SEARCH_SIZE, - defaultSearchQuery, - getAnalysisType, - getDefaultTrainingFilterQuery, -} from '../../../../common'; -import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/use_columns'; -import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common'; -import { ExplorationTitle } from '../exploration_title'; -import { ExplorationQueryBar } from '../exploration_query_bar'; -import { IndexPatternPrompt } from '../index_pattern_prompt'; - -import { useExplorationResults } from './use_exploration_results'; import { useMlKibana } from '../../../../../contexts/kibana'; -import { DataFrameAnalysisConfigType } from '../../../../../../../common/types/data_frame_analytics'; -import { useUrlState } from '../../../../../util/url_state'; -const showingDocs = i18n.translate( - 'xpack.ml.dataframe.analytics.explorationResults.documentsShownHelpText', - { - defaultMessage: 'Showing documents for which predictions exist', - } -); +import { DataFrameAnalyticsConfig } from '../../../../common'; +import { ResultsSearchQuery } from '../../../../common/analytics'; -const showingFirstDocs = i18n.translate( - 'xpack.ml.dataframe.analytics.explorationResults.firstDocumentsShownHelpText', - { - defaultMessage: 'Showing first {searchSize} documents for which predictions exist', - values: { searchSize: SEARCH_SIZE }, - } -); +import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common'; + +import { ExpandableSectionResults } from '../expandable_section'; -const filters = { - options: [ - { - id: 'training', - label: i18n.translate('xpack.ml.dataframe.analytics.explorationResults.trainingSubsetLabel', { - defaultMessage: 'Training', - }), - }, - { - id: 'testing', - label: i18n.translate('xpack.ml.dataframe.analytics.explorationResults.testingSubsetLabel', { - defaultMessage: 'Testing', - }), - }, - ], - columnId: 'ml.is_training', - key: { training: true, testing: false }, -}; +import { useExplorationResults } from './use_exploration_results'; interface Props { indexPattern: IndexPattern; jobConfig: DataFrameAnalyticsConfig; jobStatus?: DATA_FRAME_TASK_STATE; needsDestIndexPattern: boolean; - setEvaluateSearchQuery: React.Dispatch>; - title: string; - defaultIsTraining?: boolean; + searchQuery: ResultsSearchQuery; } export const ExplorationResultsTable: FC = React.memo( - ({ - indexPattern, - jobConfig, - jobStatus, - needsDestIndexPattern, - setEvaluateSearchQuery, - title, - defaultIsTraining, - }) => { + ({ indexPattern, jobConfig, jobStatus, needsDestIndexPattern, searchQuery }) => { const { services: { mlServices: { mlApiServices }, }, } = useMlKibana(); - const [globalState, setGlobalState] = useUrlState('_g'); - const [searchQuery, setSearchQuery] = useState(defaultSearchQuery); - const [defaultQueryString, setDefaultQueryString] = useState(); - - useEffect(() => { - setEvaluateSearchQuery(searchQuery); - }, [JSON.stringify(searchQuery)]); - - useEffect(() => { - if (defaultIsTraining !== undefined) { - // Apply defaultIsTraining filter - setSearchQuery( - getDefaultTrainingFilterQuery(jobConfig.dest.results_field, defaultIsTraining) - ); - setDefaultQueryString(`${jobConfig.dest.results_field}.is_training : ${defaultIsTraining}`); - // Clear defaultIsTraining from url - setGlobalState('ml', { - analysisType: globalState.ml.analysisType, - jobId: globalState.ml.jobId, - }); - } - }, []); - - const analysisType = getAnalysisType(jobConfig.analysis); const classificationData = useExplorationResults( indexPattern, @@ -125,83 +44,20 @@ export const ExplorationResultsTable: FC = React.memo( mlApiServices ); - const docFieldsCount = classificationData.columnsWithCharts.length; - const { columnsWithCharts, tableItems, visibleColumns } = classificationData; - if (jobConfig === undefined || classificationData === undefined) { return null; } return ( - - {needsDestIndexPattern && } - - - - - - - {jobStatus !== undefined && ( - - {getTaskStateBadge(jobStatus)} - - )} - - - - - - {docFieldsCount > MAX_COLUMNS && ( - - {i18n.translate( - 'xpack.ml.dataframe.analytics.explorationResults.fieldSelection', - { - defaultMessage: - '{selectedFieldsLength, number} of {docFieldsCount, number} {docFieldsCount, plural, one {field} other {fields}} selected', - values: { selectedFieldsLength: visibleColumns.length, docFieldsCount }, - } - )} - - )} - - - - - {(columnsWithCharts.length > 0 || searchQuery !== defaultSearchQuery) && ( - - - - - - - - - - - - - - - - - )} - +
+ +
); } ); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_title/exploration_title.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_title/exploration_title.tsx deleted file mode 100644 index f06c88c73df71..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_title/exploration_title.tsx +++ /dev/null @@ -1,15 +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, { FC } from 'react'; - -import { EuiTitle } from '@elastic/eui'; - -export const ExplorationTitle: FC<{ title: string }> = ({ title }) => ( - - {title} - -); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_title/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_title/index.ts deleted file mode 100644 index b34e61b3b5e76..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_title/index.ts +++ /dev/null @@ -1,7 +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. - */ - -export { ExplorationTitle } from './exploration_title'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/index_pattern_prompt/index_pattern_prompt.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/index_pattern_prompt/index_pattern_prompt.tsx index f478dc639da2f..0353129212b0a 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/index_pattern_prompt/index_pattern_prompt.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/index_pattern_prompt/index_pattern_prompt.tsx @@ -6,7 +6,7 @@ import React, { FC } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiLink, EuiSpacer, EuiText } from '@elastic/eui'; +import { EuiLink, EuiText } from '@elastic/eui'; import { useMlKibana } from '../../../../../contexts/kibana'; interface Props { @@ -42,7 +42,6 @@ export const IndexPatternPrompt: FC = ({ destIndex }) => { }} /> - ); }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/job_config_error_callout/job_config_error_callout.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/job_config_error_callout/job_config_error_callout.tsx index 959f2d18d99fe..261438cec7292 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/job_config_error_callout/job_config_error_callout.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/job_config_error_callout/job_config_error_callout.tsx @@ -10,7 +10,6 @@ import { EuiCallOut, EuiLink, EuiPanel, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { ExplorationTitle } from '../exploration_title'; import { useMlKibana } from '../../../../../contexts/kibana'; const jobConfigErrorTitle = i18n.translate('xpack.ml.dataframe.analytics.jobConfig.errorTitle', { @@ -63,7 +62,6 @@ export const JobConfigErrorCallout: FC = ({ return ( - ( - - - + <> + + + + + ); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx index 7d7f5efcae321..8fc2486599755 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx @@ -4,124 +4,25 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useEffect, useState, FC } from 'react'; +import React, { useState, FC } from 'react'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { - EuiDataGridColumn, - EuiHorizontalRule, - EuiLoadingSpinner, - EuiSpacer, - EuiText, -} from '@elastic/eui'; - -import type { DataFrameAnalysisConfigType } from '../../../../../../../common/types/data_frame_analytics'; +import { EuiSpacer, EuiText } from '@elastic/eui'; import { useColorRange, COLOR_RANGE, COLOR_RANGE_SCALE, } from '../../../../../components/color_range_legend'; -import { ColorRangeLegend } from '../../../../../components/color_range_legend'; -import { DataGrid } from '../../../../../components/data_grid'; import { SavedSearchQuery } from '../../../../../contexts/ml'; -import { getToastNotifications } from '../../../../../util/dependency_cache'; -import { ml } from '../../../../../services/ml_api_service'; - -import { getAnalysisType, defaultSearchQuery, useResultsViewConfig } from '../../../../common'; - -import { isGetDataFrameAnalyticsStatsResponseOk } from '../../../analytics_management/services/analytics_service/get_analytics'; -import { - DataFrameAnalyticsListRow, - DATA_FRAME_MODE, -} from '../../../analytics_management/components/analytics_list/common'; -import { ExpandedRow } from '../../../analytics_management/components/analytics_list/expanded_row'; +import { defaultSearchQuery, useResultsViewConfig } from '../../../../common'; -import { ExpandableSection, ExpandableSectionProps } from '../expandable_section'; +import { ExpandableSectionAnalytics, ExpandableSectionResults } from '../expandable_section'; import { ExplorationQueryBar } from '../exploration_query_bar'; -import { IndexPatternPrompt } from '../index_pattern_prompt'; import { getFeatureCount } from './common'; import { useOutlierData } from './use_outlier_data'; -const getAnalyticsSectionHeaderItems = ( - expandedRowItem: DataFrameAnalyticsListRow | undefined -): ExpandableSectionProps['headerItems'] => { - return expandedRowItem !== undefined - ? [ - { - id: 'analysisTypeLabel', - label: ( - - ), - value: expandedRowItem.job_type, - }, - { - id: 'analysisSourceIndexLabel', - label: ( - - ), - value: expandedRowItem.config.source.index, - }, - { - id: 'analysisDestinationIndexLabel', - label: ( - - ), - value: expandedRowItem.config.dest.index, - }, - ] - : 'loading'; -}; - -const getResultsSectionHeaderItems = ( - columnsWithCharts: EuiDataGridColumn[], - tableItems: Array>, - rowCount: number, - colorRange: ReturnType -): ExpandableSectionProps['headerItems'] => { - return columnsWithCharts.length > 0 && tableItems.length > 0 - ? [ - { - id: 'explorationTableTotalDocs', - label: ( - - ), - value: rowCount, - }, - { - id: 'colorRangeLegend', - value: ( - - ), - }, - ] - : 'loading'; -}; - export type TableItem = Record; interface ExplorationProps { @@ -141,89 +42,14 @@ export const OutlierExploration: FC = React.memo(({ jobId }) = jobConfig !== undefined ? getFeatureCount(jobConfig.dest.results_field, tableItems) : 1 ); - const [expandedRowItem, setExpandedRowItem] = useState(); - - const fetchStats = async () => { - const analyticsConfigs = await ml.dataFrameAnalytics.getDataFrameAnalytics(jobId); - const analyticsStats = await ml.dataFrameAnalytics.getDataFrameAnalyticsStats(jobId); - - const config = analyticsConfigs.data_frame_analytics[0]; - const stats = isGetDataFrameAnalyticsStatsResponseOk(analyticsStats) - ? analyticsStats.data_frame_analytics[0] - : undefined; - - if (stats === undefined) { - return; - } - - const newExpandedRowItem: DataFrameAnalyticsListRow = { - checkpointing: {}, - config, - id: config.id, - job_type: getAnalysisType(config.analysis) as DataFrameAnalysisConfigType, - mode: DATA_FRAME_MODE.BATCH, - state: stats.state, - stats, - }; - - setExpandedRowItem(newExpandedRowItem); - }; - - useEffect(() => { - fetchStats(); - }, [jobConfig?.id]); - - // Analytics section header items and content - const analyticsSectionHeaderItems = getAnalyticsSectionHeaderItems(expandedRowItem); - const analyticsSectionContent = ( - <> - - {expandedRowItem === undefined && ( - - - - - - )} - {(columnsWithCharts.length > 0 || searchQuery !== defaultSearchQuery) && - indexPattern !== undefined && - jobConfig !== undefined && - columnsWithCharts.length > 0 && - tableItems.length > 0 && - expandedRowItem !== undefined && } - - ); - - // Results section header items and content - const resultsSectionHeaderItems = getResultsSectionHeaderItems( - columnsWithCharts, - tableItems, - outlierData.rowCount, - colorRange - ); - const resultsSectionContent = ( - <> - {jobConfig !== undefined && needsDestIndexPattern && ( - - )} - {(columnsWithCharts.length > 0 || searchQuery !== defaultSearchQuery) && - indexPattern !== undefined && ( - <> - - {columnsWithCharts.length > 0 && tableItems.length > 0 && ( - - )} - - )} - - ); - return ( <> + {typeof jobConfig?.description !== 'undefined' && ( + <> + {jobConfig?.description} + + + )} {(columnsWithCharts.length > 0 || searchQuery !== defaultSearchQuery) && indexPattern !== undefined && ( <> @@ -231,34 +57,15 @@ export const OutlierExploration: FC = React.memo(({ jobId }) = )} - - - } - /> - - - - - } + {typeof jobConfig?.id === 'string' && } + - ); }); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx index 197160a1be4d9..4350583a907af 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx @@ -11,7 +11,6 @@ import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, - EuiPanel, EuiSpacer, EuiText, EuiTitle, @@ -27,9 +26,7 @@ import { Eval, DataFrameAnalyticsConfig, } from '../../../../common'; -import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/use_columns'; import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common'; -import { EvaluateStat } from './evaluate_stat'; import { isResultsSearchBoolQuery, isRegressionEvaluateResponse, @@ -38,6 +35,10 @@ import { EMPTY_STAT, } from '../../../../common/analytics'; +import { ExpandableSection } from '../expandable_section'; + +import { EvaluateStat } from './evaluate_stat'; + interface Props { jobConfig: DataFrameAnalyticsConfig; jobStatus?: DATA_FRAME_TASK_STATE; @@ -219,30 +220,16 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) }, [JSON.stringify(searchQuery)]); return ( - - - - - - {i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.evaluateJobIdTitle', - { - defaultMessage: 'Evaluation of regression job ID {jobId}', - values: { jobId: jobConfig.id }, - } - )} - - - - {jobStatus !== undefined && ( - - {getTaskStateBadge(jobStatus)} - - )} - - - - + <> + + } + docsLink={ = ({ jobConfig, jobStatus, searchQuery }) } )} - - - - - - - - {i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.generalizationErrorTitle', + } + headerItems={ + jobStatus !== undefined + ? [ { - defaultMessage: 'Generalization error', - } - )} - - - {generalizationDocsCount !== null && ( - - - {isTrainingFilter === true && generalizationDocsCount === 0 && ( - - )} - - )} - - + id: 'jobStatus', + label: i18n.translate( + 'xpack.ml.dataframe.analytics.classificationExploration.evaluateJobStatusLabel', + { + defaultMessage: 'Job status', + } + ), + value: jobStatus, + }, + ] + : [] + } + contentPadding={true} + content={ + - - {/* First row stats */} - - - - - - - - - - - {/* Second row stats */} + + + {i18n.translate( + 'xpack.ml.dataframe.analytics.regressionExploration.generalizationErrorTitle', + { + defaultMessage: 'Generalization error', + } + )} + + + {generalizationDocsCount !== null && ( + + + {isTrainingFilter === true && generalizationDocsCount === 0 && ( + + )} + + )} + + - + + {/* First row stats */} - + + + + + + + + + {/* Second row stats */} - + + + + + + + + + {generalizationEval.error !== null && ( + + + {isTrainingFilter === true && + generalizationDocsCount === 0 && + generalizationEval.error.includes('No documents found') + ? i18n.translate( + 'xpack.ml.dataframe.analytics.regressionExploration.evaluateNoTestingDocsError', + { + defaultMessage: 'No testing documents found', + } + ) + : generalizationEval.error} + + + )} - {generalizationEval.error !== null && ( - - - {isTrainingFilter === true && - generalizationDocsCount === 0 && - generalizationEval.error.includes('No documents found') - ? i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.evaluateNoTestingDocsError', - { - defaultMessage: 'No testing documents found', - } - ) - : generalizationEval.error} + + + + {i18n.translate( + 'xpack.ml.dataframe.analytics.regressionExploration.trainingErrorTitle', + { + defaultMessage: 'Training error', + } + )} + + + {trainingDocsCount !== null && ( + + + {isTrainingFilter === false && trainingDocsCount === 0 && ( + + )} - - )} - - - - - - {i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.trainingErrorTitle', - { - defaultMessage: 'Training error', - } - )} - - - {trainingDocsCount !== null && ( - - - {isTrainingFilter === false && trainingDocsCount === 0 && ( - )} - - )} - - - - - {/* First row stats */} + + - + + {/* First row stats */} - + + + + + + + + + {/* Second row stats */} - - - - - {/* Second row stats */} - - - - - - - + + + + + + + + + {trainingEval.error !== null && ( + + + {isTrainingFilter === false && + trainingDocsCount === 0 && + trainingEval.error.includes('No documents found') + ? i18n.translate( + 'xpack.ml.dataframe.analytics.regressionExploration.evaluateNoTrainingDocsError', + { + defaultMessage: 'No training documents found', + } + ) + : trainingEval.error} + + + )} - {trainingEval.error !== null && ( - - - {isTrainingFilter === false && - trainingDocsCount === 0 && - trainingEval.error.includes('No documents found') - ? i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.evaluateNoTrainingDocsError', - { - defaultMessage: 'No training documents found', - } - ) - : trainingEval.error} - - - )} - - - + } + /> + + ); }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/total_feature_importance_summary/feature_importance_summary.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/total_feature_importance_summary/feature_importance_summary.tsx index f7ac717caef2f..32ea2cfe8145f 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/total_feature_importance_summary/feature_importance_summary.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/total_feature_importance_summary/feature_importance_summary.tsx @@ -5,15 +5,7 @@ */ import React, { FC, useCallback, useMemo } from 'react'; -import { - EuiButtonEmpty, - EuiFlexGroup, - EuiFlexItem, - EuiIconTip, - EuiPanel, - EuiSpacer, - EuiTitle, -} from '@elastic/eui'; +import { EuiButtonEmpty, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { Chart, @@ -38,6 +30,9 @@ import { } from '../../../../../../../common/types/feature_importance'; import { useMlKibana } from '../../../../../contexts/kibana'; + +import { ExpandableSection } from '../expandable_section'; + const { euiColorMediumShade } = euiVars; const axisColor = euiColorMediumShade; @@ -194,71 +189,67 @@ export const FeatureImportanceSummaryPanel: FC Number(d.toPrecision(3)).toString(), []); return ( - -
- - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
+ <> + + } + docsLink={ + + + + } + headerItems={[ + { + id: 'FeatureImportanceSummary', + value: tooltipContent, + }, + ]} + content={ + + + + + + + + } + /> + + ); }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/page.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/page.tsx index d2767a9612e3b..0144d369c46f6 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/page.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/page.tsx @@ -12,7 +12,6 @@ import { EuiPageContentBody, EuiPageContentHeader, EuiPageContentHeaderSection, - EuiSpacer, EuiTitle, } from '@elastic/eui'; @@ -42,7 +41,6 @@ export const Page: FC<{ - {analysisType === ANALYSIS_CONFIG_TYPE.OUTLIER_DETECTION && ( )} diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 542ea4382ab88..abf1f050b69cb 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -10557,7 +10557,6 @@ "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixTestingHelpText": "データセットをテストするための正規化された混同行列", "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixTooltip": "マルチクラス混同行列には、分析が実際のクラスで正しくデータポイントを分類した発生数と、別のクラスで誤分類した発生数が含まれます。", "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixTrainingHelpText": "データセットを学習するための正規化された混同行列", - "xpack.ml.dataframe.analytics.classificationExploration.evaluateJobIdTitle": "分類ジョブID {jobId}の評価", "xpack.ml.dataframe.analytics.classificationExploration.generalizationDocsCount": "{docsCount, plural, one {# doc} other {# docs}}が評価されました", "xpack.ml.dataframe.analytics.classificationExploration.showActions": "アクションを表示", "xpack.ml.dataframe.analytics.classificationExploration.showAllColumns": "すべての列を表示", @@ -10760,13 +10759,11 @@ "xpack.ml.dataframe.analytics.errorCallout.queryParsingErrorTitle": "クエリをパースできません。", "xpack.ml.dataframe.analytics.exploration.colorRangeLegendTitle": "機能影響スコア", "xpack.ml.dataframe.analytics.explorationResults.documentsShownHelpText": "予測があるドキュメントを示す", - "xpack.ml.dataframe.analytics.explorationResults.fieldSelection": "{docFieldsCount, number}件中 showing {selectedFieldsLength, number}件の{docFieldsCount, plural, one {フィールド} other {フィールド}}", "xpack.ml.dataframe.analytics.explorationResults.firstDocumentsShownHelpText": "予測がある最初の{searchSize}のドキュメントを示す", "xpack.ml.dataframe.analytics.indexPatternPromptLinkText": "インデックスパターンを作成します", "xpack.ml.dataframe.analytics.indexPatternPromptMessage": "{destIndex}のインデックス{destIndex}. {linkToIndexPatternManagement}にはインデックスパターンが存在しません。", "xpack.ml.dataframe.analytics.jobCaps.errorTitle": "結果を取得できません。インデックスのフィールドデータの読み込み中にエラーが発生しました。", "xpack.ml.dataframe.analytics.jobConfig.errorTitle": "結果を取得できません。ジョブ構成データの読み込み中にエラーが発生しました。", - "xpack.ml.dataframe.analytics.regressionExploration.evaluateJobIdTitle": "回帰ジョブID {jobId}の評価", "xpack.ml.dataframe.analytics.regressionExploration.generalizationDocsCount": "{docsCount, plural, one {# doc} other {# docs}}が評価されました", "xpack.ml.dataframe.analytics.regressionExploration.generalizationErrorTitle": "一般化エラー", "xpack.ml.dataframe.analytics.regressionExploration.generalizationFilterText": ".学習データをフィルタリングしています。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index f2be8d94dadb9..4a2cfabc20791 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -10563,7 +10563,6 @@ "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixTestingHelpText": "用于测试数据集的标准化混淆矩阵", "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixTooltip": "多类混淆矩阵包含分析使用数据点的实际类正确分类数据点的次数以及分析使用其他类错误分类这些数据点的次数", "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixTrainingHelpText": "用于训练数据集的标准化混淆矩阵", - "xpack.ml.dataframe.analytics.classificationExploration.evaluateJobIdTitle": "分类作业 ID {jobId} 的评估", "xpack.ml.dataframe.analytics.classificationExploration.generalizationDocsCount": "{docsCount, plural, one {# 个文档} other {# 个文档}}已评估", "xpack.ml.dataframe.analytics.classificationExploration.showActions": "显示操作", "xpack.ml.dataframe.analytics.classificationExploration.showAllColumns": "显示所有列", @@ -10766,13 +10765,11 @@ "xpack.ml.dataframe.analytics.errorCallout.queryParsingErrorTitle": "无法解析查询。", "xpack.ml.dataframe.analytics.exploration.colorRangeLegendTitle": "功能影响分数", "xpack.ml.dataframe.analytics.explorationResults.documentsShownHelpText": "正在显示有相关预测存在的文档", - "xpack.ml.dataframe.analytics.explorationResults.fieldSelection": "已选择 {docFieldsCount, number} 个{docFieldsCount, plural, one {字段} other {字段}}中的 {selectedFieldsLength, number} 个", "xpack.ml.dataframe.analytics.explorationResults.firstDocumentsShownHelpText": "正在显示有相关预测存在的前 {searchSize} 个文档", "xpack.ml.dataframe.analytics.indexPatternPromptLinkText": "创建索引模式", "xpack.ml.dataframe.analytics.indexPatternPromptMessage": "不存在索引 {destIndex} 的索引模式。{destIndex} 的{linkToIndexPatternManagement}。", "xpack.ml.dataframe.analytics.jobCaps.errorTitle": "无法提取结果。加载索引的字段数据时发生错误。", "xpack.ml.dataframe.analytics.jobConfig.errorTitle": "无法提取结果。加载作业配置数据时发生错误。", - "xpack.ml.dataframe.analytics.regressionExploration.evaluateJobIdTitle": "回归作业 ID {jobId} 的评估", "xpack.ml.dataframe.analytics.regressionExploration.generalizationDocsCount": "{docsCount, plural, one {# 个文档} other {# 个文档}}已评估", "xpack.ml.dataframe.analytics.regressionExploration.generalizationErrorTitle": "泛化误差", "xpack.ml.dataframe.analytics.regressionExploration.generalizationFilterText": ".筛留训练数据。", diff --git a/x-pack/test/functional/services/ml/data_frame_analytics_results.ts b/x-pack/test/functional/services/ml/data_frame_analytics_results.ts index 8a72badebd923..a4d8fa8e692bd 100644 --- a/x-pack/test/functional/services/ml/data_frame_analytics_results.ts +++ b/x-pack/test/functional/services/ml/data_frame_analytics_results.ts @@ -15,7 +15,7 @@ export function MachineLearningDataFrameAnalyticsResultsProvider({ return { async assertRegressionEvaluatePanelElementsExists() { - await testSubjects.existOrFail('mlDFAnalyticsRegressionExplorationEvaluatePanel'); + await testSubjects.existOrFail('mlDFExpandableSection-RegressionEvaluation'); await testSubjects.existOrFail('mlDFAnalyticsRegressionGenMSEstat'); await testSubjects.existOrFail('mlDFAnalyticsRegressionGenRSquaredStat'); await testSubjects.existOrFail('mlDFAnalyticsRegressionTrainingMSEstat'); @@ -27,7 +27,7 @@ export function MachineLearningDataFrameAnalyticsResultsProvider({ }, async assertClassificationEvaluatePanelElementsExists() { - await testSubjects.existOrFail('mlDFAnalyticsClassificationExplorationEvaluatePanel'); + await testSubjects.existOrFail('mlDFExpandableSection-ClassificationEvaluation'); await testSubjects.existOrFail('mlDFAnalyticsClassificationExplorationConfusionMatrix'); },