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 9341c0aa1a33..4c4731d0dad5 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 @@ -56,6 +56,13 @@ export const OutlierExploration: FC = React.memo(({ jobId }) = const { columnsWithCharts, errorMessage, status, tableItems } = outlierData; + /* eslint-disable-next-line react-hooks/rules-of-hooks */ + const colorRange = useColorRange( + COLOR_RANGE.BLUE, + COLOR_RANGE_SCALE.INFLUENCER, + jobConfig !== undefined ? getFeatureCount(jobConfig.dest.results_field, tableItems) : 1 + ); + // if it's a searchBar syntax error leave the table visible so they can try again if (status === INDEX_STATUS.ERROR && !errorMessage.includes('failed to create query')) { return ( @@ -74,13 +81,6 @@ export const OutlierExploration: FC = React.memo(({ jobId }) = ); } - /* eslint-disable-next-line react-hooks/rules-of-hooks */ - const colorRange = useColorRange( - COLOR_RANGE.BLUE, - COLOR_RANGE_SCALE.INFLUENCER, - jobConfig !== undefined ? getFeatureCount(jobConfig.dest.results_field, tableItems) : 1 - ); - return ( {jobConfig !== undefined && needsDestIndexPattern && ( diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/get_view_link_status.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/get_view_link_status.ts new file mode 100644 index 000000000000..e5f6c27582a0 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/get_view_link_status.ts @@ -0,0 +1,83 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { + isRegressionAnalysis, + isOutlierAnalysis, + isClassificationAnalysis, +} from '../../../../common/analytics'; +import { + DataFrameAnalyticsListRow, + isDataFrameAnalyticsStopped, + isDataFrameAnalyticsFailed, + getDataFrameAnalyticsProgressPhase, +} from '../analytics_list/common'; + +const unknownJobTypeMessage = i18n.translate( + 'xpack.ml.dataframe.analyticsList.viewActionUnknownJobTypeToolTipContent', + { + defaultMessage: 'There is no results page available for this type of data frame analytics job.', + } +); +const jobNotStartedMessage = i18n.translate( + 'xpack.ml.dataframe.analyticsList.viewActionJobNotStartedToolTipContent', + { + defaultMessage: + 'The data frame analytics job did not start. There is no results page available.', + } +); +const jobNotFinishedMessage = i18n.translate( + 'xpack.ml.dataframe.analyticsList.viewActionJobNotFinishedToolTipContent', + { + defaultMessage: + 'The data frame analytics job is not finished. There is no results page available.', + } +); +const jobFailedMessage = i18n.translate( + 'xpack.ml.dataframe.analyticsList.viewActionJobFailedToolTipContent', + { + defaultMessage: 'The data frame analytics job failed. There is no results page available.', + } +); + +interface ViewLinkStatusReturn { + disabled: boolean; + tooltipContent?: string; +} + +export function getViewLinkStatus(item: DataFrameAnalyticsListRow): ViewLinkStatusReturn { + const viewLinkStatus: ViewLinkStatusReturn = { disabled: false }; + + const progressStats = getDataFrameAnalyticsProgressPhase(item.stats); + const jobFailed = isDataFrameAnalyticsFailed(item.stats.state); + const jobNotStarted = progressStats.currentPhase === 1 && progressStats.progress === 0; + const jobFinished = + isDataFrameAnalyticsStopped(item.stats.state) && + progressStats.currentPhase === progressStats.totalPhases && + progressStats.progress === 100; + const isUnknownJobType = + !isRegressionAnalysis(item.config.analysis) && + !isOutlierAnalysis(item.config.analysis) && + !isClassificationAnalysis(item.config.analysis); + + const disabled = !jobFinished || jobFailed || isUnknownJobType; + + if (disabled) { + viewLinkStatus.disabled = true; + if (isUnknownJobType) { + viewLinkStatus.tooltipContent = unknownJobTypeMessage; + } else if (jobFailed) { + viewLinkStatus.tooltipContent = jobFailedMessage; + } else if (jobNotStarted) { + viewLinkStatus.tooltipContent = jobNotStartedMessage; + } else if (!jobFinished) { + viewLinkStatus.tooltipContent = jobNotFinishedMessage; + } + } + + return viewLinkStatus; +} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/view_button.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/view_button.tsx index 52b2513d13e3..8a4509ebfd00 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/view_button.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/view_button.tsx @@ -8,16 +8,13 @@ import React, { FC } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiButtonEmpty, EuiToolTip } from '@elastic/eui'; -import { - getAnalysisType, - isRegressionAnalysis, - isOutlierAnalysis, - isClassificationAnalysis, -} from '../../../../common/analytics'; +import { getAnalysisType } from '../../../../common/analytics'; import { useMlKibana } from '../../../../../contexts/kibana'; import { getResultsUrl, DataFrameAnalyticsListRow } from '../analytics_list/common'; +import { getViewLinkStatus } from './get_view_link_status'; + interface ViewButtonProps { item: DataFrameAnalyticsListRow; isManagementTable: boolean; @@ -30,11 +27,8 @@ export const ViewButton: FC = ({ item, isManagementTable }) => }, } = useMlKibana(); + const { disabled, tooltipContent } = getViewLinkStatus(item); const analysisType = getAnalysisType(item.config.analysis); - const buttonDisabled = - !isRegressionAnalysis(item.config.analysis) && - !isOutlierAnalysis(item.config.analysis) && - !isClassificationAnalysis(item.config.analysis); const url = getResultsUrl(item.id, analysisType); const navigator = isManagementTable @@ -52,7 +46,7 @@ export const ViewButton: FC = ({ item, isManagementTable }) => data-test-subj="mlAnalyticsJobViewButton" flush="left" iconType="visTable" - isDisabled={buttonDisabled} + isDisabled={disabled} onClick={navigator} size="s" > @@ -60,15 +54,9 @@ export const ViewButton: FC = ({ item, isManagementTable }) => ); - if (buttonDisabled) { + if (disabled) { return ( - + {button} );