[Uptime] Move uptime actions to Header Actions Menu (#100298)
* Move uptime actions to Kibana's HeaderActionsMenu. * Delete a comment. * Extract ActionMenu content to dedicated component to make testing easier. * Add tests. * Use `EuiHeaderLinks` instead of `EuiFlexItem`. * Clean up tests. * Prefer `getByRole` for a test. * Fix copy mistake. * Fix a test broken by the previous commit. * Prefer `EuiHeaderSectionItem` over `EuiHeaderSectionLink` to avoid nesting `button`s within `buttons`. * Reverse "Settings" and "Alerts" menu options to make them uniform with APM. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
7270c3bf40
commit
b189d05bc3
|
@ -6,70 +6,12 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
|
||||
import {
|
||||
createExploratoryViewUrl,
|
||||
HeaderMenuPortal,
|
||||
SeriesUrl,
|
||||
} from '../../../../../observability/public';
|
||||
import { HeaderMenuPortal } from '../../../../../observability/public';
|
||||
import { AppMountParameters } from '../../../../../../../src/core/public';
|
||||
import { useUptimeSettingsContext } from '../../../contexts/uptime_settings_context';
|
||||
import { useGetUrlParams } from '../../../hooks';
|
||||
import { ActionMenuContent } from './action_menu_content';
|
||||
|
||||
const ADD_DATA_LABEL = i18n.translate('xpack.uptime.addDataButtonLabel', {
|
||||
defaultMessage: 'Add data',
|
||||
});
|
||||
|
||||
const ANALYZE_DATA = i18n.translate('xpack.uptime.analyzeDataButtonLabel', {
|
||||
defaultMessage: 'Analyze data',
|
||||
});
|
||||
|
||||
const ANALYZE_MESSAGE = i18n.translate('xpack.uptime.analyzeDataButtonLabel.message', {
|
||||
defaultMessage:
|
||||
'EXPERIMENTAL - Analyze Data allows you to select and filter result data in any dimension and look for the cause or impact of performance problems.',
|
||||
});
|
||||
|
||||
export const ActionMenu = ({ appMountParameters }: { appMountParameters: AppMountParameters }) => {
|
||||
const kibana = useKibana();
|
||||
const { basePath } = useUptimeSettingsContext();
|
||||
const { dateRangeStart, dateRangeEnd } = useGetUrlParams();
|
||||
|
||||
const syntheticExploratoryViewLink = createExploratoryViewUrl(
|
||||
{
|
||||
'synthetics-series': {
|
||||
dataType: 'synthetics',
|
||||
time: { from: dateRangeStart, to: dateRangeEnd },
|
||||
} as SeriesUrl,
|
||||
},
|
||||
basePath
|
||||
);
|
||||
|
||||
return (
|
||||
<HeaderMenuPortal setHeaderActionMenu={appMountParameters.setHeaderActionMenu}>
|
||||
<EuiFlexGroup alignItems="flexEnd" responsive={false} style={{ paddingRight: 20 }}>
|
||||
<EuiFlexItem>
|
||||
<EuiToolTip position="top" content={<p>{ANALYZE_MESSAGE}</p>}>
|
||||
<EuiButtonEmpty
|
||||
href={syntheticExploratoryViewLink}
|
||||
color="primary"
|
||||
iconType="visBarVerticalStacked"
|
||||
>
|
||||
{ANALYZE_DATA}
|
||||
</EuiButtonEmpty>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty
|
||||
href={kibana.services?.application?.getUrlForApp('/home#/tutorial/uptimeMonitors')}
|
||||
color="primary"
|
||||
iconType="indexOpen"
|
||||
>
|
||||
{ADD_DATA_LABEL}
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</HeaderMenuPortal>
|
||||
);
|
||||
};
|
||||
export const ActionMenu = ({ appMountParameters }: { appMountParameters: AppMountParameters }) => (
|
||||
<HeaderMenuPortal setHeaderActionMenu={appMountParameters.setHeaderActionMenu}>
|
||||
<ActionMenuContent />
|
||||
</HeaderMenuPortal>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { fireEvent, waitFor } from '@testing-library/react';
|
||||
import { render } from '../../../lib/helper/rtl_helpers';
|
||||
import { ActionMenuContent } from './action_menu_content';
|
||||
|
||||
describe('ActionMenuContent', () => {
|
||||
it('renders alerts dropdown', async () => {
|
||||
const { getByLabelText, getByText } = render(<ActionMenuContent />);
|
||||
|
||||
const alertsDropdown = getByLabelText('Open alert context menu');
|
||||
fireEvent.click(alertsDropdown);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(getByText('Create alert'));
|
||||
expect(getByText('Manage alerts'));
|
||||
});
|
||||
});
|
||||
|
||||
it('renders settings link', () => {
|
||||
const { getByRole, getByText } = render(<ActionMenuContent />);
|
||||
|
||||
const settingsAnchor = getByRole('link', { name: 'Navigate to the Uptime settings page' });
|
||||
expect(settingsAnchor.getAttribute('href')).toBe('/settings');
|
||||
expect(getByText('Settings'));
|
||||
});
|
||||
|
||||
it('renders exploratory view link', () => {
|
||||
const { getByLabelText, getByText } = render(<ActionMenuContent />);
|
||||
|
||||
const analyzeAnchor = getByLabelText(
|
||||
'Navigate to the "Analyze Data" view to visualize Synthetics/User data'
|
||||
);
|
||||
|
||||
expect(analyzeAnchor.getAttribute('href')).toContain('/app/observability/exploratory-view');
|
||||
expect(getByText('Analyze data'));
|
||||
});
|
||||
|
||||
it('renders Add Data link', () => {
|
||||
const { getByLabelText, getByText } = render(<ActionMenuContent />);
|
||||
|
||||
const addDataAnchor = getByLabelText('Navigate to a tutorial about adding Uptime data');
|
||||
|
||||
// this href value is mocked, so it doesn't correspond to the real link
|
||||
// that Kibana core services will provide
|
||||
expect(addDataAnchor.getAttribute('href')).toBe('/app/uptime');
|
||||
expect(getByText('Add data'));
|
||||
});
|
||||
});
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { EuiButtonEmpty, EuiHeaderLinks, EuiHeaderSectionItem, EuiToolTip } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { createExploratoryViewUrl, SeriesUrl } from '../../../../../observability/public';
|
||||
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
|
||||
import { useUptimeSettingsContext } from '../../../contexts/uptime_settings_context';
|
||||
import { useGetUrlParams } from '../../../hooks';
|
||||
import { ToggleAlertFlyoutButton } from '../../overview/alerts/alerts_containers';
|
||||
import { SETTINGS_ROUTE } from '../../../../common/constants';
|
||||
import { stringifyUrlParams } from '../../../lib/helper/stringify_url_params';
|
||||
|
||||
const ADD_DATA_LABEL = i18n.translate('xpack.uptime.addDataButtonLabel', {
|
||||
defaultMessage: 'Add data',
|
||||
});
|
||||
|
||||
const ANALYZE_DATA = i18n.translate('xpack.uptime.analyzeDataButtonLabel', {
|
||||
defaultMessage: 'Analyze data',
|
||||
});
|
||||
|
||||
const ANALYZE_MESSAGE = i18n.translate('xpack.uptime.analyzeDataButtonLabel.message', {
|
||||
defaultMessage:
|
||||
'EXPERIMENTAL - Analyze Data allows you to select and filter result data in any dimension and look for the cause or impact of performance problems.',
|
||||
});
|
||||
|
||||
export function ActionMenuContent(): React.ReactElement {
|
||||
const kibana = useKibana();
|
||||
const { basePath } = useUptimeSettingsContext();
|
||||
const params = useGetUrlParams();
|
||||
const { dateRangeStart, dateRangeEnd } = params;
|
||||
const history = useHistory();
|
||||
|
||||
const syntheticExploratoryViewLink = createExploratoryViewUrl(
|
||||
{
|
||||
'synthetics-series': {
|
||||
dataType: 'synthetics',
|
||||
time: { from: dateRangeStart, to: dateRangeEnd },
|
||||
} as SeriesUrl,
|
||||
},
|
||||
basePath
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiHeaderLinks>
|
||||
<EuiHeaderSectionItem>
|
||||
<EuiButtonEmpty
|
||||
aria-label={i18n.translate('xpack.uptime.page_header.settingsLink.label', {
|
||||
defaultMessage: 'Navigate to the Uptime settings page',
|
||||
})}
|
||||
color="primary"
|
||||
data-test-subj="settings-page-link"
|
||||
href={history.createHref({
|
||||
pathname: SETTINGS_ROUTE,
|
||||
search: stringifyUrlParams(params, true),
|
||||
})}
|
||||
iconType="gear"
|
||||
>
|
||||
<FormattedMessage id="xpack.uptime.page_header.settingsLink" defaultMessage="Settings" />
|
||||
</EuiButtonEmpty>
|
||||
</EuiHeaderSectionItem>
|
||||
<EuiHeaderSectionItem>
|
||||
<ToggleAlertFlyoutButton />
|
||||
</EuiHeaderSectionItem>
|
||||
<EuiHeaderSectionItem>
|
||||
<EuiToolTip position="top" content={<p>{ANALYZE_MESSAGE}</p>}>
|
||||
<EuiButtonEmpty
|
||||
aria-label={i18n.translate('xpack.uptime.page_header.analyzeData.label', {
|
||||
defaultMessage:
|
||||
'Navigate to the "Analyze Data" view to visualize Synthetics/User data',
|
||||
})}
|
||||
href={syntheticExploratoryViewLink}
|
||||
color="primary"
|
||||
iconType="visBarVerticalStacked"
|
||||
>
|
||||
{ANALYZE_DATA}
|
||||
</EuiButtonEmpty>
|
||||
</EuiToolTip>
|
||||
</EuiHeaderSectionItem>
|
||||
<EuiHeaderSectionItem>
|
||||
<EuiButtonEmpty
|
||||
aria-label={i18n.translate('xpack.uptime.page_header.addDataLink.label', {
|
||||
defaultMessage: 'Navigate to a tutorial about adding Uptime data',
|
||||
})}
|
||||
href={kibana.services?.application?.getUrlForApp('/home#/tutorial/uptimeMonitors')}
|
||||
color="primary"
|
||||
iconType="indexOpen"
|
||||
>
|
||||
{ADD_DATA_LABEL}
|
||||
</EuiButtonEmpty>
|
||||
</EuiHeaderSectionItem>
|
||||
</EuiHeaderLinks>
|
||||
);
|
||||
}
|
|
@ -12,7 +12,6 @@ import { UptimeDatePicker } from '../uptime_date_picker';
|
|||
import { SyntheticsCallout } from '../../overview/synthetics_callout';
|
||||
import { PageTabs } from './page_tabs';
|
||||
import { CertRefreshBtn } from '../../certificates/cert_refresh_btn';
|
||||
import { ToggleAlertFlyoutButton } from '../../overview/alerts/alerts_containers';
|
||||
import { MonitorPageTitle } from '../../monitor/monitor_title';
|
||||
|
||||
export interface Props {
|
||||
|
@ -52,9 +51,6 @@ export const PageHeader = ({
|
|||
{showMonitorTitle && <MonitorPageTitle />}
|
||||
{showTabs && <PageTabs />}
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<ToggleAlertFlyoutButton />
|
||||
</EuiFlexItem>
|
||||
{showCertificateRefreshBtn && <CertRefreshBtn />}
|
||||
{showDatePicker && (
|
||||
<StyledPicker grow={false} style={{ flexBasis: 485 }}>
|
||||
|
|
|
@ -15,7 +15,6 @@ describe('PageTabs', () => {
|
|||
const { getByText } = render(<PageTabs />);
|
||||
expect(getByText('Overview')).toBeInTheDocument();
|
||||
expect(getByText('Certificates')).toBeInTheDocument();
|
||||
expect(getByText('Settings')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('it keep params while switching', () => {
|
||||
|
@ -32,10 +31,6 @@ describe('PageTabs', () => {
|
|||
'href',
|
||||
'/certificates?dateRangeStart=now-10m'
|
||||
);
|
||||
expect(getByTestId('settings-page-link')).toHaveAttribute(
|
||||
'href',
|
||||
'/settings?dateRangeStart=now-10m'
|
||||
);
|
||||
});
|
||||
|
||||
it('it resets params on overview if already on overview', () => {
|
||||
|
|
|
@ -10,7 +10,7 @@ import React, { useEffect, useState } from 'react';
|
|||
import { EuiTabs, EuiTab } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useHistory, useRouteMatch } from 'react-router-dom';
|
||||
import { CERTIFICATES_ROUTE, OVERVIEW_ROUTE, SETTINGS_ROUTE } from '../../../../common/constants';
|
||||
import { CERTIFICATES_ROUTE, OVERVIEW_ROUTE } from '../../../../common/constants';
|
||||
import { useGetUrlParams } from '../../../hooks';
|
||||
import { stringifyUrlParams } from '../../../lib/helper/stringify_url_params';
|
||||
|
||||
|
@ -28,13 +28,6 @@ const tabs = [
|
|||
name: 'Certificates',
|
||||
dataTestSubj: 'uptimeCertificatesLink',
|
||||
},
|
||||
{
|
||||
id: SETTINGS_ROUTE,
|
||||
dataTestSubj: 'settings-page-link',
|
||||
name: i18n.translate('xpack.uptime.page_header.settingsLink', {
|
||||
defaultMessage: 'Settings',
|
||||
}),
|
||||
},
|
||||
];
|
||||
|
||||
export const PageTabs = () => {
|
||||
|
@ -45,7 +38,6 @@ export const PageTabs = () => {
|
|||
const params = useGetUrlParams();
|
||||
|
||||
const isOverView = useRouteMatch(OVERVIEW_ROUTE);
|
||||
const isSettings = useRouteMatch(SETTINGS_ROUTE);
|
||||
const isCerts = useRouteMatch(CERTIFICATES_ROUTE);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -55,13 +47,10 @@ export const PageTabs = () => {
|
|||
if (isCerts) {
|
||||
setSelectedTabId(CERTIFICATES_ROUTE);
|
||||
}
|
||||
if (isSettings) {
|
||||
setSelectedTabId(SETTINGS_ROUTE);
|
||||
}
|
||||
if (!isOverView?.isExact && !isCerts && !isSettings) {
|
||||
if (!isOverView?.isExact && !isCerts) {
|
||||
setSelectedTabId(null);
|
||||
}
|
||||
}, [isCerts, isSettings, isOverView]);
|
||||
}, [isCerts, isOverView]);
|
||||
|
||||
const createHrefForTab = (id: string) => {
|
||||
if (selectedTabId === OVERVIEW_ROUTE && id === OVERVIEW_ROUTE) {
|
||||
|
|
Loading…
Reference in a new issue