[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:
Justin Kambic 2021-05-26 15:31:15 -04:00 committed by GitHub
parent 7270c3bf40
commit b189d05bc3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 166 additions and 88 deletions

View file

@ -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>
);

View file

@ -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'));
});
});

View file

@ -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>
);
}

View file

@ -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 }}>

View file

@ -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', () => {

View file

@ -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) {