Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ML] Update the Overview page #159609

Merged
merged 24 commits into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
5cfa6a8
collapsible_panel.tsx, store state in the local storage
darnautov Jun 13, 2023
b29f998
group actions
darnautov Jun 13, 2023
aac5aac
analytics_panel
darnautov Jun 13, 2023
f0f3572
hide keys when total is 0
darnautov Jun 13, 2023
869774d
DFA empty prompt
darnautov Jun 13, 2023
e95c488
AD empty prompt
darnautov Jun 13, 2023
150d8a5
dfa panel title, fix i18n
darnautov Jun 13, 2023
bacdda5
Nodes panel
darnautov Jun 13, 2023
5241992
panel border
darnautov Jun 13, 2023
0380da1
refactor
darnautov Jun 14, 2023
8851411
update jest tests
darnautov Jun 14, 2023
9ca5a6e
mlTotalNodesCount test
darnautov Jun 14, 2023
3e95834
Update x-pack/plugins/ml/public/application/data_frame_analytics/page…
darnautov Jun 14, 2023
0efb240
Update x-pack/plugins/ml/public/application/data_frame_analytics/page…
darnautov Jun 14, 2023
49ec04c
Update x-pack/plugins/ml/public/application/jobs/jobs_list/components…
darnautov Jun 14, 2023
0852e67
Update x-pack/plugins/ml/public/application/jobs/jobs_list/components…
darnautov Jun 14, 2023
b644503
Update x-pack/plugins/ml/public/application/data_frame_analytics/page…
darnautov Jun 14, 2023
4d2ded2
refactor, remove ts-ignore
darnautov Jun 14, 2023
5049b99
Merge remote-tracking branch 'origin/ml-154294-overview-page' into ml…
darnautov Jun 14, 2023
f846d55
css panel border
darnautov Jun 14, 2023
06ef28a
Merge remote-tracking branch 'origin/main' into ml-154294-overview-page
darnautov Jun 20, 2023
1d15f22
enable accessibility tests
darnautov Jun 20, 2023
ab49032
Revert "enable accessibility tests"
darnautov Jun 20, 2023
6486ff9
Merge branch 'main' into ml-154294-overview-page
kibanamachine Jun 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions x-pack/plugins/ml/common/types/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const ML_GETTING_STARTED_CALLOUT_DISMISSED = 'ml.gettingStarted.isDismiss
export const ML_FROZEN_TIER_PREFERENCE = 'ml.frozenDataTierPreference';
export const ML_ANOMALY_EXPLORER_PANELS = 'ml.anomalyExplorerPanels';
export const ML_NOTIFICATIONS_LAST_CHECKED_AT = 'ml.notificationsLastCheckedAt';
export const ML_OVERVIEW_PANELS = 'ml.overviewPanels';

