Skip to content

Commit

Permalink
[ML] DF Analytics Creation: add progress indicator (elastic#69583) (e…
Browse files Browse the repository at this point in the history
…lastic#69837)

* add progress indicator to creation wizard page

* only show progress bar if job is started immediately

* add title and switch to timeout

* fix progress check

* clean up interval on unmount

* fix types

* clear interval if stats undefined. show progress if job created
  • Loading branch information
alvarezmelissa87 authored Jun 24, 2020
1 parent eb94c7f commit 1716239
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { CreateAnalyticsFormProps } from '../../../analytics_management/hooks/us
import { Messages } from '../shared';
import { ANALYTICS_STEPS } from '../../page';
import { BackToListPanel } from '../back_to_list_panel';
import { ProgressStats } from './progress_stats';

interface Props extends CreateAnalyticsFormProps {
step: ANALYTICS_STEPS;
Expand All @@ -27,15 +28,18 @@ interface Props extends CreateAnalyticsFormProps {
export const CreateStep: FC<Props> = ({ actions, state, step }) => {
const { createAnalyticsJob, startAnalyticsJob } = actions;
const { isAdvancedEditorValidJson, isJobCreated, isJobStarted, isValid, requestMessages } = state;
const { jobId } = state.form;

const [checked, setChecked] = useState<boolean>(true);
const [showProgress, setShowProgress] = useState<boolean>(false);

if (step !== ANALYTICS_STEPS.CREATE) return null;

const handleCreation = async () => {
await createAnalyticsJob();

if (checked) {
setShowProgress(true);
startAnalyticsJob();
}
};
Expand Down Expand Up @@ -82,6 +86,7 @@ export const CreateStep: FC<Props> = ({ actions, state, step }) => {
)}
<EuiSpacer size="s" />
<Messages messages={requestMessages} />
{isJobCreated === true && showProgress && <ProgressStats jobId={jobId} />}
{isJobCreated === true && <BackToListPanel />}
</Fragment>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* 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, useState, useEffect } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiProgress, EuiSpacer, EuiText } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useMlKibana } from '../../../../../contexts/kibana';
import { getDataFrameAnalyticsProgressPhase } from '../../../analytics_management/components/analytics_list/common';
import { isGetDataFrameAnalyticsStatsResponseOk } from '../../../analytics_management/services/analytics_service/get_analytics';
import { ml } from '../../../../../services/ml_api_service';
import { DataFrameAnalyticsId } from '../../../../common/analytics';

export const PROGRESS_REFRESH_INTERVAL_MS = 1000;

export const ProgressStats: FC<{ jobId: DataFrameAnalyticsId }> = ({ jobId }) => {
const [initialized, setInitialized] = useState<boolean>(false);
const [currentProgress, setCurrentProgress] = useState<
| {
currentPhase: number;
progress: number;
totalPhases: number;
}
| undefined
>(undefined);

const {
services: { notifications },
} = useMlKibana();

useEffect(() => {
setInitialized(true);
}, []);

useEffect(() => {
const interval = setInterval(async () => {
try {
const analyticsStats = await ml.dataFrameAnalytics.getDataFrameAnalyticsStats(jobId);
const jobStats = isGetDataFrameAnalyticsStatsResponseOk(analyticsStats)
? analyticsStats.data_frame_analytics[0]
: undefined;

if (jobStats !== undefined) {
const progressStats = getDataFrameAnalyticsProgressPhase(jobStats);
setCurrentProgress(progressStats);
if (
progressStats.currentPhase === progressStats.totalPhases &&
progressStats.progress === 100
) {
clearInterval(interval);
}
} else {
clearInterval(interval);
}
} catch (e) {
notifications.toasts.addDanger(
i18n.translate('xpack.ml.dataframe.analytics.create.analyticsProgressErrorMessage', {
defaultMessage: 'An error occurred getting progress stats for analytics job {jobId}',
values: { jobId },
})
);
clearInterval(interval);
}
}, PROGRESS_REFRESH_INTERVAL_MS);

return () => clearInterval(interval);
}, [initialized]);

if (currentProgress === undefined) return null;

return (
<>
<EuiSpacer />
<EuiText size="m">
<strong>
{i18n.translate('xpack.ml.dataframe.analytics.create.analyticsProgressTitle', {
defaultMessage: 'Progress',
})}
</strong>
</EuiText>
<EuiSpacer size="s" />
<EuiFlexGroup alignItems="center">
<EuiFlexItem grow={false}>
<EuiText size="s">
<strong>
{i18n.translate('xpack.ml.dataframe.analytics.create.analyticsProgressPhaseTitle', {
defaultMessage: 'Phase',
})}{' '}
{currentProgress.currentPhase}/{currentProgress.totalPhases}
</strong>
</EuiText>
</EuiFlexItem>
<EuiFlexItem style={{ width: '400px' }} grow={false}>
<EuiProgress
value={currentProgress.progress}
max={100}
color="primary"
size="l"
data-test-subj="mlAnalyticsCreationWizardProgress"
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText size="s">{`${currentProgress.progress}%`}</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</>
);
};

0 comments on commit 1716239

Please sign in to comment.