From 2eea2c2e077e98a44676ac204aa4c0757df8476a Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Thu, 20 Oct 2022 13:18:33 -0600 Subject: [PATCH] [ML] Display link to create data view from error cases in data frame analytics results pages (#143596) * add link to dataView creation when no dataView * update translations * add util function for destIndex * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../common/get_destination_index.ts | 11 ++++ .../data_frame_analytics/common/index.ts | 1 + .../common/use_results_view_config.ts | 5 +- .../exploration_page_wrapper.tsx | 11 +++- .../index_pattern_prompt.tsx | 13 ++--- .../outlier_exploration.tsx | 16 +++++- .../action_clone/clone_action_name.tsx | 53 ++++++++++++++++--- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 10 files changed, 90 insertions(+), 23 deletions(-) create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/common/get_destination_index.ts diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/get_destination_index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/get_destination_index.ts new file mode 100644 index 0000000000000..2058cce04850d --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/get_destination_index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { DataFrameAnalyticsConfig } from '../../../../common/types/data_frame_analytics'; + +export const getDestinationIndex = (jobConfig: DataFrameAnalyticsConfig | undefined) => + (Array.isArray(jobConfig?.dest.index) ? jobConfig?.dest.index[0] : jobConfig?.dest.index) ?? ''; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/index.ts index f47b5b66f4944..d7391f7dfa8b7 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/index.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/index.ts @@ -31,6 +31,7 @@ export { getDefaultFieldsFromJobCaps, sortExplorationResultsFields, MAX_COLUMNS export { getIndexData } from './get_index_data'; export { getIndexFields } from './get_index_fields'; +export { getDestinationIndex } from './get_destination_index'; export { getScatterplotMatrixLegendType } from './get_scatterplot_matrix_legend_type'; export { useResultsViewConfig } from './use_results_view_config'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts index 9f739bfb3d58c..df430142a3193 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts @@ -29,6 +29,7 @@ import { isClassificationAnalysis, isRegressionAnalysis, } from '../../../../common/util/analytics_utils'; +import { getDestinationIndex } from './get_destination_index'; export const useResultsViewConfig = (jobId: string) => { const mlContext = useMlContext(); @@ -95,9 +96,7 @@ export const useResultsViewConfig = (jobId: string) => { } try { - const destIndex = Array.isArray(jobConfigUpdate.dest.index) - ? jobConfigUpdate.dest.index[0] - : jobConfigUpdate.dest.index; + const destIndex = getDestinationIndex(jobConfigUpdate); const destDataViewId = (await getDataViewIdFromName(destIndex)) ?? destIndex; let dataView: DataView | undefined; 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 17453dd87b0d0..482c214f884a3 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 @@ -19,6 +19,7 @@ import { getScatterplotMatrixLegendType, useResultsViewConfig, DataFrameAnalyticsConfig, + getDestinationIndex, } from '../../../../common'; import { ResultsSearchQuery, ANALYSIS_CONFIG_TYPE } from '../../../../common/analytics'; @@ -32,6 +33,7 @@ import { LoadingPanel } from '../loading_panel'; import { FeatureImportanceSummaryPanelProps } from '../total_feature_importance_summary/feature_importance_summary'; import { useExplorationUrlState } from '../../hooks/use_exploration_url_state'; import { ExplorationQueryBarProps } from '../exploration_query_bar/exploration_query_bar'; +import { IndexPatternPrompt } from '../index_pattern_prompt'; function getFilters(resultsField: string) { return { @@ -114,6 +116,8 @@ export const ExplorationPageWrapper: FC = ({ }; const resultsField = jobConfig?.dest.results_field ?? ''; + const destIndex = getDestinationIndex(jobConfig); + const scatterplotFieldOptions = useScatterplotFieldOptions( indexPattern, jobConfig?.analyzed_fields?.includes, @@ -131,7 +135,12 @@ export const ExplorationPageWrapper: FC = ({ color="danger" iconType="cross" > -

{indexPatternErrorMessage}

+

+ {indexPatternErrorMessage} + {needsDestIndexPattern ? ( + + ) : null} +

); 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 1f9362d7e56ca..cd60be7290b96 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 @@ -11,10 +11,11 @@ import { EuiLink, EuiText } from '@elastic/eui'; import { useMlKibana } from '../../../../../contexts/kibana'; interface Props { - destIndex: string; + color?: string; + destIndex?: string; } -export const IndexPatternPrompt: FC = ({ destIndex }) => { +export const IndexPatternPrompt: FC = ({ destIndex, color }) => { const { services: { http: { basePath }, @@ -30,20 +31,20 @@ export const IndexPatternPrompt: FC = ({ destIndex }) => { return ( <> - + {canCreateDataView === true ? ( ; @@ -90,6 +96,7 @@ export const OutlierExploration: FC = React.memo(({ jobId }) = jobConfig?.analyzed_fields?.excludes, resultsField ); + const destIndex = getDestinationIndex(jobConfig); if (indexPatternErrorMessage !== undefined) { return ( @@ -101,7 +108,12 @@ export const OutlierExploration: FC = React.memo(({ jobId }) = color="danger" iconType="cross" > -

{indexPatternErrorMessage}

+

+ {indexPatternErrorMessage} + {needsDestIndexPattern ? ( + + ) : null} +

); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx index 7d2798f020242..efe5275685e9c 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx @@ -5,10 +5,12 @@ * 2.0. */ -import { EuiToolTip } from '@elastic/eui'; +import { EuiToolTip, EuiLink, EuiText } from '@elastic/eui'; import React, { FC } from 'react'; import { cloneDeep, isEqual } from 'lodash'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { toMountPoint, wrapWithTheme } from '@kbn/kibana-react-plugin/public'; import { DeepReadonly } from '../../../../../../../common/types/common'; import { DataFrameAnalyticsConfig, isOutlierAnalysis } from '../../../../common'; import { isClassificationAnalysis, isRegressionAnalysis } from '../../../../common/analytics'; @@ -401,9 +403,15 @@ export const useNavigateToWizardWithClonedJob = () => { services: { notifications: { toasts }, data: { dataViews }, + http: { basePath }, + application: { capabilities }, + theme, }, } = useMlKibana(); + const theme$ = theme.theme$; const navigateToPath = useNavigateToPath(); + const canCreateDataView = + capabilities.savedObjectsManagement.edit === true || capabilities.indexPatterns.save === true; return async (item: Pick) => { const sourceIndex = Array.isArray(item.config.source.index) @@ -416,13 +424,42 @@ export const useNavigateToWizardWithClonedJob = () => { if (dv !== undefined) { sourceIndexId = dv.id; } else { - toasts.addDanger( - i18n.translate('xpack.ml.dataframe.analyticsList.noSourceDataViewForClone', { - defaultMessage: - 'Unable to clone the analytics job. No data view exists for index {dataView}.', - values: { dataView: sourceIndex }, - }) - ); + toasts.addDanger({ + title: toMountPoint( + wrapWithTheme( + <> + + {canCreateDataView ? ( + + + + + ), + }} + /> + + ) : null} + , + theme$ + ) + ), + }); } } catch (e) { const error = extractErrorMessage(e); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 1f04ed95b4419..72d65ce1e4adb 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -19170,7 +19170,6 @@ "xpack.ml.dataframe.analyticsList.errorWithCheckingIfUserCanDeleteIndexNotificationErrorMessage": "Une erreur s'est produite lors de la vérification de la possibilité pour un utilisateur de supprimer {destinationIndex} : {error}", "xpack.ml.dataframe.analyticsList.fetchSourceDataViewForCloneErrorMessage": "Une erreur s’est produite lors de la vérification de l’existence de la vue de données {dataView} : {error}", "xpack.ml.dataframe.analyticsList.forceStopModalBody": "{analyticsId} est en état d'échec. Vous devez arrêter la tâche et corriger la défaillance.", - "xpack.ml.dataframe.analyticsList.noSourceDataViewForClone": "Impossible de cloner la tâche d'analyse. Il n’existe aucune vue de données pour l’index {dataView}.", "xpack.ml.dataframe.analyticsList.progressOfPhase": "Progression de la phase {currentPhase} : {progress}%", "xpack.ml.dataframe.analyticsList.rowCollapse": "Masquer les détails pour {analyticsId}", "xpack.ml.dataframe.analyticsList.rowExpand": "Afficher les détails pour {analyticsId}", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index b529dafaecfe2..3dd5b3c227bb0 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -19151,7 +19151,6 @@ "xpack.ml.dataframe.analyticsList.errorWithCheckingIfUserCanDeleteIndexNotificationErrorMessage": "ユーザーが{destinationIndex}を削除できるかどうかを確認するときにエラーが発生しました。{error}", "xpack.ml.dataframe.analyticsList.fetchSourceDataViewForCloneErrorMessage": "データビュー{dataView}が存在するかどうかを確認しているときにエラーが発生しました:{error}", "xpack.ml.dataframe.analyticsList.forceStopModalBody": "{analyticsId}は失敗状態です。ジョブを停止して、エラーを修正する必要があります。", - "xpack.ml.dataframe.analyticsList.noSourceDataViewForClone": "分析ジョブを複製できません。インデックス{dataView}のデータビューは存在しません。", "xpack.ml.dataframe.analyticsList.progressOfPhase": "フェーズ{currentPhase}の進捗:{progress}%", "xpack.ml.dataframe.analyticsList.rowCollapse": "{analyticsId}の詳細を非表示", "xpack.ml.dataframe.analyticsList.rowExpand": "{analyticsId}の詳細を表示", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index d6f202da17c15..bef75b6c74de9 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -19177,7 +19177,6 @@ "xpack.ml.dataframe.analyticsList.errorWithCheckingIfUserCanDeleteIndexNotificationErrorMessage": "检查用户是否能够删除 {destinationIndex} 时发生错误:{error}", "xpack.ml.dataframe.analyticsList.fetchSourceDataViewForCloneErrorMessage": "检查数据视图 {dataView} 是否存在时发生错误:{error}", "xpack.ml.dataframe.analyticsList.forceStopModalBody": "{analyticsId} 处于失败状态。您必须停止该作业并修复失败问题。", - "xpack.ml.dataframe.analyticsList.noSourceDataViewForClone": "无法克隆分析作业。对于索引 {dataView},不存在数据视图。", "xpack.ml.dataframe.analyticsList.progressOfPhase": "阶段 {currentPhase} 的进度:{progress}%", "xpack.ml.dataframe.analyticsList.rowCollapse": "隐藏 {analyticsId} 的详情", "xpack.ml.dataframe.analyticsList.rowExpand": "显示 {analyticsId} 的详情",