Skip to content

Commit

Permalink
[ML] refactor getAnalyticFactory, remove analytics stats bar component
Browse files Browse the repository at this point in the history
  • Loading branch information
darnautov committed Oct 28, 2019
1 parent dcb28b0 commit fab0e16
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 210 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React, { Fragment, FC, useState } from 'react';
import React, { Fragment, FC, useState, useEffect } from 'react';

import { i18n } from '@kbn/i18n';

Expand Down Expand Up @@ -33,6 +33,7 @@ import {
SortDirection,
SORT_DIRECTION,
} from '../../../../../components/ml_in_memory_table';
import { AnalyticStatsBarStats } from '../../../../../components/stats_bar';

function getItemIdToExpandedRowMap(
itemIds: DataFrameAnalyticsId[],
Expand Down Expand Up @@ -63,19 +64,24 @@ interface Props {
isMlEnabledInSpace?: boolean;
blockRefresh?: boolean;
openCreateJobModal?: ActionDispatchers['openModal'];
onJobStatsChange?: (stats: AnalyticStatsBarStats | undefined) => void;
}
// isManagementTable - for use in Kibana managagement ML section
export const DataFrameAnalyticsList: FC<Props> = ({
isManagementTable = false,
isMlEnabledInSpace = true,
blockRefresh = false,
openCreateJobModal,
onJobStatsChange,
}) => {
const [isInitialized, setIsInitialized] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [filterActive, setFilterActive] = useState(false);

const [analytics, setAnalytics] = useState<DataFrameAnalyticsListRow[]>([]);
const [analyticsStats, setAnalyticsStats] = useState<AnalyticStatsBarStats | undefined>(
undefined
);
const [filteredAnalytics, setFilteredAnalytics] = useState<DataFrameAnalyticsListRow[]>([]);
const [expandedRowItemIds, setExpandedRowItemIds] = useState<DataFrameAnalyticsId[]>([]);

Expand All @@ -94,10 +100,18 @@ export const DataFrameAnalyticsList: FC<Props> = ({

const getAnalytics = getAnalyticsFactory(
setAnalytics,
setAnalyticsStats,
setErrorMessage,
setIsInitialized,
blockRefresh
);

useEffect(() => {
if (onJobStatsChange) {
onJobStatsChange(analyticsStats);
}
}, [analyticsStats]);

// Subscribe to the refresh observable to trigger reloading the analytics list.
useRefreshAnalyticsList({
isLoading: setIsLoading,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React, { FC, Fragment, useEffect, useState } from 'react';
import React, { FC, Fragment, useState } from 'react';

import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
Expand All @@ -30,7 +30,6 @@ import { RefreshAnalyticsListButton } from './components/refresh_analytics_list_
import { useRefreshInterval } from './components/analytics_list/use_refresh_interval';
import { useCreateAnalyticsForm } from './hooks/use_create_analytics_form';
import { AnalyticStatsBarStats, StatsBar } from '../../../components/stats_bar';
import { getAnalyticsJobsStats } from './resolvers';

export const Page: FC = () => {
const [blockRefresh, setBlockRefresh] = useState(false);
Expand All @@ -40,14 +39,6 @@ export const Page: FC = () => {

useRefreshInterval(setBlockRefresh);

const setAnalyticsJobsStats = async () => {
setStats(await getAnalyticsJobsStats());
};

useEffect(() => {
setAnalyticsJobsStats();
}, []);

const createAnalyticsForm = useCreateAnalyticsForm();

return (
Expand Down Expand Up @@ -105,6 +96,9 @@ export const Page: FC = () => {
<DataFrameAnalyticsList
blockRefresh={blockRefresh}
openCreateJobModal={createAnalyticsForm.actions.openModal}
onJobStatsChange={analyticsStats => {
setStats(analyticsStats);
}}
/>
</EuiPanel>
</EuiPageContentBody>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { i18n } from '@kbn/i18n';
import {
GetDataFrameAnalyticsStatsResponse,
GetDataFrameAnalyticsStatsResponseError,
Expand All @@ -19,8 +20,12 @@ import {
import {
DATA_FRAME_MODE,
DataFrameAnalyticsListRow,
isDataFrameAnalyticsFailed,
isDataFrameAnalyticsRunning,
isDataFrameAnalyticsStats,
isDataFrameAnalyticsStopped,
} from '../../components/analytics_list/common';
import { AnalyticStatsBarStats } from '../../../../../components/stats_bar';

interface GetDataFrameAnalyticsResponse {
count: number;
Expand All @@ -39,8 +44,68 @@ export const isGetDataFrameAnalyticsStatsResponseOk = (

export type GetAnalytics = (forceRefresh?: boolean) => void;

/**
* Gets initial object for analytics stats.
*/
export function getInitialAnalyticsStats(): AnalyticStatsBarStats {
return {
total: {
label: i18n.translate('xpack.ml.overview.statsBar.totalAnalyticsLabel', {
defaultMessage: 'Total analytics jobs',
}),
value: 0,
show: true,
},
started: {
label: i18n.translate('xpack.ml.overview.statsBar.runningAnalyticsLabel', {
defaultMessage: 'Running',
}),
value: 0,
show: true,
},
stopped: {
label: i18n.translate('xpack.ml.overview.statsBar.stoppedAnalyticsLabel', {
defaultMessage: 'Stopped',
}),
value: 0,
show: true,
},
failed: {
label: i18n.translate('xpack.ml.overview.statsBar.failedAnalyticsLabel', {
defaultMessage: 'Failed',
}),
value: 0,
show: false,
},
};
}

/**
* Gets analytics jobs stats formatted for the stats bar.
*/
export function getAnalyticsJobsStats(
analyticsStats: GetDataFrameAnalyticsStatsResponseOk
): AnalyticStatsBarStats | undefined {
const resultStats: AnalyticStatsBarStats = analyticsStats.data_frame_analytics.reduce(
(acc, { state }) => {
if (isDataFrameAnalyticsFailed(state)) {
acc.failed.value = ++acc.failed.value;
} else if (isDataFrameAnalyticsRunning(state)) {
acc.started.value = ++acc.started.value;
} else if (isDataFrameAnalyticsStopped(state)) {
acc.stopped.value = ++acc.stopped.value;
}
return acc;
},
getInitialAnalyticsStats()
);
resultStats.total.value = analyticsStats.count;
return resultStats;
}

export const getAnalyticsFactory = (
setAnalytics: React.Dispatch<React.SetStateAction<DataFrameAnalyticsListRow[]>>,
setAnalyticsStats: React.Dispatch<React.SetStateAction<AnalyticStatsBarStats | undefined>>,
setErrorMessage: React.Dispatch<
React.SetStateAction<GetDataFrameAnalyticsStatsResponseError | undefined>
>,
Expand All @@ -62,6 +127,10 @@ export const getAnalyticsFactory = (
const analyticsConfigs: GetDataFrameAnalyticsResponse = await ml.dataFrameAnalytics.getDataFrameAnalytics();
const analyticsStats: GetDataFrameAnalyticsStatsResponse = await ml.dataFrameAnalytics.getDataFrameAnalyticsStats();

const analyticsStatsResult = isGetDataFrameAnalyticsStatsResponseOk(analyticsStats)
? getAnalyticsJobsStats(analyticsStats)
: undefined;

const tableRows = analyticsConfigs.data_frame_analytics.reduce(
(reducedtableRows, config) => {
const stats = isGetDataFrameAnalyticsStatsResponseOk(analyticsStats)
Expand All @@ -88,6 +157,7 @@ export const getAnalyticsFactory = (
);

setAnalytics(tableRows);
setAnalyticsStats(analyticsStatsResult);
setErrorMessage(undefined);
setIsInitialized(true);
refreshAnalyticsList$.next(REFRESH_ANALYTICS_LIST_STATE.IDLE);
Expand All @@ -97,6 +167,7 @@ export const getAnalyticsFactory = (
refreshAnalyticsList$.next(REFRESH_ANALYTICS_LIST_STATE.ERROR);
refreshAnalyticsList$.next(REFRESH_ANALYTICS_LIST_STATE.IDLE);
setAnalytics([]);
setAnalyticsStats(undefined);
setErrorMessage(e);
setIsInitialized(true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,44 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React, { FC, Fragment, useState, useEffect } from 'react';
import React, { FC, useEffect, useState } from 'react';
import {
EuiButton,
EuiButtonEmpty,
EuiCallOut,
EuiEmptyPrompt,
EuiFlexGroup,
EuiFlexItem,
EuiLoadingSpinner,
EuiPanel,
EuiSpacer,
EuiText,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';

import { AnalyticsTable } from './table';
import { getAnalyticsFactory } from '../../../data_frame_analytics/pages/analytics_management/services/analytics_service';
import { DataFrameAnalyticsListRow } from '../../../data_frame_analytics/pages/analytics_management/components/analytics_list/common';
import { AnalyticStatsBarStats, StatsBar } from '../../../components/stats_bar';

interface Props {
jobCreationDisabled: boolean;
}
export const AnalyticsPanel: FC<Props> = ({ jobCreationDisabled }) => {
const [analytics, setAnalytics] = useState<DataFrameAnalyticsListRow[]>([]);
const [analyticsStats, setAnalyticsStats] = useState<AnalyticStatsBarStats | undefined>(
undefined
);
const [errorMessage, setErrorMessage] = useState<any>(undefined);
const [isInitialized, setIsInitialized] = useState(false);

const getAnalytics = getAnalyticsFactory(setAnalytics, setErrorMessage, setIsInitialized, false);
const getAnalytics = getAnalyticsFactory(
setAnalytics,
setAnalyticsStats,
setErrorMessage,
setIsInitialized,
false
);

useEffect(() => {
getAnalytics(true);
Expand All @@ -38,21 +52,19 @@ export const AnalyticsPanel: FC<Props> = ({ jobCreationDisabled }) => {
};

const errorDisplay = (
<Fragment>
<EuiCallOut
title={i18n.translate('xpack.ml.overview.analyticsList.errorPromptTitle', {
defaultMessage: 'An error occurred getting the data frame analytics list.',
})}
color="danger"
iconType="alert"
>
<pre>
{errorMessage && errorMessage.message !== undefined
? errorMessage.message
: JSON.stringify(errorMessage)}
</pre>
</EuiCallOut>
</Fragment>
<EuiCallOut
title={i18n.translate('xpack.ml.overview.analyticsList.errorPromptTitle', {
defaultMessage: 'An error occurred getting the data frame analytics list.',
})}
color="danger"
iconType="alert"
>
<pre>
{errorMessage && errorMessage.message !== undefined
? errorMessage.message
: JSON.stringify(errorMessage)}
</pre>
</EuiCallOut>
);

const panelClass = isInitialized === false ? 'mlOverviewPanel__isLoading' : 'mlOverviewPanel';
Expand All @@ -75,13 +87,11 @@ export const AnalyticsPanel: FC<Props> = ({ jobCreationDisabled }) => {
</h2>
}
body={
<Fragment>
<p>
{i18n.translate('xpack.ml.overview.analyticsList.emptyPromptText', {
defaultMessage: `Data frame analytics enable you to perform different analyses of your data and annotate it with the results. The analytics job stores the annotated data, as well as a copy of the source data, in a new index.`,
})}
</p>
</Fragment>
<p>
{i18n.translate('xpack.ml.overview.analyticsList.emptyPromptText', {
defaultMessage: `Data frame analytics enable you to perform different analyses of your data and annotate it with the results. The analytics job stores the annotated data, as well as a copy of the source data, in a new index.`,
})}
</p>
}
actions={
<EuiButton
Expand All @@ -99,7 +109,24 @@ export const AnalyticsPanel: FC<Props> = ({ jobCreationDisabled }) => {
/>
)}
{isInitialized === true && analytics.length > 0 && (
<Fragment>
<>
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiText size="m">
<h3>
{i18n.translate('xpack.ml.overview.analyticsList.PanelTitle', {
defaultMessage: 'Analytics',
})}
</h3>
</EuiText>
</EuiFlexItem>
{analyticsStats !== undefined && (
<EuiFlexItem grow={false} className="mlOverviewPanel__statsBar">
<StatsBar stats={analyticsStats} dataTestSub={'mlOverviewAnalyticsStatsBar'} />
</EuiFlexItem>
)}
</EuiFlexGroup>
<EuiSpacer />
<AnalyticsTable items={analytics} />
<EuiSpacer size="m" />
<div className="mlOverviewPanel__buttons">
Expand All @@ -114,7 +141,7 @@ export const AnalyticsPanel: FC<Props> = ({ jobCreationDisabled }) => {
})}
</EuiButton>
</div>
</Fragment>
</>
)}
</EuiPanel>
);
Expand Down
Loading

0 comments on commit fab0e16

Please sign in to comment.