mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[ML] Fix responsive behaviour of page header with date picker (#149073)
Improve responsive behaviour of page header with date picker. - Removes custom breakpoint based code to determine date picker width and instead use it's native `width` option. - Adds a `flexGroup` boolean toggle to be able to get back the flex items only without the flex group if you want to embed the date picker in an already existing flex group to avoid additional nesting. - Sets the `fill` option of the refresh button to `false` to avoid the dark blue "primary". - In the `aiops` plugin and the `ml_page.tsx` component, migrates away from EUI's deprecated components for the page layout. - Adds a `min-width` to page titles to avoid narrow wrapping (e.g. wrapping after each character on narrow screens).
This commit is contained in:
parent
99e3810e0c
commit
2a57862668
14 changed files with 153 additions and 142 deletions
|
@ -5,18 +5,17 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { css } from '@emotion/react';
|
||||
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
import {
|
||||
useEuiBreakpoint,
|
||||
useIsWithinMaxBreakpoint,
|
||||
EuiButton,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiSuperDatePicker,
|
||||
type EuiSuperDatePickerProps,
|
||||
OnRefreshProps,
|
||||
OnTimeChangeProps,
|
||||
} from '@elastic/eui';
|
||||
|
@ -32,7 +31,6 @@ import { useDatePickerContext } from '../hooks/use_date_picker_context';
|
|||
import { mlTimefilterRefresh$ } from '../services/timefilter_refresh_service';
|
||||
|
||||
const DEFAULT_REFRESH_INTERVAL_MS = 5000;
|
||||
const DATE_PICKER_MAX_WIDTH = '540px';
|
||||
|
||||
interface TimePickerQuickRange {
|
||||
from: string;
|
||||
|
@ -83,6 +81,14 @@ interface DatePickerWrapperProps {
|
|||
* Boolean flag to enforce showing/hiding the refresh button.
|
||||
*/
|
||||
showRefresh?: boolean;
|
||||
/**
|
||||
* Width setting to be passed on to `EuiSuperDatePicker`
|
||||
*/
|
||||
width?: EuiSuperDatePickerProps['width'];
|
||||
/**
|
||||
* Boolean flag to set use of flex group wrapper
|
||||
*/
|
||||
flexGroup?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,7 +99,7 @@ interface DatePickerWrapperProps {
|
|||
* @returns {React.ReactElement} The DatePickerWrapper component.
|
||||
*/
|
||||
export const DatePickerWrapper: FC<DatePickerWrapperProps> = (props) => {
|
||||
const { isAutoRefreshOnly, isLoading = false, showRefresh } = props;
|
||||
const { isAutoRefreshOnly, isLoading = false, showRefresh, width, flexGroup = true } = props;
|
||||
const {
|
||||
data,
|
||||
notifications: { toasts },
|
||||
|
@ -274,15 +280,9 @@ export const DatePickerWrapper: FC<DatePickerWrapperProps> = (props) => {
|
|||
setRefreshInterval({ pause, value });
|
||||
}
|
||||
|
||||
const datePickerWidth = css({
|
||||
[useEuiBreakpoint(['xs', 's', 'm', 'l'])]: {
|
||||
maxWidth: DATE_PICKER_MAX_WIDTH,
|
||||
},
|
||||
});
|
||||
|
||||
return isAutoRefreshSelectorEnabled || isTimeRangeSelectorEnabled ? (
|
||||
<EuiFlexGroup gutterSize="s" alignItems="center">
|
||||
<EuiFlexItem grow={false} css={datePickerWidth}>
|
||||
const flexItems = (
|
||||
<>
|
||||
<EuiFlexItem>
|
||||
<EuiSuperDatePicker
|
||||
isLoading={isLoading}
|
||||
start={time.from}
|
||||
|
@ -296,14 +296,14 @@ export const DatePickerWrapper: FC<DatePickerWrapperProps> = (props) => {
|
|||
recentlyUsedRanges={recentlyUsedRanges}
|
||||
dateFormat={dateFormat}
|
||||
commonlyUsedRanges={commonlyUsedRanges}
|
||||
updateButtonProps={{ iconOnly: isWithinLBreakpoint }}
|
||||
updateButtonProps={{ iconOnly: isWithinLBreakpoint, fill: false }}
|
||||
width={width}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
{showRefresh === true || !isTimeRangeSelectorEnabled ? (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
fill
|
||||
fill={false}
|
||||
color="primary"
|
||||
iconType={'refresh'}
|
||||
onClick={() => updateLastRefresh()}
|
||||
|
@ -314,6 +314,16 @@ export const DatePickerWrapper: FC<DatePickerWrapperProps> = (props) => {
|
|||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
|
||||
const wrapped = flexGroup ? (
|
||||
<EuiFlexGroup gutterSize="s" alignItems="center">
|
||||
{flexItems}
|
||||
</EuiFlexGroup>
|
||||
) : null;
|
||||
) : (
|
||||
flexItems
|
||||
);
|
||||
|
||||
return isAutoRefreshSelectorEnabled || isTimeRangeSelectorEnabled ? wrapped : null;
|
||||
};
|
||||
|
|
|
@ -191,7 +191,7 @@ export const FullTimeRangeSelector: FC<FullTimeRangeSelectorProps> = (props) =>
|
|||
);
|
||||
|
||||
return (
|
||||
<EuiFlexGroup responsive={false} gutterSize="xs" alignItems="center">
|
||||
<EuiFlexGroup responsive={false} gutterSize="xs">
|
||||
<EuiToolTip content={buttonTooltip}>
|
||||
<EuiButton
|
||||
isDisabled={disabled}
|
||||
|
|
|
@ -11,10 +11,10 @@ import {
|
|||
EuiEmptyPrompt,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiHorizontalRule,
|
||||
EuiPageBody,
|
||||
EuiPageContentBody_Deprecated as EuiPageContentBody,
|
||||
EuiPageSection,
|
||||
EuiPanel,
|
||||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
@ -170,8 +170,8 @@ export const ExplainLogRateSpikesPage: FC = () => {
|
|||
return (
|
||||
<EuiPageBody data-test-subj="aiopsExplainLogRateSpikesPage" paddingSize="none" panelled={false}>
|
||||
<PageHeader />
|
||||
<EuiHorizontalRule />
|
||||
<EuiPageContentBody>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiPageSection paddingSize="none">
|
||||
<EuiFlexGroup gutterSize="m" direction="column">
|
||||
<EuiFlexItem>
|
||||
<SearchPanel
|
||||
|
@ -236,7 +236,7 @@ export const ExplainLogRateSpikesPage: FC = () => {
|
|||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPageContentBody>
|
||||
</EuiPageSection>
|
||||
</EuiPageBody>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -5,17 +5,10 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { css } from '@emotion/react';
|
||||
import React, { FC, useCallback, useMemo } from 'react';
|
||||
|
||||
import {
|
||||
useIsWithinMaxBreakpoint,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiSpacer,
|
||||
EuiTitle,
|
||||
EuiPageContentHeader_Deprecated as EuiPageContentHeader,
|
||||
EuiPageContentHeaderSection_Deprecated as EuiPageContentHeaderSection,
|
||||
} from '@elastic/eui';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiPageHeader } from '@elastic/eui';
|
||||
|
||||
import { useUrlState } from '@kbn/ml-url-state';
|
||||
import { useStorage } from '@kbn/ml-local-storage';
|
||||
|
@ -27,7 +20,6 @@ import {
|
|||
FROZEN_TIER_PREFERENCE,
|
||||
} from '@kbn/ml-date-picker';
|
||||
|
||||
import { useCss } from '../../hooks/use_css';
|
||||
import { useDataSource } from '../../hooks/use_data_source';
|
||||
import {
|
||||
AIOPS_FROZEN_TIER_PREFERENCE,
|
||||
|
@ -35,9 +27,11 @@ import {
|
|||
type AiOpsStorageMapped,
|
||||
} from '../../types/storage';
|
||||
|
||||
export const PageHeader: FC = () => {
|
||||
const { aiopsPageHeader, dataViewTitleHeader } = useCss();
|
||||
const dataViewTitleHeader = css({
|
||||
minWidth: '300px',
|
||||
});
|
||||
|
||||
export const PageHeader: FC = () => {
|
||||
const [, setGlobalState] = useUrlState('_g');
|
||||
const { dataView } = useDataSource();
|
||||
|
||||
|
@ -67,49 +61,32 @@ export const PageHeader: FC = () => {
|
|||
[dataView.timeFieldName]
|
||||
);
|
||||
|
||||
const isWithinLBreakpoint = useIsWithinMaxBreakpoint('l');
|
||||
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="none">
|
||||
<EuiFlexItem>
|
||||
<EuiPageContentHeader css={aiopsPageHeader}>
|
||||
<EuiPageContentHeaderSection>
|
||||
<div css={dataViewTitleHeader}>
|
||||
<EuiTitle size="s">
|
||||
<h2>{dataView.getName()}</h2>
|
||||
</EuiTitle>
|
||||
</div>
|
||||
</EuiPageContentHeaderSection>
|
||||
|
||||
{isWithinLBreakpoint ? <EuiSpacer size="m" /> : null}
|
||||
<EuiFlexGroup
|
||||
alignItems="center"
|
||||
justifyContent="flexEnd"
|
||||
gutterSize="s"
|
||||
data-test-subj="aiopsTimeRangeSelectorSection"
|
||||
>
|
||||
{hasValidTimeField ? (
|
||||
<EuiFlexItem grow={false}>
|
||||
<FullTimeRangeSelector
|
||||
frozenDataPreference={frozenDataPreference}
|
||||
setFrozenDataPreference={setFrozenDataPreference}
|
||||
dataView={dataView}
|
||||
query={undefined}
|
||||
disabled={false}
|
||||
timefilter={timefilter}
|
||||
callback={updateTimeState}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
) : null}
|
||||
<EuiPageHeader
|
||||
pageTitle={<div css={dataViewTitleHeader}>{dataView.getName()}</div>}
|
||||
rightSideItems={[
|
||||
<EuiFlexGroup gutterSize="s" data-test-subj="aiopsTimeRangeSelectorSection">
|
||||
{hasValidTimeField ? (
|
||||
<EuiFlexItem grow={false}>
|
||||
<DatePickerWrapper
|
||||
isAutoRefreshOnly={!hasValidTimeField}
|
||||
showRefresh={!hasValidTimeField}
|
||||
<FullTimeRangeSelector
|
||||
frozenDataPreference={frozenDataPreference}
|
||||
setFrozenDataPreference={setFrozenDataPreference}
|
||||
dataView={dataView}
|
||||
query={undefined}
|
||||
disabled={false}
|
||||
timefilter={timefilter}
|
||||
callback={updateTimeState}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPageContentHeader>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
) : null}
|
||||
<DatePickerWrapper
|
||||
isAutoRefreshOnly={!hasValidTimeField}
|
||||
showRefresh={!hasValidTimeField}
|
||||
width="full"
|
||||
flexGroup={false}
|
||||
/>
|
||||
</EuiFlexGroup>,
|
||||
]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -93,13 +93,8 @@ export const SearchPanel: FC<Props> = ({
|
|||
};
|
||||
|
||||
return (
|
||||
<EuiFlexGroup
|
||||
gutterSize="s"
|
||||
data-test-subj="aiopsSearchPanel"
|
||||
className={'aiopsSearchPanel__container'}
|
||||
responsive={false}
|
||||
>
|
||||
<EuiFlexItem grow={9} className={'aiopsSearchBar'}>
|
||||
<EuiFlexGroup gutterSize="s" data-test-subj="aiopsSearchPanel" responsive={false}>
|
||||
<EuiFlexItem grow={9}>
|
||||
<SearchBar
|
||||
dataTestSubj="aiopsQueryInput"
|
||||
appName={'aiops'}
|
||||
|
@ -116,7 +111,7 @@ export const SearchPanel: FC<Props> = ({
|
|||
})}
|
||||
displayStyle={'inPage'}
|
||||
isClearable={true}
|
||||
customSubmitButton={<div />}
|
||||
showSubmitButton={false}
|
||||
onFiltersUpdated={(filters: Filter[]) => searchHandler({ filters })}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* 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 { css } from '@emotion/react';
|
||||
import { useEuiBreakpoint } from '@elastic/eui';
|
||||
import { euiThemeVars } from '@kbn/ui-theme';
|
||||
|
||||
// Define fully static CSS outside hook.
|
||||
const dataViewTitleHeader = css({
|
||||
minWidth: '300px',
|
||||
padding: `${euiThemeVars.euiSizeS} 0`,
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
});
|
||||
|
||||
export const useCss = () => {
|
||||
// Define CSS referencing inline dependencies within hook.
|
||||
const aiopsPageHeader = css({
|
||||
[useEuiBreakpoint(['xs', 's', 'm', 'l'])]: {
|
||||
flexDirection: 'column',
|
||||
alignItems: 'flex-start',
|
||||
},
|
||||
});
|
||||
|
||||
return { dataViewTitleHeader, aiopsPageHeader };
|
||||
};
|
|
@ -528,6 +528,7 @@ export const IndexDataVisualizerView: FC<IndexDataVisualizerViewProps> = (dataVi
|
|||
<DatePickerWrapper
|
||||
isAutoRefreshOnly={!hasValidTimeField}
|
||||
showRefresh={!hasValidTimeField}
|
||||
width="full"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -6,16 +6,18 @@
|
|||
*/
|
||||
|
||||
import React, { createContext, FC, useEffect, useMemo, useState } from 'react';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { EuiPageContentBody_Deprecated as EuiPageContentBody } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { Redirect, Route, Switch } from 'react-router-dom';
|
||||
import type { AppMountParameters } from '@kbn/core/public';
|
||||
import { KibanaPageTemplate, RedirectAppLinks } from '@kbn/kibana-react-plugin/public';
|
||||
import { createHtmlPortalNode, HtmlPortalNode } from 'react-reverse-portal';
|
||||
import { Redirect, Route, Switch } from 'react-router-dom';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { EuiPageSection } from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { type AppMountParameters } from '@kbn/core/public';
|
||||
import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template';
|
||||
import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
|
||||
import { DatePickerWrapper } from '@kbn/ml-date-picker';
|
||||
import { MlPageHeaderRenderer } from '../page_header/page_header';
|
||||
import { useSideNavItems } from './side_nav';
|
||||
|
||||
import * as routes from '../../routing/routes';
|
||||
import { MlPageWrapper } from '../../routing/ml_page_wrapper';
|
||||
import { useMlKibana, useNavigateToPath } from '../../contexts/kibana';
|
||||
|
@ -23,6 +25,12 @@ import { MlRoute, PageDependencies } from '../../routing/router';
|
|||
import { useActiveRoute } from '../../routing/use_active_route';
|
||||
import { useDocTitle } from '../../routing/use_doc_title';
|
||||
|
||||
import { MlPageHeaderRenderer } from '../page_header/page_header';
|
||||
|
||||
import { useSideNavItems } from './side_nav';
|
||||
|
||||
const ML_APP_SELECTOR = '[data-test-subj="mlApp"]';
|
||||
|
||||
export const MlPageControlsContext = createContext<{
|
||||
headerPortal: HtmlPortalNode;
|
||||
setHeaderActionMenu?: AppMountParameters['setHeaderActionMenu'];
|
||||
|
@ -79,11 +87,30 @@ export const MlPage: FC<{ pageDeps: PageDependencies }> = React.memo(({ pageDeps
|
|||
const activeRoute = useActiveRoute(routeList);
|
||||
|
||||
const rightSideItems = useMemo(() => {
|
||||
return [...(activeRoute.enableDatePicker ? [<DatePickerWrapper isLoading={isLoading} />] : [])];
|
||||
return [
|
||||
...(activeRoute.enableDatePicker
|
||||
? [<DatePickerWrapper isLoading={isLoading} width="full" />]
|
||||
: []),
|
||||
];
|
||||
}, [activeRoute.enableDatePicker, isLoading]);
|
||||
|
||||
useDocTitle(activeRoute);
|
||||
|
||||
// The deprecated `KibanaPageTemplate` from`'@kbn/kibana-react-plugin/public'`
|
||||
// had a `pageBodyProps` prop where we could pass in the `data-test-subj` for
|
||||
// the `main` element. This is no longer available in the update template
|
||||
// imported from `'@kbn/shared-ux-page-kibana-template'`. The following is a
|
||||
// workaround to add the `data-test-subj` on the `main` element again.
|
||||
useEffect(() => {
|
||||
const mlApp = document.querySelector(ML_APP_SELECTOR) as HTMLElement;
|
||||
if (mlApp && typeof activeRoute?.['data-test-subj'] === 'string') {
|
||||
const mlAppMain = mlApp.querySelector('main') as HTMLElement;
|
||||
if (mlAppMain) {
|
||||
mlAppMain.setAttribute('data-test-subj', activeRoute?.['data-test-subj']);
|
||||
}
|
||||
}
|
||||
}, [activeRoute]);
|
||||
|
||||
return (
|
||||
<MlPageControlsContext.Provider
|
||||
value={{
|
||||
|
@ -97,11 +124,6 @@ export const MlPage: FC<{ pageDeps: PageDependencies }> = React.memo(({ pageDeps
|
|||
className={'ml-app'}
|
||||
data-test-subj={'mlApp'}
|
||||
restrictWidth={false}
|
||||
// EUI TODO
|
||||
// The different template options need to be manually recreated by the individual pages.
|
||||
// These classes help enforce the layouts.
|
||||
pageContentProps={{ className: 'kbnAppWrapper' }}
|
||||
pageContentBodyProps={{ className: 'kbnAppWrapper' }}
|
||||
solutionNav={{
|
||||
name: i18n.translate('xpack.ml.plugin.title', {
|
||||
defaultMessage: 'Machine Learning',
|
||||
|
@ -114,9 +136,6 @@ export const MlPage: FC<{ pageDeps: PageDependencies }> = React.memo(({ pageDeps
|
|||
rightSideItems,
|
||||
restrictWidth: false,
|
||||
}}
|
||||
pageBodyProps={{
|
||||
'data-test-subj': activeRoute?.['data-test-subj'],
|
||||
}}
|
||||
>
|
||||
<CommonPageWrapper
|
||||
headerPortal={headerPortalNode}
|
||||
|
@ -144,8 +163,8 @@ const CommonPageWrapper: FC<CommonPageWrapperProps> = React.memo(({ pageDeps, ro
|
|||
return (
|
||||
/** RedirectAppLinks intercepts all <a> tags to use navigateToUrl
|
||||
* avoiding full page reload **/
|
||||
<RedirectAppLinks application={application}>
|
||||
<EuiPageContentBody restrictWidth={false}>
|
||||
<RedirectAppLinks coreStart={{ application }}>
|
||||
<EuiPageSection restrictWidth={false}>
|
||||
<Switch>
|
||||
{routeList.map((route) => {
|
||||
return (
|
||||
|
@ -166,7 +185,7 @@ const CommonPageWrapper: FC<CommonPageWrapperProps> = React.memo(({ pageDeps, ro
|
|||
})}
|
||||
<Redirect to="/overview" />
|
||||
</Switch>
|
||||
</EuiPageContentBody>
|
||||
</EuiPageSection>
|
||||
</RedirectAppLinks>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -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 { PageTitle } from './page_title';
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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 { css } from '@emotion/react';
|
||||
import React, { FC } from 'react';
|
||||
|
||||
const cssPageTitle = css({
|
||||
minWidth: '300px',
|
||||
});
|
||||
|
||||
interface PageTitleProps {
|
||||
title: string;
|
||||
}
|
||||
|
||||
export const PageTitle: FC<PageTitleProps> = ({ title }) => <div css={cssPageTitle}>{title}</div>;
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import React, { FC, useState } from 'react';
|
||||
import { EuiPanel, EuiSpacer } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { mlTimefilterRefresh$, useTimefilter } from '@kbn/ml-date-picker';
|
||||
import { checkPermission } from '../capabilities/check_capabilities';
|
||||
import { mlNodesAvailable } from '../ml_nodes_check';
|
||||
|
@ -21,6 +21,7 @@ import { HelpMenu } from '../components/help_menu';
|
|||
import { useMlKibana } from '../contexts/kibana';
|
||||
import { NodesList } from '../trained_models/nodes_overview';
|
||||
import { MlPageHeader } from '../components/page_header';
|
||||
import { PageTitle } from '../components/page_title';
|
||||
|
||||
export const OverviewPage: FC = () => {
|
||||
const canViewMlNodes = checkPermission('canViewMlNodes');
|
||||
|
@ -39,7 +40,11 @@ export const OverviewPage: FC = () => {
|
|||
return (
|
||||
<div>
|
||||
<MlPageHeader>
|
||||
<FormattedMessage id="xpack.ml.overview.overviewLabel" defaultMessage="Overview" />
|
||||
<PageTitle
|
||||
title={i18n.translate('xpack.ml.overview.overviewLabel', {
|
||||
defaultMessage: 'Overview',
|
||||
})}
|
||||
/>
|
||||
</MlPageHeader>
|
||||
<NodeAvailableWarning />
|
||||
<JobsAwaitingNodeWarning jobCount={adLazyJobCount + dfaLazyJobCount} />
|
||||
|
|
|
@ -11,7 +11,6 @@ import useObservable from 'react-use/lib/useObservable';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { EuiThemeProvider as StyledComponentsThemeProvider } from '@kbn/kibana-react-plugin/common';
|
||||
import { useUrlState } from '@kbn/ml-url-state';
|
||||
import { useTimefilter } from '@kbn/ml-date-picker';
|
||||
|
@ -38,6 +37,7 @@ import { MlAnnotationUpdatesContext } from '../../contexts/ml/ml_annotation_upda
|
|||
import { AnnotationUpdatesService } from '../../services/annotations_service';
|
||||
import { useTimeBuckets } from '../../components/custom_hooks/use_time_buckets';
|
||||
import { MlPageHeader } from '../../components/page_header';
|
||||
import { PageTitle } from '../../components/page_title';
|
||||
import { AnomalyResultsViewSelector } from '../../components/anomaly_results_view_selector';
|
||||
import { AnomalyDetectionEmptyState } from '../../jobs/jobs_list/components/anomaly_detection_empty_state';
|
||||
import {
|
||||
|
@ -263,7 +263,11 @@ const ExplorerUrlStateManager: FC<ExplorerUrlStateManagerProps> = ({ jobsWithTim
|
|||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<FormattedMessage id="xpack.ml.explorer.pageTitle" defaultMessage="Anomaly Explorer" />
|
||||
<PageTitle
|
||||
title={i18n.translate('xpack.ml.explorer.pageTitle', {
|
||||
defaultMessage: 'Anomaly Explorer',
|
||||
})}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</MlPageHeader>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import React, { FC } from 'react';
|
||||
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
|
||||
|
@ -17,6 +17,7 @@ import { JobSelector } from '../components/job_selector';
|
|||
import { HelpMenu } from '../components/help_menu';
|
||||
import { useMlKibana } from '../contexts/kibana';
|
||||
import { MlPageHeader } from '../components/page_header';
|
||||
import { PageTitle } from '../components/page_title';
|
||||
|
||||
interface TimeSeriesExplorerPageProps {
|
||||
dateFormatTz?: string;
|
||||
|
@ -47,9 +48,10 @@ export const TimeSeriesExplorerPage: FC<TimeSeriesExplorerPageProps> = ({
|
|||
<AnomalyResultsViewSelector viewId="timeseriesexplorer" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<FormattedMessage
|
||||
id="xpack.ml.timeSeriesExplorer.pageTitle"
|
||||
defaultMessage="Single Metric Viewer"
|
||||
<PageTitle
|
||||
title={i18n.translate('xpack.ml.timeSeriesExplorer.pageTitle', {
|
||||
defaultMessage: 'Single Metric Viewer',
|
||||
})}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -75,5 +75,7 @@
|
|||
"@kbn/ml-date-picker",
|
||||
"@kbn/ml-is-defined",
|
||||
"@kbn/ml-query-utils",
|
||||
"@kbn/shared-ux-page-kibana-template",
|
||||
"@kbn/shared-ux-link-redirect-app",
|
||||
],
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue