Skip to content

Commit 3fb77fb

Browse files
[ML] DF Analytics creation wizard: show link to results (#74025)
* show view results card once job complete * update types * update types and move css to own file
1 parent 8759646 commit 3fb77fb

File tree

10 files changed

+201
-86
lines changed

10 files changed

+201
-86
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
@import 'pages/analytics_exploration/components/regression_exploration/index';
22
@import 'pages/analytics_management/components/analytics_list/index';
33
@import 'pages/analytics_management/components/create_analytics_button/index';
4+
@import 'pages/analytics_creation/components/index';
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.dfAnalyticsCreationWizard__card {
2+
width: 300px;
3+
}

x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/back_to_list_panel/back_to_list_panel.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
import React, { FC, Fragment } from 'react';
8-
import { EuiCard, EuiHorizontalRule, EuiIcon } from '@elastic/eui';
8+
import { EuiCard, EuiIcon } from '@elastic/eui';
99
import { i18n } from '@kbn/i18n';
1010
import { useNavigateToPath } from '../../../../../contexts/kibana';
1111

@@ -18,10 +18,8 @@ export const BackToListPanel: FC = () => {
1818

1919
return (
2020
<Fragment>
21-
<EuiHorizontalRule />
2221
<EuiCard
23-
// @ts-ignore
24-
style={{ width: '300px' }}
22+
className="dfAnalyticsCreationWizard__card"
2523
icon={<EuiIcon size="xxl" type="list" />}
2624
title={i18n.translate('xpack.ml.dataframe.analytics.create.analyticsListCardTitle', {
2725
defaultMessage: 'Data Frame Analytics',

x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/create_step/create_step.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ import { i18n } from '@kbn/i18n';
1818
import { CreateAnalyticsFormProps } from '../../../analytics_management/hooks/use_create_analytics_form';
1919
import { Messages } from '../shared';
2020
import { ANALYTICS_STEPS } from '../../page';
21-
import { BackToListPanel } from '../back_to_list_panel';
22-
import { ProgressStats } from './progress_stats';
21+
import { CreateStepFooter } from '../create_step_footer';
2322

2423
interface Props extends CreateAnalyticsFormProps {
2524
step: ANALYTICS_STEPS;
@@ -28,7 +27,7 @@ interface Props extends CreateAnalyticsFormProps {
2827
export const CreateStep: FC<Props> = ({ actions, state, step }) => {
2928
const { createAnalyticsJob, startAnalyticsJob } = actions;
3029
const { isAdvancedEditorValidJson, isJobCreated, isJobStarted, isValid, requestMessages } = state;
31-
const { jobId } = state.form;
30+
const { jobId, jobType } = state.form;
3231

3332
const [checked, setChecked] = useState<boolean>(true);
3433
const [showProgress, setShowProgress] = useState<boolean>(false);
@@ -86,8 +85,9 @@ export const CreateStep: FC<Props> = ({ actions, state, step }) => {
8685
)}
8786
<EuiSpacer size="s" />
8887
<Messages messages={requestMessages} />
89-
{isJobCreated === true && showProgress && <ProgressStats jobId={jobId} />}
90-
{isJobCreated === true && <BackToListPanel />}
88+
{isJobCreated === true && (
89+
<CreateStepFooter jobId={jobId} jobType={jobType!} showProgress={showProgress} />
90+
)}
9191
</div>
9292
);
9393
};
Lines changed: 46 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,43 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7-
import React, { FC, useState, useEffect } from 'react';
8-
import {
9-
EuiCallOut,
10-
EuiFlexGroup,
11-
EuiFlexItem,
12-
EuiProgress,
13-
EuiSpacer,
14-
EuiText,
15-
} from '@elastic/eui';
7+
import React, { FC, useEffect, useState } from 'react';
8+
import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui';
169
import { i18n } from '@kbn/i18n';
17-
import { useMlKibana } from '../../../../../contexts/kibana';
10+
1811
import {
1912
getDataFrameAnalyticsProgressPhase,
2013
DATA_FRAME_TASK_STATE,
2114
} from '../../../analytics_management/components/analytics_list/common';
2215
import { isGetDataFrameAnalyticsStatsResponseOk } from '../../../analytics_management/services/analytics_service/get_analytics';
16+
import { useMlKibana } from '../../../../../contexts/kibana';
2317
import { ml } from '../../../../../services/ml_api_service';
24-
import { DataFrameAnalyticsId } from '../../../../common/analytics';
18+
import { BackToListPanel } from '../back_to_list_panel';
19+
import { ViewResultsPanel } from '../view_results_panel';
20+
import { ProgressStats } from './progress_stats';
21+
import { ANALYSIS_CONFIG_TYPE } from '../../../../common/analytics';
2522

2623
export const PROGRESS_REFRESH_INTERVAL_MS = 1000;
2724

28-
export const ProgressStats: FC<{ jobId: DataFrameAnalyticsId }> = ({ jobId }) => {
25+
interface Props {
26+
jobId: string;
27+
jobType: ANALYSIS_CONFIG_TYPE;
28+
showProgress: boolean;
29+
}
30+
31+
export interface AnalyticsProgressStats {
32+
currentPhase: number;
33+
progress: number;
34+
totalPhases: number;
35+
}
36+
37+
export const CreateStepFooter: FC<Props> = ({ jobId, jobType, showProgress }) => {
2938
const [initialized, setInitialized] = useState<boolean>(false);
3039
const [failedJobMessage, setFailedJobMessage] = useState<string | undefined>(undefined);
31-
const [currentProgress, setCurrentProgress] = useState<
32-
| {
33-
currentPhase: number;
34-
progress: number;
35-
totalPhases: number;
36-
}
37-
| undefined
38-
>(undefined);
40+
const [jobFinished, setJobFinished] = useState<boolean>(false);
41+
const [currentProgress, setCurrentProgress] = useState<AnalyticsProgressStats | undefined>(
42+
undefined
43+
);
3944

4045
const {
4146
services: { notifications },
@@ -77,6 +82,7 @@ export const ProgressStats: FC<{ jobId: DataFrameAnalyticsId }> = ({ jobId }) =>
7782
jobStats.state === DATA_FRAME_TASK_STATE.STOPPED
7883
) {
7984
clearInterval(interval);
85+
setJobFinished(true);
8086
}
8187
} else {
8288
clearInterval(interval);
@@ -95,62 +101,26 @@ export const ProgressStats: FC<{ jobId: DataFrameAnalyticsId }> = ({ jobId }) =>
95101
return () => clearInterval(interval);
96102
}, [initialized]);
97103

98-
if (currentProgress === undefined) return null;
99-
100104
return (
101-
<>
102-
<EuiSpacer />
103-
{failedJobMessage !== undefined && (
104-
<>
105-
<EuiCallOut
106-
data-test-subj="analyticsWizardProgressCallout"
107-
title={i18n.translate(
108-
'xpack.ml.dataframe.analytics.create.analyticsProgressCalloutTitle',
109-
{
110-
defaultMessage: 'Job failed',
111-
}
112-
)}
113-
color={'danger'}
114-
iconType={'alert'}
115-
size="s"
116-
>
117-
<p>{failedJobMessage}</p>
118-
</EuiCallOut>
119-
<EuiSpacer size="s" />
120-
</>
121-
)}
122-
<EuiText size="m">
123-
<strong>
124-
{i18n.translate('xpack.ml.dataframe.analytics.create.analyticsProgressTitle', {
125-
defaultMessage: 'Progress',
126-
})}
127-
</strong>
128-
</EuiText>
129-
<EuiSpacer size="s" />
130-
<EuiFlexGroup alignItems="center">
131-
<EuiFlexItem grow={false}>
132-
<EuiText size="s">
133-
<strong>
134-
{i18n.translate('xpack.ml.dataframe.analytics.create.analyticsProgressPhaseTitle', {
135-
defaultMessage: 'Phase',
136-
})}{' '}
137-
{currentProgress.currentPhase}/{currentProgress.totalPhases}
138-
</strong>
139-
</EuiText>
140-
</EuiFlexItem>
141-
<EuiFlexItem style={{ width: '400px' }} grow={false}>
142-
<EuiProgress
143-
value={currentProgress.progress}
144-
max={100}
145-
color="primary"
146-
size="l"
147-
data-test-subj="mlAnalyticsCreationWizardProgress"
148-
/>
149-
</EuiFlexItem>
150-
<EuiFlexItem grow={false}>
151-
<EuiText size="s">{`${currentProgress.progress}%`}</EuiText>
152-
</EuiFlexItem>
153-
</EuiFlexGroup>
154-
</>
105+
<EuiFlexGroup direction="column">
106+
<EuiFlexItem grow={false}>
107+
{showProgress && (
108+
<ProgressStats currentProgress={currentProgress} failedJobMessage={failedJobMessage} />
109+
)}
110+
</EuiFlexItem>
111+
<EuiFlexItem grow={false}>
112+
<EuiHorizontalRule />
113+
<EuiFlexGroup>
114+
<EuiFlexItem grow={false}>
115+
<BackToListPanel />
116+
</EuiFlexItem>
117+
{jobFinished === true && (
118+
<EuiFlexItem grow={false}>
119+
<ViewResultsPanel jobId={jobId} analysisType={jobType} />
120+
</EuiFlexItem>
121+
)}
122+
</EuiFlexGroup>
123+
</EuiFlexItem>
124+
</EuiFlexGroup>
155125
);
156126
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
export { CreateStepFooter } from './create_step_footer';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import React, { FC } from 'react';
8+
import {
9+
EuiCallOut,
10+
EuiFlexGroup,
11+
EuiFlexItem,
12+
EuiProgress,
13+
EuiSpacer,
14+
EuiText,
15+
} from '@elastic/eui';
16+
import { i18n } from '@kbn/i18n';
17+
import { AnalyticsProgressStats } from './create_step_footer';
18+
19+
interface Props {
20+
currentProgress?: AnalyticsProgressStats;
21+
failedJobMessage: string | undefined;
22+
}
23+
24+
export const ProgressStats: FC<Props> = ({ currentProgress, failedJobMessage }) => {
25+
if (currentProgress === undefined) return null;
26+
27+
return (
28+
<>
29+
<EuiSpacer />
30+
{failedJobMessage !== undefined && (
31+
<>
32+
<EuiCallOut
33+
data-test-subj="analyticsWizardProgressCallout"
34+
title={i18n.translate(
35+
'xpack.ml.dataframe.analytics.create.analyticsProgressCalloutTitle',
36+
{
37+
defaultMessage: 'Job failed',
38+
}
39+
)}
40+
color={'danger'}
41+
iconType={'alert'}
42+
size="s"
43+
>
44+
<p>{failedJobMessage}</p>
45+
</EuiCallOut>
46+
<EuiSpacer size="s" />
47+
</>
48+
)}
49+
<EuiText size="m">
50+
<strong>
51+
{i18n.translate('xpack.ml.dataframe.analytics.create.analyticsProgressTitle', {
52+
defaultMessage: 'Progress',
53+
})}
54+
</strong>
55+
</EuiText>
56+
<EuiSpacer size="s" />
57+
<EuiFlexGroup alignItems="center">
58+
<EuiFlexItem grow={false}>
59+
<EuiText size="s">
60+
<strong>
61+
{i18n.translate('xpack.ml.dataframe.analytics.create.analyticsProgressPhaseTitle', {
62+
defaultMessage: 'Phase',
63+
})}{' '}
64+
{currentProgress.currentPhase}/{currentProgress.totalPhases}
65+
</strong>
66+
</EuiText>
67+
</EuiFlexItem>
68+
<EuiFlexItem style={{ width: '400px' }} grow={false}>
69+
<EuiProgress
70+
value={currentProgress.progress}
71+
max={100}
72+
color="primary"
73+
size="l"
74+
data-test-subj="mlAnalyticsCreationWizardProgress"
75+
/>
76+
</EuiFlexItem>
77+
<EuiFlexItem grow={false}>
78+
<EuiText size="s">{`${currentProgress.progress}%`}</EuiText>
79+
</EuiFlexItem>
80+
</EuiFlexGroup>
81+
</>
82+
);
83+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
export { ViewResultsPanel } from './view_results_panel';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import React, { FC, Fragment } from 'react';
8+
import { EuiCard, EuiIcon } from '@elastic/eui';
9+
import { i18n } from '@kbn/i18n';
10+
import { useNavigateToPath } from '../../../../../contexts/kibana';
11+
import { getResultsUrl } from '../../../analytics_management/components/analytics_list/common';
12+
import { ANALYSIS_CONFIG_TYPE } from '../../../../common/analytics';
13+
14+
interface Props {
15+
jobId: string;
16+
analysisType: ANALYSIS_CONFIG_TYPE;
17+
}
18+
19+
export const ViewResultsPanel: FC<Props> = ({ jobId, analysisType }) => {
20+
const navigateToPath = useNavigateToPath();
21+
22+
const redirectToAnalyticsManagementPage = async () => {
23+
const path = getResultsUrl(jobId, analysisType);
24+
await navigateToPath(path);
25+
};
26+
27+
return (
28+
<Fragment>
29+
<EuiCard
30+
className="dfAnalyticsCreationWizard__card"
31+
icon={<EuiIcon size="xxl" type="tableDensityNormal" />}
32+
title={i18n.translate('xpack.ml.dataframe.analytics.create.viewResultsCardTitle', {
33+
defaultMessage: 'View Results',
34+
})}
35+
description={i18n.translate(
36+
'xpack.ml.dataframe.analytics.create.viewResultsCardDescription',
37+
{
38+
defaultMessage: 'View results for the analytics job.',
39+
}
40+
)}
41+
onClick={redirectToAnalyticsManagementPage}
42+
data-test-subj="analyticsWizardViewResultsCard"
43+
/>
44+
</Fragment>
45+
);
46+
};

x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/common.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,6 @@ export function isCompletedAnalyticsJob(stats: DataFrameAnalyticsStats) {
130130
return stats.state === DATA_FRAME_TASK_STATE.STOPPED && progress === 100;
131131
}
132132

133-
export function getResultsUrl(jobId: string, analysisType: string) {
133+
export function getResultsUrl(jobId: string, analysisType: ANALYSIS_CONFIG_TYPE | string) {
134134
return `#/data_frame_analytics/exploration?_g=(ml:(jobId:${jobId},analysisType:${analysisType}))`;
135135
}

0 commit comments

Comments
 (0)