export type PartitionFieldConfig =
| {
Expand Down Expand Up @@ -52,6 +53,12 @@ export interface AnomalyExplorerPanelsState {
mainPage: { size: number };
}

export interface OverviewPanelsState {
nodes: boolean;
adJobs: boolean;
dfaJobs: boolean;
}

export interface MlStorageRecord {
[key: string]: unknown;
[ML_ENTITY_FIELDS_CONFIG]: PartitionFieldsConfig;
Expand All @@ -60,6 +67,7 @@ export interface MlStorageRecord {
[ML_FROZEN_TIER_PREFERENCE]: FrozenTierPreference;
[ML_ANOMALY_EXPLORER_PANELS]: AnomalyExplorerPanelsState | undefined;
[ML_NOTIFICATIONS_LAST_CHECKED_AT]: number | undefined;
[ML_OVERVIEW_PANELS]: OverviewPanelsState;
}

export type MlStorage = Partial<MlStorageRecord> | null;
Expand All @@ -78,6 +86,8 @@ export type TMlStorageMapped<T extends MlStorageKey> = T extends typeof ML_ENTIT
? AnomalyExplorerPanelsState | undefined
: T extends typeof ML_NOTIFICATIONS_LAST_CHECKED_AT
? number | undefined
: T extends typeof ML_OVERVIEW_PANELS
? OverviewPanelsState | undefined
: null;

export const ML_STORAGE_KEYS = [
Expand All @@ -87,4 +97,5 @@ export const ML_STORAGE_KEYS = [
ML_FROZEN_TIER_PREFERENCE,
ML_ANOMALY_EXPLORER_PANELS,
ML_NOTIFICATIONS_LAST_CHECKED_AT,
ML_OVERVIEW_PANELS,
] as const;
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* 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 {
EuiBadge,
EuiButtonIcon,
EuiFlexGroup,
EuiFlexItem,
EuiSplitPanel,
EuiText,
EuiTitle,
} from '@elastic/eui';
import React, { type FC } from 'react';
import { css } from '@emotion/react/dist/emotion-react.cjs';
import { useCurrentThemeVars } from '../../contexts/kibana';

export interface CollapsiblePanelProps {
isOpen: boolean;
onToggle: (isOpen: boolean) => void;

header: React.ReactElement;
headerItems?: React.ReactElement[];
}

export const CollapsiblePanel: FC<CollapsiblePanelProps> = ({
isOpen,
onToggle,
children,
header,
headerItems,
}) => {
const { euiTheme } = useCurrentThemeVars();

return (
<EuiSplitPanel.Outer grow hasShadow={false} hasBorder={isOpen}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, if you expand and collapse these sections they resize by 1px because of the lack of border.
Adding a border when they are collapsed looks a bit nicer and is less flickery.
Something like this, euiColorLightestShade is the closest shade I could find.

    css={isOpen ? {} : { border: `1px solid ${euiTheme.euiColorLightestShade}` }}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in f846d55

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm being very nitty now :D
The problem with using transparent rather than matching the color of the background means that the panels are all 1px smaller all the way around when collapsed. This is obvious to me when using a low res screen.
But normal people might not care.

image

image

<EuiSplitPanel.Inner color={isOpen ? 'plain' : 'subdued'}>
<EuiFlexGroup justifyContent={'spaceBetween'} alignItems={'center'}>
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize={'s'}>
<EuiFlexItem grow={false}>
<EuiButtonIcon
color={'text'}
iconType={isOpen ? 'arrowDown' : 'arrowRight'}
onClick={() => {
onToggle(!isOpen);
}}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiTitle size="xxs">
<h2>{header}</h2>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
{headerItems ? (
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize={'l'} alignItems={'center'}>
{headerItems.map((item, i) => {
return (
<EuiFlexItem key={i} grow={false}>
<div
css={
i < headerItems?.length - 1
? css`
border-right: ${euiTheme.euiBorderWidthThin} solid
${euiTheme.euiBorderColor};
padding-right: ${euiTheme.euiPanelPaddingModifiers.paddingLarge};
`
: null
}
>
{item}
</div>
</EuiFlexItem>
);
})}
</EuiFlexGroup>
</EuiFlexItem>
) : null}
</EuiFlexGroup>
</EuiSplitPanel.Inner>
{isOpen ? (
<EuiSplitPanel.Inner
css={{ borderTop: `${euiTheme.euiBorderWidthThin} solid ${euiTheme.euiBorderColor}` }}
grow={false}
>
{children}
</EuiSplitPanel.Inner>
) : null}
</EuiSplitPanel.Outer>
);
};

export interface StatEntry {
label: string;
value: number;
'data-test-subj'?: string;
}

export interface OverviewStatsBarProps {
inputStats: StatEntry[];
dataTestSub?: string;
}

export const OverviewStatsBar: FC<OverviewStatsBarProps> = ({ inputStats, dataTestSub }) => {
return (
<EuiFlexGroup data-test-subj={dataTestSub} alignItems={'center'} gutterSize={'m'}>
{inputStats.map(({ value, label, 'data-test-subj': dataTestSubjValue }) => {
return (
<EuiFlexItem grow={false} key={label}>
<EuiFlexGroup alignItems={'center'} gutterSize={'s'}>
<EuiFlexItem grow={false}>
<EuiText size={'s'}>{label}:</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiBadge data-test-subj={dataTestSubjValue}>{value}</EuiBadge>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
);
})}
</EuiFlexGroup>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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.
*/

export { CollapsiblePanel } from './collapsible_panel';
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,7 @@
*/

import React, { FC } from 'react';
import {
EuiButton,
EuiCallOut,
EuiEmptyPrompt,
EuiFlexGroup,
EuiFlexItem,
EuiImage,
EuiLink,
EuiTitle,
} from '@elastic/eui';
import { EuiButton, EuiEmptyPrompt, EuiImage, EuiLink } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import dfaImage from './data_frame_analytics_kibana.png';
Expand All @@ -26,10 +17,7 @@ import { usePermissionCheck } from '../../../../../capabilities/check_capabiliti

export const AnalyticsEmptyPrompt: FC = () => {
const {
services: {
docLinks,
http: { basePath },
},
services: { docLinks },
} = useMlKibana();

const [canCreateDataFrameAnalytics, canStartStopDataFrameAnalytics] = usePermissionCheck([
Expand All @@ -40,7 +28,6 @@ export const AnalyticsEmptyPrompt: FC = () => {
const disabled =
!mlNodesAvailable() || !canCreateDataFrameAnalytics || !canStartStopDataFrameAnalytics;

const transformsLink = `${basePath.get()}/app/management/data/transform`;
const navigateToPath = useNavigateToPath();

const navigateToSourceSelection = async () => {
Expand All @@ -57,16 +44,15 @@ export const AnalyticsEmptyPrompt: FC = () => {
size="fullWidth"
src={dfaImage}
alt={i18n.translate('xpack.ml.dataFrame.analyticsList.emptyPromptTitle', {
defaultMessage: 'Create your first data frame analytics job',
defaultMessage: 'Trained analysis of your data',
darnautov marked this conversation as resolved.
Show resolved Hide resolved
})}
/>
}
color="subdued"
title={
<h2>
<FormattedMessage
id="xpack.ml.dataFrame.analyticsList.emptyPromptTitle"
defaultMessage="Create your first data frame analytics job"
defaultMessage="Trained analysis of your data"
darnautov marked this conversation as resolved.
Show resolved Hide resolved
/>
</h2>
}
Expand All @@ -78,77 +64,26 @@ export const AnalyticsEmptyPrompt: FC = () => {
defaultMessage="Train outlier detection, regression, or classification machine learning models using data frame analytics."
/>
</p>
<EuiCallOut
size="s"
title={
<FormattedMessage
id="xpack.ml.overview.analyticsList.emptyPromptHelperText"
defaultMessage="Before building a data frame analytics job, use {transforms} to construct an {sourcedata}."
values={{
transforms: (
<EuiLink href={transformsLink} target="blank" color={'accent'}>
<FormattedMessage
id="xpack.ml.overview.gettingStartedSectionTransforms"
defaultMessage="transforms"
/>
</EuiLink>
),
sourcedata: (
<EuiLink
href={docLinks.links.ml.dFAPrepareData}
target="blank"
color={'accent'}
external
>
<FormattedMessage
id="xpack.ml.overview.gettingStartedSectionSourceData"
defaultMessage="entity-centric source data set"
/>
</EuiLink>
),
}}
/>
}
iconType="iInCircle"
/>
</>
}
actions={[
<EuiButton
onClick={navigateToSourceSelection}
isDisabled={disabled}
color="primary"
iconType="plusInCircle"
fill
data-test-subj="mlAnalyticsCreateFirstButton"
>
{i18n.translate('xpack.ml.dataFrame.analyticsList.emptyPromptButtonText', {
defaultMessage: 'Create job',
defaultMessage: 'Create data frame analytics job',
})}
</EuiButton>,
<EuiLink href={docLinks.links.ml.dataFrameAnalytics} target="_blank" external>
<FormattedMessage
id="xpack.ml.common.readDocumentationLink"
defaultMessage="Documentation"
darnautov marked this conversation as resolved.
Show resolved Hide resolved
/>
</EuiLink>,
]}
footer={
<EuiFlexGroup gutterSize={'xs'} alignItems={'center'}>
<EuiFlexItem grow={false}>
<EuiTitle size="xxs">
<h3>
<FormattedMessage
id="xpack.ml.common.learnMoreQuestion"
defaultMessage="Want to learn more?"
/>
</h3>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiLink href={docLinks.links.ml.dataFrameAnalytics} target="_blank" external>
<FormattedMessage
id="xpack.ml.common.readDocumentationLink"
defaultMessage="Read documentation"
/>
</EuiLink>
</EuiFlexItem>
</EuiFlexGroup>
}
data-test-subj="mlNoDataFrameAnalyticsFound"
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ describe('get_analytics', () => {
// act and assert
expect(getAnalyticsJobsStats(mockResponse)).toEqual({
total: {
label: 'Total analytics jobs',
label: 'Total',
value: 2,
show: true,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export function getInitialAnalyticsStats(): AnalyticStatsBarStats {
return {
total: {
label: i18n.translate('xpack.ml.overview.statsBar.totalAnalyticsLabel', {
defaultMessage: 'Total analytics jobs',
defaultMessage: 'Total',
}),
value: 0,
show: true,
Expand Down Expand Up @@ -97,6 +97,12 @@ export function getAnalyticsJobsStats(
);
resultStats.failed.show = resultStats.failed.value > 0;
resultStats.total.value = analyticsStats.count;

if (resultStats.total.value === 0) {
resultStats.started.show = false;
resultStats.stopped.show = false;
}

return resultStats;
}

Expand Down
Loading