diff --git a/x-pack/plugins/uptime/common/constants/client_defaults.ts b/x-pack/plugins/uptime/common/constants/client_defaults.ts index d8a3ef8d7cbbb..a5db67ae3b58f 100644 --- a/x-pack/plugins/uptime/common/constants/client_defaults.ts +++ b/x-pack/plugins/uptime/common/constants/client_defaults.ts @@ -31,6 +31,7 @@ export const CLIENT_DEFAULTS = { * The end of the default date range is now. */ DATE_RANGE_END: 'now', + FOCUS_CONNECTOR_FIELD: false, FILTERS: '', MONITOR_LIST_PAGE_INDEX: 0, MONITOR_LIST_PAGE_SIZE: 20, diff --git a/x-pack/plugins/uptime/common/constants/plugin.ts b/x-pack/plugins/uptime/common/constants/plugin.ts index 6064524872a0a..71bae9d8dafcd 100644 --- a/x-pack/plugins/uptime/common/constants/plugin.ts +++ b/x-pack/plugins/uptime/common/constants/plugin.ts @@ -17,7 +17,6 @@ export const PLUGIN = { NAME: i18n.translate('xpack.uptime.featureRegistry.uptimeFeatureName', { defaultMessage: 'Uptime', }), - ROUTER_BASE_NAME: '/app/uptime#', TITLE: i18n.translate('xpack.uptime.uptimeFeatureCatalogueTitle', { defaultMessage: 'Uptime', }), diff --git a/x-pack/plugins/uptime/public/apps/plugin.ts b/x-pack/plugins/uptime/public/apps/plugin.ts index 9f7907ec39187..8a6699c16269e 100644 --- a/x-pack/plugins/uptime/public/apps/plugin.ts +++ b/x-pack/plugins/uptime/public/apps/plugin.ts @@ -59,7 +59,7 @@ export class UptimePlugin title: PLUGIN.TITLE, description: PLUGIN.DESCRIPTION, icon: 'uptimeApp', - path: '/app/uptime#/', + path: '/app/uptime', showOnHomePage: false, category: FeatureCatalogueCategory.DATA, }); @@ -84,7 +84,6 @@ export class UptimePlugin }); core.application.register({ - appRoute: '/app/uptime#/', id: PLUGIN.ID, euiIconType: 'uptimeApp', order: 8400, diff --git a/x-pack/plugins/uptime/public/apps/render_app.tsx b/x-pack/plugins/uptime/public/apps/render_app.tsx index f834f8b5cdd3c..c0567ff956ce4 100644 --- a/x-pack/plugins/uptime/public/apps/render_app.tsx +++ b/x-pack/plugins/uptime/public/apps/render_app.tsx @@ -16,13 +16,12 @@ import { } from '../../common/constants'; import { UptimeApp, UptimeAppProps } from './uptime_app'; import { ClientPluginsSetup, ClientPluginsStart } from './plugin'; -import { PLUGIN } from '../../common/constants/plugin'; export function renderApp( core: CoreStart, plugins: ClientPluginsSetup, startPlugins: ClientPluginsStart, - { element }: AppMountParameters + { element, history }: AppMountParameters ) { const { application: { capabilities }, @@ -48,6 +47,7 @@ export function renderApp( basePath: basePath.get(), darkMode: core.uiSettings.get(DEFAULT_DARK_MODE), commonlyUsedRanges: core.uiSettings.get(DEFAULT_TIMEPICKER_QUICK_RANGES), + history, isApmAvailable: apm, isInfraAvailable: infrastructure, isLogsAvailable: logs, @@ -67,7 +67,6 @@ export function renderApp( }, ], }), - routerBasename: basePath.prepend(PLUGIN.ROUTER_BASE_NAME), setBadge, setBreadcrumbs: core.chrome.setBreadcrumbs, }; diff --git a/x-pack/plugins/uptime/public/apps/uptime_app.tsx b/x-pack/plugins/uptime/public/apps/uptime_app.tsx index 1dc34b44b7c64..4b58ba104314f 100644 --- a/x-pack/plugins/uptime/public/apps/uptime_app.tsx +++ b/x-pack/plugins/uptime/public/apps/uptime_app.tsx @@ -8,7 +8,7 @@ import { EuiPage, EuiErrorBoundary } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useEffect } from 'react'; import { Provider as ReduxProvider } from 'react-redux'; -import { BrowserRouter as Router } from 'react-router-dom'; +import { Router } from 'react-router-dom'; import { I18nStart, ChromeBreadcrumb, CoreStart } from 'kibana/public'; import { KibanaContextProvider, @@ -31,6 +31,7 @@ import { } from '../components/overview/alerts'; import { store } from '../state'; import { kibanaService } from '../state/kibana_service'; +import { ScopedHistory } from '../../../../../src/core/public'; export interface UptimeAppColors { danger: string; @@ -46,13 +47,13 @@ export interface UptimeAppProps { canSave: boolean; core: CoreStart; darkMode: boolean; + history: ScopedHistory; i18n: I18nStart; isApmAvailable: boolean; isInfraAvailable: boolean; isLogsAvailable: boolean; plugins: ClientPluginsSetup; startPlugins: ClientPluginsStart; - routerBasename: string; setBadge: UMUpdateBadge; renderGlobalHelpControls(): void; commonlyUsedRanges: CommonlyUsedRange[]; @@ -68,7 +69,6 @@ const Application = (props: UptimeAppProps) => { i18n: i18nCore, plugins, renderGlobalHelpControls, - routerBasename, setBadge, startPlugins, } = props; @@ -99,7 +99,7 @@ const Application = (props: UptimeAppProps) => { - + diff --git a/x-pack/plugins/uptime/public/apps/uptime_overview_fetcher.ts b/x-pack/plugins/uptime/public/apps/uptime_overview_fetcher.ts index 7e5c18f13b29e..b077f622c1dee 100644 --- a/x-pack/plugins/uptime/public/apps/uptime_overview_fetcher.ts +++ b/x-pack/plugins/uptime/public/apps/uptime_overview_fetcher.ts @@ -24,7 +24,7 @@ async function fetchUptimeOverviewData({ const pings = await fetchPingHistogram({ dateStart: start, dateEnd: end, bucketSize }); const response: UptimeFetchDataResponse = { - appLink: `/app/uptime#/?dateRangeStart=${relativeTime.start}&dateRangeEnd=${relativeTime.end}`, + appLink: `/app/uptime?dateRangeStart=${relativeTime.start}&dateRangeEnd=${relativeTime.end}`, stats: { monitors: { type: 'number', diff --git a/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/data_or_index_missing.test.tsx.snap b/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/data_or_index_missing.test.tsx.snap index 0429d36bf8741..41e46259715ee 100644 --- a/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/data_or_index_missing.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/data_or_index_missing.test.tsx.snap @@ -36,7 +36,7 @@ exports[`DataOrIndexMissing component renders headingMessage 1`] = ` - + Get https://expired.badssl.com: x509: certificate has expired or is not yet valid diff --git a/x-pack/plugins/uptime/public/hooks/__tests__/use_breadcrumbs.test.tsx b/x-pack/plugins/uptime/public/hooks/__tests__/use_breadcrumbs.test.tsx index d688660f564ca..9b9af20285304 100644 --- a/x-pack/plugins/uptime/public/hooks/__tests__/use_breadcrumbs.test.tsx +++ b/x-pack/plugins/uptime/public/hooks/__tests__/use_breadcrumbs.test.tsx @@ -44,7 +44,11 @@ describe('useBreadcrumbs', () => { ); const urlParams: UptimeUrlParams = getSupportedUrlParams({}); - expect(getBreadcrumbs()).toStrictEqual([makeBaseBreadcrumb(urlParams)].concat(expectedCrumbs)); + expect(JSON.stringify(getBreadcrumbs())).toEqual( + JSON.stringify( + [makeBaseBreadcrumb('/app/uptime', jest.fn(), urlParams)].concat(expectedCrumbs) + ) + ); }); }); @@ -54,6 +58,10 @@ const mockCore: () => [() => ChromeBreadcrumb[], any] = () => { return breadcrumbObj; }; const core = { + application: { + getUrlForApp: () => '/app/uptime', + navigateToUrl: jest.fn(), + }, chrome: { setBreadcrumbs: (newBreadcrumbs: ChromeBreadcrumb[]) => { breadcrumbObj = newBreadcrumbs; diff --git a/x-pack/plugins/uptime/public/hooks/use_breadcrumbs.ts b/x-pack/plugins/uptime/public/hooks/use_breadcrumbs.ts index 182c6b0114128..ddd3ca7c4f528 100644 --- a/x-pack/plugins/uptime/public/hooks/use_breadcrumbs.ts +++ b/x-pack/plugins/uptime/public/hooks/use_breadcrumbs.ts @@ -7,35 +7,52 @@ import { ChromeBreadcrumb } from 'kibana/public'; import { i18n } from '@kbn/i18n'; import { useEffect } from 'react'; +import { EuiBreadcrumb } from '@elastic/eui'; import { UptimeUrlParams } from '../lib/helper'; import { stringifyUrlParams } from '../lib/helper/stringify_url_params'; import { useKibana } from '../../../../../src/plugins/kibana_react/public'; import { useUrlParams } from '.'; +import { PLUGIN } from '../../common/constants/plugin'; -export const makeBaseBreadcrumb = (params?: UptimeUrlParams): ChromeBreadcrumb => { - let href = '#/'; +const EMPTY_QUERY = '?'; + +export const makeBaseBreadcrumb = ( + href: string, + navigateToHref?: (url: string) => Promise, + params?: UptimeUrlParams +): EuiBreadcrumb => { if (params) { const crumbParams: Partial = { ...params }; // We don't want to encode this values because they are often set to Date.now(), the relative // values in dateRangeStart are better for a URL. delete crumbParams.absoluteDateRangeStart; delete crumbParams.absoluteDateRangeEnd; - href += stringifyUrlParams(crumbParams, true); + const query = stringifyUrlParams(crumbParams, true); + href += query === EMPTY_QUERY ? '' : query; } return { text: i18n.translate('xpack.uptime.breadcrumbs.overviewBreadcrumbText', { defaultMessage: 'Uptime', }), href, + onClick: (event) => { + if (href && navigateToHref) { + event.preventDefault(); + navigateToHref(href); + } + }, }; }; export const useBreadcrumbs = (extraCrumbs: ChromeBreadcrumb[]) => { const params = useUrlParams()[0](); - const setBreadcrumbs = useKibana().services.chrome?.setBreadcrumbs; + const kibana = useKibana(); + const setBreadcrumbs = kibana.services.chrome?.setBreadcrumbs; + const appPath = kibana.services.application?.getUrlForApp(PLUGIN.ID) ?? ''; + const navigate = kibana.services.application?.navigateToUrl; useEffect(() => { if (setBreadcrumbs) { - setBreadcrumbs([makeBaseBreadcrumb(params)].concat(extraCrumbs)); + setBreadcrumbs([makeBaseBreadcrumb(appPath, navigate, params)].concat(extraCrumbs)); } - }, [extraCrumbs, params, setBreadcrumbs]); + }, [appPath, extraCrumbs, navigate, params, setBreadcrumbs]); }; diff --git a/x-pack/plugins/uptime/public/lib/helper/__tests__/__snapshots__/stringify_url_params.test.ts.snap b/x-pack/plugins/uptime/public/lib/helper/__tests__/__snapshots__/stringify_url_params.test.ts.snap deleted file mode 100644 index 31f5ceff7d046..0000000000000 --- a/x-pack/plugins/uptime/public/lib/helper/__tests__/__snapshots__/stringify_url_params.test.ts.snap +++ /dev/null @@ -1,5 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`stringifyUrlParams creates expected string value 1`] = `"?autorefreshInterval=50000&autorefreshIsPaused=false&dateRangeStart=now-15m&dateRangeEnd=now&filters=monitor.id%3A%20bar&search=monitor.id%3A%20foo&selectedPingStatus=down&statusFilter=up"`; - -exports[`stringifyUrlParams creates expected string value when ignore empty is true 1`] = `"?autorefreshInterval=50000&filters=monitor.id%3A%20bar"`; diff --git a/x-pack/plugins/uptime/public/lib/helper/__tests__/stringify_url_params.test.ts b/x-pack/plugins/uptime/public/lib/helper/__tests__/stringify_url_params.test.ts index a2f9b29c4ff58..8cf35c728fc04 100644 --- a/x-pack/plugins/uptime/public/lib/helper/__tests__/stringify_url_params.test.ts +++ b/x-pack/plugins/uptime/public/lib/helper/__tests__/stringify_url_params.test.ts @@ -14,11 +14,14 @@ describe('stringifyUrlParams', () => { dateRangeStart: 'now-15m', dateRangeEnd: 'now', filters: 'monitor.id: bar', + focusConnectorField: true, search: 'monitor.id: foo', selectedPingStatus: 'down', statusFilter: 'up', }); - expect(result).toMatchSnapshot(); + expect(result).toMatchInlineSnapshot( + `"?autorefreshInterval=50000&autorefreshIsPaused=false&dateRangeStart=now-15m&dateRangeEnd=now&filters=monitor.id%3A%20bar&focusConnectorField=true&search=monitor.id%3A%20foo&selectedPingStatus=down&statusFilter=up"` + ); }); it('creates expected string value when ignore empty is true', () => { @@ -29,6 +32,7 @@ describe('stringifyUrlParams', () => { dateRangeStart: 'now-15m', dateRangeEnd: 'now', filters: 'monitor.id: bar', + focusConnectorField: false, search: undefined, selectedPingStatus: undefined, statusFilter: '', @@ -36,7 +40,9 @@ describe('stringifyUrlParams', () => { }, true ); - expect(result).toMatchSnapshot(); + expect(result).toMatchInlineSnapshot( + `"?autorefreshInterval=50000&filters=monitor.id%3A%20bar"` + ); expect(result.includes('pagination')).toBeFalsy(); expect(result.includes('search')).toBeFalsy(); diff --git a/x-pack/plugins/uptime/public/lib/helper/stringify_url_params.ts b/x-pack/plugins/uptime/public/lib/helper/stringify_url_params.ts index a8ce86c4399e2..b10af15961401 100644 --- a/x-pack/plugins/uptime/public/lib/helper/stringify_url_params.ts +++ b/x-pack/plugins/uptime/public/lib/helper/stringify_url_params.ts @@ -13,6 +13,7 @@ const { AUTOREFRESH_IS_PAUSED, DATE_RANGE_START, DATE_RANGE_END, + FOCUS_CONNECTOR_FIELD, } = CLIENT_DEFAULTS; export const stringifyUrlParams = (params: Partial, ignoreEmpty = false) => { @@ -36,6 +37,9 @@ export const stringifyUrlParams = (params: Partial, ignoreEmpty if (key === 'autorefreshInterval' && val === AUTOREFRESH_INTERVAL) { delete params[key]; } + if (key === 'focusConnectorField' && val === FOCUS_CONNECTOR_FIELD) { + delete params[key]; + } }); } return `?${stringify(params, { sort: false })}`;