Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions test/functional/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ export default async function ({ readConfigFile }) {
observabilityCases: {
pathname: '/app/observability/cases',
},
fleet: {
pathname: '/app/fleet',
},
integrations: {
pathname: '/app/integrations',
},
},
junit: {
reportName: 'Chrome UI Functional Tests',
Expand Down
80 changes: 44 additions & 36 deletions x-pack/plugins/fleet/public/applications/fleet/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import React, { memo, useEffect, useState } from 'react';
import type { AppMountParameters } from 'kibana/public';
import { EuiCode, EuiEmptyPrompt, EuiErrorBoundary, EuiPanel, EuiPortal } from '@elastic/eui';
import type { History } from 'history';
import { createHashHistory } from 'history';
import { Router, Redirect, Route, Switch, useRouteMatch } from 'react-router-dom';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
Expand All @@ -20,15 +19,17 @@ import useObservable from 'react-use/lib/useObservable';
import type { TopNavMenuData } from 'src/plugins/navigation/public';

import type { FleetConfigType, FleetStartServices } from '../../plugin';
import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public';
import {
KibanaContextProvider,
RedirectAppLinks,
} from '../../../../../../src/plugins/kibana_react/public';
import { EuiThemeProvider } from '../../../../../../src/plugins/kibana_react/common';

import { PackageInstallProvider, useUrlModal } from '../integrations/hooks';

import {
ConfigContext,
FleetStatusProvider,
IntraAppStateProvider,
KibanaVersionContext,
sendGetPermissionsCheck,
sendSetup,
Expand Down Expand Up @@ -215,43 +216,31 @@ export const FleetAppContext: React.FC<{
}> = memo(
({ children, startServices, config, history, kibanaVersion, extensions, routerHistory }) => {
const isDarkMode = useObservable<boolean>(startServices.uiSettings.get$('theme:darkMode'));
const [routerHistoryInstance] = useState(routerHistory || createHashHistory());
// Sync our hash history with Kibana scoped history
useEffect(() => {
const unlistenParentHistory = history.listen(() => {
const newHash = createHashHistory();
if (newHash.location.pathname !== routerHistoryInstance.location.pathname) {
routerHistoryInstance.replace(newHash.location.pathname + newHash.location.search || '');
}
});

return unlistenParentHistory;
}, [history, routerHistoryInstance]);

return (
<startServices.i18n.Context>
<KibanaContextProvider services={{ ...startServices }}>
<EuiErrorBoundary>
<ConfigContext.Provider value={config}>
<KibanaVersionContext.Provider value={kibanaVersion}>
<EuiThemeProvider darkMode={isDarkMode}>
<UIExtensionsContext.Provider value={extensions}>
<FleetStatusProvider>
<IntraAppStateProvider kibanaScopedHistory={history}>
<Router history={routerHistoryInstance}>
<RedirectAppLinks application={startServices.application}>
<startServices.i18n.Context>
<KibanaContextProvider services={{ ...startServices }}>
<EuiErrorBoundary>
<ConfigContext.Provider value={config}>
<KibanaVersionContext.Provider value={kibanaVersion}>
<EuiThemeProvider darkMode={isDarkMode}>
<UIExtensionsContext.Provider value={extensions}>
<FleetStatusProvider>
<Router history={history}>
<PackageInstallProvider notifications={startServices.notifications}>
{children}
</PackageInstallProvider>
</Router>
</IntraAppStateProvider>
</FleetStatusProvider>
</UIExtensionsContext.Provider>
</EuiThemeProvider>
</KibanaVersionContext.Provider>
</ConfigContext.Provider>
</EuiErrorBoundary>
</KibanaContextProvider>
</startServices.i18n.Context>
</FleetStatusProvider>
</UIExtensionsContext.Provider>
</EuiThemeProvider>
</KibanaVersionContext.Provider>
</ConfigContext.Provider>
</EuiErrorBoundary>
</KibanaContextProvider>
</startServices.i18n.Context>
</RedirectAppLinks>
);
}
);
Expand All @@ -277,7 +266,7 @@ const FleetTopNav = memo(
defaultMessage: 'Fleet settings',
}),
iconType: 'gear',
run: () => (window.location.href = getModalHref('settings')),
run: () => services.application.navigateToUrl(getModalHref('settings')),
},
];
return (
Expand Down Expand Up @@ -327,7 +316,26 @@ export const AppRoutes = memo(
<CreatePackagePolicyPage />
</Route>

<Redirect to={FLEET_ROUTING_PATHS.agents} />
<Route
render={({ location }) => {
// BWC < 7.15 Fleet was using a hash router: redirect old routes using hash
const shouldRedirectHash = location.pathname === '' && location.hash.length > 0;
if (!shouldRedirectHash) {
return <Redirect to={FLEET_ROUTING_PATHS.agents} />;
}
const pathname = location.hash.replace(/^#(\/fleet)?/, '');

return (
<Redirect
to={{
...location,
pathname,
hash: undefined,
}}
/>
);
}}
/>
</Switch>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,18 +150,30 @@ const breadcrumbGetters: {
};

export function useBreadcrumbs(page: Page, values: DynamicPagePathValues = {}) {
const { chrome, http } = useStartServices();
const { chrome, http, application } = useStartServices();
const breadcrumbs =
breadcrumbGetters[page]?.(values).map((breadcrumb) => ({
...breadcrumb,
href: breadcrumb.href
breadcrumbGetters[page]?.(values).map((breadcrumb) => {
const href = breadcrumb.href
? http.basePath.prepend(
`${breadcrumb.useIntegrationsBasePath ? INTEGRATIONS_BASE_PATH : FLEET_BASE_PATH}#${
`${breadcrumb.useIntegrationsBasePath ? INTEGRATIONS_BASE_PATH : FLEET_BASE_PATH}${
breadcrumb.href
}`
)
: undefined,
})) || [];
: undefined;
return {
...breadcrumb,
href,
onClick: href
? (ev: React.MouseEvent) => {
if (ev.metaKey || ev.altKey || ev.ctrlKey || ev.shiftKey) {
return;
}
ev.preventDefault();
application.navigateToUrl(href);
}
: undefined,
};
}) || [];
const docTitle: string[] = [...breadcrumbs]
.reverse()
.map((breadcrumb) => breadcrumb.text as string);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe('when on the package policy create page', () => {
beforeEach(() => {
testRenderer = createFleetTestRendererMock();
mockApiCalls(testRenderer.startServices.http);
testRenderer.history.push(createPageUrlPath);
testRenderer.mountHistory.push(createPageUrlPath);
});

describe('and Route state is provided via Fleet HashRouter', () => {
Expand All @@ -43,7 +43,7 @@ describe('when on the package policy create page', () => {
onCancelNavigateTo: [PLUGIN_ID, { path: '/cancel/url/here' }],
};

testRenderer.history.replace({
testRenderer.mountHistory.replace({
pathname: createPageUrlPath,
state: expectedRouteState,
});
Expand Down Expand Up @@ -72,18 +72,18 @@ describe('when on the package policy create page', () => {
expect(cancelButton.href).toBe(expectedRouteState.onCancelUrl);
});

it('should redirect via Fleet HashRouter when cancel link is clicked', () => {
it('should redirect via history when cancel link is clicked', () => {
act(() => {
cancelLink.click();
});
expect(testRenderer.history.location.pathname).toBe('/cancel/url/here');
expect(testRenderer.mountHistory.location.pathname).toBe('/cancel/url/here');
});

it('should redirect via Fleet HashRouter when cancel Button (button bar) is clicked', () => {
it('should redirect via history when cancel Button (button bar) is clicked', () => {
act(() => {
cancelButton.click();
});
expect(testRenderer.history.location.pathname).toBe('/cancel/url/here');
expect(testRenderer.mountHistory.location.pathname).toBe('/cancel/url/here');
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const NoPackagePolicies = memo<{ policyId: string }>(({ policyId }) => {
fill
onClick={() =>
application.navigateToApp(INTEGRATIONS_PLUGIN_ID, {
path: `#${pagePathGetters.integrations_all()[1]}`,
path: pagePathGetters.integrations_all()[1],
state: { forAgentPolicyId: policyId },
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ export const PackagePoliciesTable: React.FunctionComponent<Props> = ({
iconType="refresh"
onClick={() => {
application.navigateToApp(INTEGRATIONS_PLUGIN_ID, {
path: `#${pagePathGetters.integrations_all()[1]}`,
path: pagePathGetters.integrations_all()[1],
state: { forAgentPolicyId: agentPolicy.id },
});
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import React from 'react';
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import { Router, Switch, Route, useHistory } from 'react-router-dom';

import { FLEET_ROUTING_PATHS } from '../../constants';
import { useBreadcrumbs } from '../../hooks';
Expand All @@ -20,9 +20,10 @@ import { EditPackagePolicyPage } from './edit_package_policy_page';

export const AgentPolicyApp: React.FunctionComponent = () => {
useBreadcrumbs('policies');
const history = useHistory();

return (
<Router>
<Router history={history}>
<Switch>
<Route path={FLEET_ROUTING_PATHS.edit_integration}>
<EditPackagePolicyPage />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import React, { useCallback, useEffect, useState, useMemo } from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import { HashRouter as Router, Route, Switch } from 'react-router-dom';
import { Router, Route, Switch, useHistory } from 'react-router-dom';
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiPortal } from '@elastic/eui';

import { FLEET_ROUTING_PATHS } from '../../constants';
Expand All @@ -30,7 +30,7 @@ import { FleetServerUpgradeModal } from './components/fleet_server_upgrade_modal

export const AgentsApp: React.FunctionComponent = () => {
useBreadcrumbs('agent_list');

const history = useHistory();
const { agents } = useConfig();
const capabilities = useCapabilities();

Expand Down Expand Up @@ -118,7 +118,7 @@ export const AgentsApp: React.FunctionComponent = () => {
) : undefined;

return (
<Router>
<Router history={history}>
<Switch>
<Route path={FLEET_ROUTING_PATHS.agent_details}>
<AgentDetailsPage />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@
*/

import React from 'react';
import { HashRouter as Router, Route, Switch } from 'react-router-dom';
import { Router, Route, Switch, useHistory } from 'react-router-dom';

import { FLEET_ROUTING_PATHS } from '../../constants';
import { DefaultLayout } from '../../layouts';

import { DataStreamListPage } from './list_page';

export const DataStreamApp: React.FunctionComponent = () => {
const history = useHistory();

return (
<Router>
<Router history={history}>
<Switch>
<Route path={FLEET_ROUTING_PATHS.data_streams}>
<DefaultLayout section="data_streams">
Expand Down
Loading