From f8347a9cfef4063376cd4618dc4c972b58d9b844 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Mon, 19 Jul 2021 15:34:22 -0400 Subject: [PATCH 01/11] [Fleet] Replace hash router by router with scoped history --- .../fleet/public/applications/fleet/app.tsx | 68 ++++++++---------- .../fleet/hooks/use_breadcrumbs.tsx | 23 ++++-- .../package_policies/no_package_policies.tsx | 2 +- .../package_policies_table.tsx | 2 +- .../fleet/sections/agent_policy/index.tsx | 5 +- .../fleet/sections/agents/index.tsx | 6 +- .../fleet/sections/data_stream/index.tsx | 6 +- .../public/applications/integrations/app.tsx | 70 ++++++++----------- .../integrations/hooks/use_breadcrumbs.tsx | 23 ++++-- .../sections/epm/screens/detail/index.tsx | 24 +++---- .../epm/screens/detail/settings/settings.tsx | 2 +- x-pack/plugins/fleet/public/hooks/use_link.ts | 2 +- x-pack/plugins/fleet/public/plugin.ts | 19 +---- .../fleet/public/search_provider.test.ts | 12 ++-- .../plugins/fleet/public/search_provider.ts | 4 +- 15 files changed, 127 insertions(+), 141 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/app.tsx b/x-pack/plugins/fleet/public/applications/fleet/app.tsx index 5ac594842d392..e71023c2da904 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/app.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/app.tsx @@ -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'; @@ -20,7 +19,10 @@ 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'; @@ -215,43 +217,33 @@ export const FleetAppContext: React.FC<{ }> = memo( ({ children, startServices, config, history, kibanaVersion, extensions, routerHistory }) => { const isDarkMode = useObservable(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 ( - - - - - - - - - - - - {children} - - - - - - - - - - - + + + + + + + + + + + + + {children} + + + + + + + + + + + + ); } ); @@ -277,7 +269,7 @@ const FleetTopNav = memo( defaultMessage: 'Fleet settings', }), iconType: 'gear', - run: () => (window.location.href = getModalHref('settings')), + run: () => services.application.navigateToUrl(getModalHref('settings')), }, ]; return ( diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_breadcrumbs.tsx b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_breadcrumbs.tsx index c0c425447e556..d0122a3e791b6 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_breadcrumbs.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_breadcrumbs.tsx @@ -150,18 +150,27 @@ 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) => { + ev.preventDefault(); + application.navigateToUrl(href); + } + : undefined, + }; + }) || []; const docTitle: string[] = [...breadcrumbs] .reverse() .map((breadcrumb) => breadcrumb.text as string); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx index 39340a21d349b..e19cb7b1ca5e8 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx @@ -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 }, }) } diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx index 49af14b7234fa..0d2d8e1882183 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx @@ -199,7 +199,7 @@ export const PackagePoliciesTable: React.FunctionComponent = ({ iconType="refresh" onClick={() => { application.navigateToApp(INTEGRATIONS_PLUGIN_ID, { - path: `#${pagePathGetters.integrations_all()[1]}`, + path: pagePathGetters.integrations_all()[1], state: { forAgentPolicyId: agentPolicy.id }, }); }} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/index.tsx index d8db44e28e4af..19f0216a39e03 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/index.tsx @@ -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'; @@ -20,9 +20,10 @@ import { EditPackagePolicyPage } from './edit_package_policy_page'; export const AgentPolicyApp: React.FunctionComponent = () => { useBreadcrumbs('policies'); + const history = useHistory(); return ( - + diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/index.tsx index 52a4c9d17648b..494541a00fc0a 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/index.tsx @@ -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'; @@ -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(); @@ -118,7 +118,7 @@ export const AgentsApp: React.FunctionComponent = () => { ) : undefined; return ( - + diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/data_stream/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/data_stream/index.tsx index c660d3ed29767..51c8346a665cf 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/data_stream/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/data_stream/index.tsx @@ -6,7 +6,7 @@ */ 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'; @@ -14,8 +14,10 @@ import { DefaultLayout } from '../../layouts'; import { DataStreamListPage } from './list_page'; export const DataStreamApp: React.FunctionComponent = () => { + const history = useHistory(); + return ( - + diff --git a/x-pack/plugins/fleet/public/applications/integrations/app.tsx b/x-pack/plugins/fleet/public/applications/integrations/app.tsx index ae59d33e44b82..6ec01329efd72 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/app.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/app.tsx @@ -26,7 +26,10 @@ import { 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 { AgentPolicyContextProvider, useUrlModal } from './hooks'; @@ -189,46 +192,35 @@ export const IntegrationsAppContext: React.FC<{ }> = memo( ({ children, startServices, config, history, kibanaVersion, extensions, routerHistory }) => { const isDarkMode = useObservable(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 ( - - - - - - - - - - - - - {children} - - - - - - - - - - - - + + + + + + + + + + + + + + {children} + + + + + + + + + + + + + ); } ); diff --git a/x-pack/plugins/fleet/public/applications/integrations/hooks/use_breadcrumbs.tsx b/x-pack/plugins/fleet/public/applications/integrations/hooks/use_breadcrumbs.tsx index 19f72fdc69bba..63c8f1cbd318c 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/hooks/use_breadcrumbs.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/hooks/use_breadcrumbs.tsx @@ -51,14 +51,23 @@ const breadcrumbGetters: { }; export function useBreadcrumbs(page: Page, values: DynamicPagePathValues = {}) { - const { chrome, http } = useStartServices(); + const { chrome, http, application } = useStartServices(); const breadcrumbs: ChromeBreadcrumb[] = - breadcrumbGetters[page]?.(values).map((breadcrumb) => ({ - ...breadcrumb, - href: breadcrumb.href - ? http.basePath.prepend(`${INTEGRATIONS_BASE_PATH}#${breadcrumb.href}`) - : undefined, - })) || []; + breadcrumbGetters[page]?.(values).map((breadcrumb) => { + const href = breadcrumb.href + ? http.basePath.prepend(`${INTEGRATIONS_BASE_PATH}${breadcrumb.href}`) + : undefined; + return { + ...breadcrumb, + href, + onClick: href + ? (ev: React.MouseEvent) => { + ev.preventDefault(); + application.navigateToUrl(href); + } + : undefined, + }; + }) || []; const docTitle: string[] = [...breadcrumbs] .reverse() .map((breadcrumb) => breadcrumb.text as string); diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx index 21a139ad11baa..26869f8fea574 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx @@ -235,22 +235,18 @@ export function Detail() { redirectToPath = [ PLUGIN_ID, { - path: `#${ - pagePathGetters.policy_details({ - policyId: agentPolicyIdFromContext, - })[1] - }`, + path: pagePathGetters.policy_details({ + policyId: agentPolicyIdFromContext, + })[1], }, ]; } else { redirectToPath = [ INTEGRATIONS_PLUGIN_ID, { - path: `#${ - pagePathGetters.integration_details_policies({ - pkgkey, - })[1] - }`, + path: pagePathGetters.integration_details_policies({ + pkgkey, + })[1], }, ]; } @@ -260,16 +256,16 @@ export function Detail() { onCancelNavigateTo: [ INTEGRATIONS_PLUGIN_ID, { - path: currentPath, + path: pagePathGetters.integration_details_overview({ + pkgkey, + })[1], }, ], onCancelUrl: currentPath, }; services.application.navigateToApp(PLUGIN_ID, { - // Necessary because of Fleet's HashRouter. Can be changed when - // https://github.com/elastic/kibana/issues/96134 is resolved - path: `#${path}`, + path, state: redirectBackRouteState, }); }, diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/settings.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/settings.tsx index 14f378bc379a6..3b161a375e7ce 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/settings.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/settings.tsx @@ -53,7 +53,7 @@ const LatestVersionLink = ({ name, version }: { name: string; version: string }) pkgkey: `${name}-${version}`, }); return ( - + { core.http.basePath.prepend(`/plugins/${PLUGIN_ID}/assets/${path}`), getHref: (page: StaticPage | DynamicPage, values?: DynamicPagePathValues) => { const [basePath, path] = getSeparatePaths(page, values); - return core.http.basePath.prepend(`${basePath}#${path}`); + return core.http.basePath.prepend(`${basePath}${path}`); }, }; }; diff --git a/x-pack/plugins/fleet/public/plugin.ts b/x-pack/plugins/fleet/public/plugin.ts index f4a347c2ab3f0..e10eab7d32136 100644 --- a/x-pack/plugins/fleet/public/plugin.ts +++ b/x-pack/plugins/fleet/public/plugin.ts @@ -16,7 +16,7 @@ import { i18n } from '@kbn/i18n'; import type { NavigationPublicPluginStart } from 'src/plugins/navigation/public'; -import { DEFAULT_APP_CATEGORIES, AppNavLinkStatus } from '../../../../src/core/public'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; import type { DataPublicPluginSetup, DataPublicPluginStart, @@ -104,6 +104,7 @@ export class FleetPlugin implements Plugin { const [coreStartServices, startDepsServices] = (await core.getStartServices()) as [ CoreStart, @@ -159,21 +161,6 @@ export class FleetPlugin implements Plugin {}; - }, - }); - // Register components for home/add data integration if (deps.home) { deps.home.tutorials.registerDirectoryNotice(PLUGIN_ID, TutorialDirectoryNotice); diff --git a/x-pack/plugins/fleet/public/search_provider.test.ts b/x-pack/plugins/fleet/public/search_provider.test.ts index 521337c9dda6b..8eee18710d477 100644 --- a/x-pack/plugins/fleet/public/search_provider.test.ts +++ b/x-pack/plugins/fleet/public/search_provider.test.ts @@ -92,7 +92,7 @@ describe('Package search provider', () => { title: 'test', type: 'integration', url: { - path: 'undefined#/detail/test-test/overview', + path: 'undefined/detail/test-test/overview', prependBasePath: false, }, }, @@ -102,7 +102,7 @@ describe('Package search provider', () => { title: 'test1', type: 'integration', url: { - path: 'undefined#/detail/test1-test1/overview', + path: 'undefined/detail/test1-test1/overview', prependBasePath: false, }, }, @@ -175,7 +175,7 @@ describe('Package search provider', () => { title: 'test1', type: 'integration', url: { - path: 'undefined#/detail/test1-test1/overview', + path: 'undefined/detail/test1-test1/overview', prependBasePath: false, }, }, @@ -231,7 +231,7 @@ describe('Package search provider', () => { title: 'test', type: 'integration', url: { - path: 'undefined#/detail/test-test/overview', + path: 'undefined/detail/test-test/overview', prependBasePath: false, }, }, @@ -241,7 +241,7 @@ describe('Package search provider', () => { title: 'test1', type: 'integration', url: { - path: 'undefined#/detail/test1-test1/overview', + path: 'undefined/detail/test1-test1/overview', prependBasePath: false, }, }, @@ -274,7 +274,7 @@ describe('Package search provider', () => { title: 'test1', type: 'integration', url: { - path: 'undefined#/detail/test1-test1/overview', + path: 'undefined/detail/test1-test1/overview', prependBasePath: false, }, }, diff --git a/x-pack/plugins/fleet/public/search_provider.ts b/x-pack/plugins/fleet/public/search_provider.ts index 9705f4da50f94..5f53c0a8e44ba 100644 --- a/x-pack/plugins/fleet/public/search_provider.ts +++ b/x-pack/plugins/fleet/public/search_provider.ts @@ -45,10 +45,8 @@ const toSearchResult = ( title: pkg.title, score: 80, url: { - // TODO: See https://github.com/elastic/kibana/issues/96134 for details about why we use '#' here. Below should be updated - // as part of migrating to non-hash based router. // prettier-ignore - path: `${application.getUrlForApp(INTEGRATIONS_PLUGIN_ID)}#${pagePathGetters.integration_details_overview({ pkgkey })[1]}`, + path: `${application.getUrlForApp(INTEGRATIONS_PLUGIN_ID)}${pagePathGetters.integration_details_overview({ pkgkey })[1]}`, prependBasePath: false, }, }; From 47513be6fa4f2bba0ca741f74c1a4beba8006c0b Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Tue, 20 Jul 2021 11:40:17 -0400 Subject: [PATCH 02/11] fix types and i18n --- .../fleet/public/applications/integrations/app.tsx | 1 - x-pack/plugins/translations/translations/ja-JP.json | 13 ++++++------- x-pack/plugins/translations/translations/zh-CN.json | 13 ++++++------- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/integrations/app.tsx b/x-pack/plugins/fleet/public/applications/integrations/app.tsx index 6ec01329efd72..3650039c07fa1 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/app.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/app.tsx @@ -9,7 +9,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 } from 'react-router-dom'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 13cb175ac908e..15e448351ea7c 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -6082,8 +6082,6 @@ "xpack.canvas.error.useImportWorkpad.missingPropertiesErrorMessage": "{CANVAS} ワークパッドに必要なプロパティの一部が欠けています。 {JSON} ファイルを編集して正しいプロパティ値を入力し、再試行してください。", "xpack.canvas.error.workpadRoutes.createFailureErrorMessage": "ワークパッドを作成できませんでした", "xpack.canvas.error.workpadRoutes.loadFailureErrorMessage": "ID でワークパッドを読み込めませんでした", - "expressionError.errorComponent.description": "表現が失敗し次のメッセージが返されました:", - "expressionError.errorComponent.title": "おっと!表現が失敗しました", "xpack.canvas.expression.cancelButtonLabel": "キャンセル", "xpack.canvas.expression.closeButtonLabel": "閉じる", "xpack.canvas.expression.learnLinkText": "表現構文の詳細", @@ -6495,15 +6493,11 @@ "xpack.canvas.renderer.advancedFilter.displayName": "高度なフィルター", "xpack.canvas.renderer.advancedFilter.helpDescription": "Canvas フィルター表現をレンダリングします。", "xpack.canvas.renderer.advancedFilter.inputPlaceholder": "フィルター表現を入力", - "expressionError.renderer.debug.displayName": "デバッグ", - "expressionError.renderer.debug.helpDescription": "デバッグアウトプットをフォーマットされた {JSON} としてレンダリングします", "xpack.canvas.renderer.dropdownFilter.displayName": "ドロップダウンフィルター", "xpack.canvas.renderer.dropdownFilter.helpDescription": "「{exactly}」フィルターの値を選択できるドロップダウンです", "xpack.canvas.renderer.dropdownFilter.matchAllOptionLabel": "すべて", "xpack.canvas.renderer.embeddable.displayName": "埋め込み可能", "xpack.canvas.renderer.embeddable.helpDescription": "Kibana の他の部分から埋め込み可能な保存済みオブジェクトをレンダリングします", - "expressionError.renderer.error.displayName": "エラー情報", - "expressionError.renderer.error.helpDescription": "エラーデータをユーザーにわかるようにレンダリングします", "xpack.canvas.renderer.image.displayName": "画像", "xpack.canvas.renderer.image.helpDescription": "画像をレンダリングします", "xpack.canvas.renderer.markdown.displayName": "マークダウン", @@ -6987,6 +6981,12 @@ "xpack.canvas.workpadTemplates.table.descriptionColumnTitle": "説明", "xpack.canvas.workpadTemplates.table.nameColumnTitle": "テンプレート名", "xpack.canvas.workpadTemplates.table.tagsColumnTitle": "タグ", + "expressionError.errorComponent.description": "表現が失敗し次のメッセージが返されました:", + "expressionError.errorComponent.title": "おっと!表現が失敗しました", + "expressionError.renderer.debug.displayName": "デバッグ", + "expressionError.renderer.debug.helpDescription": "デバッグアウトプットをフォーマットされた {JSON} としてレンダリングします", + "expressionError.renderer.error.displayName": "エラー情報", + "expressionError.renderer.error.helpDescription": "エラーデータをユーザーにわかるようにレンダリングします", "expressionRevealImage.functions.revealImage.args.emptyImageHelpText": "表示される背景画像です。画像アセットは「{BASE64}」データ {URL} として提供するか、部分式で渡します。", "expressionRevealImage.functions.revealImage.args.imageHelpText": "表示する画像です。画像アセットは{BASE64}データ{URL}として提供するか、部分式で渡します。", "expressionRevealImage.functions.revealImage.args.originHelpText": "画像で埋め始める位置です。たとえば、{list}、または {end}です。", @@ -9088,7 +9088,6 @@ "xpack.fleet.newEnrollmentKey.submitButton": "登録トークンを作成", "xpack.fleet.noAccess.accessDeniedDescription": "Elastic Fleet にアクセスする権限がありません。Elastic Fleet を使用するには、このアプリケーションの読み取り権または全権を含むユーザーロールが必要です。", "xpack.fleet.noAccess.accessDeniedTitle": "アクセスが拒否されました", - "xpack.fleet.oldAppTitle": "Ingest Manager", "xpack.fleet.overviewPageSubtitle": "Elasticエージェントとポリシーを中央の場所で管理します。", "xpack.fleet.overviewPageTitle": "Fleet", "xpack.fleet.packagePolicyInputOverrideError": "パッケージ{packageName}には入力タイプ{inputType}が存在しません。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 6e7ab7a33a0f3..dd21a1bbe805e 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -6121,8 +6121,6 @@ "xpack.canvas.error.useImportWorkpad.missingPropertiesErrorMessage": "{CANVAS} Workpad 所需的某些属性缺失。 编辑 {JSON} 文件以提供正确的属性值,然后重试。", "xpack.canvas.error.workpadRoutes.createFailureErrorMessage": "无法创建 Workpad", "xpack.canvas.error.workpadRoutes.loadFailureErrorMessage": "无法加载具有以下 ID 的 Workpad", - "expressionError.errorComponent.description": "表达式失败,并显示消息:", - "expressionError.errorComponent.title": "哎哟!表达式失败", "xpack.canvas.expression.cancelButtonLabel": "取消", "xpack.canvas.expression.closeButtonLabel": "关闭", "xpack.canvas.expression.learnLinkText": "学习表达式语法", @@ -6535,15 +6533,11 @@ "xpack.canvas.renderer.advancedFilter.displayName": "高级筛选", "xpack.canvas.renderer.advancedFilter.helpDescription": "呈现 Canvas 筛选表达式", "xpack.canvas.renderer.advancedFilter.inputPlaceholder": "输入筛选表达式", - "expressionError.renderer.debug.displayName": "故障排查", - "expressionError.renderer.debug.helpDescription": "将故障排查输出呈现为带格式的 {JSON}", "xpack.canvas.renderer.dropdownFilter.displayName": "下拉列表筛选", "xpack.canvas.renderer.dropdownFilter.helpDescription": "可以从其中为“{exactly}”筛选选择值的下拉列表", "xpack.canvas.renderer.dropdownFilter.matchAllOptionLabel": "任意", "xpack.canvas.renderer.embeddable.displayName": "可嵌入", "xpack.canvas.renderer.embeddable.helpDescription": "从 Kibana 的其他部分呈现可嵌入的已保存对象", - "expressionError.renderer.error.displayName": "错误信息", - "expressionError.renderer.error.helpDescription": "以用户友好的方式呈现错误数据", "xpack.canvas.renderer.image.displayName": "图像", "xpack.canvas.renderer.image.helpDescription": "呈现图像", "xpack.canvas.renderer.markdown.displayName": "Markdown", @@ -7035,6 +7029,12 @@ "xpack.canvas.workpadTemplates.table.descriptionColumnTitle": "描述", "xpack.canvas.workpadTemplates.table.nameColumnTitle": "模板名称", "xpack.canvas.workpadTemplates.table.tagsColumnTitle": "标签", + "expressionError.errorComponent.description": "表达式失败,并显示消息:", + "expressionError.errorComponent.title": "哎哟!表达式失败", + "expressionError.renderer.debug.displayName": "故障排查", + "expressionError.renderer.debug.helpDescription": "将故障排查输出呈现为带格式的 {JSON}", + "expressionError.renderer.error.displayName": "错误信息", + "expressionError.renderer.error.helpDescription": "以用户友好的方式呈现错误数据", "expressionRevealImage.functions.revealImage.args.emptyImageHelpText": "要显示的可选背景图像。以 `{BASE64}` 数据 {URL} 的形式提供图像资产或传入子表达式。", "expressionRevealImage.functions.revealImage.args.imageHelpText": "要显示的图像。以 {BASE64} 数据 {URL} 的形式提供图像资产或传入子表达式。", "expressionRevealImage.functions.revealImage.args.originHelpText": "要开始图像填充的位置。例如 {list} 或 {end}。", @@ -9174,7 +9174,6 @@ "xpack.fleet.newEnrollmentKey.submitButton": "创建注册令牌", "xpack.fleet.noAccess.accessDeniedDescription": "您无权访问 Elastic Fleet。要使用 Elastic Fleet,您需要包含此应用程序读取权限或所有权限的用户角色。", "xpack.fleet.noAccess.accessDeniedTitle": "访问被拒绝", - "xpack.fleet.oldAppTitle": "采集管理器", "xpack.fleet.overviewPageSubtitle": "在集中位置管理 Elastic 代理及其策略。", "xpack.fleet.overviewPageTitle": "Fleet", "xpack.fleet.packagePolicyInputOverrideError": "输入类型 {inputType} 在软件包 {packageName} 上不存在", From a916064f075d3aad0fd9270093781fdcbbcf011e Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Tue, 20 Jul 2021 15:42:28 -0400 Subject: [PATCH 03/11] Fix tests --- .../create_package_policy_page/index.test.tsx | 12 ++-- .../public/applications/integrations/app.tsx | 68 +++++++++---------- .../epm/screens/detail/index.test.tsx | 22 +++--- .../public/mock/create_test_renderer.tsx | 9 +-- .../page_objects/fleet_integrations_page.ts | 7 +- 5 files changed, 59 insertions(+), 59 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.test.tsx index a624d8ced9180..c115089cccb1e 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.test.tsx @@ -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', () => { @@ -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, }); @@ -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'); }); }); }); diff --git a/x-pack/plugins/fleet/public/applications/integrations/app.tsx b/x-pack/plugins/fleet/public/applications/integrations/app.tsx index 3650039c07fa1..da7b4bab1b2a7 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/app.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/app.tsx @@ -187,42 +187,40 @@ export const IntegrationsAppContext: React.FC<{ kibanaVersion: string; extensions: UIExtensionsStorage; /** For testing purposes only */ - routerHistory?: History; -}> = memo( - ({ children, startServices, config, history, kibanaVersion, extensions, routerHistory }) => { - const isDarkMode = useObservable(startServices.uiSettings.get$('theme:darkMode')); + routerHistory?: History; // TODO remove +}> = memo(({ children, startServices, config, history, kibanaVersion, extensions }) => { + const isDarkMode = useObservable(startServices.uiSettings.get$('theme:darkMode')); - return ( - - - - - - - - - - - - - - {children} - - - - - - - - - - - - - - ); - } -); + return ( + + + + + + + + + + + + + + {children} + + + + + + + + + + + + + + ); +}); export const AppRoutes = memo(() => { const { modal, setModal } = useUrlModal(); diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.test.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.test.tsx index f436c248abd3c..31a3e2164a247 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.test.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.test.tsx @@ -45,22 +45,22 @@ describe('when on integration detail', () => { )); - beforeEach(() => { + beforeEach(async () => { testRenderer = createIntegrationsTestRendererMock(); mockedApi = mockApiCalls(testRenderer.startServices.http); - testRenderer.history.push(detailPageUrlPath); + act(() => testRenderer.mountHistory.push(detailPageUrlPath)); }); afterEach(() => { cleanup(); - window.location.hash = '#/'; }); describe('and the package is installed', () => { beforeEach(() => render()); it('should display agent policy usage count', async () => { - await mockedApi.waitForApi(); + await act(() => mockedApi.waitForApi()); + expect(renderResult.queryByTestId('agentPolicyCount')).not.toBeNull(); }); @@ -105,11 +105,11 @@ describe('when on integration detail', () => { it('should redirect if custom url is accessed', () => { act(() => { - testRenderer.history.push( + testRenderer.mountHistory.push( pagePathGetters.integration_details_custom({ pkgkey: 'nginx-0.3.7' })[1] ); }); - expect(testRenderer.history.location.pathname).toEqual('/detail/nginx-0.3.7/overview'); + expect(testRenderer.mountHistory.location.pathname).toEqual('/detail/nginx-0.3.7/overview'); }); }); @@ -153,7 +153,7 @@ describe('when on integration detail', () => { it('should display custom content when tab is clicked', async () => { act(() => { - testRenderer.history.push( + testRenderer.mountHistory.push( pagePathGetters.integration_details_custom({ pkgkey: 'nginx-0.3.7' })[1] ); }); @@ -200,7 +200,7 @@ describe('when on integration detail', () => { it('should display custom assets when tab is clicked', async () => { act(() => { - testRenderer.history.push( + testRenderer.mountHistory.push( pagePathGetters.integration_details_assets({ pkgkey: 'nginx-0.3.7' })[1] ); }); @@ -215,7 +215,7 @@ describe('when on integration detail', () => { it('should link to the create page', () => { const addButton = renderResult.getByTestId('addIntegrationPolicyButton') as HTMLAnchorElement; expect(addButton.href).toEqual( - 'http://localhost/mock/app/fleet#/integrations/nginx-0.3.7/add-integration' + 'http://localhost/mock/app/fleet/integrations/nginx-0.3.7/add-integration' ); }); }); @@ -223,7 +223,7 @@ describe('when on integration detail', () => { describe('and on the Policies Tab', () => { const policiesTabURLPath = pagePathGetters.integration_details_policies({ pkgkey })[1]; beforeEach(() => { - testRenderer.history.push(policiesTabURLPath); + testRenderer.mountHistory.push(policiesTabURLPath); render(); }); @@ -238,7 +238,7 @@ describe('when on integration detail', () => { 'integrationNameLink' )[0] as HTMLAnchorElement; expect(firstPolicy.href).toEqual( - 'http://localhost/mock/app/integrations#/edit-integration/e8a37031-2907-44f6-89d2-98bd493f60dc' + 'http://localhost/mock/app/integrations/edit-integration/e8a37031-2907-44f6-89d2-98bd493f60dc' ); }); diff --git a/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx b/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx index 71c9650709ee2..d0724545ee902 100644 --- a/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx +++ b/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx @@ -6,7 +6,7 @@ */ import type { History } from 'history'; -import { createMemoryHistory, createHashHistory } from 'history'; +import { createMemoryHistory } from 'history'; import React, { memo } from 'react'; import type { RenderOptions, RenderResult } from '@testing-library/react'; import { render as reactRender, act } from '@testing-library/react'; @@ -47,9 +47,10 @@ export const createFleetTestRendererMock = (): TestRenderer => { const basePath = '/mock'; const extensions: UIExtensionsStorage = {}; const startServices = createStartServices(basePath); + const history = createMemoryHistory({ initialEntries: [basePath] }); const testRendererMocks: TestRenderer = { - history: createHashHistory(), - mountHistory: new ScopedHistory(createMemoryHistory({ initialEntries: [basePath] }), basePath), + history, + mountHistory: new ScopedHistory(history, basePath), startServices, config: createConfigurationMock(), startInterface: createStartMock(extensions), @@ -89,7 +90,7 @@ export const createIntegrationsTestRendererMock = (): TestRenderer => { const extensions: UIExtensionsStorage = {}; const startServices = createStartServices(basePath); const testRendererMocks: TestRenderer = { - history: createHashHistory(), + history: createMemoryHistory(), mountHistory: new ScopedHistory(createMemoryHistory({ initialEntries: [basePath] }), basePath), startServices, config: createConfigurationMock(), diff --git a/x-pack/test/security_solution_endpoint/page_objects/fleet_integrations_page.ts b/x-pack/test/security_solution_endpoint/page_objects/fleet_integrations_page.ts index 5abc842ddc9c9..9c9749abf48f4 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/fleet_integrations_page.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/fleet_integrations_page.ts @@ -17,9 +17,10 @@ export function FleetIntegrations({ getService, getPageObjects }: FtrProviderCon return { async navigateToIntegrationDetails(pkgkey: string) { - await pageObjects.common.navigateToApp(INTEGRATIONS_PLUGIN_ID, { - hash: pagePathGetters.integration_details_overview({ pkgkey })[1], - }); + await pageObjects.common.navigateToUrl( + INTEGRATIONS_PLUGIN_ID, + pagePathGetters.integration_details_overview({ pkgkey })[1] + ); }, async integrationDetailCustomTabExistsOrFail() { From 286d0a0c61972e9ddae289bb0156b849e6aecddd Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Tue, 20 Jul 2021 16:05:14 -0400 Subject: [PATCH 04/11] Fix tests --- .../functional/page_objects/synthetics_integration_page.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/test/functional/page_objects/synthetics_integration_page.ts b/x-pack/test/functional/page_objects/synthetics_integration_page.ts index 3321234a345e4..b1f7bae082f56 100644 --- a/x-pack/test/functional/page_objects/synthetics_integration_page.ts +++ b/x-pack/test/functional/page_objects/synthetics_integration_page.ts @@ -28,7 +28,7 @@ export function SyntheticsIntegrationPageProvider({ 'fleet', `/integrations/synthetics-${packageVersion}/add-integration`, { - shouldUseHashForSubUrl: true, + shouldUseHashForSubUrl: false, useActualUrl: true, } ); @@ -40,7 +40,7 @@ export function SyntheticsIntegrationPageProvider({ 'fleet', `/policies/${agentId}/edit-integration/${packageId}`, { - shouldUseHashForSubUrl: true, + shouldUseHashForSubUrl: false, useActualUrl: true, } ); From f634deb81de725a9b73b5ddad0671d1b805a074d Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Tue, 20 Jul 2021 16:49:24 -0400 Subject: [PATCH 05/11] Fix tests --- test/functional/config.js | 6 ++++++ .../page_objects/synthetics_integration_page.ts | 16 ++++------------ .../page_objects/fleet_integrations_page.ts | 2 +- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/test/functional/config.js b/test/functional/config.js index 1c0c519f21e4c..19a628be10f52 100644 --- a/test/functional/config.js +++ b/test/functional/config.js @@ -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', diff --git a/x-pack/test/functional/page_objects/synthetics_integration_page.ts b/x-pack/test/functional/page_objects/synthetics_integration_page.ts index b1f7bae082f56..81ddaf06febd9 100644 --- a/x-pack/test/functional/page_objects/synthetics_integration_page.ts +++ b/x-pack/test/functional/page_objects/synthetics_integration_page.ts @@ -24,25 +24,17 @@ export function SyntheticsIntegrationPageProvider({ * */ async navigateToPackagePage(packageVersion: string) { - await pageObjects.common.navigateToUrl( + await pageObjects.common.navigateToUrlWithBrowserHistory( 'fleet', - `/integrations/synthetics-${packageVersion}/add-integration`, - { - shouldUseHashForSubUrl: false, - useActualUrl: true, - } + `/integrations/synthetics-${packageVersion}/add-integration` ); await pageObjects.header.waitUntilLoadingHasFinished(); }, async navigateToPackageEditPage(packageId: string, agentId: string) { - await pageObjects.common.navigateToUrl( + await pageObjects.common.navigateToUrlWithBrowserHistory( 'fleet', - `/policies/${agentId}/edit-integration/${packageId}`, - { - shouldUseHashForSubUrl: false, - useActualUrl: true, - } + `/policies/${agentId}/edit-integration/${packageId}` ); await pageObjects.header.waitUntilLoadingHasFinished(); }, diff --git a/x-pack/test/security_solution_endpoint/page_objects/fleet_integrations_page.ts b/x-pack/test/security_solution_endpoint/page_objects/fleet_integrations_page.ts index 9c9749abf48f4..81e868c5a38cb 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/fleet_integrations_page.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/fleet_integrations_page.ts @@ -17,7 +17,7 @@ export function FleetIntegrations({ getService, getPageObjects }: FtrProviderCon return { async navigateToIntegrationDetails(pkgkey: string) { - await pageObjects.common.navigateToUrl( + await pageObjects.common.navigateToUrlWithBrowserHistory( INTEGRATIONS_PLUGIN_ID, pagePathGetters.integration_details_overview({ pkgkey })[1] ); From 0471fa78d07a4fe6dd521c2c78647acd1fd81bb5 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Tue, 20 Jul 2021 19:20:37 -0400 Subject: [PATCH 06/11] Remove ingestManager legacy app --- .../server/collectors/application_usage/schema.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts index 54a3fe9e4399c..637400fb4ceb2 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts @@ -144,7 +144,6 @@ export const applicationUsageSchema = { infra: commonSchema, // It's a forward app so we'll likely never report it fleet: commonSchema, integrations: commonSchema, - ingestManager: commonSchema, lens: commonSchema, maps: commonSchema, ml: commonSchema, From ad597056283b2e393d3ee0a07e9ad3b316d2c542 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Tue, 20 Jul 2021 19:51:14 -0400 Subject: [PATCH 07/11] Fix tests --- .../collectors/application_usage/schema.ts | 1 + x-pack/plugins/fleet/public/plugin.ts | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts index 637400fb4ceb2..54a3fe9e4399c 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts @@ -144,6 +144,7 @@ export const applicationUsageSchema = { infra: commonSchema, // It's a forward app so we'll likely never report it fleet: commonSchema, integrations: commonSchema, + ingestManager: commonSchema, lens: commonSchema, maps: commonSchema, ml: commonSchema, diff --git a/x-pack/plugins/fleet/public/plugin.ts b/x-pack/plugins/fleet/public/plugin.ts index e10eab7d32136..6d81b7f1b6f62 100644 --- a/x-pack/plugins/fleet/public/plugin.ts +++ b/x-pack/plugins/fleet/public/plugin.ts @@ -16,7 +16,7 @@ import { i18n } from '@kbn/i18n'; import type { NavigationPublicPluginStart } from 'src/plugins/navigation/public'; -import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; +import { DEFAULT_APP_CATEGORIES, AppNavLinkStatus } from '../../../../src/core/public'; import type { DataPublicPluginSetup, DataPublicPluginStart, @@ -161,6 +161,21 @@ export class FleetPlugin implements Plugin {}; + }, + }); + // Register components for home/add data integration if (deps.home) { deps.home.tutorials.registerDirectoryNotice(PLUGIN_ID, TutorialDirectoryNotice); From 07a9c9ea5893fb6f1fa949b8d9a22ffae4a03f99 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Wed, 21 Jul 2021 13:34:46 -0400 Subject: [PATCH 08/11] Support hash redirection --- .../fleet/public/applications/fleet/app.tsx | 21 ++++++++++++++++++- .../public/applications/integrations/app.tsx | 21 ++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/app.tsx b/x-pack/plugins/fleet/public/applications/fleet/app.tsx index e71023c2da904..6e117ab110e91 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/app.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/app.tsx @@ -319,7 +319,26 @@ export const AppRoutes = memo( - + { + // 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 ; + } + const pathname = location.hash.replace(/^#\/fleet/, ''); + + return ( + + ); + }} + /> ); diff --git a/x-pack/plugins/fleet/public/applications/integrations/app.tsx b/x-pack/plugins/fleet/public/applications/integrations/app.tsx index da7b4bab1b2a7..4473efa89851f 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/app.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/app.tsx @@ -239,7 +239,26 @@ export const AppRoutes = memo(() => { - + { + // 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 ; + } + const pathname = location.hash.replace(/^#/, ''); + + return ( + + ); + }} + /> ); From 424990a6e7dd8b1cb2c504d2ba7c0ebadf9145e2 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Thu, 22 Jul 2021 15:44:16 -0400 Subject: [PATCH 09/11] Fix after review and fix endpoint fleet urls --- .../fleet/public/applications/fleet/app.tsx | 15 +++--- .../fleet/hooks/use_breadcrumbs.tsx | 3 ++ .../public/applications/integrations/app.tsx | 18 +++---- .../public/hooks/use_intra_app_state.tsx | 53 +------------------ .../use_navigate_to_app_event_handler.ts | 2 +- .../pages/endpoint_hosts/view/hooks/hooks.ts | 4 +- .../view/hooks/use_endpoint_action_items.tsx | 16 +++--- .../pages/endpoint_hosts/view/index.test.tsx | 6 +-- .../pages/endpoint_hosts/view/index.tsx | 4 +- .../components/overview_empty/index.test.tsx | 2 +- .../components/overview_empty/index.tsx | 2 +- 11 files changed, 37 insertions(+), 88 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/app.tsx b/x-pack/plugins/fleet/public/applications/fleet/app.tsx index 6e117ab110e91..11be87f146851 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/app.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/app.tsx @@ -30,7 +30,6 @@ import { PackageInstallProvider, useUrlModal } from '../integrations/hooks'; import { ConfigContext, FleetStatusProvider, - IntraAppStateProvider, KibanaVersionContext, sendGetPermissionsCheck, sendSetup, @@ -228,13 +227,11 @@ export const FleetAppContext: React.FC<{ - - - - {children} - - - + + + {children} + + @@ -326,7 +323,7 @@ export const AppRoutes = memo( if (!shouldRedirectHash) { return ; } - const pathname = location.hash.replace(/^#\/fleet/, ''); + const pathname = location.hash.replace(/^#(\/fleet)?/, ''); return ( { + if (ev.metaKey || ev.altKey || ev.ctrlKey || ev.shiftKey) { + return; + } ev.preventDefault(); application.navigateToUrl(href); } diff --git a/x-pack/plugins/fleet/public/applications/integrations/app.tsx b/x-pack/plugins/fleet/public/applications/integrations/app.tsx index 4473efa89851f..f0c94b51677ee 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/app.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/app.tsx @@ -41,7 +41,7 @@ import type { UIExtensionsStorage } from './types'; import { EPMApp } from './sections/epm'; import { DefaultLayout, WithoutHeaderLayout } from './layouts'; import { PackageInstallProvider } from './hooks'; -import { useBreadcrumbs, IntraAppStateProvider, UIExtensionsContext } from './hooks'; +import { useBreadcrumbs, UIExtensionsContext } from './hooks'; const ErrorLayout = ({ children }: { children: JSX.Element }) => ( @@ -201,15 +201,13 @@ export const IntegrationsAppContext: React.FC<{ - - - - - {children} - - - - + + + + {children} + + + diff --git a/x-pack/plugins/fleet/public/hooks/use_intra_app_state.tsx b/x-pack/plugins/fleet/public/hooks/use_intra_app_state.tsx index 2a1df7605fcfa..ed757ee7948a2 100644 --- a/x-pack/plugins/fleet/public/hooks/use_intra_app_state.tsx +++ b/x-pack/plugins/fleet/public/hooks/use_intra_app_state.tsx @@ -11,37 +11,6 @@ import { useLocation } from 'react-router-dom'; import type { AnyIntraAppRouteState } from '../types'; -interface IntraAppState { - forRoute: string; - routeState?: S; -} - -const IntraAppStateContext = React.createContext({ forRoute: '' }); -const wasHandled = new WeakSet(); - -/** - * Provides a bridget between Kibana's ScopedHistory instance (normally used with BrowserRouter) - * and the Hash router used within the app in order to enable state to be used between kibana - * apps - */ -export const IntraAppStateProvider = memo<{ - kibanaScopedHistory: AppMountParameters['history']; - children: React.ReactNode; -}>(({ kibanaScopedHistory, children }) => { - const internalAppToAppState = useMemo(() => { - return { - forRoute: new URL(`${kibanaScopedHistory.location.hash.substr(1)}`, 'http://localhost') - .pathname, - routeState: kibanaScopedHistory.location.state as AnyIntraAppRouteState, - }; - }, [kibanaScopedHistory.location.state, kibanaScopedHistory.location.hash]); - return ( - - {children} - - ); -}); - /** * Retrieve UI Route state from the React Router History for the current URL location. * This state can be used by other Kibana Apps to influence certain behaviours in Ingest, for example, @@ -51,26 +20,6 @@ export function useIntraAppState(): | IntraAppState['routeState'] | undefined { const location = useLocation(); - const intraAppState = useContext(IntraAppStateContext); - if (!intraAppState) { - throw new Error('Hook called outside of IntraAppStateContext'); - } - return useMemo(() => { - // Due to the use of HashRouter in Ingest, we only want state to be returned - // once so that it does not impact navigation to the page from within the - // ingest app. side affect is that the browser back button would not work - // consistently either. - - if (location.pathname === intraAppState.forRoute && !wasHandled.has(intraAppState)) { - wasHandled.add(intraAppState); - return intraAppState.routeState as S; - } - // Default is to return the state in the Fleet HashRouter, in order to enable use of route state - // that is used via Kibana's ScopedHistory from within the Fleet HashRouter (ex. things like - // `core.application.navigateTo()` - // Once this https://github.com/elastic/kibana/issues/70358 is implemented (move to BrowserHistory - // using kibana's ScopedHistory), then this work-around can be removed. - return location.state as S; - }, [intraAppState, location.pathname, location.state]); + return location.state as S; } diff --git a/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_navigate_to_app_event_handler.ts b/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_navigate_to_app_event_handler.ts index 148deda9aec76..05e1c2c4dca81 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_navigate_to_app_event_handler.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_navigate_to_app_event_handler.ts @@ -26,7 +26,7 @@ type EventHandlerCallback = MouseEventHandlerSee policies */ export const useNavigateToAppEventHandler = ( diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/hooks.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/hooks.ts index ca14dde18455b..e8fa53e2cf920 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/hooks.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/hooks.ts @@ -14,6 +14,7 @@ import { MANAGEMENT_STORE_GLOBAL_NAMESPACE, } from '../../../../common/constants'; import { useAppUrl } from '../../../../../common/lib/kibana'; +import { pagePathGetters } from '../../../../../../../fleet/public'; export function useEndpointSelector(selector: (state: EndpointState) => TSelected) { return useSelector(function (state: State) { @@ -47,7 +48,8 @@ export const useAgentDetailsIngestUrl = ( ): { url: string; appId: string; appPath: string } => { const { getAppUrl } = useAppUrl(); return useMemo(() => { - const appPath = `#/fleet/agents/${agentId}/activity`; + const appPath = pagePathGetters.agent_details_logs({ agentId })[1]; + return { url: `${getAppUrl({ appId: 'fleet' })}${appPath}`, appId: 'fleet', diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx index 584e6df1ff781..03df5d2bcbac7 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx @@ -120,13 +120,13 @@ export const useEndpointActionItems = ( 'data-test-subj': 'agentPolicyLink', navigateAppId: 'fleet', navigateOptions: { - path: `#${ + path: `${ pagePathGetters.policy_details({ policyId: fleetAgentPolicies[endpointPolicyId], })[1] }`, }, - href: `${getAppUrl({ appId: 'fleet' })}#${ + href: `${getAppUrl({ appId: 'fleet' })}${ pagePathGetters.policy_details({ policyId: fleetAgentPolicies[endpointPolicyId], })[1] @@ -145,13 +145,13 @@ export const useEndpointActionItems = ( 'data-test-subj': 'agentDetailsLink', navigateAppId: 'fleet', navigateOptions: { - path: `#${ + path: `${ pagePathGetters.agent_details({ agentId: fleetAgentId, })[1] }`, }, - href: `${getAppUrl({ appId: 'fleet' })}#${ + href: `${getAppUrl({ appId: 'fleet' })}${ pagePathGetters.agent_details({ agentId: fleetAgentId, })[1] @@ -169,17 +169,17 @@ export const useEndpointActionItems = ( 'data-test-subj': 'agentPolicyReassignLink', navigateAppId: 'fleet', navigateOptions: { - path: `#${ + path: `${ pagePathGetters.agent_details({ agentId: fleetAgentId, })[1] - }/activity?openReassignFlyout=true`, + }?openReassignFlyout=true`, }, - href: `${getAppUrl({ appId: 'fleet' })}#${ + href: `${getAppUrl({ appId: 'fleet' })}${ pagePathGetters.agent_details({ agentId: fleetAgentId, })[1] - }/activity?openReassignFlyout=true`, + }?openReassignFlyout=true`, children: ( { }); it('navigates to the Ingest Agent Policy page', async () => { const agentPolicyLink = await renderResult.findByTestId('agentPolicyLink'); - expect(agentPolicyLink.getAttribute('href')).toEqual(`/app/fleet#/policies/${agentPolicyId}`); + expect(agentPolicyLink.getAttribute('href')).toEqual(`/app/fleet/policies/${agentPolicyId}`); }); it('navigates to the Ingest Agent Details page', async () => { const agentDetailsLink = await renderResult.findByTestId('agentDetailsLink'); - expect(agentDetailsLink.getAttribute('href')).toEqual(`/app/fleet#/agents/${agentId}`); + expect(agentDetailsLink.getAttribute('href')).toEqual(`/app/fleet/agents/${agentId}`); }); it('navigates to the Ingest Agent Details page with policy reassign', async () => { const agentPolicyReassignLink = await renderResult.findByTestId('agentPolicyReassignLink'); expect(agentPolicyReassignLink.getAttribute('href')).toEqual( - `/app/fleet#/agents/${agentId}/activity?openReassignFlyout=true` + `/app/fleet/agents/${agentId}/details?openReassignFlyout=true` ); }); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx index c78d4ca6af634..74f5b15a72727 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx @@ -156,7 +156,7 @@ export const EndpointList = () => { const handleCreatePolicyClick = useNavigateToAppEventHandler( 'fleet', { - path: `#/integrations/${ + path: `/integrations/${ endpointPackageVersion ? `/endpoint-${endpointPackageVersion}` : '' }/add-integration`, state: { @@ -203,7 +203,7 @@ export const EndpointList = () => { const handleDeployEndpointsClick = useNavigateToAppEventHandler( 'fleet', { - path: `#/policies/${selectedPolicyId}?openEnrollmentFlyout=true`, + path: `/policies/${selectedPolicyId}?openEnrollmentFlyout=true`, state: { onDoneNavigateTo: [ 'securitySolution', diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.test.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.test.tsx index 7af9f84ad0875..2d21ec9565476 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.test.tsx @@ -63,7 +63,7 @@ describe('OverviewEmpty', () => { fill: false, label: 'Add Endpoint Security', onClick: undefined, - url: `#/integrations/endpoint-${endpointPackageVersion}/add-integration`, + url: `/integrations/endpoint-${endpointPackageVersion}/add-integration`, }, }); }); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.tsx index c75438e18f5d5..6f885b348cdeb 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.tsx @@ -36,7 +36,7 @@ const OverviewEmptyComponent: React.FC = () => { const endpointIntegrationUrlPath = endpointPackageVersion ? `/endpoint-${endpointPackageVersion}/add-integration` : ''; - const endpointIntegrationUrl = `#/integrations${endpointIntegrationUrlPath}`; + const endpointIntegrationUrl = `/integrations${endpointIntegrationUrlPath}`; const handleEndpointClick = useNavigateToAppEventHandler('fleet', { path: endpointIntegrationUrl, }); From f299b12c0527552cbfaeb892c633d9a3696e93ec Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Thu, 22 Jul 2021 16:12:34 -0400 Subject: [PATCH 10/11] Fix type --- x-pack/plugins/fleet/public/hooks/use_intra_app_state.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/x-pack/plugins/fleet/public/hooks/use_intra_app_state.tsx b/x-pack/plugins/fleet/public/hooks/use_intra_app_state.tsx index ed757ee7948a2..265d12221018a 100644 --- a/x-pack/plugins/fleet/public/hooks/use_intra_app_state.tsx +++ b/x-pack/plugins/fleet/public/hooks/use_intra_app_state.tsx @@ -5,8 +5,6 @@ * 2.0. */ -import React, { memo, useContext, useMemo } from 'react'; -import type { AppMountParameters } from 'kibana/public'; import { useLocation } from 'react-router-dom'; import type { AnyIntraAppRouteState } from '../types'; @@ -16,9 +14,7 @@ import type { AnyIntraAppRouteState } from '../types'; * This state can be used by other Kibana Apps to influence certain behaviours in Ingest, for example, * redirecting back to an given Application after a craete action. */ -export function useIntraAppState(): - | IntraAppState['routeState'] - | undefined { +export function useIntraAppState(): S | undefined { const location = useLocation(); return location.state as S; From 1b1cf745269894f7f6137f6b465c1a63083f1b16 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Fri, 23 Jul 2021 08:23:13 -0400 Subject: [PATCH 11/11] fix test --- .../public/management/pages/endpoint_hosts/view/index.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx index 4701d2ef30499..d1d5417570fe0 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx @@ -1258,7 +1258,7 @@ describe('when on the endpoint list page', () => { it('navigates to the Ingest Agent Details page with policy reassign', async () => { const agentPolicyReassignLink = await renderResult.findByTestId('agentPolicyReassignLink'); expect(agentPolicyReassignLink.getAttribute('href')).toEqual( - `/app/fleet/agents/${agentId}/details?openReassignFlyout=true` + `/app/fleet/agents/${agentId}?openReassignFlyout=true` ); }); });