From 374070759967e3835e15b6372dd4ab07c290ccf4 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 13 May 2020 13:25:29 +0300 Subject: [PATCH 01/93] [New Platform Migration]: Management - Implement NP API Part of #47432 --- src/legacy/core_plugins/kibana/index.js | 17 +- .../core_plugins/kibana/public/.eslintrc.js | 83 ----- .../core_plugins/kibana/public/_hacks.scss | 0 .../core_plugins/kibana/public/kibana.js | 2 +- .../public/management/_management_app.scss | 69 ----- .../kibana/public/management/app.html | 4 - .../kibana/public/management/index.js | 167 ---------- .../kibana/public/management/index.scss | 4 +- .../kibana/public/management/landing.html | 3 - .../index_pattern_table.tsx | 8 +- .../management_app.test.tsx.snap | 11 - src/plugins/management/public/application.tsx | 42 +++ .../management/public/components/_index.scss | 1 - .../management/public/components/index.ts | 4 +- .../{management_chrome => langing}/index.ts | 2 +- .../public/components/langing/landing.tsx | 71 +++++ .../management_app/_management_app.scss | 19 ++ .../management_app/index.ts} | 3 +- .../management_app/management_app.tsx | 110 +++++++ .../management_app_wrapper/index.tsx} | 6 +- .../management_app_wrapper.tsx | 69 +++++ .../management_chrome/management_chrome.tsx | 59 ---- .../{ => components}/management_sections.tsx | 6 +- .../management_sidebar_nav.test.ts.snap | 95 ------ .../management_sidebar_nav.test.ts | 98 ------ .../management_sidebar_nav.tsx | 242 +++++---------- src/plugins/management/public/index.ts | 13 +- .../public/legacy/redirect_messages.tsx | 67 ---- .../management/public/legacy/section.js | 160 ---------- .../management/public/legacy/section.test.js | 285 ------------------ .../public/legacy/sections_register.js | 47 --- .../management/public/management_app.test.tsx | 66 ---- .../management/public/management_app.tsx | 107 ------- .../public/management_section.test.ts | 66 ---- .../management/public/management_section.ts | 80 ----- .../management_sections_service.test.ts | 67 ++++ .../public/management_sections_service.ts | 68 +++++ .../public/management_service.test.ts | 40 --- .../management/public/management_service.ts | 109 ------- src/plugins/management/public/mocks/index.ts | 18 +- src/plugins/management/public/plugin.ts | 62 ++-- src/plugins/management/public/types.ts | 96 ++---- .../management/public/utils/index.ts} | 17 +- .../management/public/utils/management_app.ts | 38 +++ .../public/utils/management_item.ts | 46 +++ .../public/utils/management_section.test.ts | 55 ++++ .../public/utils/management_section.ts | 58 ++++ .../management/management_service.test.ts | 46 +-- x-pack/plugins/spaces/public/plugin.test.ts | 16 +- 49 files changed, 842 insertions(+), 1980 deletions(-) delete mode 100644 src/legacy/core_plugins/kibana/public/.eslintrc.js delete mode 100644 src/legacy/core_plugins/kibana/public/_hacks.scss delete mode 100644 src/legacy/core_plugins/kibana/public/management/_management_app.scss delete mode 100644 src/legacy/core_plugins/kibana/public/management/app.html delete mode 100644 src/legacy/core_plugins/kibana/public/management/index.js delete mode 100644 src/legacy/core_plugins/kibana/public/management/landing.html delete mode 100644 src/plugins/management/public/__snapshots__/management_app.test.tsx.snap create mode 100644 src/plugins/management/public/application.tsx delete mode 100644 src/plugins/management/public/components/_index.scss rename src/plugins/management/public/components/{management_chrome => langing}/index.ts (93%) create mode 100644 src/plugins/management/public/components/langing/landing.tsx create mode 100644 src/plugins/management/public/components/management_app/_management_app.scss rename src/plugins/management/public/{legacy/index.js => components/management_app/index.ts} (87%) create mode 100644 src/plugins/management/public/components/management_app/management_app.tsx rename src/{legacy/core_plugins/kibana/public/management/saved_object_registry.ts => plugins/management/public/components/management_app_wrapper/index.tsx} (82%) create mode 100644 src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx delete mode 100644 src/plugins/management/public/components/management_chrome/management_chrome.tsx rename src/plugins/management/public/{ => components}/management_sections.tsx (93%) delete mode 100644 src/plugins/management/public/components/management_sidebar_nav/__snapshots__/management_sidebar_nav.test.ts.snap delete mode 100644 src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.test.ts delete mode 100644 src/plugins/management/public/legacy/redirect_messages.tsx delete mode 100644 src/plugins/management/public/legacy/section.js delete mode 100644 src/plugins/management/public/legacy/section.test.js delete mode 100644 src/plugins/management/public/legacy/sections_register.js delete mode 100644 src/plugins/management/public/management_app.test.tsx delete mode 100644 src/plugins/management/public/management_app.tsx delete mode 100644 src/plugins/management/public/management_section.test.ts delete mode 100644 src/plugins/management/public/management_section.ts create mode 100644 src/plugins/management/public/management_sections_service.test.ts create mode 100644 src/plugins/management/public/management_sections_service.ts delete mode 100644 src/plugins/management/public/management_service.test.ts delete mode 100644 src/plugins/management/public/management_service.ts rename src/{legacy/core_plugins/kibana/public/management/sections/index_patterns/types.ts => plugins/management/public/utils/index.ts} (75%) create mode 100644 src/plugins/management/public/utils/management_app.ts create mode 100644 src/plugins/management/public/utils/management_item.ts create mode 100644 src/plugins/management/public/utils/management_section.test.ts create mode 100644 src/plugins/management/public/utils/management_section.ts diff --git a/src/legacy/core_plugins/kibana/index.js b/src/legacy/core_plugins/kibana/index.js index 5807c439bd277..4d36f3260ca10 100644 --- a/src/legacy/core_plugins/kibana/index.js +++ b/src/legacy/core_plugins/kibana/index.js @@ -26,8 +26,7 @@ import { exportApi } from './server/routes/api/export'; import { getUiSettingDefaults } from './server/ui_setting_defaults'; import { registerCspCollector } from './server/lib/csp_usage_collector'; import { injectVars } from './inject_vars'; -import { i18n } from '@kbn/i18n'; -import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/server'; + import { kbnBaseUrl } from '../../../plugins/kibana_legacy/server'; const mkdirAsync = promisify(Fs.mkdir); @@ -59,19 +58,7 @@ export default function(kibana) { main: 'plugins/kibana/kibana', }, styleSheetPaths: resolve(__dirname, 'public/index.scss'), - links: [ - { - id: 'kibana:stack_management', - title: i18n.translate('kbn.managementTitle', { - defaultMessage: 'Stack Management', - }), - order: 9003, - url: `${kbnBaseUrl}#/management`, - euiIconType: 'managementApp', - linkToLastSubUrl: false, - category: DEFAULT_APP_CATEGORIES.management, - }, - ], + links: [], injectDefaultVars(server, options) { const mapConfig = server.config().get('map'); diff --git a/src/legacy/core_plugins/kibana/public/.eslintrc.js b/src/legacy/core_plugins/kibana/public/.eslintrc.js deleted file mode 100644 index 1153706eb8566..0000000000000 --- a/src/legacy/core_plugins/kibana/public/.eslintrc.js +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const topLevelConfig = require('../../../../../.eslintrc.js'); -const path = require('path'); - -const topLevelRestricedZones = topLevelConfig.overrides.find( - override => - override.files[0] === '**/*.{js,ts,tsx}' && - Object.keys(override.rules)[0] === '@kbn/eslint/no-restricted-paths' -).rules['@kbn/eslint/no-restricted-paths'][1].zones; - -/** - * Builds custom restricted paths configuration for the shimmed plugins within the kibana plugin. - * These custom rules extend the default checks in the top level `eslintrc.js` by also checking two other things: - * * Making sure nothing within np_ready imports from the `ui` directory - * * Making sure no other code is importing things deep from within the shimmed plugins - * @param shimmedPlugins List of plugin names within the kibana plugin that are partially np ready - * @returns zones configuration for the no-restricted-paths linter - */ -function buildRestrictedPaths(shimmedPlugins) { - return shimmedPlugins - .map(shimmedPlugin => [ - { - target: [`src/legacy/core_plugins/kibana/public/${shimmedPlugin}/np_ready/**/*`], - from: [ - 'ui/**/*', - 'src/legacy/ui/**/*', - 'src/legacy/core_plugins/kibana/public/**/*', - `!src/legacy/core_plugins/kibana/public/${shimmedPlugin}/**/*`, - ], - allowSameFolder: false, - errorMessage: `${shimmedPlugin} is a shimmed plugin that is not allowed to import modules from the legacy platform. If you need legacy modules for the transition period, import them either in the legacy_imports, kibana_services or index module.`, - }, - { - target: [ - 'src/**/*', - `!src/legacy/core_plugins/kibana/public/${shimmedPlugin}/**/*`, - 'x-pack/**/*', - ], - from: [ - `src/legacy/core_plugins/kibana/public/${shimmedPlugin}/**/*`, - `!src/legacy/core_plugins/kibana/public/${shimmedPlugin}/index.ts`, - `!src/legacy/core_plugins/kibana/public/${shimmedPlugin}/legacy.ts`, - ], - allowSameFolder: false, - errorMessage: `kibana/public/${shimmedPlugin} is behaving like a NP plugin and does not allow deep imports. If you need something from within ${shimmedPlugin} in another plugin, consider re-exporting it from the top level index module`, - }, - ]) - .reduce((acc, part) => [...acc, ...part], []); -} - -module.exports = { - rules: { - 'no-console': 2, - 'import/no-default-export': 'error', - '@kbn/eslint/no-restricted-paths': [ - 'error', - { - basePath: path.resolve(__dirname, '../../../../../'), - zones: topLevelRestricedZones.concat( - buildRestrictedPaths(['visualize', 'discover', 'dashboard', 'devTools']) - ), - }, - ], - }, -}; diff --git a/src/legacy/core_plugins/kibana/public/_hacks.scss b/src/legacy/core_plugins/kibana/public/_hacks.scss deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/src/legacy/core_plugins/kibana/public/kibana.js b/src/legacy/core_plugins/kibana/public/kibana.js index 0bf74edc77cb6..610ae4d452384 100644 --- a/src/legacy/core_plugins/kibana/public/kibana.js +++ b/src/legacy/core_plugins/kibana/public/kibana.js @@ -38,7 +38,7 @@ import 'uiExports/shareContextMenuExtensions'; import 'uiExports/interpreter'; import 'ui/autoload/all'; -import './management'; + import { localApplicationService } from './local_application_service'; npSetup.plugins.kibanaLegacy.registerLegacyAppAlias('doc', 'discover', { keepPrefix: true }); diff --git a/src/legacy/core_plugins/kibana/public/management/_management_app.scss b/src/legacy/core_plugins/kibana/public/management/_management_app.scss deleted file mode 100644 index bd3cabbc574d3..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/_management_app.scss +++ /dev/null @@ -1,69 +0,0 @@ -.mgtPanel { - margin-bottom: $euiSize; - background: $euiColorEmptyShade; -} - -/** - * 1. Override kuiPanelBody styles to accommodate padding of items within the panel body.. - */ -.mgtPanel__body { - padding: 5px 10px; /* 1 */ -} - -/** - * 1. Create vertical space between items when they wrap. - */ -.mgtPanel__item { - padding: 5px 15px; /* 1 */ -} - -// SASSTODO: Remove when this is replaced by the side nav -.mgtPanel__link { - @include euiFontSizeL; - - line-height: 1.5; // Make sure the space between wrapped lines is than the vertical space between items. - - &.mgtPanel__link--disabled { - opacity: $euiColorDarkShade; - cursor: default; - - &:hover, &:visited { - color: $euiColorPrimary; - } - } -} - -// SASSTODO: Remove when this form is replaced by EUI -kbn-management-objects { - form { - margin-bottom: $euiSize; - } - .list-unstyled { - li { - border-bottom: $euiBorderThin; - padding: $euiSizeS; - } - } - .empty { - color: $euiColorDarkShade; - } - - .item { - padding: $euiSizeM; - - .item-title { - margin-left: $euiSizeL; - } - - .actions { - margin-top: $euiSizeXS; - } - } - - .header { - .title, .controls { - padding-right: 1em; - display: inline-block; - } - } -} diff --git a/src/legacy/core_plugins/kibana/public/management/app.html b/src/legacy/core_plugins/kibana/public/management/app.html deleted file mode 100644 index 11198c02960c7..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/app.html +++ /dev/null @@ -1,4 +0,0 @@ -
-
-
-
diff --git a/src/legacy/core_plugins/kibana/public/management/index.js b/src/legacy/core_plugins/kibana/public/management/index.js deleted file mode 100644 index 2cba9fab7be22..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/index.js +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import './sections'; -import uiRoutes from 'ui/routes'; -import { I18nContext } from 'ui/i18n'; -import { uiModules } from 'ui/modules'; -import appTemplate from './app.html'; -import landingTemplate from './landing.html'; -import { management, MANAGEMENT_BREADCRUMB } from 'ui/management'; -import { ManagementSidebarNav } from '../../../../../plugins/management/public'; -import { timefilter } from 'ui/timefilter'; -import { - EuiPageContent, - EuiTitle, - EuiText, - EuiSpacer, - EuiIcon, - EuiHorizontalRule, -} from '@elastic/eui'; -import { npStart } from 'ui/new_platform'; - -const SIDENAV_ID = 'management-sidenav'; -const LANDING_ID = 'management-landing'; - -uiRoutes.when('/management', { - template: landingTemplate, - k7Breadcrumbs: () => [MANAGEMENT_BREADCRUMB], -}); - -uiRoutes.when('/management/:section', { - redirectTo: '/management', -}); - -export function updateLandingPage(version) { - const node = document.getElementById(LANDING_ID); - if (!node) { - return; - } - - render( - - -
-
- - - -

- -

-
- - - -
- - - - -

- -

-
-
-
-
, - node - ); -} - -export function updateSidebar(legacySections, id) { - const node = document.getElementById(SIDENAV_ID); - if (!node) { - return; - } - - render( - - - , - node - ); -} - -export const destroyReact = id => { - const node = document.getElementById(id); - node && unmountComponentAtNode(node); -}; - -uiModules.get('apps/management').directive('kbnManagementApp', function($location) { - return { - restrict: 'E', - template: appTemplate, - transclude: true, - scope: { - sectionName: '@section', - omitPages: '@omitBreadcrumbPages', - pageTitle: '=', - }, - - link: function($scope) { - timefilter.disableAutoRefreshSelector(); - timefilter.disableTimeRangeSelector(); - $scope.sections = management.visibleItems; - $scope.section = management.getSection($scope.sectionName) || management; - - if ($scope.section) { - $scope.section.items.forEach(item => { - item.active = `#${$location.path()}`.indexOf(item.url) > -1; - }); - } - - updateSidebar($scope.sections, $scope.section.id); - $scope.$on('$destroy', () => destroyReact(SIDENAV_ID)); - management.addListener(() => updateSidebar(management.visibleItems, $scope.section.id)); - - updateLandingPage($scope.$root.chrome.getKibanaVersion()); - $scope.$on('$destroy', () => destroyReact(LANDING_ID)); - }, - }; -}); - -uiModules.get('apps/management').directive('kbnManagementLanding', function(kbnVersion) { - return { - restrict: 'E', - link: function($scope) { - $scope.sections = management.visibleItems; - $scope.kbnVersion = kbnVersion; - }, - }; -}); diff --git a/src/legacy/core_plugins/kibana/public/management/index.scss b/src/legacy/core_plugins/kibana/public/management/index.scss index 123580c0b7907..fb267b714f1c9 100644 --- a/src/legacy/core_plugins/kibana/public/management/index.scss +++ b/src/legacy/core_plugins/kibana/public/management/index.scss @@ -7,9 +7,7 @@ // mgtChart__legend--small // mgtChart__legend-isLoading -@import 'hacks'; - // Core -@import 'management_app'; @import '../../../../../plugins/advanced_settings/public/index'; + @import 'sections/index_patterns/index'; diff --git a/src/legacy/core_plugins/kibana/public/management/landing.html b/src/legacy/core_plugins/kibana/public/management/landing.html deleted file mode 100644 index 39459b26f7415..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/landing.html +++ /dev/null @@ -1,3 +0,0 @@ - -
-
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index_pattern_table/index_pattern_table.tsx b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index_pattern_table/index_pattern_table.tsx index f254a6bc22a0d..d8efcfecebcc1 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index_pattern_table/index_pattern_table.tsx +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index_pattern_table/index_pattern_table.tsx @@ -33,9 +33,8 @@ import { FormattedMessage } from '@kbn/i18n/react'; import React from 'react'; import { CreateButton } from '../create_button'; import { CreateIndexPatternPrompt } from '../create_index_pattern_prompt'; -import { IndexPattern, IndexPatternCreationOption } from '../types'; -const columns = [ +const columns: any[] = [ { field: 'title', name: 'Pattern', @@ -86,8 +85,9 @@ const search = { }; interface Props { - indexPatterns: IndexPattern[]; - indexPatternCreationOptions: IndexPatternCreationOption[]; + // Todo: temporary. should be reverted before merge + indexPatterns: any[]; + indexPatternCreationOptions: any[]; } interface State { diff --git a/src/plugins/management/public/__snapshots__/management_app.test.tsx.snap b/src/plugins/management/public/__snapshots__/management_app.test.tsx.snap deleted file mode 100644 index 7f13472ee02ee..0000000000000 --- a/src/plugins/management/public/__snapshots__/management_app.test.tsx.snap +++ /dev/null @@ -1,11 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Management app can mount and unmount 1`] = ` -
-
- Test App - Hello world! -
-
-`; - -exports[`Management app can mount and unmount 2`] = `
`; diff --git a/src/plugins/management/public/application.tsx b/src/plugins/management/public/application.tsx new file mode 100644 index 0000000000000..5d014504b8938 --- /dev/null +++ b/src/plugins/management/public/application.tsx @@ -0,0 +1,42 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; + +import { AppMountContext, AppMountParameters } from 'kibana/public'; +import { ManagementApp, ManagementAppDependencies } from './components/management_app'; + +export const renderApp = async ( + context: AppMountContext, + { history, appBasePath, element }: AppMountParameters, + dependencies: ManagementAppDependencies +) => { + ReactDOM.render( + , + element + ); + + return () => ReactDOM.unmountComponentAtNode(element); +}; diff --git a/src/plugins/management/public/components/_index.scss b/src/plugins/management/public/components/_index.scss deleted file mode 100644 index df0ebb48803d9..0000000000000 --- a/src/plugins/management/public/components/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './management_sidebar_nav/index'; diff --git a/src/plugins/management/public/components/index.ts b/src/plugins/management/public/components/index.ts index 2650d23d3c25c..8979809c5245e 100644 --- a/src/plugins/management/public/components/index.ts +++ b/src/plugins/management/public/components/index.ts @@ -17,5 +17,5 @@ * under the License. */ -export { ManagementSidebarNav } from './management_sidebar_nav'; -export { ManagementChrome } from './management_chrome'; +export { ManagementApp } from './management_app'; +export { managementSections } from './management_sections'; diff --git a/src/plugins/management/public/components/management_chrome/index.ts b/src/plugins/management/public/components/langing/index.ts similarity index 93% rename from src/plugins/management/public/components/management_chrome/index.ts rename to src/plugins/management/public/components/langing/index.ts index b82c1af871be7..79a1c2b1145c2 100644 --- a/src/plugins/management/public/components/management_chrome/index.ts +++ b/src/plugins/management/public/components/langing/index.ts @@ -17,4 +17,4 @@ * under the License. */ -export { ManagementChrome } from './management_chrome'; +export { ManagementLandingPage } from './landing'; diff --git a/src/plugins/management/public/components/langing/landing.tsx b/src/plugins/management/public/components/langing/landing.tsx new file mode 100644 index 0000000000000..a82044784bc95 --- /dev/null +++ b/src/plugins/management/public/components/langing/landing.tsx @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { + EuiHorizontalRule, + EuiIcon, + EuiPageContent, + EuiSpacer, + EuiText, + EuiTitle, +} from '@elastic/eui'; + +interface ManagementLandingPageProps { + version: string; +} + +export const ManagementLandingPage = ({ version }: ManagementLandingPageProps) => ( + +
+
+ + + +

+ +

+
+ + + +
+ + + + +

+ +

+
+
+
+); diff --git a/src/plugins/management/public/components/management_app/_management_app.scss b/src/plugins/management/public/components/management_app/_management_app.scss new file mode 100644 index 0000000000000..6eaf82ba8283d --- /dev/null +++ b/src/plugins/management/public/components/management_app/_management_app.scss @@ -0,0 +1,19 @@ +.mgtPanel { + margin-bottom: $euiSize; + background: $euiColorEmptyShade; +} + +/** + * 1. Override kuiPanelBody styles to accommodate padding of items within the panel body.. + */ +.mgtPanel__body { + padding: 5px 10px; /* 1 */ +} + +/** + * 1. Create vertical space between items when they wrap. + */ +.mgtPanel__item { + padding: 5px 15px; /* 1 */ +} + diff --git a/src/plugins/management/public/legacy/index.js b/src/plugins/management/public/components/management_app/index.ts similarity index 87% rename from src/plugins/management/public/legacy/index.js rename to src/plugins/management/public/components/management_app/index.ts index f2e0ba89b7b59..83f8ae0159978 100644 --- a/src/plugins/management/public/legacy/index.js +++ b/src/plugins/management/public/components/management_app/index.ts @@ -17,5 +17,4 @@ * under the License. */ -export { LegacyManagementAdapter } from './sections_register'; -export { LegacyManagementSection } from './section'; +export { ManagementApp, ManagementAppDependencies } from './management_app'; diff --git a/src/plugins/management/public/components/management_app/management_app.tsx b/src/plugins/management/public/components/management_app/management_app.tsx new file mode 100644 index 0000000000000..7dffc4f5942fb --- /dev/null +++ b/src/plugins/management/public/components/management_app/management_app.tsx @@ -0,0 +1,110 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React, { useState, useEffect, useCallback } from 'react'; +import { Route, Router, Switch } from 'react-router-dom'; +import { AppMountContext, AppMountParameters, ChromeBreadcrumb } from 'kibana/public'; +import { I18nProvider } from '@kbn/i18n/src/react'; +import { EuiPage, EuiPageBody } from '@elastic/eui'; +import { ManagementStart } from '../../types'; +import { ManagementSection } from '../../utils'; + +import { ManagementLandingPage } from '../langing'; +import { ManagementSidebarNav } from '../management_sidebar_nav'; +import { ManagementAppWrapper } from '../management_app_wrapper'; + +import './_management_app.scss'; + +interface ManagementAppProps { + appBasePath: string; + context: AppMountContext; + history: AppMountParameters['history']; + dependencies: ManagementAppDependencies; +} + +export interface ManagementAppDependencies { + management: ManagementStart; + kibanaVersion: string; +} + +export const ManagementApp = ({ context, dependencies, history }: ManagementAppProps) => { + const [selectedId, setSelectedId] = useState(''); + const [sections, setSections] = useState(); + + const onManagementSectionSelected = useCallback( + (id: string, path: string) => { + history.push(path); + }, + [history] + ); + + const onAppMounted = useCallback((id: string) => { + setSelectedId(id); + }, []); + + const setBreadcrumbs = useCallback( + (crumbs: ChromeBreadcrumb[]) => { + context.core.chrome.setBreadcrumbs(crumbs); + }, + [context.core.chrome] + ); + + useEffect(() => { + setSections(dependencies.management.sections.getSectionsEnabled()); + }, [dependencies.management.sections]); + + if (!sections) { + return null; + } + + return ( + + + + + + + {sections.map(section => + section.apps.map(app => ( + ( + + )} + /> + )) + )} + } + /> + + + + + + ); +}; diff --git a/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts b/src/plugins/management/public/components/management_app_wrapper/index.tsx similarity index 82% rename from src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts rename to src/plugins/management/public/components/management_app_wrapper/index.tsx index 587a372f91555..71546e7ca1342 100644 --- a/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts +++ b/src/plugins/management/public/components/management_app_wrapper/index.tsx @@ -17,8 +17,4 @@ * under the License. */ -import { npSetup } from 'ui/new_platform'; - -const registry = npSetup.plugins.savedObjectsManagement?.serviceRegistry; - -export const savedObjectManagementRegistry = registry!; +export { ManagementAppWrapper } from './management_app_wrapper'; diff --git a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx new file mode 100644 index 0000000000000..dac219823b7ca --- /dev/null +++ b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx @@ -0,0 +1,69 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useEffect, createRef, useRef, RefObject } from 'react'; + +import { ChromeBreadcrumb } from 'kibana/public'; +import { ManagementApp } from '../../utils'; +import { Unmount } from '../../types'; + +interface ManagementSectionWrapperProps { + app: ManagementApp; + setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; + onAppMounted: (id: string) => void; +} + +export const ManagementAppWrapper = ({ + app, + setBreadcrumbs, + onAppMounted, +}: ManagementSectionWrapperProps) => { + const mountElementRef = useRef>(); + const { mount, basePath } = app; + const unmount = useRef(); + + mountElementRef.current = createRef(); + + useEffect(() => { + if (mount && basePath) { + const mountResult = mount({ + basePath, + setBreadcrumbs, + element: mountElementRef.current!.current, + }); + + onAppMounted(app.id); + + if (mountResult instanceof Promise) { + mountResult.then(um => { + unmount.current = um; + }); + } else { + unmount.current = mountResult; + } + return () => { + if (unmount.current) { + unmount.current(); + } + }; + } + }, [app.id, basePath, mount, onAppMounted, setBreadcrumbs]); + + return
; +}; diff --git a/src/plugins/management/public/components/management_chrome/management_chrome.tsx b/src/plugins/management/public/components/management_chrome/management_chrome.tsx deleted file mode 100644 index df844e2208936..0000000000000 --- a/src/plugins/management/public/components/management_chrome/management_chrome.tsx +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import * as React from 'react'; -import { EuiPage, EuiPageBody, EuiPageSideBar } from '@elastic/eui'; -import { I18nProvider } from '@kbn/i18n/react'; -import { ManagementSidebarNav } from '../management_sidebar_nav'; -import { LegacySection } from '../../types'; -import { ManagementSection } from '../../management_section'; - -interface Props { - getSections: () => ManagementSection[]; - legacySections: LegacySection[]; - selectedId: string; - onMounted: (element: HTMLDivElement) => void; -} - -export class ManagementChrome extends React.Component { - private container = React.createRef(); - componentDidMount() { - if (this.container.current) { - this.props.onMounted(this.container.current); - } - } - render() { - return ( - - - - - - -
- - - - ); - } -} diff --git a/src/plugins/management/public/management_sections.tsx b/src/plugins/management/public/components/management_sections.tsx similarity index 93% rename from src/plugins/management/public/management_sections.tsx rename to src/plugins/management/public/components/management_sections.tsx index 77e494626a00e..33c3526c4d23b 100644 --- a/src/plugins/management/public/management_sections.tsx +++ b/src/plugins/management/public/components/management_sections.tsx @@ -20,14 +20,14 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiToolTip, EuiIcon } from '@elastic/eui'; -import { ManagementSectionId } from './types'; +import { ManagementSectionId } from '../types'; -interface Props { +interface ManagementSectionTitleProps { text: string; tip: string; } -const ManagementSectionTitle = ({ text, tip }: Props) => ( +const ManagementSectionTitle = ({ text, tip }: ManagementSectionTitleProps) => ( {text} diff --git a/src/plugins/management/public/components/management_sidebar_nav/__snapshots__/management_sidebar_nav.test.ts.snap b/src/plugins/management/public/components/management_sidebar_nav/__snapshots__/management_sidebar_nav.test.ts.snap deleted file mode 100644 index e7225b356ed68..0000000000000 --- a/src/plugins/management/public/components/management_sidebar_nav/__snapshots__/management_sidebar_nav.test.ts.snap +++ /dev/null @@ -1,95 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Management adds legacy apps to existing SidebarNav sections 1`] = ` -Array [ - Object { - "data-test-subj": "activeSection", - "icon": null, - "id": "activeSection", - "items": Array [ - Object { - "data-test-subj": "item", - "href": undefined, - "id": "item", - "isSelected": false, - "name": "item", - "order": undefined, - }, - ], - "name": "activeSection", - "order": 10, - }, - Object { - "data-test-subj": "no-active-items", - "icon": null, - "id": "no-active-items", - "items": Array [ - Object { - "data-test-subj": "disabled", - "href": undefined, - "id": "disabled", - "isSelected": false, - "name": "disabled", - "order": undefined, - }, - Object { - "data-test-subj": "notVisible", - "href": undefined, - "id": "notVisible", - "isSelected": false, - "name": "notVisible", - "order": undefined, - }, - ], - "name": "No active items", - "order": 10, - }, -] -`; - -exports[`Management maps legacy sections and apps into SidebarNav items 1`] = ` -Array [ - Object { - "data-test-subj": "no-active-items", - "icon": null, - "id": "no-active-items", - "items": Array [ - Object { - "data-test-subj": "disabled", - "href": undefined, - "id": "disabled", - "isSelected": false, - "name": "disabled", - "order": undefined, - }, - Object { - "data-test-subj": "notVisible", - "href": undefined, - "id": "notVisible", - "isSelected": false, - "name": "notVisible", - "order": undefined, - }, - ], - "name": "No active items", - "order": 10, - }, - Object { - "data-test-subj": "activeSection", - "icon": null, - "id": "activeSection", - "items": Array [ - Object { - "data-test-subj": "item", - "href": undefined, - "id": "item", - "isSelected": false, - "name": "item", - "order": undefined, - }, - ], - "name": "activeSection", - "order": 10, - }, -] -`; diff --git a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.test.ts b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.test.ts deleted file mode 100644 index e04e0a7572612..0000000000000 --- a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.test.ts +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { IndexedArray } from '../../../../../legacy/ui/public/indexed_array'; -import { mergeLegacyItems } from './management_sidebar_nav'; - -const toIndexedArray = (initialSet: any[]) => - new IndexedArray({ - index: ['id'], - order: ['order'], - initialSet, - }); - -const activeProps = { visible: true, disabled: false }; -const disabledProps = { visible: true, disabled: true }; -const notVisibleProps = { visible: false, disabled: false }; -const visibleItem = { display: 'item', id: 'item', ...activeProps }; - -const notVisibleSection = { - display: 'Not visible', - id: 'not-visible', - order: 10, - visibleItems: toIndexedArray([visibleItem]), - ...notVisibleProps, -}; -const disabledSection = { - display: 'Disabled', - id: 'disabled', - order: 10, - visibleItems: toIndexedArray([visibleItem]), - ...disabledProps, -}; -const noItemsSection = { - display: 'No items', - id: 'no-items', - order: 10, - visibleItems: toIndexedArray([]), - ...activeProps, -}; -const noActiveItemsSection = { - display: 'No active items', - id: 'no-active-items', - order: 10, - visibleItems: toIndexedArray([ - { display: 'disabled', id: 'disabled', ...disabledProps }, - { display: 'notVisible', id: 'notVisible', ...notVisibleProps }, - ]), - ...activeProps, -}; -const activeSection = { - display: 'activeSection', - id: 'activeSection', - order: 10, - visibleItems: toIndexedArray([visibleItem]), - ...activeProps, -}; - -const managementSections = [ - notVisibleSection, - disabledSection, - noItemsSection, - noActiveItemsSection, - activeSection, -]; - -describe('Management', () => { - it('maps legacy sections and apps into SidebarNav items', () => { - expect(mergeLegacyItems([], managementSections, 'active-item-id')).toMatchSnapshot(); - }); - - it('adds legacy apps to existing SidebarNav sections', () => { - const navSection = { - 'data-test-subj': 'activeSection', - icon: null, - id: 'activeSection', - items: [], - name: 'activeSection', - order: 10, - }; - expect(mergeLegacyItems([navSection], managementSections, 'active-item-id')).toMatchSnapshot(); - }); -}); diff --git a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx index c58de6d8b0a81..0fa338710ae5a 100644 --- a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx +++ b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx @@ -17,184 +17,94 @@ * under the License. */ -import { - EuiIcon, - // @ts-ignore - EuiSideNav, - EuiScreenReaderOnly, -} from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiIcon, EuiSideNav, EuiSideNavItemType, EuiScreenReaderOnly } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import React, { ReactElement } from 'react'; -import { LegacySection, LegacyApp } from '../../types'; -import { ManagementApp } from '../../management_app'; -import { ManagementSection } from '../../management_section'; +import React, { useState } from 'react'; +import { ManagementApp, ManagementSection } from '../../utils'; -interface NavApp { - id: string; - name: ReactElement | string; - [key: string]: unknown; - order: number; // only needed while merging platform and legacy -} - -interface NavSection extends NavApp { - items: NavApp[]; -} +import './_index.scss'; +import { ManagementItem } from '../../utils/management_item'; interface ManagementSidebarNavProps { - getSections: () => ManagementSection[]; - legacySections: LegacySection[]; + sections: ManagementSection[]; + onManagementSectionSelected: (id: string, path: string) => void; selectedId: string; } -interface ManagementSidebarNavState { - isSideNavOpenOnMobile: boolean; -} - -const managementSectionOrAppToNav = (appOrSection: ManagementApp | ManagementSection) => ({ - id: appOrSection.id, - name: appOrSection.title, - 'data-test-subj': appOrSection.id, - order: appOrSection.order, -}); - -const managementSectionToNavSection = (section: ManagementSection) => { - const iconType = section.euiIconType - ? section.euiIconType - : section.icon - ? section.icon - : 'empty'; - - return { - icon: , - ...managementSectionOrAppToNav(section), - }; -}; - -const managementAppToNavItem = (selectedId?: string, parentId?: string) => ( - app: ManagementApp -) => ({ - isSelected: selectedId === app.id, - href: `#/management/${parentId}/${app.id}`, - ...managementSectionOrAppToNav(app), -}); - -const legacySectionToNavSection = (section: LegacySection) => ({ - name: section.display, - id: section.id, - icon: section.icon ? : null, - items: [], - 'data-test-subj': section.id, - // @ts-ignore - order: section.order, +const headerLabel = i18n.translate('management.nav.label', { + defaultMessage: 'Management', }); -const legacyAppToNavItem = (app: LegacyApp, selectedId: string) => ({ - isSelected: selectedId === app.id, - name: app.display, - id: app.id, - href: app.url, - 'data-test-subj': app.id, - // @ts-ignore - order: app.order, +const navMenuLabel = i18n.translate('management.nav.menu', { + defaultMessage: 'Management menu', }); -const sectionVisible = (section: LegacySection | LegacyApp) => !section.disabled && section.visible; - -const sideNavItems = (sections: ManagementSection[], selectedId: string) => - sections.map(section => ({ - items: section.getAppsEnabled().map(managementAppToNavItem(selectedId, section.id)), - ...managementSectionToNavSection(section), - })); - -const findOrAddSection = (navItems: NavSection[], legacySection: LegacySection): NavSection => { - const foundSection = navItems.find(sec => sec.id === legacySection.id); - - if (foundSection) { - return foundSection; - } else { - const newSection = legacySectionToNavSection(legacySection); - navItems.push(newSection); - navItems.sort((a: NavSection, b: NavSection) => a.order - b.order); // only needed while merging platform and legacy - return newSection; - } -}; - -export const mergeLegacyItems = ( - navItems: NavSection[], - legacySections: LegacySection[], - selectedId: string -) => { - const filteredLegacySections = legacySections - .filter(sectionVisible) - .filter(section => section.visibleItems.length); - - filteredLegacySections.forEach(legacySection => { - const section = findOrAddSection(navItems, legacySection); - legacySection.visibleItems.forEach(app => { - section.items.push(legacyAppToNavItem(app, selectedId)); - return section.items.sort((a, b) => a.order - b.order); - }); - }); - - return navItems; -}; +/** @internal **/ +export const ManagementSidebarNav = ({ + selectedId, + sections, + onManagementSectionSelected, +}: ManagementSidebarNavProps) => { + const HEADER_ID = 'stack-management-nav-header'; + const [isSideNavOpenOnMobile, setIsSideNavOpenOnMobile] = useState(false); + const toggleOpenOnMobile = () => setIsSideNavOpenOnMobile(!isSideNavOpenOnMobile); + + const sectionsToNavItems = (managementSections: ManagementSection[]) => { + if (!managementSections) { + return undefined; + } + + return (managementSections || []) + .filter(section => section.getAppsEnabled()) + .map(section => ({ + ...createNavItem(section, { + items: appsToNavItems(section.apps), + }), + })); + }; -const sectionsToItems = ( - sections: ManagementSection[], - legacySections: LegacySection[], - selectedId: string -) => { - const navItems = sideNavItems(sections, selectedId); - return mergeLegacyItems(navItems, legacySections, selectedId); -}; + const appsToNavItems = (managementApps: ManagementApp[]) => { + if (!managementApps) { + return undefined; + } + + return (managementApps || []) + .filter(app => app.enabled) + .map(app => ({ + ...createNavItem(app, { + onClick: () => onManagementSectionSelected(app.id, app.basePath), + }), + })); + }; -export class ManagementSidebarNav extends React.Component< - ManagementSidebarNavProps, - ManagementSidebarNavState -> { - constructor(props: ManagementSidebarNavProps) { - super(props); - this.state = { - isSideNavOpenOnMobile: false, + const createNavItem = ( + item: T, + customParams: Record = {} + ): EuiSideNavItemType => { + const iconType = item.euiIconType || item.icon; + + return { + id: item.id, + name: item.title, + isSelected: item.id === selectedId, + icon: iconType ? : undefined, + ...customParams, }; - } - - public render() { - const HEADER_ID = 'stack-management-nav-header'; - - return ( - <> - -

- {i18n.translate('management.nav.label', { - defaultMessage: 'Management', - })} -

-
- - - ); - } - - private renderMobileTitle() { - return ; - } - - private toggleOpenOnMobile = () => { - this.setState({ - isSideNavOpenOnMobile: !this.state.isSideNavOpenOnMobile, - }); }; -} + + return ( + <> + +

{headerLabel}

+
+ + + ); +}; diff --git a/src/plugins/management/public/index.ts b/src/plugins/management/public/index.ts index f2cc6a00b93d8..3ba469c7831f6 100644 --- a/src/plugins/management/public/index.ts +++ b/src/plugins/management/public/index.ts @@ -21,17 +21,14 @@ import { PluginInitializerContext } from 'kibana/public'; import { ManagementPlugin } from './plugin'; export function plugin(initializerContext: PluginInitializerContext) { - return new ManagementPlugin(); + return new ManagementPlugin(initializerContext); } +export { RegisterManagementAppArgs, ManagementSection, ManagementApp } from './utils'; + export { - ManagementSetup, - ManagementStart, - RegisterManagementApp, ManagementSectionId, - RegisterManagementAppArgs, ManagementAppMountParams, + ManagementSetup, + ManagementStart, } from './types'; -export { ManagementApp } from './management_app'; -export { ManagementSection } from './management_section'; -export { ManagementSidebarNav } from './components'; // for use in legacy management apps diff --git a/src/plugins/management/public/legacy/redirect_messages.tsx b/src/plugins/management/public/legacy/redirect_messages.tsx deleted file mode 100644 index f8cb975e6fae5..0000000000000 --- a/src/plugins/management/public/legacy/redirect_messages.tsx +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { EuiCallOut } from '@elastic/eui'; -import { NotificationsStart, OverlayStart } from 'kibana/public'; -import { parse } from 'query-string'; -import { i18n } from '@kbn/i18n'; -import { toMountPoint } from '../../../kibana_react/public'; -import { MarkdownSimple } from '../../../kibana_react/public'; - -/** - * Show banners and toasts carried over from other applications. This is only necessary as long as - * management is rendered in the legacy platform (which requires a full page reload to switch to). - * - * Once management is rendered using the core application service, this file and the places setting - * bannerMessage and notFoundMessage URL params can be removed. - * @param notifications Core notifications service - * @param overlays Core overlays service - */ -export function showLegacyRedirectMessages( - notifications: NotificationsStart, - overlays: OverlayStart -) { - const queryPosition = window.location.hash.indexOf('?'); - if (queryPosition === -1) { - return; - } - - const urlParams = parse(window.location.hash.substr(queryPosition)) as Record; - - if (urlParams.bannerMessage) { - const bannerId = overlays.banners.add( - toMountPoint( - - ) - ); - setTimeout(() => { - overlays.banners.remove(bannerId); - }, 15000); - } - - if (urlParams.notFoundMessage) { - notifications.toasts.addWarning({ - title: i18n.translate('management.history.savedObjectIsMissingNotificationMessage', { - defaultMessage: 'Saved object is missing', - }), - text: toMountPoint({urlParams.notFoundMessage}), - }); - } -} diff --git a/src/plugins/management/public/legacy/section.js b/src/plugins/management/public/legacy/section.js deleted file mode 100644 index 7d733b7b3173b..0000000000000 --- a/src/plugins/management/public/legacy/section.js +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { assign } from 'lodash'; -import { IndexedArray } from '../../../../legacy/ui/public/indexed_array'; - -const listeners = []; - -export class LegacyManagementSection { - /** - * @param {string} id - * @param {object} options - * @param {number|null} options.order - * @param {string|null} options.display - defaults to id - * @param {string|null} options.url - defaults to '' - * @param {boolean|null} options.visible - defaults to true - * @param {boolean|null} options.disabled - defaults to false - * @param {string|null} options.tooltip - defaults to '' - * @param {string|null} options.icon - defaults to '' - * @returns {ManagementSection} - */ - - constructor(id, options = {}, capabilities) { - this.display = id; - this.id = id; - this.items = new IndexedArray({ - index: ['id'], - order: ['order'], - }); - this.visible = true; - this.disabled = false; - this.tooltip = ''; - this.icon = ''; - this.url = ''; - this.capabilities = capabilities; - - assign(this, options); - } - - get visibleItems() { - return this.items.inOrder.filter(item => { - const capabilityManagementSection = this.capabilities.management[this.id]; - const itemCapability = capabilityManagementSection - ? capabilityManagementSection[item.id] - : null; - - return item.visible && itemCapability !== false; - }); - } - - /** - * Registers a callback that will be executed when management sections are updated - * Globally bound to solve for sidebar nav needs - * - * @param {function} fn - */ - addListener(fn) { - listeners.push(fn); - } - - /** - * Registers a sub-section - * - * @param {string} id - * @param {object} options - * @returns {ManagementSection} - */ - - register(id, options = {}) { - const item = new LegacyManagementSection( - id, - assign(options, { parent: this }), - this.capabilities - ); - - if (this.hasItem(id)) { - throw new Error(`'${id}' is already registered`); - } - - this.items.push(item); - listeners.forEach(fn => fn()); - - return item; - } - - /** - * Deregisters a section - * - * @param {string} id - */ - deregister(id) { - this.items.remove(item => item.id === id); - listeners.forEach(fn => fn(this.items)); - } - - /** - * Determine if an id is already registered - * - * @param {string} id - * @returns {boolean} - */ - - hasItem(id) { - return this.items.byId.hasOwnProperty(id); - } - - /** - * Fetches a section by id - * - * @param {string} id - * @returns {ManagementSection} - */ - - getSection(id) { - if (!id) { - return; - } - - const sectionPath = id.split('/'); - return sectionPath.reduce((currentSection, nextSection) => { - if (!currentSection) { - return; - } - - return currentSection.items.byId[nextSection]; - }, this); - } - - hide() { - this.visible = false; - } - - show() { - this.visible = true; - } - - disable() { - this.disabled = true; - } - - enable() { - this.disabled = false; - } -} diff --git a/src/plugins/management/public/legacy/section.test.js b/src/plugins/management/public/legacy/section.test.js deleted file mode 100644 index 45cc80ef80edd..0000000000000 --- a/src/plugins/management/public/legacy/section.test.js +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { LegacyManagementSection } from './section'; -import { IndexedArray } from '../../../../legacy/ui/public/indexed_array'; - -const capabilitiesMock = { - management: { - kibana: { sampleFeature2: false }, - }, -}; - -describe('ManagementSection', () => { - describe('constructor', () => { - it('defaults display to id', () => { - const section = new LegacyManagementSection('kibana', {}, capabilitiesMock); - expect(section.display).toBe('kibana'); - }); - - it('defaults visible to true', () => { - const section = new LegacyManagementSection('kibana', {}, capabilitiesMock); - expect(section.visible).toBe(true); - }); - - it('defaults disabled to false', () => { - const section = new LegacyManagementSection('kibana', {}, capabilitiesMock); - expect(section.disabled).toBe(false); - }); - - it('defaults tooltip to empty string', () => { - const section = new LegacyManagementSection('kibana', {}, capabilitiesMock); - expect(section.tooltip).toBe(''); - }); - - it('defaults url to empty string', () => { - const section = new LegacyManagementSection('kibana', {}, capabilitiesMock); - expect(section.url).toBe(''); - }); - - it('exposes items', () => { - const section = new LegacyManagementSection('kibana', {}, capabilitiesMock); - expect(section.items).toHaveLength(0); - }); - - it('exposes visibleItems', () => { - const section = new LegacyManagementSection('kibana', {}, capabilitiesMock); - expect(section.visibleItems).toHaveLength(0); - }); - - it('assigns all options', () => { - const section = new LegacyManagementSection( - 'kibana', - { description: 'test', url: 'foobar' }, - capabilitiesMock - ); - expect(section.description).toBe('test'); - expect(section.url).toBe('foobar'); - }); - }); - - describe('register', () => { - let section; - - beforeEach(() => { - section = new LegacyManagementSection('kibana', {}, capabilitiesMock); - }); - - it('returns a ManagementSection', () => { - expect(section.register('about')).toBeInstanceOf(LegacyManagementSection); - }); - - it('provides a reference to the parent', () => { - expect(section.register('about').parent).toBe(section); - }); - - it('adds item', function() { - section.register('about', { description: 'test' }); - - expect(section.items).toHaveLength(1); - expect(section.items[0]).toBeInstanceOf(LegacyManagementSection); - expect(section.items[0].id).toBe('about'); - }); - - it('can only register a section once', () => { - let threwException = false; - section.register('about'); - - try { - section.register('about'); - } catch (e) { - threwException = e.message.indexOf('is already registered') > -1; - } - - expect(threwException).toBe(true); - }); - - it('calls listener when item added', () => { - let listerCalled = false; - const listenerFn = () => { - listerCalled = true; - }; - - section.addListener(listenerFn); - section.register('about'); - expect(listerCalled).toBe(true); - }); - }); - - describe('deregister', () => { - let section; - - beforeEach(() => { - section = new LegacyManagementSection('kibana', {}, capabilitiesMock); - section.register('about'); - }); - - it('deregisters an existing section', () => { - section.deregister('about'); - expect(section.items).toHaveLength(0); - }); - - it('allows deregistering a section more than once', () => { - section.deregister('about'); - section.deregister('about'); - expect(section.items).toHaveLength(0); - }); - - it('calls listener when item added', () => { - let listerCalled = false; - const listenerFn = () => { - listerCalled = true; - }; - - section.addListener(listenerFn); - section.deregister('about'); - expect(listerCalled).toBe(true); - }); - }); - - describe('getSection', () => { - let section; - - beforeEach(() => { - section = new LegacyManagementSection('kibana', {}, capabilitiesMock); - section.register('about'); - }); - - it('returns registered section', () => { - expect(section.getSection('about')).toBeInstanceOf(LegacyManagementSection); - }); - - it('returns undefined if un-registered', () => { - expect(section.getSection('unknown')).not.toBeDefined(); - }); - - it('returns sub-sections specified via a /-separated path', () => { - section.getSection('about').register('time'); - expect(section.getSection('about/time')).toBeInstanceOf(LegacyManagementSection); - expect(section.getSection('about/time')).toBe(section.getSection('about').getSection('time')); - }); - - it('returns undefined if a sub-section along a /-separated path does not exist', () => { - expect(section.getSection('about/damn/time')).toBe(undefined); - }); - }); - - describe('items', () => { - let section; - - beforeEach(() => { - section = new LegacyManagementSection('kibana', {}, capabilitiesMock); - - section.register('three', { order: 3 }); - section.register('one', { order: 1 }); - section.register('two', { order: 2 }); - }); - - it('is an indexed array', () => { - expect(section.items).toBeInstanceOf(IndexedArray); - }); - - it('is indexed on id', () => { - const keys = Object.keys(section.items.byId).sort(); - expect(section.items.byId).toBeInstanceOf(Object); - - expect(keys).toEqual(['one', 'three', 'two']); - }); - - it('can be ordered', () => { - const ids = section.items.inOrder.map(i => { - return i.id; - }); - expect(ids).toEqual(['one', 'two', 'three']); - }); - }); - - describe('visible', () => { - let section; - - beforeEach(() => { - section = new LegacyManagementSection('kibana', {}, capabilitiesMock); - }); - - it('hide sets visible to false', () => { - section.hide(); - expect(section.visible).toBe(false); - }); - - it('show sets visible to true', () => { - section.hide(); - section.show(); - expect(section.visible).toBe(true); - }); - }); - - describe('disabled', () => { - let section; - - beforeEach(() => { - section = new LegacyManagementSection('kibana', {}, capabilitiesMock); - }); - - it('disable sets disabled to true', () => { - section.disable(); - expect(section.disabled).toBe(true); - }); - - it('enable sets disabled to false', () => { - section.enable(); - expect(section.disabled).toBe(false); - }); - }); - - describe('visibleItems', () => { - let section; - - beforeEach(() => { - section = new LegacyManagementSection('kibana', {}, capabilitiesMock); - - section.register('three', { order: 3 }); - section.register('one', { order: 1 }); - section.register('two', { order: 2 }); - }); - - it('maintains the order', () => { - const ids = section.visibleItems.map(i => { - return i.id; - }); - expect(ids).toEqual(['one', 'two', 'three']); - }); - - it('does not include hidden items', () => { - section.getSection('two').hide(); - - const ids = section.visibleItems.map(i => { - return i.id; - }); - expect(ids).toEqual(['one', 'three']); - }); - - it('does not include visible items hidden via uiCapabilities', () => { - section.register('sampleFeature2', { order: 4, visible: true }); - const ids = section.visibleItems.map(i => { - return i.id; - }); - expect(ids).toEqual(['one', 'two', 'three']); - }); - }); -}); diff --git a/src/plugins/management/public/legacy/sections_register.js b/src/plugins/management/public/legacy/sections_register.js deleted file mode 100644 index 3fa1998c378f6..0000000000000 --- a/src/plugins/management/public/legacy/sections_register.js +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { LegacyManagementSection } from './section'; -import { managementSections } from '../management_sections'; - -export class LegacyManagementAdapter { - main = undefined; - init = capabilities => { - this.main = new LegacyManagementSection( - 'management', - { - display: i18n.translate('management.displayName', { - defaultMessage: 'Stack Management', - }), - }, - capabilities - ); - - managementSections.forEach(({ id, title }, idx) => { - this.main.register(id, { - display: title, - order: idx, - }); - }); - - return this.main; - }; - getManagement = () => this.main; -} diff --git a/src/plugins/management/public/management_app.test.tsx b/src/plugins/management/public/management_app.test.tsx deleted file mode 100644 index a76b234d95ef5..0000000000000 --- a/src/plugins/management/public/management_app.test.tsx +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import * as React from 'react'; -import * as ReactDOM from 'react-dom'; -import { coreMock } from '../../../core/public/mocks'; - -import { ManagementApp } from './management_app'; -// @ts-ignore -import { LegacyManagementSection } from './legacy'; - -function createTestApp() { - const legacySection = new LegacyManagementSection('legacy'); - return new ManagementApp( - { - id: 'test-app', - title: 'Test App', - basePath: '', - mount(params) { - params.setBreadcrumbs([{ text: 'Test App' }]); - ReactDOM.render(
Test App - Hello world!
, params.element); - - return () => { - ReactDOM.unmountComponentAtNode(params.element); - }; - }, - }, - () => [], - jest.fn(), - () => legacySection, - coreMock.createSetup().getStartServices - ); -} - -test('Management app can mount and unmount', async () => { - const testApp = createTestApp(); - const container = document.createElement('div'); - document.body.appendChild(container); - const unmount = testApp.mount({ element: container, basePath: '', setBreadcrumbs: jest.fn() }); - expect(container).toMatchSnapshot(); - (await unmount)(); - expect(container).toMatchSnapshot(); -}); - -test('Enabled by default, can disable', () => { - const testApp = createTestApp(); - expect(testApp.enabled).toBe(true); - testApp.disable(); - expect(testApp.enabled).toBe(false); -}); diff --git a/src/plugins/management/public/management_app.tsx b/src/plugins/management/public/management_app.tsx deleted file mode 100644 index 843bbfde654ee..0000000000000 --- a/src/plugins/management/public/management_app.tsx +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import * as React from 'react'; -import ReactDOM from 'react-dom'; -import { i18n } from '@kbn/i18n'; -import { CreateManagementApp, ManagementSectionMount, Unmount } from './types'; -import { KibanaLegacySetup } from '../../kibana_legacy/public'; -// @ts-ignore -import { LegacyManagementSection } from './legacy'; -import { ManagementChrome } from './components'; -import { ManagementSection } from './management_section'; -import { ChromeBreadcrumb, StartServicesAccessor } from '../../../core/public/'; - -export class ManagementApp { - readonly id: string; - readonly title: string; - readonly basePath: string; - readonly order: number; - readonly mount: ManagementSectionMount; - private enabledStatus = true; - - constructor( - { id, title, basePath, order = 100, mount }: CreateManagementApp, - getSections: () => ManagementSection[], - registerLegacyApp: KibanaLegacySetup['registerLegacyApp'], - getLegacyManagementSections: () => LegacyManagementSection, - getStartServices: StartServicesAccessor - ) { - this.id = id; - this.title = title; - this.basePath = basePath; - this.order = order; - this.mount = mount; - - registerLegacyApp({ - id: basePath.substr(1), // get rid of initial slash - title, - mount: async ({}, params) => { - let appUnmount: Unmount; - if (!this.enabledStatus) { - const [coreStart] = await getStartServices(); - coreStart.application.navigateToApp('kibana#/management'); - return () => {}; - } - async function setBreadcrumbs(crumbs: ChromeBreadcrumb[]) { - const [coreStart] = await getStartServices(); - coreStart.chrome.setBreadcrumbs([ - { - text: i18n.translate('management.breadcrumb', { - defaultMessage: 'Stack Management', - }), - href: '#/management', - }, - ...crumbs, - ]); - } - - ReactDOM.render( - { - appUnmount = await mount({ - basePath, - element, - setBreadcrumbs, - }); - }} - />, - params.element - ); - - return async () => { - appUnmount(); - ReactDOM.unmountComponentAtNode(params.element); - }; - }, - }); - } - public enable() { - this.enabledStatus = true; - } - public disable() { - this.enabledStatus = false; - } - public get enabled() { - return this.enabledStatus; - } -} diff --git a/src/plugins/management/public/management_section.test.ts b/src/plugins/management/public/management_section.test.ts deleted file mode 100644 index e1d047425ac18..0000000000000 --- a/src/plugins/management/public/management_section.test.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { ManagementSection } from './management_section'; -import { ManagementSectionId } from './types'; -// @ts-ignore -import { LegacyManagementSection } from './legacy'; -import { coreMock } from '../../../core/public/mocks'; - -function createSection(registerLegacyApp: () => void) { - const legacySection = new LegacyManagementSection('legacy'); - const getLegacySection = () => legacySection; - const getManagementSections: () => ManagementSection[] = () => []; - - const testSectionConfig = { id: ManagementSectionId.Data, title: 'Test Section' }; - return new ManagementSection( - testSectionConfig, - getManagementSections, - registerLegacyApp, - getLegacySection, - coreMock.createSetup().getStartServices - ); -} - -test('cannot register two apps with the same id', () => { - const registerLegacyApp = jest.fn(); - const section = createSection(registerLegacyApp); - - const testAppConfig = { id: 'test-app', title: 'Test App', mount: () => () => {} }; - - section.registerApp(testAppConfig); - expect(registerLegacyApp).toHaveBeenCalled(); - expect(section.apps.length).toEqual(1); - - expect(() => { - section.registerApp(testAppConfig); - }).toThrow(); -}); - -test('can enable and disable apps', () => { - const registerLegacyApp = jest.fn(); - const section = createSection(registerLegacyApp); - - const testAppConfig = { id: 'test-app', title: 'Test App', mount: () => () => {} }; - - const app = section.registerApp(testAppConfig); - expect(section.getAppsEnabled().length).toEqual(1); - app.disable(); - expect(section.getAppsEnabled().length).toEqual(0); -}); diff --git a/src/plugins/management/public/management_section.ts b/src/plugins/management/public/management_section.ts deleted file mode 100644 index ace8f87bec766..0000000000000 --- a/src/plugins/management/public/management_section.ts +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { ReactElement } from 'react'; - -import { CreateSection, RegisterManagementAppArgs, ManagementSectionId } from './types'; -import { KibanaLegacySetup } from '../../kibana_legacy/public'; -import { StartServicesAccessor } from '../../../core/public'; -// @ts-ignore -import { LegacyManagementSection } from './legacy'; -import { ManagementApp } from './management_app'; - -export class ManagementSection { - public readonly id: ManagementSectionId; - public readonly title: string | ReactElement = ''; - public readonly apps: ManagementApp[] = []; - public readonly order: number; - public readonly euiIconType?: string; - public readonly icon?: string; - private readonly getSections: () => ManagementSection[]; - private readonly registerLegacyApp: KibanaLegacySetup['registerLegacyApp']; - private readonly getLegacyManagementSection: () => LegacyManagementSection; - private readonly getStartServices: StartServicesAccessor; - - constructor( - { id, title, order = 100, euiIconType, icon }: CreateSection, - getSections: () => ManagementSection[], - registerLegacyApp: KibanaLegacySetup['registerLegacyApp'], - getLegacyManagementSection: () => ManagementSection, - getStartServices: StartServicesAccessor - ) { - this.id = id; - this.title = title; - this.order = order; - this.euiIconType = euiIconType; - this.icon = icon; - this.getSections = getSections; - this.registerLegacyApp = registerLegacyApp; - this.getLegacyManagementSection = getLegacyManagementSection; - this.getStartServices = getStartServices; - } - - registerApp({ id, title, order, mount }: RegisterManagementAppArgs) { - if (this.getApp(id)) { - throw new Error(`Management app already registered - id: ${id}, title: ${title}`); - } - - const app = new ManagementApp( - { id, title, order, mount, basePath: `/management/${this.id}/${id}` }, - this.getSections, - this.registerLegacyApp, - this.getLegacyManagementSection, - this.getStartServices - ); - this.apps.push(app); - return app; - } - getApp(id: ManagementApp['id']) { - return this.apps.find(app => app.id === id); - } - getAppsEnabled() { - return this.apps.filter(app => app.enabled).sort((a, b) => a.order - b.order); - } -} diff --git a/src/plugins/management/public/management_sections_service.test.ts b/src/plugins/management/public/management_sections_service.test.ts new file mode 100644 index 0000000000000..27bff646117aa --- /dev/null +++ b/src/plugins/management/public/management_sections_service.test.ts @@ -0,0 +1,67 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ManagementSectionId } from './index'; +import { ManagementSectionsService } from './management_sections_service'; + +describe('ManagementService', () => { + let managementService: ManagementSectionsService; + + beforeEach(() => { + managementService = new ManagementSectionsService(); + }); + + test('Provides default sections', () => { + managementService.setup(); + const start = managementService.start(); + + expect(start.getAllSections().length).toEqual(6); + expect(start.getSection(ManagementSectionId.Ingest)).toBeDefined(); + expect(start.getSection(ManagementSectionId.Data)).toBeDefined(); + expect(start.getSection(ManagementSectionId.InsightsAndAlerting)).toBeDefined(); + expect(start.getSection(ManagementSectionId.Security)).toBeDefined(); + expect(start.getSection(ManagementSectionId.Kibana)).toBeDefined(); + expect(start.getSection(ManagementSectionId.Stack)).toBeDefined(); + }); + + test('Register section, enable and disable', () => { + // Setup phase: + const setup = managementService.setup(); + const testSection = setup.register({ id: 'test-section', title: 'Test Section' }); + + expect(setup.getSection('test-section')).not.toBeUndefined(); + + const testApp = testSection.registerApp({ + id: 'test-app', + title: 'Test App', + mount: () => () => {}, + }); + + expect(testSection.getApp('test-app')).not.toBeUndefined(); + + // Start phase: + const start = managementService.start(); + + expect(start.getSectionsEnabled().length).toEqual(1); + + testApp.disable(); + + expect(start.getSectionsEnabled().length).toEqual(0); + }); +}); diff --git a/src/plugins/management/public/management_sections_service.ts b/src/plugins/management/public/management_sections_service.ts new file mode 100644 index 0000000000000..4fc041df340ce --- /dev/null +++ b/src/plugins/management/public/management_sections_service.ts @@ -0,0 +1,68 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ReactElement } from 'react'; +import { ManagementSection, RegisterManagementSectionArgs } from './utils'; +import { managementSections } from './components/management_sections'; + +import { ManagementSectionId, SectionsServiceSetup, SectionsServiceStart } from './types'; + +export class ManagementSectionsService { + private sections: Map = new Map(); + + private getSection = (sectionId: ManagementSectionId | string) => + this.sections.get(sectionId) as ManagementSection; + + private getAllSections = () => [...this.sections.values()]; + + private registerSection = (section: RegisterManagementSectionArgs) => { + if (this.sections.has(section.id)) { + throw Error(`ManagementSection '${section.id}' already registered`); + } + + const newSection = new ManagementSection(section); + + this.sections.set(section.id, newSection); + return newSection; + }; + + setup(): SectionsServiceSetup { + managementSections.forEach( + ({ id, title }: { id: ManagementSectionId; title: ReactElement }, idx: number) => { + this.registerSection({ id, title, order: idx }); + } + ); + + return { + register: this.registerSection, + getSection: this.getSection, + }; + } + + start(): SectionsServiceStart { + return { + getSection: this.getSection, + getAllSections: this.getAllSections, + getSectionsEnabled: () => + this.getAllSections() + .filter(section => section.enabled && section.apps.length) + .sort((a, b) => a.order - b.order), + }; + } +} diff --git a/src/plugins/management/public/management_service.test.ts b/src/plugins/management/public/management_service.test.ts deleted file mode 100644 index 1507d6f43619d..0000000000000 --- a/src/plugins/management/public/management_service.test.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { ManagementService } from './management_service'; -import { ManagementSectionId } from './types'; -import { coreMock } from '../../../core/public/mocks'; -import { npSetup } from '../../../legacy/ui/public/new_platform/__mocks__'; - -jest.mock('ui/new_platform'); - -test('Provides default sections', () => { - const service = new ManagementService().setup( - npSetup.plugins.kibanaLegacy, - () => {}, - coreMock.createSetup().getStartServices - ); - expect(service.getAllSections().length).toEqual(6); - expect(service.getSection(ManagementSectionId.Ingest)).toBeDefined(); - expect(service.getSection(ManagementSectionId.Data)).toBeDefined(); - expect(service.getSection(ManagementSectionId.InsightsAndAlerting)).toBeDefined(); - expect(service.getSection(ManagementSectionId.Security)).toBeDefined(); - expect(service.getSection(ManagementSectionId.Kibana)).toBeDefined(); - expect(service.getSection(ManagementSectionId.Stack)).toBeDefined(); -}); diff --git a/src/plugins/management/public/management_service.ts b/src/plugins/management/public/management_service.ts deleted file mode 100644 index 85d27a526d402..0000000000000 --- a/src/plugins/management/public/management_service.ts +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { ReactElement } from 'react'; - -import { ManagementSection } from './management_section'; -import { managementSections } from './management_sections'; -import { KibanaLegacySetup } from '../../kibana_legacy/public'; -// @ts-ignore -import { LegacyManagementSection, sections } from './legacy'; -import { CreateSection, ManagementSectionId } from './types'; -import { StartServicesAccessor, CoreStart } from '../../../core/public'; - -export class ManagementService { - private sections: ManagementSection[] = []; - - private register( - registerLegacyApp: KibanaLegacySetup['registerLegacyApp'], - getLegacyManagement: () => LegacyManagementSection, - getStartServices: StartServicesAccessor - ) { - return (section: CreateSection) => { - if (this.getSection(section.id)) { - throw Error(`ManagementSection '${section.id}' already registered`); - } - - const newSection = new ManagementSection( - section, - this.getSectionsEnabled.bind(this), - registerLegacyApp, - getLegacyManagement, - getStartServices - ); - this.sections.push(newSection); - return newSection; - }; - } - - private getSection(sectionId: ManagementSectionId) { - return this.sections.find(section => section.id === sectionId); - } - - private getAllSections() { - return this.sections; - } - - private getSectionsEnabled() { - return this.sections - .filter(section => section.getAppsEnabled().length > 0) - .sort((a, b) => a.order - b.order); - } - - private sharedInterface = { - getSection: (sectionId: ManagementSectionId) => { - const section = this.getSection(sectionId); - if (!section) { - throw new Error(`Management section with id ${sectionId} is undefined`); - } - return section; - }, - getSectionsEnabled: this.getSectionsEnabled.bind(this), - getAllSections: this.getAllSections.bind(this), - }; - - public setup( - kibanaLegacy: KibanaLegacySetup, - getLegacyManagement: () => LegacyManagementSection, - getStartServices: StartServicesAccessor - ) { - const register = this.register.bind(this)( - kibanaLegacy.registerLegacyApp, - getLegacyManagement, - getStartServices - ); - - managementSections.forEach( - ({ id, title }: { id: ManagementSectionId; title: ReactElement }, idx: number) => { - register({ id, title, order: idx }); - } - ); - - return { - ...this.sharedInterface, - }; - } - - public start(navigateToApp: CoreStart['application']['navigateToApp']) { - return { - navigateToApp, // apps are currently registered as top level apps but this may change in the future - ...this.sharedInterface, - }; - } -} diff --git a/src/plugins/management/public/mocks/index.ts b/src/plugins/management/public/mocks/index.ts index 3e32ff4fe26b2..123e3f28877aa 100644 --- a/src/plugins/management/public/mocks/index.ts +++ b/src/plugins/management/public/mocks/index.ts @@ -18,29 +18,29 @@ */ import { ManagementSetup, ManagementStart } from '../types'; -import { ManagementSection } from '../management_section'; +import { ManagementSection } from '../index'; -const createManagementSectionMock = (): jest.Mocked> => { - return { +const createManagementSectionMock = () => + (({ + disable: jest.fn(), + enable: jest.fn(), registerApp: jest.fn(), getApp: jest.fn(), - getAppsEnabled: jest.fn().mockReturnValue([]), - }; -}; + getEnabledItems: jest.fn().mockReturnValue([]), + } as unknown) as ManagementSection); const createSetupContract = (): DeeplyMockedKeys => ({ sections: { + register: jest.fn(), getSection: jest.fn().mockReturnValue(createManagementSectionMock()), - getAllSections: jest.fn().mockReturnValue([]), }, }); const createStartContract = (): DeeplyMockedKeys => ({ - legacy: {}, sections: { getSection: jest.fn(), getAllSections: jest.fn(), - navigateToApp: jest.fn(), + getSectionsEnabled: jest.fn(), }, }); diff --git a/src/plugins/management/public/plugin.ts b/src/plugins/management/public/plugin.ts index e7f86996a9a1b..71656d7c0b83b 100644 --- a/src/plugins/management/public/plugin.ts +++ b/src/plugins/management/public/plugin.ts @@ -18,23 +18,30 @@ */ import { i18n } from '@kbn/i18n'; -import { CoreSetup, CoreStart, Plugin } from 'kibana/public'; import { ManagementSetup, ManagementStart } from './types'; -import { ManagementService } from './management_service'; -import { KibanaLegacySetup } from '../../kibana_legacy/public'; import { FeatureCatalogueCategory, HomePublicPluginSetup } from '../../home/public'; -// @ts-ignore -import { LegacyManagementAdapter } from './legacy'; -import { showLegacyRedirectMessages } from './legacy/redirect_messages'; +import { + CoreSetup, + CoreStart, + Plugin, + DEFAULT_APP_CATEGORIES, + PluginInitializerContext, +} from '../../../core/public'; + +import { ManagementSectionsService } from './management_sections_service'; + +interface ManagementSetupDependencies { + home: HomePublicPluginSetup; +} export class ManagementPlugin implements Plugin { - private managementSections = new ManagementService(); - private legacyManagement = new LegacyManagementAdapter(); + private readonly managementSections = new ManagementSectionsService(); + + constructor(private initializerContext: PluginInitializerContext) {} + + public setup(core: CoreSetup, { home }: ManagementSetupDependencies) { + const kibanaVersion = this.initializerContext.env.packageInfo.version; - public setup( - core: CoreSetup, - { kibanaLegacy, home }: { kibanaLegacy: KibanaLegacySetup; home: HomePublicPluginSetup } - ) { home.featureCatalogue.register({ id: 'stack-management', title: i18n.translate('management.stackManagement.managementLabel', { @@ -44,25 +51,38 @@ export class ManagementPlugin implements Plugin ManagementSection; + getSection: (sectionId: ManagementSectionId | string) => ManagementSection; +} + +export interface SectionsServiceStart { + getSection: (sectionId: ManagementSectionId | string) => ManagementSection; + getAllSections: () => ManagementSection[]; + getSectionsEnabled: () => ManagementSection[]; } export enum ManagementSectionId { @@ -60,37 +48,8 @@ export enum ManagementSectionId { Stack = 'stack', } -interface SectionsServiceSetup { - getSection: (sectionId: ManagementSectionId) => ManagementSection; - getAllSections: () => ManagementSection[]; -} - -interface SectionsServiceStart { - getSection: (sectionId: ManagementSectionId) => ManagementSection; - getAllSections: () => ManagementSection[]; - navigateToApp: ApplicationStart['navigateToApp']; -} - -export interface CreateSection { - id: ManagementSectionId; - title: string | ReactElement; - order?: number; - euiIconType?: string; // takes precedence over `icon` property. - icon?: string; // URL to image file; fallback if no `euiIconType` -} - -export type RegisterSection = (section: CreateSection) => ManagementSection; - -export interface RegisterManagementAppArgs { - id: string; - title: string; - mount: ManagementSectionMount; - order?: number; -} - -export type RegisterManagementApp = (managementApp: RegisterManagementAppArgs) => ManagementApp; - export type Unmount = () => Promise | void; +export type Mount = (params: ManagementAppMountParams) => Unmount | Promise; export interface ManagementAppMountParams { basePath: string; // base path for setting up your router @@ -98,29 +57,10 @@ export interface ManagementAppMountParams { setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; } -export type ManagementSectionMount = ( - params: ManagementAppMountParams -) => Unmount | Promise; - -export interface CreateManagementApp { +export interface CreateManagementItemArgs { id: string; - title: string; - basePath: string; + title: string | ReactElement; order?: number; - mount: ManagementSectionMount; -} - -export interface LegacySection extends LegacyApp { - visibleItems: LegacyApp[]; -} - -export interface LegacyApp { - disabled: boolean; - visible: boolean; - id: string; - display: string; - url?: string; - euiIconType?: IconType; - icon?: string; - order: number; + euiIconType?: string; // takes precedence over `icon` property. + icon?: string; // URL to image file; fallback if no `euiIconType` } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/types.ts b/src/plugins/management/public/utils/index.ts similarity index 75% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/types.ts rename to src/plugins/management/public/utils/index.ts index 81184d6fdd1a3..a1d759a3ec628 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/types.ts +++ b/src/plugins/management/public/utils/index.ts @@ -17,18 +17,5 @@ * under the License. */ -export interface IndexPatternCreationOption { - text: string; - description?: string; - onClick: () => void; -} - -export interface IndexPattern { - id: string; - title: string; - url: string; - active: boolean; - default: boolean; - tag?: string[]; - sort: string; -} +export { ManagementApp, RegisterManagementAppArgs } from './management_app'; +export { ManagementSection, RegisterManagementSectionArgs } from './management_section'; diff --git a/src/plugins/management/public/utils/management_app.ts b/src/plugins/management/public/utils/management_app.ts new file mode 100644 index 0000000000000..a27db5522af82 --- /dev/null +++ b/src/plugins/management/public/utils/management_app.ts @@ -0,0 +1,38 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CreateManagementItemArgs, Mount } from '../types'; +import { ManagementItem } from './management_item'; + +export interface RegisterManagementAppArgs extends CreateManagementItemArgs { + mount: Mount; + basePath: string; +} + +export class ManagementApp extends ManagementItem { + public readonly mount: Mount; + public readonly basePath: string; + + constructor(args: RegisterManagementAppArgs) { + super(args); + + this.mount = args.mount; + this.basePath = args.basePath; + } +} diff --git a/src/plugins/management/public/utils/management_item.ts b/src/plugins/management/public/utils/management_item.ts new file mode 100644 index 0000000000000..ef0c8e4693895 --- /dev/null +++ b/src/plugins/management/public/utils/management_item.ts @@ -0,0 +1,46 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { ReactElement } from 'react'; +import { CreateManagementItemArgs } from '../types'; + +export class ManagementItem { + public readonly id: string = ''; + public readonly title: string | ReactElement = ''; + public readonly order: number; + public readonly euiIconType?: string; + public readonly icon?: string; + + public enabled: boolean = true; + + constructor({ id, title, order = 100, euiIconType, icon }: CreateManagementItemArgs) { + this.id = id; + this.title = title; + this.order = order; + this.euiIconType = euiIconType; + this.icon = icon; + } + + disable() { + this.enabled = false; + } + + enable() { + this.enabled = true; + } +} diff --git a/src/plugins/management/public/utils/management_section.test.ts b/src/plugins/management/public/utils/management_section.test.ts new file mode 100644 index 0000000000000..f5ce86f5dc963 --- /dev/null +++ b/src/plugins/management/public/utils/management_section.test.ts @@ -0,0 +1,55 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ManagementSection, RegisterManagementSectionArgs } from './management_section'; + +describe('ManagementSection', () => { + const createSection = ( + config: RegisterManagementSectionArgs = { + id: 'test-section', + title: 'Test Section', + } as RegisterManagementSectionArgs + ) => new ManagementSection(config); + + test('cannot register two apps with the same id', () => { + const section = createSection(); + const testAppConfig = { id: 'test-app', title: 'Test App', mount: () => () => {} }; + + section.registerApp(testAppConfig); + + expect(section.apps.length).toEqual(1); + + expect(() => { + section.registerApp(testAppConfig); + }).toThrow(); + }); + + test('can enable and disable apps', () => { + const section = createSection(); + const testAppConfig = { id: 'test-app', title: 'Test App', mount: () => () => {} }; + + const app = section.registerApp(testAppConfig); + + expect(section.getAppsEnabled().length).toEqual(1); + + app.disable(); + + expect(section.getAppsEnabled().length).toEqual(0); + }); +}); diff --git a/src/plugins/management/public/utils/management_section.ts b/src/plugins/management/public/utils/management_section.ts new file mode 100644 index 0000000000000..e00c2b942e0c4 --- /dev/null +++ b/src/plugins/management/public/utils/management_section.ts @@ -0,0 +1,58 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { Assign } from '@kbn/utility-types'; +import { CreateManagementItemArgs, ManagementSectionId } from '../types'; +import { ManagementItem } from './management_item'; +import { ManagementApp, RegisterManagementAppArgs } from './management_app'; + +export type RegisterManagementSectionArgs = Assign< + CreateManagementItemArgs, + { id: ManagementSectionId | string } +>; + +export class ManagementSection extends ManagementItem { + public readonly apps: ManagementApp[] = []; + + constructor(args: RegisterManagementSectionArgs) { + super(args); + } + + registerApp(args: Omit) { + if (this.getApp(args.id)) { + throw new Error(`Management app already registered - id: ${args.id}, title: ${args.title}`); + } + + const app = new ManagementApp({ + ...args, + basePath: `/${this.id}/${args.id}`, + }); + + this.apps.push(app); + + return app; + } + + getApp(id: ManagementApp['id']) { + return this.apps.find(app => app.id === id); + } + + getAppsEnabled() { + return this.apps.filter(app => app.enabled).sort((a, b) => a.order - b.order); + } +} diff --git a/x-pack/plugins/security/public/management/management_service.test.ts b/x-pack/plugins/security/public/management/management_service.test.ts index 466e1aa9b3c68..78d7f7ff118a6 100644 --- a/x-pack/plugins/security/public/management/management_service.test.ts +++ b/x-pack/plugins/security/public/management/management_service.test.ts @@ -5,7 +5,11 @@ */ import { BehaviorSubject } from 'rxjs'; -import { ManagementApp } from '../../../../../src/plugins/management/public'; +import { + ManagementApp, + ManagementSetup, + ManagementStart, +} from '../../../../../src/plugins/management/public'; import { SecurityLicenseFeatures } from '../../common/licensing/license_features'; import { ManagementService } from './management_service'; import { usersManagementApp } from './users'; @@ -25,10 +29,10 @@ describe('ManagementService', () => { const license = licenseMock.create(); const mockSection = { registerApp: jest.fn() }; - const managementSetup = { + const managementSetup: ManagementSetup = { sections: { + register: jest.fn(), getSection: jest.fn().mockReturnValue(mockSection), - getAllSections: jest.fn(), }, }; @@ -80,17 +84,20 @@ describe('ManagementService', () => { license.features$ = licenseSubject; const service = new ManagementService(); + + const managementSetup: ManagementSetup = { + sections: { + register: jest.fn(), + getSection: jest.fn().mockReturnValue(mockSection), + }, + }; + service.setup({ getStartServices: getStartServices as any, license, fatalErrors, authc: securityMock.createSetup().authc, - management: { - sections: { - getSection: jest.fn().mockReturnValue({ registerApp: jest.fn() }), - getAllSections: jest.fn(), - }, - }, + management: managementSetup, }); const getMockedApp = () => { @@ -115,17 +122,18 @@ describe('ManagementService', () => { [roleMappingsManagementApp.id, getMockedApp()], ] as Array<[string, jest.Mocked]>); - service.start({ - management: { - sections: { - getSection: jest - .fn() - .mockReturnValue({ getApp: jest.fn().mockImplementation(id => mockApps.get(id)) }), - getAllSections: jest.fn(), - navigateToApp: jest.fn(), - }, - legacy: undefined, + const managementStart: ManagementStart = { + sections: { + getSection: jest + .fn() + .mockReturnValue({ getApp: jest.fn().mockImplementation(id => mockApps.get(id)) }), + getAllSections: jest.fn(), + getSectionsEnabled: jest.fn(), }, + }; + + service.start({ + management: managementStart, }); return { diff --git a/x-pack/plugins/spaces/public/plugin.test.ts b/x-pack/plugins/spaces/public/plugin.test.ts index a98f593f546a0..4a49cf20d3a4a 100644 --- a/x-pack/plugins/spaces/public/plugin.test.ts +++ b/x-pack/plugins/spaces/public/plugin.test.ts @@ -33,17 +33,11 @@ describe('Spaces plugin', () => { it('should register the management and feature catalogue sections when the management and home plugins are both available', () => { const coreSetup = coreMock.createSetup(); - const kibanaSection = new ManagementSection( - { - id: ManagementSectionId.Kibana, - title: 'Mock Kibana Section', - order: 1, - }, - jest.fn(), - jest.fn(), - jest.fn(), - coreSetup.getStartServices - ); + const kibanaSection = new ManagementSection({ + id: ManagementSectionId.Kibana, + title: 'Mock Kibana Section', + order: 1, + }); const registerAppSpy = jest.spyOn(kibanaSection, 'registerApp'); From 0a3a79f3d62692f4e6a32e42e2a393b2c743cd35 Mon Sep 17 00:00:00 2001 From: Matt Kime Date: Mon, 18 May 2020 23:37:11 -0500 Subject: [PATCH 02/93] partial progress on a number of management sections --- .../mount_management_section.tsx | 6 ++--- .../edit_index_pattern/tabs/utils.ts | 2 +- .../index_pattern_table.tsx | 8 ++++--- .../mount_management_section.tsx | 6 ++--- .../management_app/management_app.tsx | 1 + .../management_app_wrapper.tsx | 7 ++++-- src/plugins/management/public/types.ts | 3 +++ .../management_section/mount_section.tsx | 8 +++---- .../beats_management/public/application.tsx | 16 ++++--------- .../public/app/index.tsx | 18 +++++++++----- .../public/application/app.tsx | 17 ++++++------- .../public/application/index.tsx | 10 +++++--- .../public/plugin.tsx | 4 ++-- .../public/application/app.js | 6 ++--- .../public/application/app_context.tsx | 2 ++ .../public/application/index.tsx | 12 ++++++---- .../license_management/public/plugin.ts | 3 ++- .../logstash/public/application/index.tsx | 18 +++++++------- .../role_mappings_management_app.tsx | 8 +++---- .../management/roles/roles_management_app.tsx | 8 +++---- .../users/users_grid/users_grid_page.tsx | 2 +- .../management/users/users_management_app.tsx | 8 +++---- .../management/spaces_management_app.tsx | 8 +++---- x-pack/plugins/transform/public/app/app.tsx | 24 +++++++++---------- .../transform/public/app/app_dependencies.tsx | 2 ++ .../public/app/mount_management_section.ts | 3 ++- .../watcher/public/application/app.tsx | 22 ++++++++--------- x-pack/plugins/watcher/public/plugin.ts | 3 ++- 28 files changed, 129 insertions(+), 106 deletions(-) diff --git a/src/plugins/advanced_settings/public/management_app/mount_management_section.tsx b/src/plugins/advanced_settings/public/management_app/mount_management_section.tsx index df44ea45e9d01..b4779d051ab02 100644 --- a/src/plugins/advanced_settings/public/management_app/mount_management_section.tsx +++ b/src/plugins/advanced_settings/public/management_app/mount_management_section.tsx @@ -19,7 +19,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { HashRouter, Switch, Route } from 'react-router-dom'; +import { Router, Switch, Route } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { I18nProvider } from '@kbn/i18n/react'; @@ -60,7 +60,7 @@ export async function mountManagementSection( ReactDOM.render( - + - + , params.element ); diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.ts index b9b59142290dc..d544bd11a1480 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.ts +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.ts @@ -117,7 +117,7 @@ export function getTabs( } export function getPath(field: IndexPatternField) { - return `${field.indexPattern?.id}/field/${field.name}`; + return `/patterns/${field.indexPattern?.id}/field/${field.name}`; } const allTypesDropDown = i18n.translate( diff --git a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx index 599ed1fa04ee2..e2e71632a10f4 100644 --- a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx +++ b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx @@ -28,6 +28,7 @@ import { EuiSpacer, EuiText, } from '@elastic/eui'; +import { AppMountParameters } from 'kibana/public'; import { FormattedMessage } from '@kbn/i18n/react'; import { withRouter, RouteComponentProps } from 'react-router-dom'; import React, { useState, useEffect } from 'react'; @@ -45,7 +46,7 @@ import { IndexPatternManagementStart } from '../../plugin'; import { getIndexPatterns } from '../utils'; import { getListBreadcrumbs } from '../breadcrumbs'; -const columns = [ +const columns = (history: AppMountParameters['history']) => [ { field: 'title', name: 'Pattern', @@ -59,7 +60,7 @@ const columns = [ }>; } ) => ( - + history.push(`/patterns/${index.id}`)}> {name} {index.tags && index.tags.map(({ key: tagKey, name: tagName }) => ( @@ -106,6 +107,7 @@ const title = i18n.translate('indexPatternManagement.indexPatternTable.title', { interface Props extends RouteComponentProps { getIndexPatternCreationOptions: IndexPatternManagementStart['creation']['getIndexPatternCreationOptions']; canSave: boolean; + history: AppMountParameters['history']; services: { savedObjectsClient: SavedObjectsClientContract; uiSettings: IUiSettingsClient; @@ -195,7 +197,7 @@ export const IndexPatternTable = ({ itemId="id" isSelectable={false} items={indexPatterns} - columns={columns} + columns={columns(history)} pagination={pagination} sorting={sorting} search={search} diff --git a/src/plugins/index_pattern_management/public/management_app/mount_management_section.tsx b/src/plugins/index_pattern_management/public/management_app/mount_management_section.tsx index b6b58d8f006c8..ea900f2d24039 100644 --- a/src/plugins/index_pattern_management/public/management_app/mount_management_section.tsx +++ b/src/plugins/index_pattern_management/public/management_app/mount_management_section.tsx @@ -19,7 +19,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { HashRouter, Switch, Route } from 'react-router-dom'; +import { Router, Switch, Route } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { I18nProvider } from '@kbn/i18n/react'; @@ -61,7 +61,7 @@ export async function mountManagementSection( ReactDOM.render( - + - + , params.element ); diff --git a/src/plugins/management/public/components/management_app/management_app.tsx b/src/plugins/management/public/components/management_app/management_app.tsx index 7dffc4f5942fb..e2ff105268abe 100644 --- a/src/plugins/management/public/components/management_app/management_app.tsx +++ b/src/plugins/management/public/components/management_app/management_app.tsx @@ -92,6 +92,7 @@ export const ManagementApp = ({ context, dependencies, history }: ManagementAppP app={app} setBreadcrumbs={setBreadcrumbs} onAppMounted={onAppMounted} + history={history.createSubHistory(app.basePath)} /> )} /> diff --git a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx index dac219823b7ca..4341197173a82 100644 --- a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx +++ b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx @@ -19,7 +19,7 @@ import React, { useEffect, createRef, useRef, RefObject } from 'react'; -import { ChromeBreadcrumb } from 'kibana/public'; +import { ChromeBreadcrumb, AppMountParameters } from 'kibana/public'; import { ManagementApp } from '../../utils'; import { Unmount } from '../../types'; @@ -27,12 +27,14 @@ interface ManagementSectionWrapperProps { app: ManagementApp; setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; onAppMounted: (id: string) => void; + history: AppMountParameters['history']; } export const ManagementAppWrapper = ({ app, setBreadcrumbs, onAppMounted, + history, }: ManagementSectionWrapperProps) => { const mountElementRef = useRef>(); const { mount, basePath } = app; @@ -46,6 +48,7 @@ export const ManagementAppWrapper = ({ basePath, setBreadcrumbs, element: mountElementRef.current!.current, + history, }); onAppMounted(app.id); @@ -63,7 +66,7 @@ export const ManagementAppWrapper = ({ } }; } - }, [app.id, basePath, mount, onAppMounted, setBreadcrumbs]); + }, [app.id, basePath, history, mount, onAppMounted, setBreadcrumbs]); return
; }; diff --git a/src/plugins/management/public/types.ts b/src/plugins/management/public/types.ts index 05992c9f1f5a2..2dbcacbffa169 100644 --- a/src/plugins/management/public/types.ts +++ b/src/plugins/management/public/types.ts @@ -16,7 +16,9 @@ * specific language governing permissions and limitations * under the License. */ + import { ReactElement } from 'react'; +import { AppMountParameters } from 'kibana/public'; import { ManagementSection, RegisterManagementSectionArgs } from './utils'; import { ChromeBreadcrumb } from '../../../core/public/'; @@ -55,6 +57,7 @@ export interface ManagementAppMountParams { basePath: string; // base path for setting up your router element: HTMLElement; // element the section should render into setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; + history: AppMountParameters['history']; } export interface CreateManagementItemArgs { diff --git a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx index c1daf3445219f..3ca0c3772a243 100644 --- a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx +++ b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx @@ -19,7 +19,7 @@ import React, { lazy, Suspense } from 'react'; import ReactDOM from 'react-dom'; -import { HashRouter, Switch, Route } from 'react-router-dom'; +import { Router, Switch, Route } from 'react-router-dom'; import { I18nProvider } from '@kbn/i18n/react'; import { EuiLoadingSpinner } from '@elastic/eui'; import { CoreSetup, Capabilities } from 'src/core/public'; @@ -44,7 +44,7 @@ export const mountManagementSection = async ({ serviceRegistry, }: MountParams) => { const [coreStart, { data }, pluginStart] = await core.getStartServices(); - const { element, basePath, setBreadcrumbs } = mountParams; + const { element, history, setBreadcrumbs } = mountParams; if (allowedObjectTypes === undefined) { allowedObjectTypes = await getAllowedTypes(coreStart.http); } @@ -53,7 +53,7 @@ export const mountManagementSection = async ({ ReactDOM.render( - + @@ -81,7 +81,7 @@ export const mountManagementSection = async ({ - + , element ); diff --git a/x-pack/plugins/beats_management/public/application.tsx b/x-pack/plugins/beats_management/public/application.tsx index 6711e93895b62..0b8b0ad3dafc9 100644 --- a/x-pack/plugins/beats_management/public/application.tsx +++ b/x-pack/plugins/beats_management/public/application.tsx @@ -8,7 +8,7 @@ import * as euiVars from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; import React from 'react'; import ReactDOM from 'react-dom'; -import { HashRouter } from 'react-router-dom'; +import { Router } from 'react-router-dom'; import { ThemeProvider } from 'styled-components'; import { Provider as UnstatedProvider, Subscribe } from 'unstated'; import { Background } from './components/layouts/background'; @@ -19,19 +19,13 @@ import { TagsContainer } from './containers/tags'; import { FrontendLibs } from './lib/types'; import { AppRouter } from './router'; import { services } from './kbn_services'; -import { - ManagementAppMountParams, - ManagementSectionId, -} from '../../../../src/plugins/management/public'; +import { ManagementAppMountParams } from '../../../../src/plugins/management/public'; -export const renderApp = ( - { basePath, element, setBreadcrumbs }: ManagementAppMountParams, - libs: FrontendLibs -) => { +export const renderApp = ({ element, history }: ManagementAppMountParams, libs: FrontendLibs) => { ReactDOM.render( - + @@ -48,7 +42,7 @@ export const renderApp = ( - + , element diff --git a/x-pack/plugins/cross_cluster_replication/public/app/index.tsx b/x-pack/plugins/cross_cluster_replication/public/app/index.tsx index 79569b587f97f..d4a74aefb1571 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/index.tsx +++ b/x-pack/plugins/cross_cluster_replication/public/app/index.tsx @@ -6,8 +6,8 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { Provider } from 'react-redux'; -import { HashRouter } from 'react-router-dom'; -import { I18nStart } from 'kibana/public'; +import { Router } from 'react-router-dom'; +import { I18nStart, AppMountParameters } from 'kibana/public'; import { UnmountCallback } from 'src/core/public'; import { init as initBreadcrumbs, SetBreadcrumbs } from './services/breadcrumbs'; @@ -15,13 +15,17 @@ import { init as initDocumentation } from './services/documentation_links'; import { App } from './app'; import { ccrStore } from './store'; -const renderApp = (element: Element, I18nContext: I18nStart['Context']): UnmountCallback => { +const renderApp = ( + element: Element, + I18nContext: I18nStart['Context'], + history: AppMountParameters['history'] +): UnmountCallback => { render( - + - + , element @@ -36,17 +40,19 @@ export async function mountApp({ I18nContext, ELASTIC_WEBSITE_URL, DOC_LINK_VERSION, + history, }: { element: Element; setBreadcrumbs: SetBreadcrumbs; I18nContext: I18nStart['Context']; ELASTIC_WEBSITE_URL: string; DOC_LINK_VERSION: string; + history: AppMountParameters['history']; }): Promise { // Import and initialize additional services here instead of in plugin.ts to reduce the size of the // initial bundle as much as possible. initBreadcrumbs(setBreadcrumbs); initDocumentation(`${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`); - return renderApp(element, I18nContext); + return renderApp(element, I18nContext, history); } diff --git a/x-pack/plugins/index_lifecycle_management/public/application/app.tsx b/x-pack/plugins/index_lifecycle_management/public/application/app.tsx index 993dced20bbe6..dff21fb6d796d 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/app.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/app.tsx @@ -5,25 +5,26 @@ */ import React, { useEffect } from 'react'; -import { HashRouter, Switch, Route, Redirect } from 'react-router-dom'; +import { Router, Switch, Route, Redirect } from 'react-router-dom'; +import { AppMountParameters } from 'kibana/public'; import { METRIC_TYPE } from '@kbn/analytics'; -import { BASE_PATH } from '../../common/constants'; import { UIM_APP_LOAD } from './constants'; import { EditPolicy } from './sections/edit_policy'; import { PolicyTable } from './sections/policy_table'; import { trackUiMetric } from './services/ui_metric'; -export const App = () => { +export const App = ({ history }: { history: AppMountParameters['history'] }) => { useEffect(() => trackUiMetric(METRIC_TYPE.LOADED, UIM_APP_LOAD), []); return ( - + - - - + + + + - + ); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/index.tsx b/x-pack/plugins/index_lifecycle_management/public/application/index.tsx index a7d88d31e58fc..9d9120398810b 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/index.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/index.tsx @@ -7,17 +7,21 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { Provider } from 'react-redux'; -import { I18nStart } from 'kibana/public'; +import { I18nStart, AppMountParameters } from 'kibana/public'; import { UnmountCallback } from 'src/core/public'; import { App } from './app'; import { indexLifecycleManagementStore } from './store'; -export const renderApp = (element: Element, I18nContext: I18nStart['Context']): UnmountCallback => { +export const renderApp = ( + element: Element, + I18nContext: I18nStart['Context'], + history: AppMountParameters['history'] +): UnmountCallback => { render( - + , element diff --git a/x-pack/plugins/index_lifecycle_management/public/plugin.tsx b/x-pack/plugins/index_lifecycle_management/public/plugin.tsx index 8fce57b0e79b0..3f8d7d7f88487 100644 --- a/x-pack/plugins/index_lifecycle_management/public/plugin.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/plugin.tsx @@ -42,7 +42,7 @@ export class IndexLifecycleManagementPlugin { id: PLUGIN.ID, title: PLUGIN.TITLE, order: 2, - mount: async ({ element }) => { + mount: async ({ element, history }) => { const [coreStart] = await getStartServices(); const { i18n: { Context: I18nContext }, @@ -55,7 +55,7 @@ export class IndexLifecycleManagementPlugin { ); const { renderApp } = await import('./application'); - return renderApp(element, I18nContext); + return renderApp(element, I18nContext, history); }, }); diff --git a/x-pack/plugins/license_management/public/application/app.js b/x-pack/plugins/license_management/public/application/app.js index 1bc8e9cd563e2..222a6f879cbf8 100644 --- a/x-pack/plugins/license_management/public/application/app.js +++ b/x-pack/plugins/license_management/public/application/app.js @@ -8,7 +8,7 @@ import React, { Component } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { LicenseDashboard, UploadLicense } from './sections'; import { Switch, Route } from 'react-router-dom'; -import { APP_PERMISSION, BASE_PATH } from '../../common/constants'; +import { APP_PERMISSION } from '../../common/constants'; import { EuiPageBody, EuiEmptyPrompt, EuiText, EuiLoadingSpinner, EuiCallOut } from '@elastic/eui'; export class App extends Component { @@ -89,8 +89,8 @@ export class App extends Component { return ( - - + + ); diff --git a/x-pack/plugins/license_management/public/application/app_context.tsx b/x-pack/plugins/license_management/public/application/app_context.tsx index 1e90f4c907b8c..28fa16641a369 100644 --- a/x-pack/plugins/license_management/public/application/app_context.tsx +++ b/x-pack/plugins/license_management/public/application/app_context.tsx @@ -5,6 +5,7 @@ */ import React, { createContext, useContext } from 'react'; +import { AppMountParameters } from 'kibana/public'; import { CoreStart } from '../../../../../src/core/public'; import { LicensingPluginSetup, ILicense } from '../../../licensing/public'; @@ -18,6 +19,7 @@ export interface AppDependencies { core: CoreStart; services: { breadcrumbService: BreadcrumbService; + history: AppMountParameters['history']; }; plugins: { licensing: LicensingPluginSetup; diff --git a/x-pack/plugins/license_management/public/application/index.tsx b/x-pack/plugins/license_management/public/application/index.tsx index 75f2f98f51e6e..84f3067a528ea 100644 --- a/x-pack/plugins/license_management/public/application/index.tsx +++ b/x-pack/plugins/license_management/public/application/index.tsx @@ -6,7 +6,8 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { HashRouter } from 'react-router-dom'; +import { Router } from 'react-router-dom'; +import { AppMountParameters } from 'kibana/public'; import { AppDependencies } from './app_context'; import { AppProviders } from './app_providers'; @@ -14,15 +15,18 @@ import { AppProviders } from './app_providers'; import { App } from './app.container'; const AppWithRouter = (props: { [key: string]: any }) => ( - + - + ); export const renderApp = (element: Element, dependencies: AppDependencies) => { render( - + , element ); diff --git a/x-pack/plugins/license_management/public/plugin.ts b/x-pack/plugins/license_management/public/plugin.ts index 927902945cd8c..e2e6437d12d2a 100644 --- a/x-pack/plugins/license_management/public/plugin.ts +++ b/x-pack/plugins/license_management/public/plugin.ts @@ -48,7 +48,7 @@ export class LicenseManagementUIPlugin id: PLUGIN.id, title: PLUGIN.title, order: 0, - mount: async ({ element, setBreadcrumbs }) => { + mount: async ({ element, setBreadcrumbs, history }) => { const [core] = await getStartServices(); const initialLicense = await plugins.licensing.license$.pipe(first()).toPromise(); @@ -72,6 +72,7 @@ export class LicenseManagementUIPlugin }, services: { breadcrumbService: this.breadcrumbService, + history, }, store: { initialLicense, diff --git a/x-pack/plugins/logstash/public/application/index.tsx b/x-pack/plugins/logstash/public/application/index.tsx index 3588e1f6b2417..8d515ad6b3932 100644 --- a/x-pack/plugins/logstash/public/application/index.tsx +++ b/x-pack/plugins/logstash/public/application/index.tsx @@ -6,7 +6,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { HashRouter, Route, Switch, Redirect } from 'react-router-dom'; +import { Router, Route, Switch, Redirect } from 'react-router-dom'; import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; @@ -30,7 +30,7 @@ import * as Breadcrumbs from './breadcrumbs'; export const renderApp = async ( core: CoreStart, - { basePath, element, setBreadcrumbs }: ManagementAppMountParams, + { history, element, setBreadcrumbs }: ManagementAppMountParams, isMonitoringEnabled: boolean, licenseService$: Observable ) => { @@ -43,12 +43,12 @@ export const renderApp = async ( ReactDOM.render( - + { + render={() => { setBreadcrumbs(Breadcrumbs.getPipelineListBreadcrumbs()); return ( history.push(`/pipeline/${id}/edit`)} clonePipeline={(id: string) => history.push(`/pipeline/${id}/edit?clone`)} - createPipeline={() => history.push(`/pipeline/new-pipeline`)} + createPipeline={() => history.push(`pipeline/new-pipeline`)} pipelinesService={pipelinesService} toastNotifications={core.notifications.toasts} /> @@ -70,7 +70,7 @@ export const renderApp = async ( ( + render={() => ( ( + render={({ match }) => ( - + , element ); diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx index ffb6d6d98f180..4f0cb6d382470 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { HashRouter as Router, Route, Switch, useParams } from 'react-router-dom'; +import { Router, Route, Switch, useParams } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { StartServicesAccessor } from 'src/core/public'; import { RegisterManagementAppArgs } from '../../../../../../src/plugins/management/public'; @@ -26,7 +26,7 @@ export const roleMappingsManagementApp = Object.freeze({ title: i18n.translate('xpack.security.management.roleMappingsTitle', { defaultMessage: 'Role Mappings', }), - async mount({ basePath, element, setBreadcrumbs }) { + async mount({ basePath, element, setBreadcrumbs, history }) { const roleMappingsBreadcrumbs = [ { text: i18n.translate('xpack.security.roleMapping.breadcrumb', { @@ -91,9 +91,9 @@ export const roleMappingsManagementApp = Object.freeze({ render( - + - + diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.tsx index 9aaa3b47f3b19..860d07e400f65 100644 --- a/x-pack/plugins/security/public/management/roles/roles_management_app.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_management_app.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { HashRouter as Router, Route, Switch, useParams } from 'react-router-dom'; +import { Router, Route, Switch, useParams } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { StartServicesAccessor, FatalErrorsSetup } from 'src/core/public'; import { RegisterManagementAppArgs } from '../../../../../../src/plugins/management/public'; @@ -27,7 +27,7 @@ export const rolesManagementApp = Object.freeze({ id: this.id, order: 20, title: i18n.translate('xpack.security.management.rolesTitle', { defaultMessage: 'Roles' }), - async mount({ basePath, element, setBreadcrumbs }) { + async mount({ basePath, element, setBreadcrumbs, history }) { const rolesBreadcrumbs = [ { text: i18n.translate('xpack.security.roles.breadcrumb', { defaultMessage: 'Roles' }), @@ -101,9 +101,9 @@ export const rolesManagementApp = Object.freeze({ render( - + - + diff --git a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx index f8882129772f7..e63dc3682336c 100644 --- a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx +++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx @@ -97,7 +97,7 @@ export class UsersGridPage extends Component { ); } - const path = '#/management/security/'; + const path = '/'; const columns: Array> = [ { field: 'username', diff --git a/x-pack/plugins/security/public/management/users/users_management_app.tsx b/x-pack/plugins/security/public/management/users/users_management_app.tsx index 9d337c1508ad4..04fa8df24bec7 100644 --- a/x-pack/plugins/security/public/management/users/users_management_app.tsx +++ b/x-pack/plugins/security/public/management/users/users_management_app.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { HashRouter as Router, Route, Switch, useParams } from 'react-router-dom'; +import { Router, Route, Switch, useParams } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { StartServicesAccessor } from 'src/core/public'; import { RegisterManagementAppArgs } from '../../../../../../src/plugins/management/public'; @@ -25,7 +25,7 @@ export const usersManagementApp = Object.freeze({ id: this.id, order: 10, title: i18n.translate('xpack.security.management.usersTitle', { defaultMessage: 'Users' }), - async mount({ basePath, element, setBreadcrumbs }) { + async mount({ basePath, element, setBreadcrumbs, history }) { const usersBreadcrumbs = [ { text: i18n.translate('xpack.security.users.breadcrumb', { defaultMessage: 'Users' }), @@ -87,9 +87,9 @@ export const usersManagementApp = Object.freeze({ render( - + - + diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx index 079cf2234b13b..9216cc31ee77c 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { HashRouter as Router, Route, Switch, useParams } from 'react-router-dom'; +import { Router, Route, Switch, useParams } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { StartServicesAccessor } from 'src/core/public'; import { SecurityLicense } from '../../../security/public'; @@ -32,7 +32,7 @@ export const spacesManagementApp = Object.freeze({ title: i18n.translate('xpack.spaces.displayName', { defaultMessage: 'Spaces', }), - async mount({ basePath, element, setBreadcrumbs }) { + async mount({ basePath, element, setBreadcrumbs, history }) { const [ { notifications, i18n: i18nStart, application }, { features }, @@ -108,9 +108,9 @@ export const spacesManagementApp = Object.freeze({ render( - + - + diff --git a/x-pack/plugins/transform/public/app/app.tsx b/x-pack/plugins/transform/public/app/app.tsx index 01ff7f5bff27f..330fb7a17f5fa 100644 --- a/x-pack/plugins/transform/public/app/app.tsx +++ b/x-pack/plugins/transform/public/app/app.tsx @@ -6,7 +6,8 @@ import React, { useContext, FC } from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { HashRouter, Redirect, Route, Switch } from 'react-router-dom'; +import { Router, Redirect, Route, Switch } from 'react-router-dom'; +import { AppMountParameters } from 'kibana/public'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -23,7 +24,7 @@ import { CloneTransformSection } from './sections/clone_transform'; import { CreateTransformSection } from './sections/create_transform'; import { TransformManagementSection } from './sections/transform_management'; -export const App: FC = () => { +export const App: FC<{ history: AppMountParameters['history'] }> = ({ history }) => { const { apiError } = useContext(AuthorizationContext); if (apiError !== null) { return ( @@ -41,24 +42,21 @@ export const App: FC = () => { return (
- + - - + + + - +
); }; @@ -70,7 +68,7 @@ export const renderApp = (element: HTMLElement, appDependencies: AppDependencies - + , diff --git a/x-pack/plugins/transform/public/app/app_dependencies.tsx b/x-pack/plugins/transform/public/app/app_dependencies.tsx index 87db02988adf0..586381fd3b2b5 100644 --- a/x-pack/plugins/transform/public/app/app_dependencies.tsx +++ b/x-pack/plugins/transform/public/app/app_dependencies.tsx @@ -6,6 +6,7 @@ import { CoreSetup, CoreStart } from 'src/core/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; +import { AppMountParameters } from 'kibana/public'; import { useKibana } from '../../../../../src/plugins/kibana_react/public'; import { Storage } from '../../../../../src/plugins/kibana_utils/public'; @@ -21,6 +22,7 @@ export interface AppDependencies { savedObjects: CoreStart['savedObjects']; storage: Storage; overlays: CoreStart['overlays']; + history: AppMountParameters['history']; } export const useAppDependencies = () => { diff --git a/x-pack/plugins/transform/public/app/mount_management_section.ts b/x-pack/plugins/transform/public/app/mount_management_section.ts index f3a48975a68e6..454738f7a313a 100644 --- a/x-pack/plugins/transform/public/app/mount_management_section.ts +++ b/x-pack/plugins/transform/public/app/mount_management_section.ts @@ -21,7 +21,7 @@ export async function mountManagementSection( coreSetup: CoreSetup, params: ManagementAppMountParams ) { - const { element, setBreadcrumbs } = params; + const { element, setBreadcrumbs, history } = params; const { http, notifications, getStartServices } = coreSetup; const startServices = await getStartServices(); const [core, plugins] = startServices; @@ -46,6 +46,7 @@ export async function mountManagementSection( savedObjects, storage: localStorage, uiSettings, + history, }; return renderApp(element, appDependencies); diff --git a/x-pack/plugins/watcher/public/application/app.tsx b/x-pack/plugins/watcher/public/application/app.tsx index 8a6d2746237e9..5e75eff5ac949 100644 --- a/x-pack/plugins/watcher/public/application/app.tsx +++ b/x-pack/plugins/watcher/public/application/app.tsx @@ -6,16 +6,15 @@ import React, { useEffect, useState } from 'react'; import { Observable } from 'rxjs'; -import { DocLinksStart, HttpSetup, ToastsSetup, IUiSettingsClient } from 'kibana/public'; - import { - HashRouter, - Switch, - Route, - Redirect, - withRouter, - RouteComponentProps, -} from 'react-router-dom'; + DocLinksStart, + HttpSetup, + ToastsSetup, + IUiSettingsClient, + AppMountParameters, +} from 'kibana/public'; + +import { Router, Switch, Route, Redirect, withRouter, RouteComponentProps } from 'react-router-dom'; import { EuiCallOut, EuiLink } from '@elastic/eui'; @@ -46,6 +45,7 @@ export interface AppDeps { createTimeBuckets: () => any; licenseStatus$: Observable; setBreadcrumbs: Parameters[0]['setBreadcrumbs']; + history: AppMountParameters['history']; } export const App = (deps: AppDeps) => { @@ -79,13 +79,13 @@ export const App = (deps: AppDeps) => { ); } return ( - + - +
); }; diff --git a/x-pack/plugins/watcher/public/plugin.ts b/x-pack/plugins/watcher/public/plugin.ts index 6496c742fcb40..a772d26308dfd 100644 --- a/x-pack/plugins/watcher/public/plugin.ts +++ b/x-pack/plugins/watcher/public/plugin.ts @@ -38,7 +38,7 @@ export class WatcherUIPlugin implements Plugin { { defaultMessage: 'Watcher' } ), order: 3, - mount: async ({ element, setBreadcrumbs }) => { + mount: async ({ element, setBreadcrumbs, history }) => { const [core] = await getStartServices(); const { i18n: i18nDep, docLinks, savedObjects } = core; const { boot } = await import('./application/boot'); @@ -58,6 +58,7 @@ export class WatcherUIPlugin implements Plugin { savedObjects: savedObjects.client, I18nContext: i18nDep.Context, createTimeBuckets: () => new TimeBuckets(uiSettings, data), + history, }); }, }); From 0a96008b663f1c60de9d30d3bc54f6ee6b7319a0 Mon Sep 17 00:00:00 2001 From: Matt Kime Date: Tue, 19 May 2020 09:22:02 -0500 Subject: [PATCH 03/93] fix passing history --- x-pack/plugins/cross_cluster_replication/public/plugin.ts | 3 ++- .../management/api_keys/api_keys_management_app.test.tsx | 2 ++ .../role_mappings/role_mappings_management_app.test.tsx | 3 ++- .../public/management/roles/roles_management_app.test.tsx | 3 ++- .../public/management/users/users_management_app.test.tsx | 3 ++- .../spaces/public/management/spaces_management_app.test.tsx | 3 ++- x-pack/plugins/transform/public/app/app.tsx | 2 +- .../__jest__/client_integration/helpers/app_context.mock.tsx | 2 ++ x-pack/plugins/watcher/public/application/app.tsx | 2 +- 9 files changed, 16 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/cross_cluster_replication/public/plugin.ts b/x-pack/plugins/cross_cluster_replication/public/plugin.ts index 561da838a4202..388185b38889f 100644 --- a/x-pack/plugins/cross_cluster_replication/public/plugin.ts +++ b/x-pack/plugins/cross_cluster_replication/public/plugin.ts @@ -41,7 +41,7 @@ export class CrossClusterReplicationPlugin implements Plugin { id: MANAGEMENT_ID, title: PLUGIN.TITLE, order: 6, - mount: async ({ element, setBreadcrumbs }) => { + mount: async ({ element, setBreadcrumbs, history }) => { const { mountApp } = await import('./app'); const [coreStart] = await getStartServices(); @@ -56,6 +56,7 @@ export class CrossClusterReplicationPlugin implements Plugin { I18nContext, ELASTIC_WEBSITE_URL, DOC_LINK_VERSION, + history, }); }, }); diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.test.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.test.tsx index 11e65f14e2708..16332b6df15e3 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.test.tsx @@ -10,6 +10,7 @@ jest.mock('./api_keys_grid', () => ({ import { apiKeysManagementApp } from './api_keys_management_app'; import { coreMock } from '../../../../../../src/core/public/mocks'; +import { ScopedHistory } from 'kibana/public'; describe('apiKeysManagementApp', () => { it('create() returns proper management app descriptor', () => { @@ -37,6 +38,7 @@ describe('apiKeysManagementApp', () => { basePath: '/some-base-path', element: container, setBreadcrumbs, + history: {} as ScopedHistory, }); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx index 5907413d7299e..2f59da91941b8 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx @@ -12,6 +12,7 @@ jest.mock('./edit_role_mapping', () => ({ EditRoleMappingPage: (props: any) => `Role Mapping Edit Page: ${JSON.stringify(props)}`, })); +import { ScopedHistory } from 'kibana/public'; import { roleMappingsManagementApp } from './role_mappings_management_app'; import { coreMock } from '../../../../../../src/core/public/mocks'; @@ -22,7 +23,7 @@ async function mountApp(basePath: string) { const unmount = await roleMappingsManagementApp .create({ getStartServices: coreMock.createSetup().getStartServices as any }) - .mount({ basePath, element: container, setBreadcrumbs }); + .mount({ basePath, element: container, setBreadcrumbs, history: {} as ScopedHistory }); return { unmount, container, setBreadcrumbs }; } diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx index 96051dbd7fa56..0c6e9f87b6325 100644 --- a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx @@ -5,6 +5,7 @@ */ import { licenseMock } from '../../../common/licensing/index.mock'; +import { ScopedHistory } from 'kibana/public'; jest.mock('./roles_grid', () => ({ RolesGridPage: (props: any) => `Roles Page: ${JSON.stringify(props)}`, @@ -34,7 +35,7 @@ async function mountApp(basePath: string) { .fn() .mockResolvedValue([coreMock.createStart(), { data: {}, features: featuresStart }]), }) - .mount({ basePath, element: container, setBreadcrumbs }); + .mount({ basePath, element: container, setBreadcrumbs, history: {} as ScopedHistory }); return { unmount, container, setBreadcrumbs }; } diff --git a/x-pack/plugins/security/public/management/users/users_management_app.test.tsx b/x-pack/plugins/security/public/management/users/users_management_app.test.tsx index 05491d6f889b6..543904858f7f7 100644 --- a/x-pack/plugins/security/public/management/users/users_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/users/users_management_app.test.tsx @@ -12,6 +12,7 @@ jest.mock('./edit_user', () => ({ EditUserPage: (props: any) => `User Edit Page: ${JSON.stringify(props)}`, })); +import { ScopedHistory } from 'kibana/public'; import { usersManagementApp } from './users_management_app'; import { coreMock } from '../../../../../../src/core/public/mocks'; @@ -26,7 +27,7 @@ async function mountApp(basePath: string) { authc: securityMock.createSetup().authc, getStartServices: coreMock.createSetup().getStartServices as any, }) - .mount({ basePath, element: container, setBreadcrumbs }); + .mount({ basePath, element: container, setBreadcrumbs, history: {} as ScopedHistory }); return { unmount, container, setBreadcrumbs }; } diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx index 92c78d63d1b2e..6d4cb3a58c1b3 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx @@ -17,6 +17,7 @@ jest.mock('./edit_space', () => ({ }, })); +import { ScopedHistory } from 'kibana/public'; import { spacesManagementApp } from './spaces_management_app'; import { coreMock } from '../../../../../src/core/public/mocks'; @@ -53,7 +54,7 @@ async function mountApp(basePath: string, spaceId?: string) { securityLicense, getStartServices: async () => [coreStart, pluginsStart as PluginsStart, {}], }) - .mount({ basePath, element: container, setBreadcrumbs }); + .mount({ basePath, element: container, setBreadcrumbs, history: {} as ScopedHistory }); return { unmount, container, setBreadcrumbs }; } diff --git a/x-pack/plugins/transform/public/app/app.tsx b/x-pack/plugins/transform/public/app/app.tsx index 330fb7a17f5fa..7b0c49c7a49b7 100644 --- a/x-pack/plugins/transform/public/app/app.tsx +++ b/x-pack/plugins/transform/public/app/app.tsx @@ -16,7 +16,7 @@ import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/p import { API_BASE_PATH } from '../../common/constants'; import { SectionError } from './components'; -import { CLIENT_BASE_PATH, SECTION_SLUG } from './constants'; +import { SECTION_SLUG } from './constants'; import { AuthorizationContext, AuthorizationProvider } from './lib/authorization'; import { AppDependencies } from './app_dependencies'; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx b/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx index 27aa3ba93684e..2b1b333638c95 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx +++ b/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { of } from 'rxjs'; import { ComponentType } from 'enzyme'; +import { ScopedHistory } from 'kibana/public'; import { docLinksServiceMock, uiSettingsServiceMock, @@ -39,6 +40,7 @@ export const mockContextValue = { } as any, // For our test harness, we don't use this mocked out http service http: httpServiceMock.createSetupContract(), + history: {} as ScopedHistory, }; export const withAppContext = (Component: ComponentType) => (props: any) => { diff --git a/x-pack/plugins/watcher/public/application/app.tsx b/x-pack/plugins/watcher/public/application/app.tsx index 5e75eff5ac949..af8e84146a16f 100644 --- a/x-pack/plugins/watcher/public/application/app.tsx +++ b/x-pack/plugins/watcher/public/application/app.tsx @@ -79,7 +79,7 @@ export const App = (deps: AppDeps) => { ); } return ( - + From 3f0f2e46c6830acbc0803fc30bd735c0af6467cf Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Tue, 19 May 2020 17:59:29 +0300 Subject: [PATCH 04/93] Fixed types --- .../management_app/management_app.tsx | 2 +- src/plugins/management/public/types.ts | 4 ++-- .../cross_cluster_replication/public/plugin.ts | 3 ++- .../api_keys/api_keys_management_app.test.tsx | 5 +++-- .../management/management_service.test.ts | 3 ++- .../role_mappings_management_app.test.tsx | 11 +++++++++-- .../roles/roles_management_app.test.tsx | 11 +++++++++-- .../users/users_management_app.test.tsx | 11 +++++++++-- .../management/spaces_management_app.test.tsx | 11 +++++++++-- x-pack/plugins/transform/public/app/app.tsx | 2 +- .../helpers/app_context.mock.tsx | 3 +++ .../plugins/watcher/public/application/app.tsx | 17 +++++++---------- 12 files changed, 57 insertions(+), 26 deletions(-) diff --git a/src/plugins/management/public/components/management_app/management_app.tsx b/src/plugins/management/public/components/management_app/management_app.tsx index e2ff105268abe..3586882bcf808 100644 --- a/src/plugins/management/public/components/management_app/management_app.tsx +++ b/src/plugins/management/public/components/management_app/management_app.tsx @@ -19,7 +19,7 @@ import React, { useState, useEffect, useCallback } from 'react'; import { Route, Router, Switch } from 'react-router-dom'; import { AppMountContext, AppMountParameters, ChromeBreadcrumb } from 'kibana/public'; -import { I18nProvider } from '@kbn/i18n/src/react'; +import { I18nProvider } from '@kbn/i18n/react'; import { EuiPage, EuiPageBody } from '@elastic/eui'; import { ManagementStart } from '../../types'; import { ManagementSection } from '../../utils'; diff --git a/src/plugins/management/public/types.ts b/src/plugins/management/public/types.ts index 2dbcacbffa169..54ed598ae57d9 100644 --- a/src/plugins/management/public/types.ts +++ b/src/plugins/management/public/types.ts @@ -18,7 +18,7 @@ */ import { ReactElement } from 'react'; -import { AppMountParameters } from 'kibana/public'; +import { ScopedHistory } from 'kibana/public'; import { ManagementSection, RegisterManagementSectionArgs } from './utils'; import { ChromeBreadcrumb } from '../../../core/public/'; @@ -57,7 +57,7 @@ export interface ManagementAppMountParams { basePath: string; // base path for setting up your router element: HTMLElement; // element the section should render into setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; - history: AppMountParameters['history']; + history: ScopedHistory; } export interface CreateManagementItemArgs { diff --git a/x-pack/plugins/cross_cluster_replication/public/plugin.ts b/x-pack/plugins/cross_cluster_replication/public/plugin.ts index 561da838a4202..388185b38889f 100644 --- a/x-pack/plugins/cross_cluster_replication/public/plugin.ts +++ b/x-pack/plugins/cross_cluster_replication/public/plugin.ts @@ -41,7 +41,7 @@ export class CrossClusterReplicationPlugin implements Plugin { id: MANAGEMENT_ID, title: PLUGIN.TITLE, order: 6, - mount: async ({ element, setBreadcrumbs }) => { + mount: async ({ element, setBreadcrumbs, history }) => { const { mountApp } = await import('./app'); const [coreStart] = await getStartServices(); @@ -56,6 +56,7 @@ export class CrossClusterReplicationPlugin implements Plugin { I18nContext, ELASTIC_WEBSITE_URL, DOC_LINK_VERSION, + history, }); }, }); diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.test.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.test.tsx index 11e65f14e2708..725698e767bec 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.test.tsx @@ -7,9 +7,9 @@ jest.mock('./api_keys_grid', () => ({ APIKeysGridPage: (props: any) => `Page: ${JSON.stringify(props)}`, })); - +import { ScopedHistory } from 'src/core/public'; import { apiKeysManagementApp } from './api_keys_management_app'; -import { coreMock } from '../../../../../../src/core/public/mocks'; +import { coreMock, scopedHistoryMock } from '../../../../../../src/core/public/mocks'; describe('apiKeysManagementApp', () => { it('create() returns proper management app descriptor', () => { @@ -37,6 +37,7 @@ describe('apiKeysManagementApp', () => { basePath: '/some-base-path', element: container, setBreadcrumbs, + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, }); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/security/public/management/management_service.test.ts b/x-pack/plugins/security/public/management/management_service.test.ts index 78d7f7ff118a6..78dcda411191a 100644 --- a/x-pack/plugins/security/public/management/management_service.test.ts +++ b/x-pack/plugins/security/public/management/management_service.test.ts @@ -21,6 +21,8 @@ import { rolesManagementApp } from './roles'; import { apiKeysManagementApp } from './api_keys'; import { roleMappingsManagementApp } from './role_mappings'; +const mockSection = { registerApp: jest.fn() }; + describe('ManagementService', () => { describe('setup()', () => { it('properly registers security section and its applications', () => { @@ -28,7 +30,6 @@ describe('ManagementService', () => { const { authc } = securityMock.createSetup(); const license = licenseMock.create(); - const mockSection = { registerApp: jest.fn() }; const managementSetup: ManagementSetup = { sections: { register: jest.fn(), diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx index 5907413d7299e..9e0b7b028bb2b 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx @@ -12,9 +12,11 @@ jest.mock('./edit_role_mapping', () => ({ EditRoleMappingPage: (props: any) => `Role Mapping Edit Page: ${JSON.stringify(props)}`, })); +import { ScopedHistory } from 'src/core/public'; + import { roleMappingsManagementApp } from './role_mappings_management_app'; -import { coreMock } from '../../../../../../src/core/public/mocks'; +import { coreMock, scopedHistoryMock } from '../../../../../../src/core/public/mocks'; async function mountApp(basePath: string) { const container = document.createElement('div'); @@ -22,7 +24,12 @@ async function mountApp(basePath: string) { const unmount = await roleMappingsManagementApp .create({ getStartServices: coreMock.createSetup().getStartServices as any }) - .mount({ basePath, element: container, setBreadcrumbs }); + .mount({ + basePath, + element: container, + setBreadcrumbs, + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, + }); return { unmount, container, setBreadcrumbs }; } diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx index 96051dbd7fa56..850dcce278185 100644 --- a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx @@ -14,9 +14,11 @@ jest.mock('./edit_role', () => ({ EditRolePage: (props: any) => `Role Edit Page: ${JSON.stringify(props)}`, })); +import { ScopedHistory } from 'src/core/public'; + import { rolesManagementApp } from './roles_management_app'; -import { coreMock } from '../../../../../../src/core/public/mocks'; +import { coreMock, scopedHistoryMock } from '../../../../../../src/core/public/mocks'; import { featuresPluginMock } from '../../../../features/public/mocks'; async function mountApp(basePath: string) { @@ -34,7 +36,12 @@ async function mountApp(basePath: string) { .fn() .mockResolvedValue([coreMock.createStart(), { data: {}, features: featuresStart }]), }) - .mount({ basePath, element: container, setBreadcrumbs }); + .mount({ + basePath, + element: container, + setBreadcrumbs, + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, + }); return { unmount, container, setBreadcrumbs }; } diff --git a/x-pack/plugins/security/public/management/users/users_management_app.test.tsx b/x-pack/plugins/security/public/management/users/users_management_app.test.tsx index 05491d6f889b6..e05dff81a0524 100644 --- a/x-pack/plugins/security/public/management/users/users_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/users/users_management_app.test.tsx @@ -12,9 +12,11 @@ jest.mock('./edit_user', () => ({ EditUserPage: (props: any) => `User Edit Page: ${JSON.stringify(props)}`, })); +import { ScopedHistory } from 'src/core/public'; + import { usersManagementApp } from './users_management_app'; -import { coreMock } from '../../../../../../src/core/public/mocks'; +import { coreMock, scopedHistoryMock } from '../../../../../../src/core/public/mocks'; import { securityMock } from '../../mocks'; async function mountApp(basePath: string) { @@ -26,7 +28,12 @@ async function mountApp(basePath: string) { authc: securityMock.createSetup().authc, getStartServices: coreMock.createSetup().getStartServices as any, }) - .mount({ basePath, element: container, setBreadcrumbs }); + .mount({ + basePath, + element: container, + setBreadcrumbs, + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, + }); return { unmount, container, setBreadcrumbs }; } diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx index 92c78d63d1b2e..d35e31093800c 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx @@ -17,9 +17,11 @@ jest.mock('./edit_space', () => ({ }, })); +import { ScopedHistory } from 'src/core/public'; + import { spacesManagementApp } from './spaces_management_app'; -import { coreMock } from '../../../../../src/core/public/mocks'; +import { coreMock, scopedHistoryMock } from '../../../../../src/core/public/mocks'; import { securityMock } from '../../../security/public/mocks'; import { spacesManagerMock } from '../spaces_manager/mocks'; import { SecurityLicenseFeatures } from '../../../security/public'; @@ -53,7 +55,12 @@ async function mountApp(basePath: string, spaceId?: string) { securityLicense, getStartServices: async () => [coreStart, pluginsStart as PluginsStart, {}], }) - .mount({ basePath, element: container, setBreadcrumbs }); + .mount({ + basePath, + element: container, + setBreadcrumbs, + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, + }); return { unmount, container, setBreadcrumbs }; } diff --git a/x-pack/plugins/transform/public/app/app.tsx b/x-pack/plugins/transform/public/app/app.tsx index 330fb7a17f5fa..7b0c49c7a49b7 100644 --- a/x-pack/plugins/transform/public/app/app.tsx +++ b/x-pack/plugins/transform/public/app/app.tsx @@ -16,7 +16,7 @@ import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/p import { API_BASE_PATH } from '../../common/constants'; import { SectionError } from './components'; -import { CLIENT_BASE_PATH, SECTION_SLUG } from './constants'; +import { SECTION_SLUG } from './constants'; import { AuthorizationContext, AuthorizationProvider } from './lib/authorization'; import { AppDependencies } from './app_dependencies'; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx b/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx index 27aa3ba93684e..e381d2717e54a 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx +++ b/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx @@ -7,11 +7,13 @@ import React from 'react'; import { of } from 'rxjs'; import { ComponentType } from 'enzyme'; +import { ScopedHistory } from 'src/core/public'; import { docLinksServiceMock, uiSettingsServiceMock, notificationServiceMock, httpServiceMock, + scopedHistoryMock, } from '../../../../../../src/core/public/mocks'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { AppContextProvider } from '../../../public/application/app_context'; @@ -39,6 +41,7 @@ export const mockContextValue = { } as any, // For our test harness, we don't use this mocked out http service http: httpServiceMock.createSetupContract(), + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, }; export const withAppContext = (Component: ComponentType) => (props: any) => { diff --git a/x-pack/plugins/watcher/public/application/app.tsx b/x-pack/plugins/watcher/public/application/app.tsx index 5e75eff5ac949..da7ca45dd58ca 100644 --- a/x-pack/plugins/watcher/public/application/app.tsx +++ b/x-pack/plugins/watcher/public/application/app.tsx @@ -6,13 +6,7 @@ import React, { useEffect, useState } from 'react'; import { Observable } from 'rxjs'; -import { - DocLinksStart, - HttpSetup, - ToastsSetup, - IUiSettingsClient, - AppMountParameters, -} from 'kibana/public'; +import { DocLinksStart, HttpSetup, ToastsSetup, IUiSettingsClient } from 'kibana/public'; import { Router, Switch, Route, Redirect, withRouter, RouteComponentProps } from 'react-router-dom'; @@ -20,7 +14,10 @@ import { EuiCallOut, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { RegisterManagementAppArgs } from '../../../../../src/plugins/management/public'; +import { + RegisterManagementAppArgs, + ManagementAppMountParams, +} from '../../../../../src/plugins/management/public'; import { LicenseStatus } from '../../common/types/license_status'; import { WatchStatus } from './sections/watch_status/components/watch_status'; @@ -45,7 +42,7 @@ export interface AppDeps { createTimeBuckets: () => any; licenseStatus$: Observable; setBreadcrumbs: Parameters[0]['setBreadcrumbs']; - history: AppMountParameters['history']; + history: ManagementAppMountParams['history']; } export const App = (deps: AppDeps) => { @@ -79,7 +76,7 @@ export const App = (deps: AppDeps) => { ); } return ( - + From 12d6ac2bd0420950f3621ac60cdf926771622954 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Tue, 19 May 2020 18:34:40 +0300 Subject: [PATCH 05/93] Fixed routing for Ingest Node Pipelines --- .../public/application/app.tsx | 19 +++++++++++-------- .../public/application/index.tsx | 2 ++ .../application/mount_management_section.ts | 3 ++- .../sections/pipelines_list/empty_list.tsx | 2 +- .../sections/pipelines_list/table.tsx | 10 +++++++--- .../application/services/breadcrumbs.ts | 4 ++-- 6 files changed, 25 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/ingest_pipelines/public/application/app.tsx b/x-pack/plugins/ingest_pipelines/public/application/app.tsx index 98b49bafd6ed6..4b3f6d27ae8ef 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/app.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/app.tsx @@ -6,9 +6,11 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { EuiPageContent } from '@elastic/eui'; import React, { FunctionComponent } from 'react'; -import { HashRouter, Switch, Route } from 'react-router-dom'; +import { Router, Switch, Route } from 'react-router-dom'; -import { BASE_PATH, APP_CLUSTER_REQUIRED_PRIVILEGES } from '../../common/constants'; +import { useKibana } from '../shared_imports'; + +import { APP_CLUSTER_REQUIRED_PRIVILEGES } from '../../common/constants'; import { SectionError, @@ -22,10 +24,10 @@ import { PipelinesList, PipelinesCreate, PipelinesEdit, PipelinesClone } from '. export const AppWithoutRouter = () => ( - - - - + + + + {/* Catch all */} @@ -33,6 +35,7 @@ export const AppWithoutRouter = () => ( export const App: FunctionComponent = () => { const { apiError } = useAuthorizationContext(); + const { history } = useKibana().services; if (apiError) { return ( @@ -91,9 +94,9 @@ export const App: FunctionComponent = () => { } return ( - + - + ); }} diff --git a/x-pack/plugins/ingest_pipelines/public/application/index.tsx b/x-pack/plugins/ingest_pipelines/public/application/index.tsx index e43dba4689b44..a8e6febeb2e59 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/index.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/index.tsx @@ -8,6 +8,7 @@ import { HttpSetup } from 'kibana/public'; import React, { ReactNode } from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { NotificationsSetup } from 'kibana/public'; +import { ManagementAppMountParams } from 'src/plugins/management/public'; import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; import { API_BASE_PATH } from '../../common/constants'; @@ -23,6 +24,7 @@ export interface AppServices { documentation: DocumentationService; api: ApiService; notifications: NotificationsSetup; + history: ManagementAppMountParams['history']; } export interface CoreServices { diff --git a/x-pack/plugins/ingest_pipelines/public/application/mount_management_section.ts b/x-pack/plugins/ingest_pipelines/public/application/mount_management_section.ts index e36f27cbf5f62..49c8f5a7b2e1e 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/mount_management_section.ts +++ b/x-pack/plugins/ingest_pipelines/public/application/mount_management_section.ts @@ -13,7 +13,7 @@ export async function mountManagementSection( { http, getStartServices, notifications }: CoreSetup, params: ManagementAppMountParams ) { - const { element, setBreadcrumbs } = params; + const { element, setBreadcrumbs, history } = params; const [coreStart] = await getStartServices(); const { docLinks, @@ -29,6 +29,7 @@ export async function mountManagementSection( documentation: documentationService, api: apiService, notifications, + history, }; return renderApp(element, I18nContext, services, { http }); diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx index f6fe2f0cf65fa..b8d4a8006a1d0 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx @@ -41,7 +41,7 @@ export const EmptyList: FunctionComponent = () => {

} actions={ - + {i18n.translate('xpack.ingestPipelines.list.table.emptyPrompt.createButtonLabel', { defaultMessage: 'Create a pipeline', })} diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx index e5c708b5c0e53..47c505dd38d24 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx @@ -14,8 +14,8 @@ import { EuiTableFieldDataColumnType, } from '@elastic/eui'; -import { BASE_PATH } from '../../../../common/constants'; import { Pipeline } from '../../../../common/types'; +import { useKibana } from '../../../shared_imports'; export interface Props { pipelines: Pipeline[]; @@ -32,6 +32,7 @@ export const PipelineTable: FunctionComponent = ({ onClonePipelineClick, onDeletePipelineClick, }) => { + const { history } = useKibana().services; const [selection, setSelection] = useState([]); const tableProps: EuiInMemoryTableProps = { @@ -82,7 +83,7 @@ export const PipelineTable: FunctionComponent = ({ })} , = ({ }), sortable: true, render: (name: string) => ( - + {name} ), diff --git a/x-pack/plugins/ingest_pipelines/public/application/services/breadcrumbs.ts b/x-pack/plugins/ingest_pipelines/public/application/services/breadcrumbs.ts index 1ccdbbad9b1bb..9b974fdea283a 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/services/breadcrumbs.ts +++ b/x-pack/plugins/ingest_pipelines/public/application/services/breadcrumbs.ts @@ -28,7 +28,7 @@ export class BreadcrumbService { create: [ { text: homeBreadcrumbText, - href: `#${BASE_PATH}`, + href: `/`, }, { text: i18n.translate('xpack.ingestPipelines.breadcrumb.createPipelineLabel', { @@ -39,7 +39,7 @@ export class BreadcrumbService { edit: [ { text: homeBreadcrumbText, - href: `#${BASE_PATH}`, + href: `/`, }, { text: i18n.translate('xpack.ingestPipelines.breadcrumb.editPipelineLabel', { From 8890dc8a367478b530eada920c6ba12c6a64dae1 Mon Sep 17 00:00:00 2001 From: Matt Kime Date: Tue, 19 May 2020 14:13:53 -0500 Subject: [PATCH 06/93] introduce and use react router wrapped eui components --- .../index_pattern_table.tsx | 10 +-- .../eui_button_empty_react_router.tsx | 56 +++++++++++++++++ .../eui_button_react_router.tsx | 56 +++++++++++++++++ .../eui_link_react_router.tsx | 57 +++++++++++++++++ .../public/eui_link_react_router/index.ts | 22 +++++++ .../react_router_element_wrapper.tsx | 63 +++++++++++++++++++ src/plugins/kibana_react/public/index.ts | 1 + .../management_app/management_app.tsx | 1 + .../sections/pipelines_list/empty_list.tsx | 8 +-- .../sections/pipelines_list/table.tsx | 18 +++--- 10 files changed, 276 insertions(+), 16 deletions(-) create mode 100644 src/plugins/kibana_react/public/eui_link_react_router/eui_button_empty_react_router.tsx create mode 100644 src/plugins/kibana_react/public/eui_link_react_router/eui_button_react_router.tsx create mode 100644 src/plugins/kibana_react/public/eui_link_react_router/eui_link_react_router.tsx create mode 100644 src/plugins/kibana_react/public/eui_link_react_router/index.ts create mode 100644 src/plugins/kibana_react/public/eui_link_react_router/react_router_element_wrapper.tsx diff --git a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx index e2e71632a10f4..13a037aa1c492 100644 --- a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx +++ b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx @@ -19,7 +19,6 @@ import { EuiBadge, - EuiButtonEmpty, EuiButtonIcon, EuiFlexGroup, EuiFlexItem, @@ -33,6 +32,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { withRouter, RouteComponentProps } from 'react-router-dom'; import React, { useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; +import { EuiButtonEmptyReactRouter } from '../../../../kibana_react/public'; import { SavedObjectsClientContract, IUiSettingsClient, @@ -46,7 +46,7 @@ import { IndexPatternManagementStart } from '../../plugin'; import { getIndexPatterns } from '../utils'; import { getListBreadcrumbs } from '../breadcrumbs'; -const columns = (history: AppMountParameters['history']) => [ +const columns = [ { field: 'title', name: 'Pattern', @@ -60,7 +60,7 @@ const columns = (history: AppMountParameters['history']) => [ }>; } ) => ( - history.push(`/patterns/${index.id}`)}> + {name} {index.tags && index.tags.map(({ key: tagKey, name: tagName }) => ( @@ -68,7 +68,7 @@ const columns = (history: AppMountParameters['history']) => [ {tagName} ))} - + ), dataType: 'string' as const, sortable: ({ sort }: { sort: string }) => sort, @@ -197,7 +197,7 @@ export const IndexPatternTable = ({ itemId="id" isSelectable={false} items={indexPatterns} - columns={columns(history)} + columns={columns} pagination={pagination} sorting={sorting} search={search} diff --git a/src/plugins/kibana_react/public/eui_link_react_router/eui_button_empty_react_router.tsx b/src/plugins/kibana_react/public/eui_link_react_router/eui_button_empty_react_router.tsx new file mode 100644 index 0000000000000..5985a93f2821a --- /dev/null +++ b/src/plugins/kibana_react/public/eui_link_react_router/eui_button_empty_react_router.tsx @@ -0,0 +1,56 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { EuiButtonEmpty, EuiButtonEmptyProps } from '@elastic/eui'; +import { useHistory } from 'react-router-dom'; + +type EuiButtonReactRouterProps = EuiButtonEmptyProps & { + to: string; + children: React.ReactNode; +}; + +const isModifiedEvent = (event: any) => + !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); + +const isLeftClickEvent = (event: any) => event.button === 0; + +export function EuiButtonEmptyReactRouter({ to, ...props }: EuiButtonReactRouterProps) { + const history = useHistory(); + + function onClick(event: any) { + if (event.defaultPrevented) { + return; + } + + if (event.target.getAttribute('target')) { + return; + } + + if (isModifiedEvent(event) || !isLeftClickEvent(event)) { + return; + } + + // prevents page reload + event.preventDefault(); + history.push(to); + } + + return ; // eslint-disable-line +} diff --git a/src/plugins/kibana_react/public/eui_link_react_router/eui_button_react_router.tsx b/src/plugins/kibana_react/public/eui_link_react_router/eui_button_react_router.tsx new file mode 100644 index 0000000000000..000a4e2877956 --- /dev/null +++ b/src/plugins/kibana_react/public/eui_link_react_router/eui_button_react_router.tsx @@ -0,0 +1,56 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { EuiButton, EuiButtonProps } from '@elastic/eui'; +import { useHistory } from 'react-router-dom'; + +type EuiButtonReactRouterProps = EuiButtonProps & { + to: string; + children: React.ReactNode; +}; + +const isModifiedEvent = (event: any) => + !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); + +const isLeftClickEvent = (event: any) => event.button === 0; + +export function EuiButtonReactRouter({ to, ...props }: EuiButtonReactRouterProps) { + const history = useHistory(); + + function onClick(event: any) { + if (event.defaultPrevented) { + return; + } + + if (event.target.getAttribute('target')) { + return; + } + + if (isModifiedEvent(event) || !isLeftClickEvent(event)) { + return; + } + + // prevents page reload + event.preventDefault(); + history.push(to); + } + + return ; // eslint-disable-line +} diff --git a/src/plugins/kibana_react/public/eui_link_react_router/eui_link_react_router.tsx b/src/plugins/kibana_react/public/eui_link_react_router/eui_link_react_router.tsx new file mode 100644 index 0000000000000..fd569892e9243 --- /dev/null +++ b/src/plugins/kibana_react/public/eui_link_react_router/eui_link_react_router.tsx @@ -0,0 +1,57 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { EuiLink, EuiLinkAnchorProps } from '@elastic/eui'; +import { useHistory } from 'react-router-dom'; + +type EuiLinkReactRouterProps = EuiLinkAnchorProps & { + to: string | { pathname?: string; search?: string; hash?: string }; +}; + +const isModifiedEvent = (event: any) => + !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); + +const isLeftClickEvent = (event: any) => event.button === 0; + +export function EuiLinkReactRouter({ to, ...props }: EuiLinkReactRouterProps) { + const toAsObject = typeof to === 'string' ? { pathname: to } : to; + const history = useHistory(); + + function onClick(event: any) { + if (event.defaultPrevented) { + return; + } + + if (event.target.getAttribute('target')) { + return; + } + + if (isModifiedEvent(event) || !isLeftClickEvent(event)) { + return; + } + + // prevents page reload + event.preventDefault(); + + history.push(toAsObject); + } + + return ; // eslint-disable-line +} diff --git a/src/plugins/kibana_react/public/eui_link_react_router/index.ts b/src/plugins/kibana_react/public/eui_link_react_router/index.ts new file mode 100644 index 0000000000000..a8e11a82f387e --- /dev/null +++ b/src/plugins/kibana_react/public/eui_link_react_router/index.ts @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { EuiLinkReactRouter } from './eui_link_react_router'; +export { EuiButtonReactRouter } from './eui_button_react_router'; +export { EuiButtonEmptyReactRouter } from './eui_button_empty_react_router'; diff --git a/src/plugins/kibana_react/public/eui_link_react_router/react_router_element_wrapper.tsx b/src/plugins/kibana_react/public/eui_link_react_router/react_router_element_wrapper.tsx new file mode 100644 index 0000000000000..f221e7fbf2cab --- /dev/null +++ b/src/plugins/kibana_react/public/eui_link_react_router/react_router_element_wrapper.tsx @@ -0,0 +1,63 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { useHistory } from 'react-router-dom'; + +const isModifiedEvent = (event: any) => + !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); + +const isLeftClickEvent = (event: any) => event.button === 0; + +/* + * Attempt at abstracting react router wrapped eui components + */ + +export function reactRouterElementWrapper({ + Component, + to, + props, +}: { + Component: React.ComponentClass; + to: string | { pathname?: string; search?: string; hash?: string }; + props: { [key: string]: any }; +}) { + const toAsObject = typeof to === 'string' ? { pathname: to } : to; + const history = useHistory(); + + function onClick(event: any) { + if (event.defaultPrevented) { + return; + } + + if (event.target.getAttribute('target')) { + return; + } + + if (isModifiedEvent(event) || !isLeftClickEvent(event)) { + return; + } + + // prevents page reload + event.preventDefault(); + history.push(toAsObject); + } + + return ; +} diff --git a/src/plugins/kibana_react/public/index.ts b/src/plugins/kibana_react/public/index.ts index 9bec91b859ab7..b9b32988642b2 100644 --- a/src/plugins/kibana_react/public/index.ts +++ b/src/plugins/kibana_react/public/index.ts @@ -25,6 +25,7 @@ export * from './ui_settings'; export * from './field_icon'; export * from './table_list_view'; export * from './split_panel'; +export * from './eui_link_react_router'; export { ValidatedDualRange, Value } from './validated_range'; export * from './notifications'; export { Markdown, MarkdownSimple } from './markdown'; diff --git a/src/plugins/management/public/components/management_app/management_app.tsx b/src/plugins/management/public/components/management_app/management_app.tsx index 3586882bcf808..8483b95486ea3 100644 --- a/src/plugins/management/public/components/management_app/management_app.tsx +++ b/src/plugins/management/public/components/management_app/management_app.tsx @@ -49,6 +49,7 @@ export const ManagementApp = ({ context, dependencies, history }: ManagementAppP const onManagementSectionSelected = useCallback( (id: string, path: string) => { history.push(path); + window.scrollTo(0, 0); }, [history] ); diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx index b8d4a8006a1d0..f6bb5edc1ce9f 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx @@ -6,8 +6,8 @@ import React, { FunctionComponent } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiButton, EuiEmptyPrompt, EuiLink, EuiPageBody, EuiPageContent } from '@elastic/eui'; -import { BASE_PATH } from '../../../../common/constants'; +import { EuiEmptyPrompt, EuiLink, EuiPageBody, EuiPageContent } from '@elastic/eui'; +import { EuiButtonReactRouter } from '../../../../../../../src/plugins/kibana_react/public'; import { useKibana } from '../../../shared_imports'; export const EmptyList: FunctionComponent = () => { @@ -41,11 +41,11 @@ export const EmptyList: FunctionComponent = () => {

} actions={ - + {i18n.translate('xpack.ingestPipelines.list.table.emptyPrompt.createButtonLabel', { defaultMessage: 'Create a pipeline', })} - + } /> diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx index 47c505dd38d24..948496332ffd5 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx @@ -13,6 +13,10 @@ import { EuiInMemoryTableProps, EuiTableFieldDataColumnType, } from '@elastic/eui'; +import { + EuiButtonReactRouter, + EuiLinkReactRouter, +} from '../../../../../../../src/plugins/kibana_react/public'; import { Pipeline } from '../../../../common/types'; import { useKibana } from '../../../shared_imports'; @@ -82,17 +86,17 @@ export const PipelineTable: FunctionComponent = ({ defaultMessage: 'Reload', })}
, - {i18n.translate('xpack.ingestPipelines.list.table.createPipelineButtonLabel', { - defaultMessage: 'Create a pipeline', + defaultMessage: 'Create a pipeline here', })} - , + , ], box: { incremental: true, @@ -110,12 +114,12 @@ export const PipelineTable: FunctionComponent = ({ }), sortable: true, render: (name: string) => ( - {name} - + ), }, { From dbfe0e4f6f02e0605670c07ad67f5b535450e950 Mon Sep 17 00:00:00 2001 From: Matt Kime Date: Tue, 19 May 2020 14:34:47 -0500 Subject: [PATCH 07/93] react router utils --- .../react_router_element_wrapper.tsx | 63 ++++++++++++------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/src/plugins/kibana_react/public/eui_link_react_router/react_router_element_wrapper.tsx b/src/plugins/kibana_react/public/eui_link_react_router/react_router_element_wrapper.tsx index f221e7fbf2cab..8a23d836ef3ef 100644 --- a/src/plugins/kibana_react/public/eui_link_react_router/react_router_element_wrapper.tsx +++ b/src/plugins/kibana_react/public/eui_link_react_router/react_router_element_wrapper.tsx @@ -19,45 +19,62 @@ import React from 'react'; import { useHistory } from 'react-router-dom'; +import { ScopedHistory } from 'kibana/public'; const isModifiedEvent = (event: any) => !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); const isLeftClickEvent = (event: any) => event.button === 0; +export const reactRouterHrefOnClick = (to: string | LocationObject) => { + const toAsObject = typeof to === 'string' ? { pathname: to } : to; + const history = useHistory() as ScopedHistory; + + return { + href: history.createHref(toAsObject), + onClick: reactRouterOnClickHandler(history, toAsObject), + }; +}; + +export const reactRouterOnClickHandler = ( + history: ScopedHistory, + locationObject: LocationObject +) => (event: any) => { + if (event.defaultPrevented) { + return; + } + + if (event.target.getAttribute('target')) { + return; + } + + if (isModifiedEvent(event) || !isLeftClickEvent(event)) { + return; + } + + // prevents page reload + event.preventDefault(); + history.push(locationObject); +}; + /* * Attempt at abstracting react router wrapped eui components */ +interface LocationObject { + pathname?: string; + search?: string; + hash?: string; +} + export function reactRouterElementWrapper({ Component, to, props, }: { Component: React.ComponentClass; - to: string | { pathname?: string; search?: string; hash?: string }; + to: string | LocationObject; props: { [key: string]: any }; }) { - const toAsObject = typeof to === 'string' ? { pathname: to } : to; - const history = useHistory(); - - function onClick(event: any) { - if (event.defaultPrevented) { - return; - } - - if (event.target.getAttribute('target')) { - return; - } - - if (isModifiedEvent(event) || !isLeftClickEvent(event)) { - return; - } - - // prevents page reload - event.preventDefault(); - history.push(toAsObject); - } - - return ; + return ; } From 13bf37c16b228b1c4f1e6fde2382f9ccac2693fd Mon Sep 17 00:00:00 2001 From: Matt Kime Date: Tue, 19 May 2020 21:12:23 -0500 Subject: [PATCH 08/93] work in progress => hashRouter to router --- .../index_pattern_table.tsx | 15 ++--- .../eui_button_empty_react_router.tsx | 56 ------------------ .../eui_button_react_router.tsx | 56 ------------------ .../eui_link_react_router.tsx | 57 ------------------- src/plugins/kibana_react/public/index.ts | 2 +- .../index.ts | 4 +- .../react_router_navigate.tsx} | 34 +++-------- .../plugins/apm/public/application/index.tsx | 9 +-- .../app/Main/route_config/index.tsx | 7 +++ .../public/app/app.tsx | 25 +++----- .../public/app/index.tsx | 6 +- .../public/application/app.tsx | 4 +- .../public/application/index.tsx | 4 +- .../public/application/app.tsx | 22 +++---- .../public/application/app_context.tsx | 2 + .../public/application/index.tsx | 6 +- .../application/mount_management_section.ts | 5 +- .../sections/pipelines_list/empty_list.tsx | 11 ++-- .../sections/pipelines_list/table.tsx | 17 +++--- .../public/application/app_context.tsx | 4 +- .../public/application/index.tsx | 3 +- .../ml/public/application/routing/router.tsx | 6 +- .../public/application/index.d.ts | 4 +- .../public/application/index.js | 8 +-- .../plugins/remote_clusters/public/plugin.ts | 4 +- x-pack/plugins/rollup/public/crud_app/app.js | 13 ++--- .../public/application/app.tsx | 31 ++++------ .../public/application/index.tsx | 13 +++-- .../application/mount_management_section.ts | 4 +- x-pack/plugins/transform/public/app/app.tsx | 4 +- .../transform/public/app/app_dependencies.tsx | 4 +- .../watcher/public/application/app.tsx | 16 ++---- 32 files changed, 127 insertions(+), 329 deletions(-) delete mode 100644 src/plugins/kibana_react/public/eui_link_react_router/eui_button_empty_react_router.tsx delete mode 100644 src/plugins/kibana_react/public/eui_link_react_router/eui_button_react_router.tsx delete mode 100644 src/plugins/kibana_react/public/eui_link_react_router/eui_link_react_router.tsx rename src/plugins/kibana_react/public/{eui_link_react_router => react_router_navigate}/index.ts (79%) rename src/plugins/kibana_react/public/{eui_link_react_router/react_router_element_wrapper.tsx => react_router_navigate/react_router_navigate.tsx} (76%) diff --git a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx index 13a037aa1c492..3aaa1571994d5 100644 --- a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx +++ b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx @@ -19,6 +19,7 @@ import { EuiBadge, + EuiButtonEmpty, EuiButtonIcon, EuiFlexGroup, EuiFlexItem, @@ -27,12 +28,12 @@ import { EuiSpacer, EuiText, } from '@elastic/eui'; -import { AppMountParameters } from 'kibana/public'; +import { AppMountParameters, ScopedHistory } from 'kibana/public'; import { FormattedMessage } from '@kbn/i18n/react'; import { withRouter, RouteComponentProps } from 'react-router-dom'; import React, { useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiButtonEmptyReactRouter } from '../../../../kibana_react/public'; +import { reactRouterNavigate } from '../../../../kibana_react/public'; import { SavedObjectsClientContract, IUiSettingsClient, @@ -46,7 +47,7 @@ import { IndexPatternManagementStart } from '../../plugin'; import { getIndexPatterns } from '../utils'; import { getListBreadcrumbs } from '../breadcrumbs'; -const columns = [ +const columns = (history: ScopedHistory) => [ { field: 'title', name: 'Pattern', @@ -60,7 +61,7 @@ const columns = [ }>; } ) => ( - + {name} {index.tags && index.tags.map(({ key: tagKey, name: tagName }) => ( @@ -68,7 +69,7 @@ const columns = [ {tagName} ))} - +
), dataType: 'string' as const, sortable: ({ sort }: { sort: string }) => sort, @@ -107,7 +108,7 @@ const title = i18n.translate('indexPatternManagement.indexPatternTable.title', { interface Props extends RouteComponentProps { getIndexPatternCreationOptions: IndexPatternManagementStart['creation']['getIndexPatternCreationOptions']; canSave: boolean; - history: AppMountParameters['history']; + history: ScopedHistory; services: { savedObjectsClient: SavedObjectsClientContract; uiSettings: IUiSettingsClient; @@ -197,7 +198,7 @@ export const IndexPatternTable = ({ itemId="id" isSelectable={false} items={indexPatterns} - columns={columns} + columns={columns(history)} pagination={pagination} sorting={sorting} search={search} diff --git a/src/plugins/kibana_react/public/eui_link_react_router/eui_button_empty_react_router.tsx b/src/plugins/kibana_react/public/eui_link_react_router/eui_button_empty_react_router.tsx deleted file mode 100644 index 5985a93f2821a..0000000000000 --- a/src/plugins/kibana_react/public/eui_link_react_router/eui_button_empty_react_router.tsx +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { EuiButtonEmpty, EuiButtonEmptyProps } from '@elastic/eui'; -import { useHistory } from 'react-router-dom'; - -type EuiButtonReactRouterProps = EuiButtonEmptyProps & { - to: string; - children: React.ReactNode; -}; - -const isModifiedEvent = (event: any) => - !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); - -const isLeftClickEvent = (event: any) => event.button === 0; - -export function EuiButtonEmptyReactRouter({ to, ...props }: EuiButtonReactRouterProps) { - const history = useHistory(); - - function onClick(event: any) { - if (event.defaultPrevented) { - return; - } - - if (event.target.getAttribute('target')) { - return; - } - - if (isModifiedEvent(event) || !isLeftClickEvent(event)) { - return; - } - - // prevents page reload - event.preventDefault(); - history.push(to); - } - - return ; // eslint-disable-line -} diff --git a/src/plugins/kibana_react/public/eui_link_react_router/eui_button_react_router.tsx b/src/plugins/kibana_react/public/eui_link_react_router/eui_button_react_router.tsx deleted file mode 100644 index 000a4e2877956..0000000000000 --- a/src/plugins/kibana_react/public/eui_link_react_router/eui_button_react_router.tsx +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { EuiButton, EuiButtonProps } from '@elastic/eui'; -import { useHistory } from 'react-router-dom'; - -type EuiButtonReactRouterProps = EuiButtonProps & { - to: string; - children: React.ReactNode; -}; - -const isModifiedEvent = (event: any) => - !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); - -const isLeftClickEvent = (event: any) => event.button === 0; - -export function EuiButtonReactRouter({ to, ...props }: EuiButtonReactRouterProps) { - const history = useHistory(); - - function onClick(event: any) { - if (event.defaultPrevented) { - return; - } - - if (event.target.getAttribute('target')) { - return; - } - - if (isModifiedEvent(event) || !isLeftClickEvent(event)) { - return; - } - - // prevents page reload - event.preventDefault(); - history.push(to); - } - - return ; // eslint-disable-line -} diff --git a/src/plugins/kibana_react/public/eui_link_react_router/eui_link_react_router.tsx b/src/plugins/kibana_react/public/eui_link_react_router/eui_link_react_router.tsx deleted file mode 100644 index fd569892e9243..0000000000000 --- a/src/plugins/kibana_react/public/eui_link_react_router/eui_link_react_router.tsx +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { EuiLink, EuiLinkAnchorProps } from '@elastic/eui'; -import { useHistory } from 'react-router-dom'; - -type EuiLinkReactRouterProps = EuiLinkAnchorProps & { - to: string | { pathname?: string; search?: string; hash?: string }; -}; - -const isModifiedEvent = (event: any) => - !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); - -const isLeftClickEvent = (event: any) => event.button === 0; - -export function EuiLinkReactRouter({ to, ...props }: EuiLinkReactRouterProps) { - const toAsObject = typeof to === 'string' ? { pathname: to } : to; - const history = useHistory(); - - function onClick(event: any) { - if (event.defaultPrevented) { - return; - } - - if (event.target.getAttribute('target')) { - return; - } - - if (isModifiedEvent(event) || !isLeftClickEvent(event)) { - return; - } - - // prevents page reload - event.preventDefault(); - - history.push(toAsObject); - } - - return ; // eslint-disable-line -} diff --git a/src/plugins/kibana_react/public/index.ts b/src/plugins/kibana_react/public/index.ts index b9b32988642b2..c7fd734a56cec 100644 --- a/src/plugins/kibana_react/public/index.ts +++ b/src/plugins/kibana_react/public/index.ts @@ -25,7 +25,7 @@ export * from './ui_settings'; export * from './field_icon'; export * from './table_list_view'; export * from './split_panel'; -export * from './eui_link_react_router'; +export * from './react_router_navigate'; export { ValidatedDualRange, Value } from './validated_range'; export * from './notifications'; export { Markdown, MarkdownSimple } from './markdown'; diff --git a/src/plugins/kibana_react/public/eui_link_react_router/index.ts b/src/plugins/kibana_react/public/react_router_navigate/index.ts similarity index 79% rename from src/plugins/kibana_react/public/eui_link_react_router/index.ts rename to src/plugins/kibana_react/public/react_router_navigate/index.ts index a8e11a82f387e..b00cc30ab031f 100644 --- a/src/plugins/kibana_react/public/eui_link_react_router/index.ts +++ b/src/plugins/kibana_react/public/react_router_navigate/index.ts @@ -17,6 +17,4 @@ * under the License. */ -export { EuiLinkReactRouter } from './eui_link_react_router'; -export { EuiButtonReactRouter } from './eui_button_react_router'; -export { EuiButtonEmptyReactRouter } from './eui_button_empty_react_router'; +export { reactRouterNavigate, reactRouterOnClickHandler } from './react_router_navigate'; diff --git a/src/plugins/kibana_react/public/eui_link_react_router/react_router_element_wrapper.tsx b/src/plugins/kibana_react/public/react_router_navigate/react_router_navigate.tsx similarity index 76% rename from src/plugins/kibana_react/public/eui_link_react_router/react_router_element_wrapper.tsx rename to src/plugins/kibana_react/public/react_router_navigate/react_router_navigate.tsx index 8a23d836ef3ef..448f3ebb74299 100644 --- a/src/plugins/kibana_react/public/eui_link_react_router/react_router_element_wrapper.tsx +++ b/src/plugins/kibana_react/public/react_router_navigate/react_router_navigate.tsx @@ -17,19 +17,21 @@ * under the License. */ -import React from 'react'; -import { useHistory } from 'react-router-dom'; import { ScopedHistory } from 'kibana/public'; +interface LocationObject { + pathname?: string; + search?: string; + hash?: string; +} + const isModifiedEvent = (event: any) => !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); const isLeftClickEvent = (event: any) => event.button === 0; -export const reactRouterHrefOnClick = (to: string | LocationObject) => { +export const reactRouterNavigate = (history: ScopedHistory, to: string | LocationObject) => { const toAsObject = typeof to === 'string' ? { pathname: to } : to; - const history = useHistory() as ScopedHistory; - return { href: history.createHref(toAsObject), onClick: reactRouterOnClickHandler(history, toAsObject), @@ -56,25 +58,3 @@ export const reactRouterOnClickHandler = ( event.preventDefault(); history.push(locationObject); }; - -/* - * Attempt at abstracting react router wrapped eui components - */ - -interface LocationObject { - pathname?: string; - search?: string; - hash?: string; -} - -export function reactRouterElementWrapper({ - Component, - to, - props, -}: { - Component: React.ComponentClass; - to: string | LocationObject; - props: { [key: string]: any }; -}) { - return ; -} diff --git a/x-pack/plugins/apm/public/application/index.tsx b/x-pack/plugins/apm/public/application/index.tsx index 6c1c3d3262a0e..4bca2c9140f91 100644 --- a/x-pack/plugins/apm/public/application/index.tsx +++ b/x-pack/plugins/apm/public/application/index.tsx @@ -9,6 +9,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { Route, Router, Switch } from 'react-router-dom'; import styled from 'styled-components'; +import { ScopedHistory } from 'kibana/public'; import { CoreStart, AppMountParameters } from '../../../../../src/core/public'; import { ApmPluginSetupDeps } from '../plugin'; import { ApmPluginContext } from '../context/ApmPluginContext'; @@ -24,7 +25,7 @@ import { UpdateBreadcrumbs } from '../components/app/Main/UpdateBreadcrumbs'; import { APMIndicesPermission } from '../components/app/APMIndicesPermission'; import { ScrollToTopOnPathChange } from '../components/app/Main/ScrollToTopOnPathChange'; import { routes } from '../components/app/Main/route_config'; -import { history, resetHistory } from '../utils/history'; +// import { history, resetHistory } from '../utils/history'; import { ConfigSchema } from '..'; import 'react-vis/dist/style.css'; @@ -58,7 +59,7 @@ const ApmAppRoot = ({ }: { core: CoreStart; deps: ApmPluginSetupDeps; - routerHistory: typeof history; + routerHistory: ScopedHistory; config: ConfigSchema; }) => { const i18nCore = core.i18n; @@ -108,10 +109,10 @@ const ApmAppRoot = ({ export const renderApp = ( core: CoreStart, deps: ApmPluginSetupDeps, - { element }: AppMountParameters, + { element, history }: AppMountParameters, config: ConfigSchema ) => { - resetHistory(); + // resetHistory(); ReactDOM.render( { }; export const routes: BreadcrumbRoute[] = [ + { + exact: true, + path: '', + render: renderAsRedirectTo('/services'), + breadcrumb: 'APM', + name: RouteName.HOME + }, { exact: true, path: '/', diff --git a/x-pack/plugins/cross_cluster_replication/public/app/app.tsx b/x-pack/plugins/cross_cluster_replication/public/app/app.tsx index ec349ccd6f2c7..48531e212b2f5 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/app.tsx +++ b/x-pack/plugins/cross_cluster_replication/public/app/app.tsx @@ -191,24 +191,13 @@ class AppComponent extends Component { return (
- - - - - - + + + + + + +
); diff --git a/x-pack/plugins/cross_cluster_replication/public/app/index.tsx b/x-pack/plugins/cross_cluster_replication/public/app/index.tsx index d4a74aefb1571..79bef6d7aeaea 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/index.tsx +++ b/x-pack/plugins/cross_cluster_replication/public/app/index.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { Provider } from 'react-redux'; import { Router } from 'react-router-dom'; -import { I18nStart, AppMountParameters } from 'kibana/public'; +import { I18nStart, ScopedHistory } from 'kibana/public'; import { UnmountCallback } from 'src/core/public'; import { init as initBreadcrumbs, SetBreadcrumbs } from './services/breadcrumbs'; @@ -18,7 +18,7 @@ import { ccrStore } from './store'; const renderApp = ( element: Element, I18nContext: I18nStart['Context'], - history: AppMountParameters['history'] + history: ScopedHistory ): UnmountCallback => { render( @@ -47,7 +47,7 @@ export async function mountApp({ I18nContext: I18nStart['Context']; ELASTIC_WEBSITE_URL: string; DOC_LINK_VERSION: string; - history: AppMountParameters['history']; + history: ScopedHistory; }): Promise { // Import and initialize additional services here instead of in plugin.ts to reduce the size of the // initial bundle as much as possible. diff --git a/x-pack/plugins/index_lifecycle_management/public/application/app.tsx b/x-pack/plugins/index_lifecycle_management/public/application/app.tsx index dff21fb6d796d..0358a5f67cd8b 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/app.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/app.tsx @@ -6,7 +6,7 @@ import React, { useEffect } from 'react'; import { Router, Switch, Route, Redirect } from 'react-router-dom'; -import { AppMountParameters } from 'kibana/public'; +import { ScopedHistory } from 'kibana/public'; import { METRIC_TYPE } from '@kbn/analytics'; import { UIM_APP_LOAD } from './constants'; @@ -14,7 +14,7 @@ import { EditPolicy } from './sections/edit_policy'; import { PolicyTable } from './sections/policy_table'; import { trackUiMetric } from './services/ui_metric'; -export const App = ({ history }: { history: AppMountParameters['history'] }) => { +export const App = ({ history }: { history: ScopedHistory }) => { useEffect(() => trackUiMetric(METRIC_TYPE.LOADED, UIM_APP_LOAD), []); return ( diff --git a/x-pack/plugins/index_lifecycle_management/public/application/index.tsx b/x-pack/plugins/index_lifecycle_management/public/application/index.tsx index 9d9120398810b..b0a7101a236db 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/index.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/index.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { Provider } from 'react-redux'; -import { I18nStart, AppMountParameters } from 'kibana/public'; +import { I18nStart, ScopedHistory } from 'kibana/public'; import { UnmountCallback } from 'src/core/public'; import { App } from './app'; @@ -16,7 +16,7 @@ import { indexLifecycleManagementStore } from './store'; export const renderApp = ( element: Element, I18nContext: I18nStart['Context'], - history: AppMountParameters['history'] + history: ScopedHistory ): UnmountCallback => { render( diff --git a/x-pack/plugins/index_management/public/application/app.tsx b/x-pack/plugins/index_management/public/application/app.tsx index 83997dd6ece18..9cccedd7f50b3 100644 --- a/x-pack/plugins/index_management/public/application/app.tsx +++ b/x-pack/plugins/index_management/public/application/app.tsx @@ -5,8 +5,9 @@ */ import React, { useEffect } from 'react'; -import { HashRouter, Switch, Route, Redirect } from 'react-router-dom'; -import { BASE_PATH, UIM_APP_LOAD } from '../../common/constants'; +import { Router, Switch, Route, Redirect } from 'react-router-dom'; +import { ScopedHistory } from 'kibana/public'; +import { UIM_APP_LOAD } from '../../common/constants'; import { IndexManagementHome } from './sections/home'; import { TemplateCreate } from './sections/template_create'; import { TemplateClone } from './sections/template_clone'; @@ -14,24 +15,25 @@ import { TemplateEdit } from './sections/template_edit'; import { useServices } from './app_context'; -export const App = () => { +export const App = ({ history }: { history: ScopedHistory }) => { const { uiMetricService } = useServices(); useEffect(() => uiMetricService.trackMetric('loaded', UIM_APP_LOAD), [uiMetricService]); + console.log('3 - app'); return ( - + - +
); }; // Export this so we can test it with a different router. export const AppWithoutRouter = () => ( - - - - - + + + + + ); diff --git a/x-pack/plugins/index_management/public/application/app_context.tsx b/x-pack/plugins/index_management/public/application/app_context.tsx index 2bb618ad8efce..ad934c18c18e3 100644 --- a/x-pack/plugins/index_management/public/application/app_context.tsx +++ b/x-pack/plugins/index_management/public/application/app_context.tsx @@ -5,6 +5,7 @@ */ import React, { createContext, useContext } from 'react'; +import { ScopedHistory } from 'kibana/public'; import { CoreStart } from '../../../../../src/core/public'; import { UsageCollectionSetup } from '../../../../../src/plugins/usage_collection/public'; @@ -27,6 +28,7 @@ export interface AppDependencies { httpService: HttpService; notificationService: NotificationService; }; + history: ScopedHistory; } export const AppContextProvider = ({ diff --git a/x-pack/plugins/index_management/public/application/index.tsx b/x-pack/plugins/index_management/public/application/index.tsx index 5850cb8d42f1a..a9343552759b7 100644 --- a/x-pack/plugins/index_management/public/application/index.tsx +++ b/x-pack/plugins/index_management/public/application/index.tsx @@ -24,13 +24,13 @@ export const renderApp = ( const { i18n } = core; const { Context: I18nContext } = i18n; - const { services } = dependencies; - + const { services, history } = dependencies; + console.log('2 before render', history); render( - + , diff --git a/x-pack/plugins/index_management/public/application/mount_management_section.ts b/x-pack/plugins/index_management/public/application/mount_management_section.ts index c47b0603dc1c8..a432ccc190400 100644 --- a/x-pack/plugins/index_management/public/application/mount_management_section.ts +++ b/x-pack/plugins/index_management/public/application/mount_management_section.ts @@ -30,13 +30,13 @@ export async function mountManagementSection( services: InternalServices, params: ManagementAppMountParams ) { - const { element, setBreadcrumbs } = params; + const { element, setBreadcrumbs, history } = params; const [core] = await coreSetup.getStartServices(); const { docLinks, fatalErrors } = core; breadcrumbService.setup(setBreadcrumbs); documentationService.setup(docLinks); - + console.log('1 before render app', history); const appDependencies: AppDependencies = { core: { fatalErrors, @@ -45,6 +45,7 @@ export async function mountManagementSection( usageCollection, }, services, + history, }; return renderApp(element, { core, dependencies: appDependencies }); diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx index f6bb5edc1ce9f..eba69ff454911 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx @@ -6,12 +6,15 @@ import React, { FunctionComponent } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiEmptyPrompt, EuiLink, EuiPageBody, EuiPageContent } from '@elastic/eui'; -import { EuiButtonReactRouter } from '../../../../../../../src/plugins/kibana_react/public'; +import { EuiEmptyPrompt, EuiLink, EuiPageBody, EuiPageContent, EuiButton } from '@elastic/eui'; +import { useHistory } from 'react-router-dom'; +import { ScopedHistory } from 'kibana/public'; +import { reactRouterNavigate } from '../../../../../../../src/plugins/kibana_react/public'; import { useKibana } from '../../../shared_imports'; export const EmptyList: FunctionComponent = () => { const { services } = useKibana(); + const history = useHistory() as ScopedHistory; return ( @@ -41,11 +44,11 @@ export const EmptyList: FunctionComponent = () => {

} actions={ - + {i18n.translate('xpack.ingestPipelines.list.table.emptyPrompt.createButtonLabel', { defaultMessage: 'Create a pipeline', })} - + } /> diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx index 948496332ffd5..5b426f17e0e8c 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx @@ -13,10 +13,7 @@ import { EuiInMemoryTableProps, EuiTableFieldDataColumnType, } from '@elastic/eui'; -import { - EuiButtonReactRouter, - EuiLinkReactRouter, -} from '../../../../../../../src/plugins/kibana_react/public'; +import { reactRouterNavigate } from '../../../../../../../src/plugins/kibana_react/public'; import { Pipeline } from '../../../../common/types'; import { useKibana } from '../../../shared_imports'; @@ -86,17 +83,17 @@ export const PipelineTable: FunctionComponent = ({ defaultMessage: 'Reload', })} , - {i18n.translate('xpack.ingestPipelines.list.table.createPipelineButtonLabel', { defaultMessage: 'Create a pipeline here', })} - , + , ], box: { incremental: true, @@ -114,12 +111,12 @@ export const PipelineTable: FunctionComponent = ({ }), sortable: true, render: (name: string) => ( - {name} - + ), }, { diff --git a/x-pack/plugins/license_management/public/application/app_context.tsx b/x-pack/plugins/license_management/public/application/app_context.tsx index 28fa16641a369..39e7ef5f16e79 100644 --- a/x-pack/plugins/license_management/public/application/app_context.tsx +++ b/x-pack/plugins/license_management/public/application/app_context.tsx @@ -5,7 +5,7 @@ */ import React, { createContext, useContext } from 'react'; -import { AppMountParameters } from 'kibana/public'; +import { ScopedHistory } from 'kibana/public'; import { CoreStart } from '../../../../../src/core/public'; import { LicensingPluginSetup, ILicense } from '../../../licensing/public'; @@ -19,7 +19,7 @@ export interface AppDependencies { core: CoreStart; services: { breadcrumbService: BreadcrumbService; - history: AppMountParameters['history']; + history: ScopedHistory; }; plugins: { licensing: LicensingPluginSetup; diff --git a/x-pack/plugins/license_management/public/application/index.tsx b/x-pack/plugins/license_management/public/application/index.tsx index 84f3067a528ea..cca164b14b8b8 100644 --- a/x-pack/plugins/license_management/public/application/index.tsx +++ b/x-pack/plugins/license_management/public/application/index.tsx @@ -7,7 +7,6 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { Router } from 'react-router-dom'; -import { AppMountParameters } from 'kibana/public'; import { AppDependencies } from './app_context'; import { AppProviders } from './app_providers'; @@ -15,7 +14,7 @@ import { AppProviders } from './app_providers'; import { App } from './app.container'; const AppWithRouter = (props: { [key: string]: any }) => ( - + ); diff --git a/x-pack/plugins/ml/public/application/routing/router.tsx b/x-pack/plugins/ml/public/application/routing/router.tsx index f4d6fec5e6ee3..540265c1a0a05 100644 --- a/x-pack/plugins/ml/public/application/routing/router.tsx +++ b/x-pack/plugins/ml/public/application/routing/router.tsx @@ -5,7 +5,7 @@ */ import React, { FC } from 'react'; -import { HashRouter, Route, RouteProps } from 'react-router-dom'; +import { Router, Route, RouteProps } from 'react-router-dom'; import { Location } from 'history'; import { IUiSettingsClient, ChromeStart } from 'kibana/public'; @@ -47,7 +47,7 @@ export const MlRouter: FC<{ pageDeps: PageDependencies }> = ({ pageDeps }) => { const setBreadcrumbs = pageDeps.setBreadcrumbs; return ( - +
{Object.entries(routes).map(([name, route]) => ( = ({ pageDeps }) => { /> ))}
-
+
); }; diff --git a/x-pack/plugins/remote_clusters/public/application/index.d.ts b/x-pack/plugins/remote_clusters/public/application/index.d.ts index b021dca51bacd..8b2af65e4fff7 100644 --- a/x-pack/plugins/remote_clusters/public/application/index.d.ts +++ b/x-pack/plugins/remote_clusters/public/application/index.d.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { ScopedHistory } from 'kibana/public'; import { RegisterManagementAppArgs, I18nStart } from '../types'; export declare const renderApp: ( @@ -11,5 +12,6 @@ export declare const renderApp: ( I18nContext: I18nStart['Context'], appDependencies: { isCloudEnabled?: boolean; - } + }, + history: ScopedHistory ) => ReturnType; diff --git a/x-pack/plugins/remote_clusters/public/application/index.js b/x-pack/plugins/remote_clusters/public/application/index.js index cf6e855ba58df..5881e886c7384 100644 --- a/x-pack/plugins/remote_clusters/public/application/index.js +++ b/x-pack/plugins/remote_clusters/public/application/index.js @@ -6,7 +6,7 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { HashRouter } from 'react-router-dom'; +import { Router } from 'react-router-dom'; import { Provider } from 'react-redux'; import { App } from './app'; @@ -15,14 +15,14 @@ import { AppContextProvider } from './app_context'; import './_hacks.scss'; -export const renderApp = (elem, I18nContext, appDependencies) => { +export const renderApp = (elem, I18nContext, appDependencies, history) => { render( - + - +
, diff --git a/x-pack/plugins/remote_clusters/public/plugin.ts b/x-pack/plugins/remote_clusters/public/plugin.ts index fde8ffa511319..8881db0f9196e 100644 --- a/x-pack/plugins/remote_clusters/public/plugin.ts +++ b/x-pack/plugins/remote_clusters/public/plugin.ts @@ -41,7 +41,7 @@ export class RemoteClustersUIPlugin defaultMessage: 'Remote Clusters', }), order: 7, - mount: async ({ element, setBreadcrumbs }) => { + mount: async ({ element, setBreadcrumbs, history }) => { const [core] = await getStartServices(); const { i18n: { Context: i18nContext }, @@ -59,7 +59,7 @@ export class RemoteClustersUIPlugin const isCloudEnabled = Boolean(cloud?.isCloudEnabled); const { renderApp } = await import('./application'); - return renderApp(element, i18nContext, { isCloudEnabled }); + return renderApp(element, i18nContext, { isCloudEnabled }, history); }, }); } diff --git a/x-pack/plugins/rollup/public/crud_app/app.js b/x-pack/plugins/rollup/public/crud_app/app.js index 0ef3253eeb94e..4eff849776aef 100644 --- a/x-pack/plugins/rollup/public/crud_app/app.js +++ b/x-pack/plugins/rollup/public/crud_app/app.js @@ -6,10 +6,9 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { HashRouter, Switch, Route, Redirect, withRouter } from 'react-router-dom'; +import { Router, Switch, Route, Redirect, withRouter } from 'react-router-dom'; import { UIM_APP_LOAD } from '../../common'; -import { CRUD_APP_BASE_PATH } from './constants'; import { registerRouter, setUserHasLeftApp, METRIC_TYPE } from './services'; import { trackUiMetric } from '../kibana_services'; import { JobList, JobCreate } from './sections'; @@ -53,15 +52,15 @@ export class App extends Component { render() { return ( - + - - - + + + - +
); } } diff --git a/x-pack/plugins/snapshot_restore/public/application/app.tsx b/x-pack/plugins/snapshot_restore/public/application/app.tsx index 350d8aec711ed..04f5b1a3c78aa 100644 --- a/x-pack/plugins/snapshot_restore/public/application/app.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/app.tsx @@ -17,7 +17,7 @@ import { NotAuthorizedSection, } from '../shared_imports'; import { SectionLoading } from './components'; -import { BASE_PATH, DEFAULT_SECTION, Section } from './constants'; +import { DEFAULT_SECTION, Section } from './constants'; import { RepositoryAdd, RepositoryEdit, @@ -63,34 +63,23 @@ export const App: React.FunctionComponent = () => { ) : hasPrivileges ? (
- + + - - + - {slmUi.enabled && ( - - )} - {slmUi.enabled && ( - - )} - + {slmUi.enabled && } + {slmUi.enabled && } + +
) : ( diff --git a/x-pack/plugins/snapshot_restore/public/application/index.tsx b/x-pack/plugins/snapshot_restore/public/application/index.tsx index 220efd82859d2..49881ee4f3259 100644 --- a/x-pack/plugins/snapshot_restore/public/application/index.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/index.tsx @@ -6,22 +6,23 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { HashRouter } from 'react-router-dom'; +import { Router } from 'react-router-dom'; +import { ScopedHistory } from 'kibana/public'; import { App } from './app'; import { AppProviders } from './app_providers'; import { AppDependencies } from './app_context'; -const AppWithRouter = () => ( - +const AppWithRouter = ({ history }: { history: ScopedHistory }) => ( + - +
); -export const renderApp = (elem: Element, dependencies: AppDependencies) => { +export const renderApp = (elem: Element, dependencies: AppDependencies, history: ScopedHistory) => { render( - + , elem ); diff --git a/x-pack/plugins/snapshot_restore/public/application/mount_management_section.ts b/x-pack/plugins/snapshot_restore/public/application/mount_management_section.ts index 9697e24a7147e..87a9170307ea6 100644 --- a/x-pack/plugins/snapshot_restore/public/application/mount_management_section.ts +++ b/x-pack/plugins/snapshot_restore/public/application/mount_management_section.ts @@ -23,7 +23,7 @@ export async function mountManagementSection( config: ClientConfigType, params: ManagementAppMountParams ) { - const { element, setBreadcrumbs } = params; + const { element, setBreadcrumbs, history } = params; const [core] = await coreSetup.getStartServices(); const { docLinks, @@ -44,5 +44,5 @@ export async function mountManagementSection( }, }; - return renderApp(element, appDependencies); + return renderApp(element, appDependencies, history); } diff --git a/x-pack/plugins/transform/public/app/app.tsx b/x-pack/plugins/transform/public/app/app.tsx index 7b0c49c7a49b7..c9a8cb3f8539c 100644 --- a/x-pack/plugins/transform/public/app/app.tsx +++ b/x-pack/plugins/transform/public/app/app.tsx @@ -7,7 +7,7 @@ import React, { useContext, FC } from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { Router, Redirect, Route, Switch } from 'react-router-dom'; -import { AppMountParameters } from 'kibana/public'; +import { ScopedHistory } from 'kibana/public'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -24,7 +24,7 @@ import { CloneTransformSection } from './sections/clone_transform'; import { CreateTransformSection } from './sections/create_transform'; import { TransformManagementSection } from './sections/transform_management'; -export const App: FC<{ history: AppMountParameters['history'] }> = ({ history }) => { +export const App: FC<{ history: ScopedHistory }> = ({ history }) => { const { apiError } = useContext(AuthorizationContext); if (apiError !== null) { return ( diff --git a/x-pack/plugins/transform/public/app/app_dependencies.tsx b/x-pack/plugins/transform/public/app/app_dependencies.tsx index 586381fd3b2b5..704875330fdd2 100644 --- a/x-pack/plugins/transform/public/app/app_dependencies.tsx +++ b/x-pack/plugins/transform/public/app/app_dependencies.tsx @@ -6,7 +6,7 @@ import { CoreSetup, CoreStart } from 'src/core/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; -import { AppMountParameters } from 'kibana/public'; +import { ScopedHistory } from 'kibana/public'; import { useKibana } from '../../../../../src/plugins/kibana_react/public'; import { Storage } from '../../../../../src/plugins/kibana_utils/public'; @@ -22,7 +22,7 @@ export interface AppDependencies { savedObjects: CoreStart['savedObjects']; storage: Storage; overlays: CoreStart['overlays']; - history: AppMountParameters['history']; + history: ScopedHistory; } export const useAppDependencies = () => { diff --git a/x-pack/plugins/watcher/public/application/app.tsx b/x-pack/plugins/watcher/public/application/app.tsx index da7ca45dd58ca..ca4371045c45d 100644 --- a/x-pack/plugins/watcher/public/application/app.tsx +++ b/x-pack/plugins/watcher/public/application/app.tsx @@ -24,7 +24,6 @@ import { WatchStatus } from './sections/watch_status/components/watch_status'; import { WatchEdit } from './sections/watch_edit/components/watch_edit'; import { WatchList } from './sections/watch_list/components/watch_list'; import { registerRouter } from './lib/navigation'; -import { BASE_PATH } from './constants'; import { AppContextProvider } from './app_context'; import { ChartsPluginSetup } from '../../../../../src/plugins/charts/public'; @@ -89,14 +88,11 @@ export const App = (deps: AppDeps) => { // Export this so we can test it with a different router. export const AppWithoutRouter = () => ( - - - - - + + + + + + ); From beaaa70d0f92e6ae41a070da8943562e0b62b5b1 Mon Sep 17 00:00:00 2001 From: Matt Kime Date: Tue, 19 May 2020 22:37:17 -0500 Subject: [PATCH 09/93] more partial progress --- .../index_pattern_table.tsx | 2 +- .../react_router_navigate.tsx | 23 +++++++++---------- .../plugins/apm/public/application/index.tsx | 1 - .../public/app/app.tsx | 1 - .../public/application/app.tsx | 1 - .../public/application/sections/home/home.tsx | 9 ++++---- .../home/template_list/template_list.tsx | 2 ++ .../template_table/template_table.tsx | 8 +++++-- .../public/application/services/navigation.ts | 9 +++----- .../public/application/services/routing.ts | 11 ++++----- .../application/services/breadcrumbs.ts | 1 - x-pack/plugins/ml/public/application/app.tsx | 11 ++++++--- .../ml/public/application/routing/router.tsx | 3 ++- .../remote_clusters/public/application/app.js | 13 ++++++----- 14 files changed, 48 insertions(+), 47 deletions(-) diff --git a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx index 3aaa1571994d5..baf9e32ba85db 100644 --- a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx +++ b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx @@ -28,7 +28,7 @@ import { EuiSpacer, EuiText, } from '@elastic/eui'; -import { AppMountParameters, ScopedHistory } from 'kibana/public'; +import { ScopedHistory } from 'kibana/public'; import { FormattedMessage } from '@kbn/i18n/react'; import { withRouter, RouteComponentProps } from 'react-router-dom'; import React, { useState, useEffect } from 'react'; diff --git a/src/plugins/kibana_react/public/react_router_navigate/react_router_navigate.tsx b/src/plugins/kibana_react/public/react_router_navigate/react_router_navigate.tsx index 448f3ebb74299..2de3c569dd6cd 100644 --- a/src/plugins/kibana_react/public/react_router_navigate/react_router_navigate.tsx +++ b/src/plugins/kibana_react/public/react_router_navigate/react_router_navigate.tsx @@ -30,18 +30,17 @@ const isModifiedEvent = (event: any) => const isLeftClickEvent = (event: any) => event.button === 0; -export const reactRouterNavigate = (history: ScopedHistory, to: string | LocationObject) => { - const toAsObject = typeof to === 'string' ? { pathname: to } : to; - return { - href: history.createHref(toAsObject), - onClick: reactRouterOnClickHandler(history, toAsObject), - }; -}; +export const toLocationObject = (to: string | LocationObject) => + typeof to === 'string' ? { pathname: to } : to; + +export const reactRouterNavigate = (history: ScopedHistory, to: string | LocationObject) => ({ + href: history.createHref(toLocationObject(to)), + onClick: reactRouterOnClickHandler(history, toLocationObject(to)), +}); -export const reactRouterOnClickHandler = ( - history: ScopedHistory, - locationObject: LocationObject -) => (event: any) => { +export const reactRouterOnClickHandler = (history: ScopedHistory, to: string | LocationObject) => ( + event: any +) => { if (event.defaultPrevented) { return; } @@ -56,5 +55,5 @@ export const reactRouterOnClickHandler = ( // prevents page reload event.preventDefault(); - history.push(locationObject); + history.push(toLocationObject(to)); }; diff --git a/x-pack/plugins/apm/public/application/index.tsx b/x-pack/plugins/apm/public/application/index.tsx index 4bca2c9140f91..0361d4eea27f3 100644 --- a/x-pack/plugins/apm/public/application/index.tsx +++ b/x-pack/plugins/apm/public/application/index.tsx @@ -112,7 +112,6 @@ export const renderApp = ( { element, history }: AppMountParameters, config: ConfigSchema ) => { - // resetHistory(); ReactDOM.render( { const { uiMetricService } = useServices(); useEffect(() => uiMetricService.trackMetric('loaded', UIM_APP_LOAD), [uiMetricService]); - console.log('3 - app'); return ( diff --git a/x-pack/plugins/index_management/public/application/sections/home/home.tsx b/x-pack/plugins/index_management/public/application/sections/home/home.tsx index 5d8e32031ea10..3310b4a4291d4 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/home.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/home.tsx @@ -18,7 +18,6 @@ import { EuiTabs, EuiTitle, } from '@elastic/eui'; -import { BASE_PATH } from '../../../../common/constants'; import { documentationService } from '../../services/documentation'; import { IndexList } from './index_list'; import { TemplateList } from './template_list'; @@ -53,7 +52,7 @@ export const IndexManagementHome: React.FunctionComponent { - history.push(`${BASE_PATH}${newSection}`); + history.push(`/${newSection}`); }; useEffect(() => { @@ -107,9 +106,9 @@ export const IndexManagementHome: React.FunctionComponent - - - + + + diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx index 1e84202639ee8..0d75defa674d0 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx @@ -7,6 +7,7 @@ import React, { Fragment, useState, useEffect, useMemo } from 'react'; import { RouteComponentProps } from 'react-router-dom'; import { FormattedMessage } from '@kbn/i18n/react'; +import { ScopedHistory } from 'kibana/public'; import { EuiEmptyPrompt, EuiSpacer, @@ -144,6 +145,7 @@ export const TemplateList: React.FunctionComponent ); diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx index ef583a5a1fdf2..a1f89f957656c 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx @@ -8,18 +8,21 @@ import React, { useState, Fragment } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiInMemoryTable, EuiIcon, EuiButton, EuiLink, EuiBasicTableColumn } from '@elastic/eui'; +import { ScopedHistory } from 'kibana/public'; import { TemplateListItem, IndexTemplateFormatVersion } from '../../../../../../common'; -import { BASE_PATH, UIM_TEMPLATE_SHOW_DETAILS_CLICK } from '../../../../../../common/constants'; +import { UIM_TEMPLATE_SHOW_DETAILS_CLICK } from '../../../../../../common/constants'; import { TemplateDeleteModal } from '../../../../components'; import { useServices } from '../../../../app_context'; import { getTemplateDetailsLink } from '../../../../services/routing'; import { SendRequestResponse } from '../../../../../shared_imports'; +import { reactRouterNavigate } from '../../../../../../../../../src/plugins/kibana_react/public'; interface Props { templates: TemplateListItem[]; reload: () => Promise; editTemplate: (name: string, formatVersion: IndexTemplateFormatVersion) => void; cloneTemplate: (name: string, formatVersion: IndexTemplateFormatVersion) => void; + history: ScopedHistory; } export const TemplateTable: React.FunctionComponent = ({ @@ -27,6 +30,7 @@ export const TemplateTable: React.FunctionComponent = ({ reload, editTemplate, cloneTemplate, + history, }) => { const { uiMetricService } = useServices(); const [selection, setSelection] = useState([]); @@ -239,11 +243,11 @@ export const TemplateTable: React.FunctionComponent = ({ /> , { if (filter) { // React router tries to decode url params but it can't because the browser partially // decodes them. So we have to encode both the URL and the filter to get it all to // work correctly for filters with URL unsafe characters in them. - return encodeURI(`#${BASE_PATH}indices/filter/${encodeURIComponent(filter)}`); + return encodeURI(`/indices/filter/${encodeURIComponent(filter)}`); } // If no filter, URI is already safe so no need to encode. - return `#${BASE_PATH}indices`; + return '/indices'; }; export const getILMPolicyPath = (policyName: string) => { - return encodeURI( - `#/management/data/index_lifecycle_management/policies/edit/${encodeURIComponent(policyName)}` - ); + return encodeURI(`/policies/edit/${encodeURIComponent(policyName)}`); }; diff --git a/x-pack/plugins/index_management/public/application/services/routing.ts b/x-pack/plugins/index_management/public/application/services/routing.ts index a6d8f67751cd1..fe118b1181082 100644 --- a/x-pack/plugins/index_management/public/application/services/routing.ts +++ b/x-pack/plugins/index_management/public/application/services/routing.ts @@ -3,11 +3,10 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { BASE_PATH } from '../../../common/constants'; import { IndexTemplateFormatVersion } from '../../../common'; export const getTemplateListLink = () => { - return `${BASE_PATH}templates`; + return `/templates`; }; // Need to add some additonal encoding/decoding logic to work with React Router @@ -17,22 +16,20 @@ export const getTemplateDetailsLink = ( formatVersion: IndexTemplateFormatVersion, withHash = false ) => { - const baseUrl = `${BASE_PATH}templates/${encodeURIComponent( - encodeURIComponent(name) - )}?v=${formatVersion}`; + const baseUrl = `/templates/${encodeURIComponent(encodeURIComponent(name))}?v=${formatVersion}`; const url = withHash ? `#${baseUrl}` : baseUrl; return encodeURI(url); }; export const getTemplateEditLink = (name: string, formatVersion: IndexTemplateFormatVersion) => { return encodeURI( - `${BASE_PATH}edit_template/${encodeURIComponent(encodeURIComponent(name))}?v=${formatVersion}` + `/edit_template/${encodeURIComponent(encodeURIComponent(name))}?v=${formatVersion}` ); }; export const getTemplateCloneLink = (name: string, formatVersion: IndexTemplateFormatVersion) => { return encodeURI( - `${BASE_PATH}clone_template/${encodeURIComponent(encodeURIComponent(name))}?v=${formatVersion}` + `/clone_template/${encodeURIComponent(encodeURIComponent(name))}?v=${formatVersion}` ); }; diff --git a/x-pack/plugins/ingest_pipelines/public/application/services/breadcrumbs.ts b/x-pack/plugins/ingest_pipelines/public/application/services/breadcrumbs.ts index 9b974fdea283a..5fc8e13e3dcad 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/services/breadcrumbs.ts +++ b/x-pack/plugins/ingest_pipelines/public/application/services/breadcrumbs.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ import { i18n } from '@kbn/i18n'; -import { BASE_PATH } from '../../../common/constants'; import { ManagementAppMountParams } from '../../../../../../src/plugins/management/public'; type SetBreadcrumbs = ManagementAppMountParams['setBreadcrumbs']; diff --git a/x-pack/plugins/ml/public/application/app.tsx b/x-pack/plugins/ml/public/application/app.tsx index e9796fcbb0fe4..b10b7395c6d7f 100644 --- a/x-pack/plugins/ml/public/application/app.tsx +++ b/x-pack/plugins/ml/public/application/app.tsx @@ -7,7 +7,7 @@ import React, { FC } from 'react'; import ReactDOM from 'react-dom'; -import { AppMountParameters, CoreStart } from 'kibana/public'; +import { AppMountParameters, CoreStart, ScopedHistory } from 'kibana/public'; import { Storage } from '../../../../../src/plugins/kibana_utils/public'; @@ -23,15 +23,17 @@ type MlDependencies = MlSetupDependencies & MlStartDependencies; interface AppProps { coreStart: CoreStart; deps: MlDependencies; + history: ScopedHistory; } const localStorage = new Storage(window.localStorage); -const App: FC = ({ coreStart, deps }) => { +const App: FC = ({ coreStart, deps, history }) => { const pageDeps = { indexPatterns: deps.data.indexPatterns, config: coreStart.uiSettings!, setBreadcrumbs: coreStart.chrome!.setBreadcrumbs, + history, }; const services = { appName: 'ML', @@ -80,7 +82,10 @@ export const renderApp = ( appMountParams.onAppLeave(actions => actions.default()); - ReactDOM.render(, appMountParams.element); + ReactDOM.render( + , + appMountParams.element + ); return () => { mlLicense.unsubscribe(); diff --git a/x-pack/plugins/ml/public/application/routing/router.tsx b/x-pack/plugins/ml/public/application/routing/router.tsx index 540265c1a0a05..cb35afd40090d 100644 --- a/x-pack/plugins/ml/public/application/routing/router.tsx +++ b/x-pack/plugins/ml/public/application/routing/router.tsx @@ -8,7 +8,7 @@ import React, { FC } from 'react'; import { Router, Route, RouteProps } from 'react-router-dom'; import { Location } from 'history'; -import { IUiSettingsClient, ChromeStart } from 'kibana/public'; +import { IUiSettingsClient, ChromeStart, ScopedHistory } from 'kibana/public'; import { ChromeBreadcrumb } from 'kibana/public'; import { IndexPatternsContract } from 'src/plugins/data/public'; import { MlContext, MlContextValue } from '../contexts/ml'; @@ -35,6 +35,7 @@ interface PageDependencies { setBreadcrumbs: ChromeStart['setBreadcrumbs']; indexPatterns: IndexPatternsContract; config: IUiSettingsClient; + history: ScopedHistory; } export const PageLoader: FC<{ context: MlContextValue }> = ({ context, children }) => { diff --git a/x-pack/plugins/remote_clusters/public/application/app.js b/x-pack/plugins/remote_clusters/public/application/app.js index 483b2f5b97e27..dca9568eaee6c 100644 --- a/x-pack/plugins/remote_clusters/public/application/app.js +++ b/x-pack/plugins/remote_clusters/public/application/app.js @@ -8,7 +8,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { Switch, Route, Redirect, withRouter } from 'react-router-dom'; -import { CRUD_APP_BASE_PATH, UIM_APP_LOAD } from './constants'; +import { UIM_APP_LOAD } from './constants'; import { registerRouter, setUserHasLeftApp, trackUiMetric, METRIC_TYPE } from './services'; import { RemoteClusterList, RemoteClusterAdd, RemoteClusterEdit } from './sections'; @@ -47,11 +47,12 @@ class AppComponent extends Component { return (
- - - - - + + + + + +
); From a729bcef490385e816b9437fe0f9158aa4c991ca Mon Sep 17 00:00:00 2001 From: Matt Kime Date: Tue, 19 May 2020 23:21:02 -0500 Subject: [PATCH 10/93] remove console.log --- x-pack/plugins/index_management/public/application/index.tsx | 2 +- .../public/application/mount_management_section.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/index_management/public/application/index.tsx b/x-pack/plugins/index_management/public/application/index.tsx index a9343552759b7..8da556cc81fcc 100644 --- a/x-pack/plugins/index_management/public/application/index.tsx +++ b/x-pack/plugins/index_management/public/application/index.tsx @@ -25,7 +25,7 @@ export const renderApp = ( const { i18n } = core; const { Context: I18nContext } = i18n; const { services, history } = dependencies; - console.log('2 before render', history); + render( diff --git a/x-pack/plugins/index_management/public/application/mount_management_section.ts b/x-pack/plugins/index_management/public/application/mount_management_section.ts index a432ccc190400..5e8282fcdcdf8 100644 --- a/x-pack/plugins/index_management/public/application/mount_management_section.ts +++ b/x-pack/plugins/index_management/public/application/mount_management_section.ts @@ -36,7 +36,7 @@ export async function mountManagementSection( breadcrumbService.setup(setBreadcrumbs); documentationService.setup(docLinks); - console.log('1 before render app', history); + const appDependencies: AppDependencies = { core: { fatalErrors, From 0bacead3b33e721da770ccf1e324ba344fa34ffb Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 20 May 2020 12:04:07 +0300 Subject: [PATCH 11/93] use reactRouterNavigate for management_sidebar --- .../components/management_app/management_app.tsx | 15 ++------------- .../management_app_wrapper.tsx | 4 ++-- .../management_sidebar_nav.tsx | 9 ++++++--- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/plugins/management/public/components/management_app/management_app.tsx b/src/plugins/management/public/components/management_app/management_app.tsx index 8483b95486ea3..dd5e7c45ec1c3 100644 --- a/src/plugins/management/public/components/management_app/management_app.tsx +++ b/src/plugins/management/public/components/management_app/management_app.tsx @@ -46,16 +46,9 @@ export const ManagementApp = ({ context, dependencies, history }: ManagementAppP const [selectedId, setSelectedId] = useState(''); const [sections, setSections] = useState(); - const onManagementSectionSelected = useCallback( - (id: string, path: string) => { - history.push(path); - window.scrollTo(0, 0); - }, - [history] - ); - const onAppMounted = useCallback((id: string) => { setSelectedId(id); + window.scrollTo(0, 0); }, []); const setBreadcrumbs = useCallback( @@ -77,11 +70,7 @@ export const ManagementApp = ({ context, dependencies, history }: ManagementAppP - + {sections.map(section => diff --git a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx index 4341197173a82..63ef777dfe41c 100644 --- a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx +++ b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx @@ -40,7 +40,7 @@ export const ManagementAppWrapper = ({ const { mount, basePath } = app; const unmount = useRef(); - mountElementRef.current = createRef(); + mountElementRef.current = createRef(); useEffect(() => { if (mount && basePath) { @@ -68,5 +68,5 @@ export const ManagementAppWrapper = ({ } }, [app.id, basePath, history, mount, onAppMounted, setBreadcrumbs]); - return
; + return
; }; diff --git a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx index 0fa338710ae5a..4e5addf0e7137 100644 --- a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx +++ b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx @@ -20,14 +20,17 @@ import { EuiIcon, EuiSideNav, EuiSideNavItemType, EuiScreenReaderOnly } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useState } from 'react'; +import { AppMountParameters } from 'kibana/public'; import { ManagementApp, ManagementSection } from '../../utils'; import './_index.scss'; + import { ManagementItem } from '../../utils/management_item'; +import { reactRouterNavigate } from '../../../../kibana_react/public'; interface ManagementSidebarNavProps { sections: ManagementSection[]; - onManagementSectionSelected: (id: string, path: string) => void; + history: AppMountParameters['history']; selectedId: string; } @@ -43,7 +46,7 @@ const navMenuLabel = i18n.translate('management.nav.menu', { export const ManagementSidebarNav = ({ selectedId, sections, - onManagementSectionSelected, + history, }: ManagementSidebarNavProps) => { const HEADER_ID = 'stack-management-nav-header'; const [isSideNavOpenOnMobile, setIsSideNavOpenOnMobile] = useState(false); @@ -72,7 +75,7 @@ export const ManagementSidebarNav = ({ .filter(app => app.enabled) .map(app => ({ ...createNavItem(app, { - onClick: () => onManagementSectionSelected(app.id, app.basePath), + ...reactRouterNavigate(history, app.basePath), }), })); }; From e570f0f70c5f047138ca94459e7e141e9e375a93 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 20 May 2020 12:14:41 +0300 Subject: [PATCH 12/93] Breadcrumbs will need to make use of the reactRouterNavigate function --- .../management_app/management_app.tsx | 18 +++++++++++++++--- .../management_app_wrapper.tsx | 6 +++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/plugins/management/public/components/management_app/management_app.tsx b/src/plugins/management/public/components/management_app/management_app.tsx index dd5e7c45ec1c3..7f3e61aa9b2f0 100644 --- a/src/plugins/management/public/components/management_app/management_app.tsx +++ b/src/plugins/management/public/components/management_app/management_app.tsx @@ -18,7 +18,12 @@ */ import React, { useState, useEffect, useCallback } from 'react'; import { Route, Router, Switch } from 'react-router-dom'; -import { AppMountContext, AppMountParameters, ChromeBreadcrumb } from 'kibana/public'; +import { + AppMountContext, + AppMountParameters, + ChromeBreadcrumb, + ScopedHistory, +} from 'kibana/public'; import { I18nProvider } from '@kbn/i18n/react'; import { EuiPage, EuiPageBody } from '@elastic/eui'; import { ManagementStart } from '../../types'; @@ -28,6 +33,8 @@ import { ManagementLandingPage } from '../langing'; import { ManagementSidebarNav } from '../management_sidebar_nav'; import { ManagementAppWrapper } from '../management_app_wrapper'; +import { reactRouterNavigate } from '../../../../kibana_react/public'; + import './_management_app.scss'; interface ManagementAppProps { @@ -52,8 +59,13 @@ export const ManagementApp = ({ context, dependencies, history }: ManagementAppP }, []); const setBreadcrumbs = useCallback( - (crumbs: ChromeBreadcrumb[]) => { - context.core.chrome.setBreadcrumbs(crumbs); + (crumbs: ChromeBreadcrumb[] = [], appHistory: ScopedHistory) => { + context.core.chrome.setBreadcrumbs( + crumbs.map(item => ({ + ...item, + ...(item.href ? reactRouterNavigate(appHistory, item.href) : {}), + })) + ); }, [context.core.chrome] ); diff --git a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx index 63ef777dfe41c..1e15a0eabfbf3 100644 --- a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx +++ b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx @@ -19,13 +19,13 @@ import React, { useEffect, createRef, useRef, RefObject } from 'react'; -import { ChromeBreadcrumb, AppMountParameters } from 'kibana/public'; +import { ChromeBreadcrumb, AppMountParameters, ScopedHistory } from 'kibana/public'; import { ManagementApp } from '../../utils'; import { Unmount } from '../../types'; interface ManagementSectionWrapperProps { app: ManagementApp; - setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; + setBreadcrumbs: (crumbs: ChromeBreadcrumb[], history: ScopedHistory) => void; onAppMounted: (id: string) => void; history: AppMountParameters['history']; } @@ -46,7 +46,7 @@ export const ManagementAppWrapper = ({ if (mount && basePath) { const mountResult = mount({ basePath, - setBreadcrumbs, + setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => setBreadcrumbs(crumbs, history), element: mountElementRef.current!.current, history, }); From b95a10ae3b8fa8ac1fbcd3be05c25d60d1dd0ea7 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 20 May 2020 13:47:31 +0300 Subject: [PATCH 13/93] [triggersActions] app. Hash Router -> Router --- .../app/ServiceDetails/AlertIntegrations/index.tsx | 2 +- .../metric_threshold/components/alert_dropdown.tsx | 2 +- .../alerting/inventory/alert_dropdown.tsx | 2 +- .../components/alerting/logs/alert_dropdown.tsx | 4 ++-- .../triggers_actions_ui/public/application/app.tsx | 14 ++++++++------ .../public/application/constants/index.ts | 10 ++++------ .../public/application/home.tsx | 4 ++-- .../public/application/lib/breadcrumb.test.ts | 6 +++--- .../public/application/lib/breadcrumb.ts | 6 +++--- .../connector_add_flyout.test.tsx | 2 +- .../action_connector_form/connector_add_flyout.tsx | 2 +- .../components/actions_connectors_list.test.tsx | 9 ++++++++- .../alerts_list/components/alerts_list.test.tsx | 8 +++++++- .../plugins/triggers_actions_ui/public/plugin.ts | 1 + .../overview/alerts/toggle_alert_flyout_button.tsx | 2 +- x-pack/test/functional_with_es_ssl/config.ts | 3 +-- 16 files changed, 45 insertions(+), 32 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/ServiceDetails/AlertIntegrations/index.tsx b/x-pack/plugins/apm/public/components/app/ServiceDetails/AlertIntegrations/index.tsx index 9001eb6992a96..c1de9c2af8f8c 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceDetails/AlertIntegrations/index.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceDetails/AlertIntegrations/index.tsx @@ -82,7 +82,7 @@ export function AlertIntegrations(props: Props) { } ), href: plugin.core.http.basePath.prepend( - '/app/kibana#/management/insightsAndAlerting/triggersActions/alerts' + '/app/management/insightsAndAlerting/triggersActions/alerts' ), icon: 'tableOfContents' } diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/alert_dropdown.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/alert_dropdown.tsx index bafb38459b17b..52033a00327c0 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/alert_dropdown.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/alert_dropdown.tsx @@ -35,7 +35,7 @@ export const MetricsAlertDropdown = () => { icon="tableOfContents" key="manageLink" href={kibana.services?.application?.getUrlForApp( - 'kibana#/management/insightsAndAlerting/triggersActions/alerts' + 'management/insightsAndAlerting/triggersActions/alerts' )} > diff --git a/x-pack/plugins/infra/public/components/alerting/inventory/alert_dropdown.tsx b/x-pack/plugins/infra/public/components/alerting/inventory/alert_dropdown.tsx index a3cebcf33f386..c48b5b9a2cc58 100644 --- a/x-pack/plugins/infra/public/components/alerting/inventory/alert_dropdown.tsx +++ b/x-pack/plugins/infra/public/components/alerting/inventory/alert_dropdown.tsx @@ -35,7 +35,7 @@ export const InventoryAlertDropdown = () => { icon="tableOfContents" key="manageLink" href={kibana.services?.application?.getUrlForApp( - 'kibana#/management/insightsAndAlerting/triggersActions/alerts' + 'management/insightsAndAlerting/triggersActions/alerts' )} > diff --git a/x-pack/plugins/infra/public/components/alerting/logs/alert_dropdown.tsx b/x-pack/plugins/infra/public/components/alerting/logs/alert_dropdown.tsx index d808b4f3b64aa..b8eb73b99f45e 100644 --- a/x-pack/plugins/infra/public/components/alerting/logs/alert_dropdown.tsx +++ b/x-pack/plugins/infra/public/components/alerting/logs/alert_dropdown.tsx @@ -15,8 +15,8 @@ export const AlertDropdown = () => { const [flyoutVisible, setFlyoutVisible] = useState(false); const manageAlertsLinkProps = useLinkProps( { - app: 'kibana', - hash: 'management/insightsAndAlerting/triggersActions/alerts', + app: 'management', + pathname: '/insightsAndAlerting/triggersActions/alerts', }, { hrefOnly: true, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/app.tsx b/x-pack/plugins/triggers_actions_ui/public/application/app.tsx index ebd9294ce1e6d..d0d3b65b17a9d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/app.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/app.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import React, { lazy } from 'react'; -import { Switch, Route, Redirect, HashRouter } from 'react-router-dom'; +import { Switch, Route, Redirect, Router } from 'react-router-dom'; import { ChromeStart, DocLinksStart, @@ -14,8 +14,9 @@ import { ApplicationStart, ChromeBreadcrumb, CoreStart, + ScopedHistory, } from 'kibana/public'; -import { BASE_PATH, Section, routeToAlertDetails } from './constants'; +import { Section, routeToAlertDetails } from './constants'; import { AppContextProvider, useAppDependencies } from './app_context'; import { hasShowAlertsCapability } from './lib/capabilities'; import { ActionTypeModel, AlertTypeModel } from '../types'; @@ -44,6 +45,7 @@ export interface AppDeps { capabilities: ApplicationStart['capabilities']; actionTypeRegistry: TypeRegistry; alertTypeRegistry: TypeRegistry; + history: ScopedHistory; } export const App = (appDeps: AppDeps) => { @@ -52,11 +54,11 @@ export const App = (appDeps: AppDeps) => { const sectionsRegex = sections.join('|'); return ( - + - + ); }; @@ -67,7 +69,7 @@ export const AppWithoutRouter = ({ sectionsRegex }: { sectionsRegex: string }) = return ( {canShowAlerts && ( @@ -76,7 +78,7 @@ export const AppWithoutRouter = ({ sectionsRegex }: { sectionsRegex: string }) = component={suspendedComponentWithProps(AlertDetailsRoute, 'xl')} /> )} - + ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts index 265cfddab4c06..7623f010c21fb 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts @@ -7,14 +7,12 @@ export { BASE_ALERT_API_PATH } from '../../../../alerting/common'; export { BASE_ACTION_API_PATH } from '../../../../actions/common'; -export const BASE_PATH = '/management/insightsAndAlerting/triggersActions'; - export type Section = 'connectors' | 'alerts'; -export const routeToHome = `${BASE_PATH}`; -export const routeToConnectors = `${BASE_PATH}/connectors`; -export const routeToAlerts = `${BASE_PATH}/alerts`; -export const routeToAlertDetails = `${BASE_PATH}/alert/:alertId`; +export const routeToHome = `/`; +export const routeToConnectors = `/connectors`; +export const routeToAlerts = `/alerts`; +export const routeToAlertDetails = `/alert/:alertId`; export { TIME_UNITS } from './time_units'; export enum SORT_ORDERS { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/home.tsx b/x-pack/plugins/triggers_actions_ui/public/application/home.tsx index b5f3b63c58a93..00571dd9348f5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/home.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/home.tsx @@ -21,7 +21,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { BASE_PATH, Section, routeToConnectors, routeToAlerts } from './constants'; +import { Section, routeToConnectors, routeToAlerts } from './constants'; import { getCurrentBreadcrumb } from './lib/breadcrumb'; import { getCurrentDocTitle } from './lib/doc_title'; import { useAppDependencies } from './app_context'; @@ -76,7 +76,7 @@ export const TriggersActionsUIHome: React.FunctionComponent { - history.push(`${BASE_PATH}/${newSection}`); + history.push(`/${newSection}`); }; // Set breadcrumb and page title diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/breadcrumb.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/breadcrumb.test.ts index b75e014640d72..8ba909beff2a8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/breadcrumb.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/breadcrumb.test.ts @@ -13,19 +13,19 @@ describe('getCurrentBreadcrumb', () => { text: i18n.translate('xpack.triggersActionsUI.connectors.breadcrumbTitle', { defaultMessage: 'Connectors', }), - href: `#${routeToConnectors}`, + href: `${routeToConnectors}`, }); expect(getCurrentBreadcrumb('alerts')).toMatchObject({ text: i18n.translate('xpack.triggersActionsUI.alerts.breadcrumbTitle', { defaultMessage: 'Alerts', }), - href: `#${routeToAlerts}`, + href: `${routeToAlerts}`, }); expect(getCurrentBreadcrumb('home')).toMatchObject({ text: i18n.translate('xpack.triggersActionsUI.home.breadcrumbTitle', { defaultMessage: 'Alerts and Actions', }), - href: `#${routeToHome}`, + href: `${routeToHome}`, }); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/breadcrumb.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/breadcrumb.ts index f833ae9eb39ac..3735942ff97af 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/breadcrumb.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/breadcrumb.ts @@ -15,21 +15,21 @@ export const getCurrentBreadcrumb = (type: string): { text: string; href: string text: i18n.translate('xpack.triggersActionsUI.connectors.breadcrumbTitle', { defaultMessage: 'Connectors', }), - href: `#${routeToConnectors}`, + href: `${routeToConnectors}`, }; case 'alerts': return { text: i18n.translate('xpack.triggersActionsUI.alerts.breadcrumbTitle', { defaultMessage: 'Alerts', }), - href: `#${routeToAlerts}`, + href: `${routeToAlerts}`, }; default: return { text: i18n.translate('xpack.triggersActionsUI.home.breadcrumbTitle', { defaultMessage: 'Alerts and Actions', }), - href: `#${routeToHome}`, + href: `${routeToHome}`, }; } }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.test.tsx index 1da9abea40dba..a96abfe312663 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.test.tsx @@ -127,7 +127,7 @@ describe('connector_add_flyout', () => { const manageLink = callout.find('EuiButton'); expect(manageLink).toHaveLength(1); expect(manageLink.getElements()[0].props.href).toMatchInlineSnapshot( - `"/app/kibana#/management/stack/license_management/"` + `"/app//management/stack/license_management/"` ); const subscriptionLink = callout.find('EuiButtonEmpty'); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx index adee2e09a56fd..19de36b4f09ac 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx @@ -293,7 +293,7 @@ const UpgradeYourLicenseCallOut = ({ http }: { http: HttpSetup }) => ( diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.test.tsx index 12b6f99319596..b9ec083ed68e8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.test.tsx @@ -4,9 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ import * as React from 'react'; +import { ScopedHistory } from 'kibana/public'; + import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { ActionsConnectorsList } from './actions_connectors_list'; -import { coreMock } from '../../../../../../../../src/core/public/mocks'; +import { coreMock, scopedHistoryMock } from '../../../../../../../../src/core/public/mocks'; import { ReactWrapper } from 'enzyme'; import { act } from 'react-dom/test-utils'; import { actionTypeRegistryMock } from '../../../action_type_registry.mock'; @@ -66,6 +68,7 @@ describe('actions_connectors_list component empty', () => { 'actions:delete': true, }, }, + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, setBreadcrumbs: jest.fn(), actionTypeRegistry: actionTypeRegistry as any, alertTypeRegistry: {} as any, @@ -171,6 +174,7 @@ describe('actions_connectors_list component with items', () => { 'actions:delete': true, }, }, + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, setBreadcrumbs: jest.fn(), actionTypeRegistry: { get() { @@ -256,6 +260,7 @@ describe('actions_connectors_list component empty with show only capability', () 'actions:delete': false, }, }, + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, setBreadcrumbs: jest.fn(), actionTypeRegistry: { get() { @@ -341,6 +346,7 @@ describe('actions_connectors_list with show only capability', () => { 'actions:delete': false, }, }, + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, setBreadcrumbs: jest.fn(), actionTypeRegistry: { get() { @@ -438,6 +444,7 @@ describe('actions_connectors_list component with disabled items', () => { 'actions:delete': true, }, }, + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, setBreadcrumbs: jest.fn(), actionTypeRegistry: { get() { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx index cf1524094b41d..a28f638914cf2 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx @@ -4,8 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ import * as React from 'react'; +import { ScopedHistory } from 'kibana/public'; + import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; -import { coreMock } from '../../../../../../../../src/core/public/mocks'; +import { coreMock, scopedHistoryMock } from '../../../../../../../../src/core/public/mocks'; import { ReactWrapper } from 'enzyme'; import { act } from 'react-dom/test-utils'; import { actionTypeRegistryMock } from '../../../action_type_registry.mock'; @@ -101,6 +103,7 @@ describe('alerts_list component empty', () => { 'alerting:delete': true, }, }, + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, setBreadcrumbs: jest.fn(), actionTypeRegistry: actionTypeRegistry as any, alertTypeRegistry: alertTypeRegistry as any, @@ -219,6 +222,7 @@ describe('alerts_list component with items', () => { 'alerting:delete': true, }, }, + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, setBreadcrumbs: jest.fn(), actionTypeRegistry: actionTypeRegistry as any, alertTypeRegistry: alertTypeRegistry as any, @@ -300,6 +304,7 @@ describe('alerts_list component empty with show only capability', () => { 'alerting:delete': false, }, }, + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, setBreadcrumbs: jest.fn(), actionTypeRegistry: { get() { @@ -414,6 +419,7 @@ describe('alerts_list with show only capability', () => { 'alerting:delete': false, }, }, + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, setBreadcrumbs: jest.fn(), actionTypeRegistry: actionTypeRegistry as any, alertTypeRegistry: alertTypeRegistry as any, diff --git a/x-pack/plugins/triggers_actions_ui/public/plugin.ts b/x-pack/plugins/triggers_actions_ui/public/plugin.ts index 016b564c47d00..f6505573dfb8f 100644 --- a/x-pack/plugins/triggers_actions_ui/public/plugin.ts +++ b/x-pack/plugins/triggers_actions_ui/public/plugin.ts @@ -95,6 +95,7 @@ export class Plugin capabilities: core.application.capabilities, navigateToApp: core.application.navigateToApp, setBreadcrumbs: params.setBreadcrumbs, + history: params.history, actionTypeRegistry: this.actionTypeRegistry, alertTypeRegistry: this.alertTypeRegistry, }); diff --git a/x-pack/plugins/uptime/public/components/overview/alerts/toggle_alert_flyout_button.tsx b/x-pack/plugins/uptime/public/components/overview/alerts/toggle_alert_flyout_button.tsx index 0cdb3c0feb71f..c683d6afd278e 100644 --- a/x-pack/plugins/uptime/public/components/overview/alerts/toggle_alert_flyout_button.tsx +++ b/x-pack/plugins/uptime/public/components/overview/alerts/toggle_alert_flyout_button.tsx @@ -61,7 +61,7 @@ export const ToggleAlertFlyoutButtonComponent: React.FC = ({ Date: Wed, 20 May 2020 14:49:40 +0300 Subject: [PATCH 14/93] Replace /app/kibana#/management urls to /app/management --- .../ui_settings/saved_objects/ui_settings.ts | 2 +- .../server/lib/__tests__/relationships.js | 6 ++-- .../ensure_default_index_pattern.tsx | 2 +- .../public/search/long_query_notification.tsx | 2 +- .../server/saved_objects/index_patterns.ts | 2 +- .../index_pattern_management/public/plugin.ts | 2 +- .../url/kbn_url_storage.test.ts | 28 +++++++++---------- .../components/relationships.test.tsx | 2 +- .../saved_objects_management/public/plugin.ts | 2 +- src/plugins/telemetry/common/constants.ts | 2 +- .../apis/saved_objects_management/find.ts | 2 +- .../saved_objects_management/relationships.ts | 4 +-- .../ServiceIntegrations/index.tsx | 2 +- .../InvalidLicenseNotification.tsx | 2 +- .../plugins/licensing/public/plugin.test.ts | 2 +- x-pack/plugins/licensing/public/plugin.ts | 2 +- x-pack/plugins/logstash/public/plugin.ts | 2 +- .../components/no_index_pattern_callout.js | 2 +- .../datavisualizer_selector.tsx | 5 +--- .../results_links/results_links.tsx | 4 +-- .../create_watch_service.js | 2 +- .../overview/components/sidebar.tsx | 2 +- .../components/cluster/listing/listing.js | 2 +- .../public/components/license/index.js | 2 +- x-pack/plugins/reporting/constants.ts | 2 +- .../public/components/report_listing.tsx | 2 +- x-pack/plugins/reporting/public/plugin.tsx | 2 +- x-pack/plugins/security/public/plugin.tsx | 2 +- .../ml_popover/upgrade_contents.tsx | 2 +- .../components/news_feed/no_news/index.tsx | 2 +- .../public/create_feature_catalogue_entry.ts | 2 +- .../transform/public/register_feature.ts | 2 +- .../components/monitor/ml/license_info.tsx | 2 +- x-pack/plugins/watcher/public/plugin.ts | 2 +- 34 files changed, 51 insertions(+), 54 deletions(-) diff --git a/src/core/server/ui_settings/saved_objects/ui_settings.ts b/src/core/server/ui_settings/saved_objects/ui_settings.ts index 1bea65ddee924..0eab40a7b3a5d 100644 --- a/src/core/server/ui_settings/saved_objects/ui_settings.ts +++ b/src/core/server/ui_settings/saved_objects/ui_settings.ts @@ -38,7 +38,7 @@ export const uiSettingsType: SavedObjectsType = { importableAndExportable: true, getInAppUrl() { return { - path: `/app/kibana#/management/kibana/settings`, + path: `/app/management/kibana/settings`, uiCapabilitiesPath: 'advancedSettings.show', }; }, diff --git a/src/legacy/core_plugins/kibana/server/lib/__tests__/relationships.js b/src/legacy/core_plugins/kibana/server/lib/__tests__/relationships.js index 64676b1bce75c..4df0e7a140205 100644 --- a/src/legacy/core_plugins/kibana/server/lib/__tests__/relationships.js +++ b/src/legacy/core_plugins/kibana/server/lib/__tests__/relationships.js @@ -69,7 +69,7 @@ const savedObjectsManagement = getManagementaMock({ }, getInAppUrl(obj) { return { - path: `/app/kibana#/management/kibana/indexPatterns/patterns/${encodeURIComponent(obj.id)}`, + path: `/app/management/kibana/indexPatterns/patterns/${encodeURIComponent(obj.id)}`, uiCapabilitiesPath: 'management.kibana.index_patterns', }; }, @@ -325,7 +325,7 @@ describe('findRelationships', () => { title: 'My Index Pattern', editUrl: '/management/kibana/indexPatterns/patterns/1', inAppUrl: { - path: '/app/kibana#/management/kibana/indexPatterns/patterns/1', + path: '/app/management/kibana/indexPatterns/patterns/1', uiCapabilitiesPath: 'management.kibana.index_patterns', }, }, @@ -439,7 +439,7 @@ describe('findRelationships', () => { title: 'My Index Pattern', editUrl: '/management/kibana/indexPatterns/patterns/1', inAppUrl: { - path: '/app/kibana#/management/kibana/indexPatterns/patterns/1', + path: '/app/management/kibana/indexPatterns/patterns/1', uiCapabilitiesPath: 'management.kibana.index_patterns', }, }, diff --git a/src/plugins/data/public/index_patterns/index_patterns/ensure_default_index_pattern.tsx b/src/plugins/data/public/index_patterns/index_patterns/ensure_default_index_pattern.tsx index 9115e523f5302..2ee6965bb4125 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/ensure_default_index_pattern.tsx +++ b/src/plugins/data/public/index_patterns/index_patterns/ensure_default_index_pattern.tsx @@ -92,7 +92,7 @@ export const createEnsureDefaultIndexPattern = (core: CoreStart) => { core.application.navigateToApp('home'); } else { window.location.href = core.http.basePath.prepend( - `/app/kibana#/management/kibana/indexPatterns?bannerMessage=${bannerMessage}` + `/app/management/kibana/indexPatterns?bannerMessage=${bannerMessage}` ); } diff --git a/src/plugins/data/public/search/long_query_notification.tsx b/src/plugins/data/public/search/long_query_notification.tsx index 0bdf8ab7c66f8..1db298618fae8 100644 --- a/src/plugins/data/public/search/long_query_notification.tsx +++ b/src/plugins/data/public/search/long_query_notification.tsx @@ -44,7 +44,7 @@ export function LongQueryNotification(props: Props) { { - await props.application.navigateToApp('kibana#/management/stack/license_management'); + await props.application.navigateToApp('management/stack/license_management'); }} > '/create'); diff --git a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.test.ts b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.test.ts index 8db1d60f09d72..b8c06c8479926 100644 --- a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.test.ts +++ b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.test.ts @@ -35,7 +35,7 @@ import { ScopedHistory } from '../../../../../core/public'; describe('kbn_url_storage', () => { describe('getStateFromUrl & setStateToUrl', () => { - const url = 'http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id'; + const url = 'http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id'; const state1 = { testStr: '123', testNumber: 0, @@ -50,14 +50,14 @@ describe('kbn_url_storage', () => { it('should set expanded state to url', () => { let newUrl = setStateToKbnUrl('_s', state1, { useHash: false }, url); expect(newUrl).toMatchInlineSnapshot( - `"http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_s=(testArray:!(1,2,()),testNull:!n,testNumber:0,testObj:(test:'123'),testStr:'123')"` + `"http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_s=(testArray:!(1,2,()),testNull:!n,testNumber:0,testObj:(test:'123'),testStr:'123')"` ); const retrievedState1 = getStateFromKbnUrl('_s', newUrl); expect(retrievedState1).toEqual(state1); newUrl = setStateToKbnUrl('_s', state2, { useHash: false }, newUrl); expect(newUrl).toMatchInlineSnapshot( - `"http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_s=(test:'123')"` + `"http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_s=(test:'123')"` ); const retrievedState2 = getStateFromKbnUrl('_s', newUrl); expect(retrievedState2).toEqual(state2); @@ -66,14 +66,14 @@ describe('kbn_url_storage', () => { it('should set hashed state to url', () => { let newUrl = setStateToKbnUrl('_s', state1, { useHash: true }, url); expect(newUrl).toMatchInlineSnapshot( - `"http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_s=h@a897fac"` + `"http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_s=h@a897fac"` ); const retrievedState1 = getStateFromKbnUrl('_s', newUrl); expect(retrievedState1).toEqual(state1); newUrl = setStateToKbnUrl('_s', state2, { useHash: true }, newUrl); expect(newUrl).toMatchInlineSnapshot( - `"http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_s=h@40f94d5"` + `"http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_s=h@40f94d5"` ); const retrievedState2 = getStateFromKbnUrl('_s', newUrl); expect(retrievedState2).toEqual(state2); @@ -244,20 +244,20 @@ describe('kbn_url_storage', () => { it('should extract path relative to browser history without basename', () => { const history = createBrowserHistory(); const url = - "http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const relativePath = getRelativeToHistoryPath(url, history); expect(relativePath).toEqual( - "/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" + "/oxf/app/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" ); }); it('should extract path relative to browser history with basename', () => { const url = - "http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const history1 = createBrowserHistory({ basename: '/oxf/app/' }); const relativePath1 = getRelativeToHistoryPath(url, history1); expect(relativePath1).toEqual( - "/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" + "/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" ); const history2 = createBrowserHistory({ basename: '/oxf/app/kibana/' }); @@ -270,17 +270,17 @@ describe('kbn_url_storage', () => { it('should extract path relative to browser history with basename from relative url', () => { const history = createBrowserHistory({ basename: '/oxf/app/' }); const url = - "/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "/oxf/app/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const relativePath = getRelativeToHistoryPath(url, history); expect(relativePath).toEqual( - "/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" + "/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" ); }); it('should extract path relative to hash history without basename', () => { const history = createHashHistory(); const url = - "http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const relativePath = getRelativeToHistoryPath(url, history); expect(relativePath).toEqual( "/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" @@ -290,7 +290,7 @@ describe('kbn_url_storage', () => { it('should extract path relative to hash history with basename', () => { const history = createHashHistory({ basename: 'management' }); const url = - "http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const relativePath = getRelativeToHistoryPath(url, history); expect(relativePath).toEqual( "/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" @@ -300,7 +300,7 @@ describe('kbn_url_storage', () => { it('should extract path relative to hash history with basename from relative url', () => { const history = createHashHistory({ basename: 'management' }); const url = - "/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "/oxf/app/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const relativePath = getRelativeToHistoryPath(url, history); expect(relativePath).toEqual( "/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx index b3372ccb6fda5..8d8453c227bfa 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx @@ -112,7 +112,7 @@ describe('Relationships', () => { editUrl: '/management/kibana/indexPatterns/patterns/1', icon: 'indexPatternApp', inAppUrl: { - path: '/app/kibana#/management/kibana/indexPatterns/patterns/1', + path: '/app/management/kibana/indexPatterns/patterns/1', uiCapabilitiesPath: 'management.kibana.index_patterns', }, title: 'My Index Pattern', diff --git a/src/plugins/saved_objects_management/public/plugin.ts b/src/plugins/saved_objects_management/public/plugin.ts index b0c6b1952a2a5..fc83c061aabd4 100644 --- a/src/plugins/saved_objects_management/public/plugin.ts +++ b/src/plugins/saved_objects_management/public/plugin.ts @@ -82,7 +82,7 @@ export class SavedObjectsManagementPlugin 'Import, export, and manage your saved searches, visualizations, and dashboards.', }), icon: 'savedObjectsApp', - path: '/app/kibana#/management/kibana/objects', + path: '/app/management/kibana/objects', showOnHomePage: true, category: FeatureCatalogueCategory.ADMIN, }); diff --git a/src/plugins/telemetry/common/constants.ts b/src/plugins/telemetry/common/constants.ts index 2e058fdc13e4a..53c79b738f750 100644 --- a/src/plugins/telemetry/common/constants.ts +++ b/src/plugins/telemetry/common/constants.ts @@ -49,7 +49,7 @@ export const LOCALSTORAGE_KEY = 'telemetry.data'; /** * Link to Advanced Settings. */ -export const PATH_TO_ADVANCED_SETTINGS = 'kibana#/management/kibana/settings'; +export const PATH_TO_ADVANCED_SETTINGS = 'management/kibana/settings'; /** * Link to the Elastic Telemetry privacy statement. diff --git a/test/api_integration/apis/saved_objects_management/find.ts b/test/api_integration/apis/saved_objects_management/find.ts index ef7c5ab22ee66..797c5d34af3b9 100644 --- a/test/api_integration/apis/saved_objects_management/find.ts +++ b/test/api_integration/apis/saved_objects_management/find.ts @@ -285,7 +285,7 @@ export default function({ getService }: FtrProviderContext) { '/management/kibana/indexPatterns/patterns/8963ca30-3224-11e8-a572-ffca06da1357', inAppUrl: { path: - '/app/kibana#/management/kibana/indexPatterns/patterns/8963ca30-3224-11e8-a572-ffca06da1357', + '/app/management/kibana/indexPatterns/patterns/8963ca30-3224-11e8-a572-ffca06da1357', uiCapabilitiesPath: 'management.kibana.index_patterns', }, }); diff --git a/test/api_integration/apis/saved_objects_management/relationships.ts b/test/api_integration/apis/saved_objects_management/relationships.ts index 00972a97f41e8..d78ac42a156f0 100644 --- a/test/api_integration/apis/saved_objects_management/relationships.ts +++ b/test/api_integration/apis/saved_objects_management/relationships.ts @@ -86,7 +86,7 @@ export default function({ getService }: FtrProviderContext) { '/management/kibana/indexPatterns/patterns/8963ca30-3224-11e8-a572-ffca06da1357', inAppUrl: { path: - '/app/kibana#/management/kibana/indexPatterns/patterns/8963ca30-3224-11e8-a572-ffca06da1357', + '/app/management/kibana/indexPatterns/patterns/8963ca30-3224-11e8-a572-ffca06da1357', uiCapabilitiesPath: 'management.kibana.index_patterns', }, }, @@ -127,7 +127,7 @@ export default function({ getService }: FtrProviderContext) { '/management/kibana/indexPatterns/patterns/8963ca30-3224-11e8-a572-ffca06da1357', inAppUrl: { path: - '/app/kibana#/management/kibana/indexPatterns/patterns/8963ca30-3224-11e8-a572-ffca06da1357', + '/app/management/kibana/indexPatterns/patterns/8963ca30-3224-11e8-a572-ffca06da1357', uiCapabilitiesPath: 'management.kibana.index_patterns', }, }, diff --git a/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/index.tsx b/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/index.tsx index e1f58b7b35210..d6769ccf0ca5f 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/index.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/index.tsx @@ -92,7 +92,7 @@ export class ServiceIntegrations extends React.Component { ), icon: 'watchesApp', href: core.http.basePath.prepend( - '/app/kibana#/management/insightsAndAlerting/watcher' + '/app/management/insightsAndAlerting/watcher' ), target: '_blank', onClick: () => this.closePopover() diff --git a/x-pack/plugins/apm/public/context/LicenseContext/InvalidLicenseNotification.tsx b/x-pack/plugins/apm/public/context/LicenseContext/InvalidLicenseNotification.tsx index 8ed02f039289e..13ba123914fcb 100644 --- a/x-pack/plugins/apm/public/context/LicenseContext/InvalidLicenseNotification.tsx +++ b/x-pack/plugins/apm/public/context/LicenseContext/InvalidLicenseNotification.tsx @@ -11,7 +11,7 @@ import { useApmPluginContext } from '../../hooks/useApmPluginContext'; export function InvalidLicenseNotification() { const { core } = useApmPluginContext(); const manageLicenseURL = core.http.basePath.prepend( - '/app/kibana#/management/stack/license_management' + '/app/management/stack/license_management' ); return ( diff --git a/x-pack/plugins/licensing/public/plugin.test.ts b/x-pack/plugins/licensing/public/plugin.test.ts index 9f0019680d14b..846eb193258c7 100644 --- a/x-pack/plugins/licensing/public/plugin.test.ts +++ b/x-pack/plugins/licensing/public/plugin.test.ts @@ -367,7 +367,7 @@ describe('licensing plugin', () => { expect(coreStart.overlays.banners.add).toHaveBeenCalledTimes(1); expect(mountExpiredBannerMock).toHaveBeenCalledWith({ type: 'gold', - uploadUrl: '/app/kibana#/management/stack/license_management/upload_license', + uploadUrl: '/app/management/stack/license_management/upload_license', }); }); }); diff --git a/x-pack/plugins/licensing/public/plugin.ts b/x-pack/plugins/licensing/public/plugin.ts index 31910d81b3434..3f16f14744179 100644 --- a/x-pack/plugins/licensing/public/plugin.ts +++ b/x-pack/plugins/licensing/public/plugin.ts @@ -148,7 +148,7 @@ export class LicensingPlugin implements Plugin { private showExpiredBanner(license: ILicense) { const uploadUrl = this.coreStart!.http.basePath.prepend( - '/app/kibana#/management/stack/license_management/upload_license' + '/app/management/stack/license_management/upload_license' ); this.coreStart!.overlays.banners.add( mountExpiredBanner({ diff --git a/x-pack/plugins/logstash/public/plugin.ts b/x-pack/plugins/logstash/public/plugin.ts index 7d4afc0a4ea13..cbfe8fe1ff4e5 100644 --- a/x-pack/plugins/logstash/public/plugin.ts +++ b/x-pack/plugins/logstash/public/plugin.ts @@ -71,7 +71,7 @@ export class LogstashPlugin implements Plugin { defaultMessage: 'Create, delete, update, and clone data ingestion pipelines.', }), icon: 'pipelineApp', - path: '/app/kibana#/management/ingest/pipelines', + path: '/app/management/ingest/pipelines', showOnHomePage: true, category: FeatureCatalogueCategory.ADMIN, }); diff --git a/x-pack/plugins/maps/public/components/no_index_pattern_callout.js b/x-pack/plugins/maps/public/components/no_index_pattern_callout.js index 89cd884a6dd32..2daab8c6322dd 100644 --- a/x-pack/plugins/maps/public/components/no_index_pattern_callout.js +++ b/x-pack/plugins/maps/public/components/no_index_pattern_callout.js @@ -24,7 +24,7 @@ export function NoIndexPatternCallout() { id="xpack.maps.noIndexPattern.doThisPrefixDescription" defaultMessage="You'll need to " /> - + { } description={startTrialDescription()} footer={ - + = ({ /> } description="" - href={`${basePath.get()}/app/kibana#/management/data/index_management/indices/filter/${index}`} + href={`${basePath.get()}/app/management/data/index_management/indices/filter/${index}`} /> @@ -153,7 +153,7 @@ export const ResultsLinks: FC = ({ /> } description="" - href={`${basePath.get()}/app/kibana#/management/kibana/indexPatterns${ + href={`${basePath.get()}/app/management/kibana/indexPatterns${ createIndexPattern ? `/patterns/${indexPatternId}` : '' }`} /> diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/create_watch_service.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/create_watch_service.js index 307fa79f5dea2..4f8cccdbb335e 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/create_watch_service.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/create_watch_service.js @@ -167,7 +167,7 @@ class CreateWatchService { saveWatch(watchModel) .then(() => { this.status.watch = this.STATUS.SAVED; - this.config.watcherEditURL = `${basePath.get()}/app/kibana#/management/insightsAndAlerting/watcher/watches/watch/${id}/edit?_g=()`; + this.config.watcherEditURL = `${basePath.get()}/app/management/insightsAndAlerting/watcher/watches/watch/${id}/edit?_g=()`; resolve({ id, url: this.config.watcherEditURL, diff --git a/x-pack/plugins/ml/public/application/overview/components/sidebar.tsx b/x-pack/plugins/ml/public/application/overview/components/sidebar.tsx index 87a7156b6f52e..119346ec8035a 100644 --- a/x-pack/plugins/ml/public/application/overview/components/sidebar.tsx +++ b/x-pack/plugins/ml/public/application/overview/components/sidebar.tsx @@ -42,7 +42,7 @@ export const OverviewSideBar: FC = ({ createAnomalyDetectionJobDisabled } const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = docLinks; const docsLink = `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/xpack-ml.html`; - const transformsLink = `${basePath.get()}/app/kibana#/management/data/transform`; + const transformsLink = `${basePath.get()}/app/management/data/transform`; return ( diff --git a/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js b/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js index 69d7727f9a20a..cf403005df0bf 100644 --- a/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js +++ b/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js @@ -288,7 +288,7 @@ const handleClickIncompatibleLicense = (scope, clusterName) => { }; const handleClickInvalidLicense = (scope, clusterName) => { - const licensingPath = `${Legacy.shims.getBasePath()}/app/kibana#/management/stack/license_management/home`; + const licensingPath = `${Legacy.shims.getBasePath()}/app/management/stack/license_management/home`; licenseWarning(scope, { title: toMountPoint( diff --git a/x-pack/plugins/monitoring/public/components/license/index.js b/x-pack/plugins/monitoring/public/components/license/index.js index e8ea1f8df227a..076b8e6d543e6 100644 --- a/x-pack/plugins/monitoring/public/components/license/index.js +++ b/x-pack/plugins/monitoring/public/components/license/index.js @@ -169,7 +169,7 @@ const LicenseUpdateInfoForRemote = ({ isPrimaryCluster }) => { export function License(props) { const { status, type, isExpired, expiryDate } = props; - const licenseManagement = `${Legacy.shims.getBasePath()}/app/kibana#/management/stack/license_management`; + const licenseManagement = `${Legacy.shims.getBasePath()}/app/management/stack/license_management`; return ( diff --git a/x-pack/plugins/reporting/constants.ts b/x-pack/plugins/reporting/constants.ts index 8079c5b1d9887..a610ff0bb16a9 100644 --- a/x-pack/plugins/reporting/constants.ts +++ b/x-pack/plugins/reporting/constants.ts @@ -12,7 +12,7 @@ export const API_BASE_URL = '/api/reporting'; export const API_LIST_URL = `${API_BASE_URL}/jobs`; export const API_BASE_GENERATE = `${API_BASE_URL}/generate`; export const API_GENERATE_IMMEDIATE = `${API_BASE_URL}/v1/generate/immediate/csv/saved-object`; -export const REPORTING_MANAGEMENT_HOME = '/app/kibana#/management/kibana/reporting'; +export const REPORTING_MANAGEMENT_HOME = '/app/management/kibana/reporting'; // Statuses export const JOB_STATUS_FAILED = 'failed'; diff --git a/x-pack/plugins/reporting/public/components/report_listing.tsx b/x-pack/plugins/reporting/public/components/report_listing.tsx index d8f9b7d37cfbf..ca97692c650e8 100644 --- a/x-pack/plugins/reporting/public/components/report_listing.tsx +++ b/x-pack/plugins/reporting/public/components/report_listing.tsx @@ -266,7 +266,7 @@ class ReportListingUi extends Component { } catch (fetchError) { if (!this.licenseAllowsToShowThisPage()) { this.props.toasts.addDanger(this.state.badLicenseMessage); - this.props.redirect('kibana#/management'); + this.props.redirect('management'); return; } diff --git a/x-pack/plugins/reporting/public/plugin.tsx b/x-pack/plugins/reporting/public/plugin.tsx index ac8ea661a21ab..c5fed538e3b01 100644 --- a/x-pack/plugins/reporting/public/plugin.tsx +++ b/x-pack/plugins/reporting/public/plugin.tsx @@ -111,7 +111,7 @@ export class ReportingPublicPlugin implements Plugin { defaultMessage: 'Manage your reports generated from Discover, Visualize, and Dashboard.', }), icon: 'reportingApp', - path: '/app/kibana#/management/kibana/reporting', + path: '/app/management/kibana/reporting', showOnHomePage: false, category: FeatureCatalogueCategory.ADMIN, }); diff --git a/x-pack/plugins/security/public/plugin.tsx b/x-pack/plugins/security/public/plugin.tsx index 38ef552e75a9e..da69dd051c11d 100644 --- a/x-pack/plugins/security/public/plugin.tsx +++ b/x-pack/plugins/security/public/plugin.tsx @@ -122,7 +122,7 @@ export class SecurityPlugin 'Protect your data and easily manage who has access to what with users and roles.', }), icon: 'securityApp', - path: '/app/kibana#/management/security/users', + path: '/app/management/security/users', showOnHomePage: true, category: FeatureCatalogueCategory.ADMIN, }); diff --git a/x-pack/plugins/siem/public/common/components/ml_popover/upgrade_contents.tsx b/x-pack/plugins/siem/public/common/components/ml_popover/upgrade_contents.tsx index eda6b0f28499c..e9efd7df23903 100644 --- a/x-pack/plugins/siem/public/common/components/ml_popover/upgrade_contents.tsx +++ b/x-pack/plugins/siem/public/common/components/ml_popover/upgrade_contents.tsx @@ -59,7 +59,7 @@ export const UpgradeContentsComponent = () => ( diff --git a/x-pack/plugins/siem/public/common/components/news_feed/no_news/index.tsx b/x-pack/plugins/siem/public/common/components/news_feed/no_news/index.tsx index c4e0482c6b30a..8061a8f9799e3 100644 --- a/x-pack/plugins/siem/public/common/components/news_feed/no_news/index.tsx +++ b/x-pack/plugins/siem/public/common/components/news_feed/no_news/index.tsx @@ -13,7 +13,7 @@ export const NoNews = React.memo(() => ( <> {i18n.NO_NEWS_MESSAGE}{' '} - + {i18n.ADVANCED_SETTINGS_LINK_TITLE} {'.'} diff --git a/x-pack/plugins/spaces/public/create_feature_catalogue_entry.ts b/x-pack/plugins/spaces/public/create_feature_catalogue_entry.ts index 2cf34e842ce33..15d141ccc328e 100644 --- a/x-pack/plugins/spaces/public/create_feature_catalogue_entry.ts +++ b/x-pack/plugins/spaces/public/create_feature_catalogue_entry.ts @@ -19,7 +19,7 @@ export const createSpacesFeatureCatalogueEntry = (): FeatureCatalogueEntry => { }), description: getSpacesFeatureDescription(), icon: 'spacesApp', - path: '/app/kibana#/management/kibana/spaces', + path: '/app/management/kibana/spaces', showOnHomePage: true, category: FeatureCatalogueCategory.ADMIN, }; diff --git a/x-pack/plugins/transform/public/register_feature.ts b/x-pack/plugins/transform/public/register_feature.ts index c81a18a3def87..796fa370dab25 100644 --- a/x-pack/plugins/transform/public/register_feature.ts +++ b/x-pack/plugins/transform/public/register_feature.ts @@ -22,7 +22,7 @@ export const registerFeature = (home: HomePublicPluginSetup) => { 'Use transforms to pivot existing Elasticsearch indices into summarized or entity-centric indices.', }), icon: 'managementApp', // there is currently no Transforms icon, so using the general management app icon - path: '/app/kibana#/management/data/transform', + path: '/app/management/data/transform', showOnHomePage: true, category: FeatureCatalogueCategory.ADMIN, }); diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/license_info.tsx b/x-pack/plugins/uptime/public/components/monitor/ml/license_info.tsx index 33fbbb117a11a..e37ec4cc4715d 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/license_info.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ml/license_info.tsx @@ -22,7 +22,7 @@ export const ShowLicenseInfo = () => {

{labels.START_TRAIL_DESC}

{labels.START_TRAIL} diff --git a/x-pack/plugins/watcher/public/plugin.ts b/x-pack/plugins/watcher/public/plugin.ts index a772d26308dfd..a8df9d6dbce29 100644 --- a/x-pack/plugins/watcher/public/plugin.ts +++ b/x-pack/plugins/watcher/public/plugin.ts @@ -77,7 +77,7 @@ export class WatcherUIPlugin implements Plugin { defaultMessage: 'Detect changes in your data by creating, managing, and monitoring alerts.', }), icon: 'watchesApp', - path: '/app/kibana#/management/insightsAndAlerting/watcher/watches', + path: '/app/management/insightsAndAlerting/watcher/watches', showOnHomePage: false, }; From a1c51d7536cc881581403147361deae7cd952146 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 20 May 2020 16:36:49 +0300 Subject: [PATCH 15/93] remove ui/public/management --- src/legacy/ui/public/management/index.d.ts | 27 -------- src/legacy/ui/public/management/index.js | 22 ------ .../public/components/breadcrumbs.ts | 6 +- .../public/components/langing/landing.tsx | 69 ++++++++++--------- .../management_app/management_app.tsx | 28 +++++--- .../management_app_wrapper.tsx | 2 +- .../management/public/utils}/breadcrumbs.ts | 8 +-- src/plugins/management/public/utils/index.ts | 1 + .../public/application/index.tsx | 2 +- .../application/mount_management_section.ts | 2 +- 10 files changed, 66 insertions(+), 101 deletions(-) delete mode 100644 src/legacy/ui/public/management/index.d.ts delete mode 100644 src/legacy/ui/public/management/index.js rename src/{legacy/ui/public/management => plugins/management/public/utils}/breadcrumbs.ts (85%) diff --git a/src/legacy/ui/public/management/index.d.ts b/src/legacy/ui/public/management/index.d.ts deleted file mode 100644 index 529efd36623a3..0000000000000 --- a/src/legacy/ui/public/management/index.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -declare module 'ui/management' { - export const SidebarNav: React.FC; - export const management: any; // TODO - properly provide types - export const MANAGEMENT_BREADCRUMB: { - text: string; - href: string; - }; -} diff --git a/src/legacy/ui/public/management/index.js b/src/legacy/ui/public/management/index.js deleted file mode 100644 index 25d3678c5dbba..0000000000000 --- a/src/legacy/ui/public/management/index.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { MANAGEMENT_BREADCRUMB } from './breadcrumbs'; -import { npStart } from 'ui/new_platform'; -export const management = npStart.plugins.management.legacy; diff --git a/src/plugins/index_pattern_management/public/components/breadcrumbs.ts b/src/plugins/index_pattern_management/public/components/breadcrumbs.ts index 6ffb929150b82..e62c46baa2c22 100644 --- a/src/plugins/index_pattern_management/public/components/breadcrumbs.ts +++ b/src/plugins/index_pattern_management/public/components/breadcrumbs.ts @@ -26,7 +26,7 @@ export function getListBreadcrumbs() { text: i18n.translate('indexPatternManagement.indexPatterns.listBreadcrumb', { defaultMessage: 'Index patterns', }), - href: `#/management/kibana/indexPatterns/`, + href: `/`, }, ]; } @@ -38,7 +38,7 @@ export function getCreateBreadcrumbs() { text: i18n.translate('indexPatternManagement.indexPatterns.createBreadcrumb', { defaultMessage: 'Create index pattern', }), - href: `#/management/kibana/indexPatterns/create`, + href: `/create`, }, ]; } @@ -48,7 +48,7 @@ export function getEditBreadcrumbs(indexPattern: IndexPattern) { ...getListBreadcrumbs(), { text: indexPattern.title, - href: `#/management/kibana/indexPatterns/patterns/${indexPattern.id}`, + href: `/patterns/${indexPattern.id}`, }, ]; } diff --git a/src/plugins/management/public/components/langing/landing.tsx b/src/plugins/management/public/components/langing/landing.tsx index a82044784bc95..c35f8b10b8163 100644 --- a/src/plugins/management/public/components/langing/landing.tsx +++ b/src/plugins/management/public/components/langing/landing.tsx @@ -31,41 +31,46 @@ import { interface ManagementLandingPageProps { version: string; + setBreadcrumbs: () => void; } -export const ManagementLandingPage = ({ version }: ManagementLandingPageProps) => ( - -
-
- - - -

+export const ManagementLandingPage = ({ version, setBreadcrumbs }: ManagementLandingPageProps) => { + setBreadcrumbs(); + + return ( + +
+
+ + + +

+ +

+
+ -

-
- - - -
+ +
- + - -

- -

-
-
- -); + +

+ +

+
+
+ + ); +}; diff --git a/src/plugins/management/public/components/management_app/management_app.tsx b/src/plugins/management/public/components/management_app/management_app.tsx index 7f3e61aa9b2f0..0e85333af3546 100644 --- a/src/plugins/management/public/components/management_app/management_app.tsx +++ b/src/plugins/management/public/components/management_app/management_app.tsx @@ -27,7 +27,7 @@ import { import { I18nProvider } from '@kbn/i18n/react'; import { EuiPage, EuiPageBody } from '@elastic/eui'; import { ManagementStart } from '../../types'; -import { ManagementSection } from '../../utils'; +import { ManagementSection, MANAGEMENT_BREADCRUMB } from '../../utils'; import { ManagementLandingPage } from '../langing'; import { ManagementSidebarNav } from '../management_sidebar_nav'; @@ -59,15 +59,18 @@ export const ManagementApp = ({ context, dependencies, history }: ManagementAppP }, []); const setBreadcrumbs = useCallback( - (crumbs: ChromeBreadcrumb[] = [], appHistory: ScopedHistory) => { - context.core.chrome.setBreadcrumbs( - crumbs.map(item => ({ - ...item, - ...(item.href ? reactRouterNavigate(appHistory, item.href) : {}), - })) - ); + (crumbs: ChromeBreadcrumb[] = [], appHistory?: ScopedHistory) => { + const wrapBreadcrumb = (item: ChromeBreadcrumb, scopedHistory: ScopedHistory) => ({ + ...item, + ...(item.href ? reactRouterNavigate(scopedHistory, item.href) : {}), + }); + + context.core.chrome.setBreadcrumbs([ + wrapBreadcrumb(MANAGEMENT_BREADCRUMB, history), + ...crumbs.map(item => wrapBreadcrumb(item, appHistory || history)), + ]); }, - [context.core.chrome] + [context.core.chrome, history] ); useEffect(() => { @@ -102,7 +105,12 @@ export const ManagementApp = ({ context, dependencies, history }: ManagementAppP )} } + component={() => ( + + )} /> diff --git a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx index 1e15a0eabfbf3..41546651e2684 100644 --- a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx +++ b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx @@ -25,7 +25,7 @@ import { Unmount } from '../../types'; interface ManagementSectionWrapperProps { app: ManagementApp; - setBreadcrumbs: (crumbs: ChromeBreadcrumb[], history: ScopedHistory) => void; + setBreadcrumbs: (crumbs?: ChromeBreadcrumb[], history?: ScopedHistory) => void; onAppMounted: (id: string) => void; history: AppMountParameters['history']; } diff --git a/src/legacy/ui/public/management/breadcrumbs.ts b/src/plugins/management/public/utils/breadcrumbs.ts similarity index 85% rename from src/legacy/ui/public/management/breadcrumbs.ts rename to src/plugins/management/public/utils/breadcrumbs.ts index 936e99caff565..147d157d29d7f 100644 --- a/src/legacy/ui/public/management/breadcrumbs.ts +++ b/src/plugins/management/public/utils/breadcrumbs.ts @@ -19,9 +19,9 @@ import { i18n } from '@kbn/i18n'; -export const MANAGEMENT_BREADCRUMB = Object.freeze({ - text: i18n.translate('common.ui.stackManagement.breadcrumb', { +export const MANAGEMENT_BREADCRUMB = { + text: i18n.translate('management.breadcrumb', { defaultMessage: 'Stack Management', }), - href: '#/management', -}); + href: '/', +}; diff --git a/src/plugins/management/public/utils/index.ts b/src/plugins/management/public/utils/index.ts index a1d759a3ec628..04c0c4c6811c7 100644 --- a/src/plugins/management/public/utils/index.ts +++ b/src/plugins/management/public/utils/index.ts @@ -17,5 +17,6 @@ * under the License. */ +export { MANAGEMENT_BREADCRUMB } from './breadcrumbs'; export { ManagementApp, RegisterManagementAppArgs } from './management_app'; export { ManagementSection, RegisterManagementSectionArgs } from './management_section'; diff --git a/x-pack/plugins/index_management/public/application/index.tsx b/x-pack/plugins/index_management/public/application/index.tsx index a9343552759b7..8da556cc81fcc 100644 --- a/x-pack/plugins/index_management/public/application/index.tsx +++ b/x-pack/plugins/index_management/public/application/index.tsx @@ -25,7 +25,7 @@ export const renderApp = ( const { i18n } = core; const { Context: I18nContext } = i18n; const { services, history } = dependencies; - console.log('2 before render', history); + render( diff --git a/x-pack/plugins/index_management/public/application/mount_management_section.ts b/x-pack/plugins/index_management/public/application/mount_management_section.ts index a432ccc190400..5e8282fcdcdf8 100644 --- a/x-pack/plugins/index_management/public/application/mount_management_section.ts +++ b/x-pack/plugins/index_management/public/application/mount_management_section.ts @@ -36,7 +36,7 @@ export async function mountManagementSection( breadcrumbService.setup(setBreadcrumbs); documentationService.setup(docLinks); - console.log('1 before render app', history); + const appDependencies: AppDependencies = { core: { fatalErrors, From ec4cde3e9e05cae80d40e61763f00483e40a8d40 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 20 May 2020 18:00:47 +0300 Subject: [PATCH 16/93] fix some links to management apps --- .../public/application/angular/discover.js | 4 ++-- .../components/top_nav/open_search_panel.js | 5 ++++- .../public/application/components/add_data.js | 3 ++- .../public/application/components/welcome.tsx | 4 ++-- .../public/angular/angular_config.tsx | 6 +++++- .../visualize/public/application/legacy_app.js | 18 ++++++------------ 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/plugins/discover/public/application/angular/discover.js b/src/plugins/discover/public/application/angular/discover.js index 84b4b2254e703..fefad01f55c59 100644 --- a/src/plugins/discover/public/application/angular/discover.js +++ b/src/plugins/discover/public/application/angular/discover.js @@ -162,8 +162,8 @@ app.config($routeProvider => { mapping: { search: '/', 'index-pattern': { - app: 'kibana', - path: `#/management/kibana/objects/savedSearches/${$route.current.params.id}`, + app: 'management', + path: `kibana/objects/savedSearches/${$route.current.params.id}`, }, }, toastNotifications, diff --git a/src/plugins/discover/public/application/components/top_nav/open_search_panel.js b/src/plugins/discover/public/application/components/top_nav/open_search_panel.js index 06267407dcb21..74154d41a6951 100644 --- a/src/plugins/discover/public/application/components/top_nav/open_search_panel.js +++ b/src/plugins/discover/public/application/components/top_nav/open_search_panel.js @@ -40,6 +40,7 @@ const SEARCH_OBJECT_TYPE = 'search'; export function OpenSearchPanel(props) { const { core: { uiSettings, savedObjects }, + addBasePath, } = getServices(); return ( @@ -86,7 +87,9 @@ export function OpenSearchPanel(props) { { const basePath = getServices().getBasePath(); + const renderCards = () => { const apmData = { title: intl.formatMessage({ @@ -296,7 +297,7 @@ const AddDataUi = ({ apmUiEnabled, isNewKibanaInstance, intl, mlEnabled }) => { { id="home.dataManagementDisableCollection" defaultMessage=" To stop collection, " /> - + { id="home.dataManagementEnableCollection" defaultMessage=" To start collection, " /> - + state:storeInSessionStorage, advancedSettingsLink: ( - + Date: Wed, 20 May 2020 19:01:37 +0300 Subject: [PATCH 17/93] fix management url for functional tests --- test/functional/config.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/functional/config.js b/test/functional/config.js index fee7a6f249f53..90bb372334742 100644 --- a/test/functional/config.js +++ b/test/functional/config.js @@ -84,8 +84,7 @@ export default async function({ readConfigFile }) { hash: '/list', }, settings: { - pathname: '/app/kibana', - hash: '/management', + pathname: '/app/management', }, timelion: { pathname: '/app/timelion', From 817f458430a30b087cde6488cef0c735c1e884a8 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 20 May 2020 19:48:43 +0300 Subject: [PATCH 18/93] add data-test-subj for EuiSideNavItem --- .../management_sidebar_nav/management_sidebar_nav.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx index 4e5addf0e7137..fe9126fd9e623 100644 --- a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx +++ b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { EuiIcon, EuiSideNav, EuiSideNavItemType, EuiScreenReaderOnly } from '@elastic/eui'; +import { EuiIcon, EuiSideNav, EuiScreenReaderOnly } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useState } from 'react'; import { AppMountParameters } from 'kibana/public'; @@ -83,7 +83,7 @@ export const ManagementSidebarNav = ({ const createNavItem = ( item: T, customParams: Record = {} - ): EuiSideNavItemType => { + ) => { const iconType = item.euiIconType || item.icon; return { @@ -91,6 +91,7 @@ export const ManagementSidebarNav = ({ name: item.title, isSelected: item.id === selectedId, icon: iconType ? : undefined, + 'data-test-subj': item.id, ...customParams, }; }; From edc75a0cab8ec1708159e66a57aad5c205473ad4 Mon Sep 17 00:00:00 2001 From: Matt Kime Date: Wed, 20 May 2020 16:29:28 -0500 Subject: [PATCH 19/93] partial progress --- .../ingest_pipelines/common/constants.ts | 2 +- .../public/management/management_urls.ts | 21 ++++++++-------- .../role_mappings_grid_page.test.tsx | 4 +-- .../role_mappings_management_app.tsx | 2 +- .../roles/edit_role/edit_role_page.tsx | 8 ++++-- .../roles/roles_grid/roles_grid_page.tsx | 25 +++++++++++++++---- .../management/roles/roles_management_app.tsx | 9 ++++++- 7 files changed, 48 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/ingest_pipelines/common/constants.ts b/x-pack/plugins/ingest_pipelines/common/constants.ts index de291e364e02f..4c6c6fefaad83 100644 --- a/x-pack/plugins/ingest_pipelines/common/constants.ts +++ b/x-pack/plugins/ingest_pipelines/common/constants.ts @@ -11,7 +11,7 @@ export const PLUGIN_ID = 'ingest_pipelines'; export const PLUGIN_MIN_LICENSE_TYPE = basicLicense; -export const BASE_PATH = '/management/ingest/ingest_pipelines'; +export const BASE_PATH = '/'; export const API_BASE_PATH = '/api/ingest_pipelines'; diff --git a/x-pack/plugins/security/public/management/management_urls.ts b/x-pack/plugins/security/public/management/management_urls.ts index 0d4e3fc920bdb..c7d325fd1d2d9 100644 --- a/x-pack/plugins/security/public/management/management_urls.ts +++ b/x-pack/plugins/security/public/management/management_urls.ts @@ -4,20 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ -const MANAGEMENT_PATH = '/management'; -const SECURITY_PATH = `${MANAGEMENT_PATH}/security`; -export const ROLES_PATH = `${SECURITY_PATH}/roles`; -export const EDIT_ROLES_PATH = `${ROLES_PATH}/edit`; -export const CLONE_ROLES_PATH = `${ROLES_PATH}/clone`; -export const USERS_PATH = `${SECURITY_PATH}/users`; +// const MANAGEMENT_PATH = '/management'; +// const SECURITY_PATH = `${MANAGEMENT_PATH}/security`; +// export const ROLES_PATH = `/roles`; +export const EDIT_ROLES_PATH = `/edit`; +export const CLONE_ROLES_PATH = `/clone`; +export const USERS_PATH = `../users`; export const EDIT_USERS_PATH = `${USERS_PATH}/edit`; -export const ROLE_MAPPINGS_PATH = `${SECURITY_PATH}/role_mappings`; +export const ROLE_MAPPINGS_PATH = `../role_mappings`; const CREATE_ROLE_MAPPING_PATH = `${ROLE_MAPPINGS_PATH}/edit`; -export const getEditRoleHref = (roleName: string) => - `#${ROLES_PATH}/edit/${encodeURIComponent(roleName)}`; +export const getEditRoleHref = (roleName: string) => `/edit/${encodeURIComponent(roleName)}`; -export const getCreateRoleMappingHref = () => `#${CREATE_ROLE_MAPPING_PATH}`; +export const getCreateRoleMappingHref = () => `${CREATE_ROLE_MAPPING_PATH}`; export const getEditRoleMappingHref = (roleMappingName: string) => - `#${CREATE_ROLE_MAPPING_PATH}/${encodeURIComponent(roleMappingName)}`; + `${CREATE_ROLE_MAPPING_PATH}/${encodeURIComponent(roleMappingName)}`; diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx index 0d343ad33d78e..2318384650e78 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx @@ -138,7 +138,7 @@ describe('RoleMappingsGridPage', () => { const links = findTestSubject(wrapper, 'roleMappingRoles').find(EuiLink); expect(links).toHaveLength(1); expect(links.at(0).props()).toMatchObject({ - href: '#/management/security/roles/edit/superuser', + href: '/edit/superuser', }); }); @@ -274,7 +274,7 @@ describe('RoleMappingsGridPage', () => { Object { "children":
kibana_user - + = ({ docLinks, uiCapabilities, notifications, + history, }) => { // We should keep the same mutable instance of Validator for every re-render since we'll // eventually enable validation after the first time user tries to save a role. @@ -462,7 +466,7 @@ export const EditRolePage: FunctionComponent = ({ const getReturnToRoleListButton = () => { return ( - + = ({ - {getFormButtons()} + {getFormButtons(history)}
); diff --git a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx index 04a74a1a9b99a..4ecfffb8e0212 100644 --- a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx @@ -26,6 +26,7 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { NotificationsStart } from 'src/core/public'; +import { ScopedHistory } from 'kibana/public'; import { Role, isRoleEnabled, @@ -38,10 +39,12 @@ import { RolesAPIClient } from '../roles_api_client'; import { ConfirmDelete } from './confirm_delete'; import { PermissionDenied } from './permission_denied'; import { DisabledBadge, DeprecatedBadge, ReservedBadge } from '../../badges'; +import { reactRouterNavigate } from '../../../../../../../src/plugins/kibana_react/public'; interface Props { notifications: NotificationsStart; rolesAPIClient: PublicMethodsOf; + history: ScopedHistory; } interface State { @@ -55,7 +58,7 @@ interface State { } const getRoleManagementHref = (action: 'edit' | 'clone', roleName?: string) => { - return `#/management/security/roles/${action}${roleName ? `/${roleName}` : ''}`; + return `/${action}${roleName ? `/${roleName}` : ''}`; }; export class RolesGridPage extends Component { @@ -106,7 +109,10 @@ export class RolesGridPage extends Component { - + { render: (name: string, record: Role) => { return ( - + {name} @@ -228,7 +237,10 @@ export class RolesGridPage extends Component { title={title} color={'primary'} iconType={'pencil'} - href={getRoleManagementHref('edit', role.name)} + {...reactRouterNavigate( + this.props.history, + getRoleManagementHref('edit', role.name) + )} /> ); }, @@ -248,7 +260,10 @@ export class RolesGridPage extends Component { title={title} color={'primary'} iconType={'copy'} - href={getRoleManagementHref('clone', role.name)} + {...reactRouterNavigate( + this.props.history, + getRoleManagementHref('edit', role.name) + )} /> ); }, diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.tsx index 860d07e400f65..1e6f720c7ce71 100644 --- a/x-pack/plugins/security/public/management/roles/roles_management_app.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_management_app.tsx @@ -59,7 +59,13 @@ export const rolesManagementApp = Object.freeze({ const rolesAPIClient = new RolesAPIClient(http); const RolesGridPageWithBreadcrumbs = () => { setBreadcrumbs(rolesBreadcrumbs); - return ; + return ( + + ); }; const EditRolePageWithBreadcrumbs = ({ action }: { action: 'edit' | 'clone' }) => { @@ -95,6 +101,7 @@ export const rolesManagementApp = Object.freeze({ docLinks={new DocumentationLinksService(docLinks)} uiCapabilities={application.capabilities} indexPatterns={data.indexPatterns} + history={history} /> ); }; From 9cccf1cd7cc0757423973bb14988f56dcf5df8f7 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 21 May 2020 12:45:17 +0300 Subject: [PATCH 20/93] fix some of ts issues --- .../roles/edit_role/edit_role_page.test.tsx | 5 +++-- .../roles/edit_role/edit_role_page.tsx | 16 +++------------- .../roles/roles_grid/roles_grid_page.test.tsx | 11 ++++++++++- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx index f1ee681331005..afb8b6ec5dbe0 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx @@ -8,7 +8,7 @@ import { ReactWrapper } from 'enzyme'; import React from 'react'; import { act } from '@testing-library/react'; import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; -import { Capabilities } from 'src/core/public'; +import { Capabilities, ScopedHistory } from 'src/core/public'; import { Feature } from '../../../../../features/public'; import { Role } from '../../../../common/model'; import { DocumentationLinksService } from '../documentation_links'; @@ -16,7 +16,7 @@ import { EditRolePage } from './edit_role_page'; import { SimplePrivilegeSection } from './privileges/kibana/simple_privilege_section'; import { TransformErrorSection } from './privileges/kibana/transform_error_section'; -import { coreMock } from '../../../../../../../src/core/public/mocks'; +import { coreMock, scopedHistoryMock } from '../../../../../../../src/core/public/mocks'; import { dataPluginMock } from '../../../../../../../src/plugins/data/public/mocks'; import { licenseMock } from '../../../../common/licensing/index.mock'; import { userAPIClientMock } from '../../users/index.mock'; @@ -183,6 +183,7 @@ function getProps({ fatalErrors, spacesEnabled, uiCapabilities: buildUICapabilities(canManageSpaces), + history: (scopedHistoryMock.create() as unknown) as ScopedHistory, }; } diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx index b5c083c6a6110..760a869f12ef9 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx @@ -54,7 +54,6 @@ import { RoleIndexPrivilege, getExtendedRoleDeprecationNotice, } from '../../../../common/model'; -import { ROLES_PATH } from '../../management_urls'; import { RoleValidationResult, RoleValidator } from './validate_role'; import { DeleteRoleButton } from './delete_role_button'; import { ElasticsearchPrivileges, KibanaPrivilegesRegion } from './privileges'; @@ -267,7 +266,8 @@ function useFeatures( } function backToRoleList() { - window.location.hash = ROLES_PATH; + // todo: window.location.hash = ROLES_PATH; + // window.location.hash = ''; } export const EditRolePage: FunctionComponent = ({ @@ -572,11 +572,8 @@ export const EditRolePage: FunctionComponent = ({
{getFormTitle()} - - {description} - {isRoleReserved && ( @@ -590,7 +587,6 @@ export const EditRolePage: FunctionComponent = ({ )} - {isDeprecatedRole && ( @@ -601,18 +597,12 @@ export const EditRolePage: FunctionComponent = ({ /> )} - - {getRoleName()} - {getElasticsearchPrivileges()} - {getKibanaPrivileges()} - - - {getFormButtons(history)} + {getFormButtons()}
); diff --git a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx index 410d5bc9f7643..2976bde141b76 100644 --- a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx @@ -12,10 +12,11 @@ import { RolesAPIClient } from '../roles_api_client'; import { PermissionDenied } from './permission_denied'; import { RolesGridPage } from './roles_grid_page'; -import { coreMock } from '../../../../../../../src/core/public/mocks'; +import { coreMock, scopedHistoryMock } from '../../../../../../../src/core/public/mocks'; import { rolesAPIClientMock } from '../index.mock'; import { ReservedBadge, DisabledBadge } from '../../badges'; import { findTestSubject } from 'test_utils/find_test_subject'; +import { ScopedHistory } from 'kibana/public'; const mock403 = () => ({ body: { statusCode: 403 } }); @@ -41,7 +42,10 @@ const waitForRender = async ( describe('', () => { let apiClientMock: jest.Mocked>; + let history: ScopedHistory; + beforeEach(() => { + history = (scopedHistoryMock.create() as unknown) as ScopedHistory; apiClientMock = rolesAPIClientMock.create(); apiClientMock.getRoles.mockResolvedValue([ { @@ -68,6 +72,7 @@ describe('', () => { const wrapper = mountWithIntl( ); @@ -85,6 +90,7 @@ describe('', () => { const wrapper = mountWithIntl( ); @@ -104,6 +110,7 @@ describe('', () => { const wrapper = mountWithIntl( ); @@ -117,6 +124,7 @@ describe('', () => { const wrapper = mountWithIntl( ); @@ -146,6 +154,7 @@ describe('', () => { const wrapper = mountWithIntl( ); From 5cff1a8778c2b5b26918100e34388d0b375199ff Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Thu, 21 May 2020 13:15:02 +0300 Subject: [PATCH 21/93] Fixed breadcrumbs for data index management --- .../public/application/services/breadcrumbs.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/index_management/public/application/services/breadcrumbs.ts b/x-pack/plugins/index_management/public/application/services/breadcrumbs.ts index 8128ccd545dce..e3d0058b2b9b0 100644 --- a/x-pack/plugins/index_management/public/application/services/breadcrumbs.ts +++ b/x-pack/plugins/index_management/public/application/services/breadcrumbs.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ import { i18n } from '@kbn/i18n'; -import { BASE_PATH } from '../../../common/constants'; import { ManagementAppMountParams } from '../../../../../../src/plugins/management/public'; type SetBreadcrumbs = ManagementAppMountParams['setBreadcrumbs']; @@ -28,7 +27,7 @@ class BreadcrumbService { text: i18n.translate('xpack.idxMgmt.breadcrumb.homeLabel', { defaultMessage: 'Index Management', }), - href: `#${BASE_PATH}`, + href: `/`, }, ]; @@ -38,7 +37,7 @@ class BreadcrumbService { text: i18n.translate('xpack.idxMgmt.breadcrumb.templatesLabel', { defaultMessage: 'Templates', }), - href: `#${BASE_PATH}templates`, + href: `/templates`, }, ]; From bda4b31e1d938244c2ccd40ed3e68bffc9b78f31 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 21 May 2020 14:33:11 +0300 Subject: [PATCH 22/93] [kibana/spaces] section --- .../management_sidebar_nav.tsx | 12 ++-------- .../secure_space_message.tsx | 12 ++++++++-- .../enabled_features.test.tsx.snap | 2 +- .../enabled_features.test.tsx | 5 ++++ .../enabled_features/enabled_features.tsx | 6 ++++- .../edit_space/manage_space_page.test.tsx | 17 +++++++++++++- .../edit_space/manage_space_page.tsx | 15 +++++++----- .../spaces_grid_pages.test.tsx.snap | 6 +++-- .../spaces_grid/spaces_grid_page.tsx | 23 +++++++++++-------- .../spaces_grid/spaces_grid_pages.test.tsx | 14 ++++++++++- .../management/spaces_management_app.tsx | 10 ++++++-- .../components/manage_spaces_button.tsx | 2 +- 12 files changed, 88 insertions(+), 36 deletions(-) diff --git a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx index fe9126fd9e623..b880fd465a885 100644 --- a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx +++ b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx @@ -53,11 +53,7 @@ export const ManagementSidebarNav = ({ const toggleOpenOnMobile = () => setIsSideNavOpenOnMobile(!isSideNavOpenOnMobile); const sectionsToNavItems = (managementSections: ManagementSection[]) => { - if (!managementSections) { - return undefined; - } - - return (managementSections || []) + return managementSections .filter(section => section.getAppsEnabled()) .map(section => ({ ...createNavItem(section, { @@ -67,11 +63,7 @@ export const ManagementSidebarNav = ({ }; const appsToNavItems = (managementApps: ManagementApp[]) => { - if (!managementApps) { - return undefined; - } - - return (managementApps || []) + return managementApps .filter(app => app.enabled) .map(app => ({ ...createNavItem(app, { diff --git a/x-pack/plugins/spaces/public/management/components/secure_space_message/secure_space_message.tsx b/x-pack/plugins/spaces/public/management/components/secure_space_message/secure_space_message.tsx index 38d8451b658a8..3ce24f35ec8de 100644 --- a/x-pack/plugins/spaces/public/management/components/secure_space_message/secure_space_message.tsx +++ b/x-pack/plugins/spaces/public/management/components/secure_space_message/secure_space_message.tsx @@ -8,8 +8,13 @@ import { EuiHorizontalRule, EuiLink, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import React, { Fragment } from 'react'; +import { ApplicationStart } from 'kibana/public'; -export const SecureSpaceMessage = () => { +interface SecureSpaceMessageProps { + getUrlForApp: ApplicationStart['getUrlForApp']; +} + +export const SecureSpaceMessage = (props: SecureSpaceMessageProps) => { const rolesLinkTextAriaLabel = i18n.translate( 'xpack.spaces.management.secureSpaceMessage.rolesLinkTextAriaLabel', { defaultMessage: 'Roles management page' } @@ -24,7 +29,10 @@ export const SecureSpaceMessage = () => { defaultMessage="Want to assign a role to a space? Go to {rolesLink}." values={{ rolesLink: ( - + { + const getUrlForApp = (appId: string) => appId; + it(`renders as expected`, () => { expect( shallowWithIntl( @@ -44,6 +46,7 @@ describe('EnabledFeatures', () => { space={space} securityEnabled={true} onChange={jest.fn()} + getUrlForApp={getUrlForApp} /> ) ).toMatchSnapshot(); @@ -58,6 +61,7 @@ describe('EnabledFeatures', () => { space={space} securityEnabled={true} onChange={changeHandler} + getUrlForApp={getUrlForApp} /> ); @@ -92,6 +96,7 @@ describe('EnabledFeatures', () => { space={space} securityEnabled={true} onChange={changeHandler} + getUrlForApp={getUrlForApp} /> ); diff --git a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.tsx b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.tsx index 6f0462a6ddcc2..9fe3bac73eeb1 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.tsx @@ -8,6 +8,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiLink, EuiSpacer, EuiText, EuiTitle } from import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import React, { Component, Fragment, ReactNode } from 'react'; +import { ApplicationStart } from 'kibana/public'; import { FeatureConfig } from '../../../../../../plugins/features/public'; import { Space } from '../../../../common/model/space'; import { getEnabledFeatures } from '../../lib/feature_utils'; @@ -19,6 +20,7 @@ interface Props { features: FeatureConfig[]; securityEnabled: boolean; onChange: (space: Partial) => void; + getUrlForApp: ApplicationStart['getUrlForApp']; } export class EnabledFeatures extends Component { @@ -136,7 +138,9 @@ export class EnabledFeatures extends Component { defaultMessage="Want to secure access? Go to {rolesLink}." values={{ rolesLink: ( - + { + const getUrlForApp = (appId: string) => appId; + const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; + it('allows a space to be created', async () => { const spacesManager = spacesManagerMock.create(); spacesManager.createSpace = jest.fn(spacesManager.createSpace); @@ -46,6 +51,8 @@ describe('ManageSpacePage', () => { getFeatures={featuresStart.getFeatures} notifications={notificationServiceMock.createStartContract()} securityEnabled={true} + getUrlForApp={getUrlForApp} + history={history} capabilities={{ navLinks: {}, management: {}, @@ -103,6 +110,8 @@ describe('ManageSpacePage', () => { getFeatures={featuresStart.getFeatures} notifications={notificationServiceMock.createStartContract()} securityEnabled={true} + getUrlForApp={getUrlForApp} + history={history} capabilities={{ navLinks: {}, management: {}, @@ -152,6 +161,8 @@ describe('ManageSpacePage', () => { getFeatures={() => Promise.reject(error)} notifications={notifications} securityEnabled={true} + getUrlForApp={getUrlForApp} + history={history} capabilities={{ navLinks: {}, management: {}, @@ -187,6 +198,8 @@ describe('ManageSpacePage', () => { getFeatures={featuresStart.getFeatures} notifications={notificationServiceMock.createStartContract()} securityEnabled={true} + getUrlForApp={getUrlForApp} + history={history} capabilities={{ navLinks: {}, management: {}, @@ -246,6 +259,8 @@ describe('ManageSpacePage', () => { getFeatures={featuresStart.getFeatures} notifications={notificationServiceMock.createStartContract()} securityEnabled={true} + getUrlForApp={getUrlForApp} + history={history} capabilities={{ navLinks: {}, management: {}, diff --git a/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx b/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx index 0cb471854f815..9733e6c84f99e 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx @@ -18,7 +18,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import _ from 'lodash'; import React, { Component, Fragment } from 'react'; -import { Capabilities, NotificationsStart } from 'src/core/public'; +import { ApplicationStart, Capabilities, NotificationsStart, ScopedHistory } from 'src/core/public'; import { Feature, FeaturesPluginStart } from '../../../../features/public'; import { isReservedSpace } from '../../../common'; import { Space } from '../../../common/model/space'; @@ -40,6 +40,8 @@ interface Props { onLoadSpace?: (space: Space) => void; capabilities: Capabilities; securityEnabled: boolean; + history: ScopedHistory; + getUrlForApp: ApplicationStart['getUrlForApp']; } interface State { @@ -154,6 +156,7 @@ export class ManageSpacePage extends Component { space={this.state.space} features={this.state.features} onChange={this.onSpaceChange} + getUrlForApp={this.props.getUrlForApp} securityEnabled={this.props.securityEnabled} /> @@ -195,7 +198,7 @@ export class ManageSpacePage extends Component { public maybeGetSecureSpacesMessage = () => { if (this.editingExistingSpace() && this.props.securityEnabled) { - return ; + return ; } return null; }; @@ -387,7 +390,9 @@ export class ManageSpacePage extends Component { } ) ); - window.location.hash = `#/management/kibana/spaces`; + + this.backToSpacesList(); + if (requireRefresh) { setTimeout(() => { window.location.reload(); @@ -408,9 +413,7 @@ export class ManageSpacePage extends Component { }); }; - private backToSpacesList = () => { - window.location.hash = `#/management/kibana/spaces`; - }; + private backToSpacesList = () => this.props.history.push('/'); private editingExistingSpace = () => !!this.props.spaceId; } diff --git a/x-pack/plugins/spaces/public/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap b/x-pack/plugins/spaces/public/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap index aa6db7e22fd5d..200c9c55a4f7c 100644 --- a/x-pack/plugins/spaces/public/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap +++ b/x-pack/plugins/spaces/public/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap @@ -39,7 +39,7 @@ exports[`SpacesGridPage renders as expected 1`] = ` > - +
`; diff --git a/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx b/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx index df5e6a2ca34af..014684704710a 100644 --- a/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx @@ -20,7 +20,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { Capabilities, NotificationsStart } from 'src/core/public'; +import { ApplicationStart, Capabilities, NotificationsStart, ScopedHistory } from 'src/core/public'; import { Feature, FeaturesPluginStart } from '../../../../features/public'; import { isReservedSpace } from '../../../common'; import { DEFAULT_SPACE_ID } from '../../../common/constants'; @@ -32,6 +32,7 @@ import { ConfirmDeleteModal } from '../components/confirm_delete_modal'; import { SecureSpaceMessage } from '../components/secure_space_message'; import { UnauthorizedPrompt } from '../components/unauthorized_prompt'; import { getEnabledFeatures } from '../lib/feature_utils'; +import { reactRouterNavigate } from '../../../../../../src/plugins/kibana_react/public'; interface Props { spacesManager: SpacesManager; @@ -39,6 +40,8 @@ interface Props { getFeatures: FeaturesPluginStart['getFeatures']; capabilities: Capabilities; securityEnabled: boolean; + history: ScopedHistory; + getUrlForApp: ApplicationStart['getUrlForApp']; } interface State { @@ -71,7 +74,9 @@ export class SpacesGridPage extends Component { return (
{this.getPageContent()} - {this.props.securityEnabled && } + {this.props.securityEnabled && ( + + )} {this.getConfirmDeleteModal()}
); @@ -137,7 +142,7 @@ export class SpacesGridPage extends Component { public getPrimaryActionButton() { return ( - + { name: '', width: '50px', render: (value: string, record: Space) => ( - + ), @@ -258,7 +263,9 @@ export class SpacesGridPage extends Component { }), sortable: true, render: (value: string, record: Space) => ( - {value} + + {value} + ), }, { @@ -338,7 +345,7 @@ export class SpacesGridPage extends Component { )} color={'primary'} iconType={'pencil'} - href={this.getEditSpacePath(record)} + {...reactRouterNavigate(this.props.history, this.getEditSpacePath(record))} /> ), }, @@ -364,9 +371,7 @@ export class SpacesGridPage extends Component { ]; } - private getEditSpacePath = (space: Space) => { - return `#/management/kibana/spaces/edit/${encodeURIComponent(space.id)}`; - }; + private getEditSpacePath = (space: Space) => `edit/${encodeURIComponent(space.id)}`; private onDeleteSpaceClick = (space: Space) => { this.setState({ diff --git a/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_pages.test.tsx b/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_pages.test.tsx index 9b7dc921b9a25..1868823823a1a 100644 --- a/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_pages.test.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_pages.test.tsx @@ -5,12 +5,13 @@ */ import React from 'react'; +import { ScopedHistory } from 'kibana/public'; import { mountWithIntl, shallowWithIntl, nextTick } from 'test_utils/enzyme_helpers'; import { SpaceAvatar } from '../../space_avatar'; import { spacesManagerMock } from '../../spaces_manager/mocks'; import { SpacesManager } from '../../spaces_manager'; import { SpacesGridPage } from './spaces_grid_page'; -import { httpServiceMock } from 'src/core/public/mocks'; +import { httpServiceMock, scopedHistoryMock } from 'src/core/public/mocks'; import { notificationServiceMock } from 'src/core/public/mocks'; import { featuresPluginMock } from '../../../../features/public/mocks'; import { Feature } from '../../../../features/public'; @@ -52,6 +53,9 @@ featuresStart.getFeatures.mockResolvedValue([ ]); describe('SpacesGridPage', () => { + const getUrlForApp = (appId: string) => appId; + const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; + it('renders as expected', () => { const httpStart = httpServiceMock.createStartContract(); httpStart.get.mockResolvedValue([]); @@ -63,6 +67,8 @@ describe('SpacesGridPage', () => { getFeatures={featuresStart.getFeatures} notifications={notificationServiceMock.createStartContract()} securityEnabled={true} + getUrlForApp={getUrlForApp} + history={history} capabilities={{ navLinks: {}, management: {}, @@ -84,6 +90,8 @@ describe('SpacesGridPage', () => { getFeatures={featuresStart.getFeatures} notifications={notificationServiceMock.createStartContract()} securityEnabled={true} + getUrlForApp={getUrlForApp} + history={history} capabilities={{ navLinks: {}, management: {}, @@ -116,6 +124,8 @@ describe('SpacesGridPage', () => { getFeatures={featuresStart.getFeatures} notifications={notifications} securityEnabled={true} + getUrlForApp={getUrlForApp} + history={history} capabilities={{ navLinks: {}, management: {}, @@ -149,6 +159,8 @@ describe('SpacesGridPage', () => { getFeatures={() => Promise.reject(error)} notifications={notifications} securityEnabled={true} + getUrlForApp={getUrlForApp} + history={history} capabilities={{ navLinks: {}, management: {}, diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx index 9216cc31ee77c..050babdbc7b19 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx @@ -42,7 +42,7 @@ export const spacesManagementApp = Object.freeze({ text: i18n.translate('xpack.spaces.management.breadcrumb', { defaultMessage: 'Spaces', }), - href: `#${basePath}`, + href: `/`, }, ]; @@ -54,6 +54,8 @@ export const spacesManagementApp = Object.freeze({ getFeatures={features.getFeatures} notifications={notifications} spacesManager={spacesManager} + history={history} + getUrlForApp={application.getUrlForApp} securityEnabled={securityLicense?.getFeatures().showLinks ?? false} /> ); @@ -75,6 +77,8 @@ export const spacesManagementApp = Object.freeze({ getFeatures={features.getFeatures} notifications={notifications} spacesManager={spacesManager} + history={history} + getUrlForApp={application.getUrlForApp} securityEnabled={securityLicense?.getFeatures().showLinks ?? false} /> ); @@ -88,7 +92,7 @@ export const spacesManagementApp = Object.freeze({ ...spacesBreadcrumbs, { text: space.name, - href: `#${basePath}/edit/${encodeURIComponent(space.id)}`, + href: `/edit/${encodeURIComponent(space.id)}`, }, ]); }; @@ -101,6 +105,8 @@ export const spacesManagementApp = Object.freeze({ spacesManager={spacesManager} spaceId={spaceId} onLoadSpace={onLoadSpace} + history={history} + getUrlForApp={application.getUrlForApp} securityEnabled={securityLicense?.getFeatures().showLinks ?? false} /> ); diff --git a/x-pack/plugins/spaces/public/nav_control/components/manage_spaces_button.tsx b/x-pack/plugins/spaces/public/nav_control/components/manage_spaces_button.tsx index 456b7b0189a75..98467ebdb790b 100644 --- a/x-pack/plugins/spaces/public/nav_control/components/manage_spaces_button.tsx +++ b/x-pack/plugins/spaces/public/nav_control/components/manage_spaces_button.tsx @@ -46,6 +46,6 @@ export class ManageSpacesButton extends Component { this.props.onClick(); } - this.props.navigateToApp('kibana', { path: '#/management/kibana/spaces' }); + this.props.navigateToApp('management', { path: 'kibana/spaces' }); }; } From d49c9f9b2193417f3db6b21b888c441afce03e40 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 21 May 2020 15:56:27 +0300 Subject: [PATCH 23/93] fix functional test --- .../scripted_fields_table/components/header/header.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.tsx index dc48f61d1aa65..e432b9b466367 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.tsx @@ -22,9 +22,13 @@ import { withRouter, RouteComponentProps } from 'react-router-dom'; import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiText, EuiTitle } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import { ScopedHistory } from 'kibana/public'; + +import { reactRouterNavigate } from '../../../../../../../kibana_react/public'; interface HeaderProps extends RouteComponentProps { indexPatternId: string; + history: ScopedHistory; } export const Header = withRouter(({ indexPatternId, history }: HeaderProps) => ( @@ -52,9 +56,7 @@ export const Header = withRouter(({ indexPatternId, history }: HeaderProps) => ( { - history.push(`${indexPatternId}/create-field/`); - }} + {...reactRouterNavigate(history, `patterns/${indexPatternId}/create-field/`)} > Date: Thu, 21 May 2020 16:23:18 +0300 Subject: [PATCH 24/93] [role_management] fix Breadcrumbs --- .../security/public/management/roles/roles_management_app.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.tsx index 1e6f720c7ce71..596f95a78bdfd 100644 --- a/x-pack/plugins/security/public/management/roles/roles_management_app.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_management_app.tsx @@ -31,7 +31,7 @@ export const rolesManagementApp = Object.freeze({ const rolesBreadcrumbs = [ { text: i18n.translate('xpack.security.roles.breadcrumb', { defaultMessage: 'Roles' }), - href: `#${basePath}`, + href: `/`, }, ]; @@ -74,7 +74,7 @@ export const rolesManagementApp = Object.freeze({ setBreadcrumbs([ ...rolesBreadcrumbs, action === 'edit' && roleName - ? { text: roleName, href: `#${basePath}/edit/${encodeURIComponent(roleName)}` } + ? { text: roleName, href: `/edit/${encodeURIComponent(roleName)}` } : { text: i18n.translate('xpack.security.roles.createBreadcrumb', { defaultMessage: 'Create', From 57cfa836586b8fb543639e99b147fff342dd78bc Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 21 May 2020 18:01:13 +0300 Subject: [PATCH 25/93] [api_keys] fix Breadcrumbs and Navigation --- .../components/header/header.test.tsx | 3 ++- .../api_keys_grid/api_keys_grid_page.test.tsx | 1 + .../api_keys/api_keys_grid/api_keys_grid_page.tsx | 9 +++++++-- .../api_keys_grid/empty_prompt/empty_prompt.tsx | 11 +++++++++-- .../api_keys/api_keys_management_app.test.tsx | 2 +- .../management/api_keys/api_keys_management_app.tsx | 7 ++++--- 6 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx index 11fdae39aee3c..75a3baad11b30 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx @@ -20,6 +20,7 @@ import React from 'react'; import { render } from 'enzyme'; import { RouteComponentProps } from 'react-router-dom'; +import { ScopedHistory } from 'kibana/public'; import { Header } from './header'; @@ -28,7 +29,7 @@ describe('Header', () => { const component = render( diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx index dea04a0eac396..e3efedbe8226a 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx @@ -67,6 +67,7 @@ describe('APIKeysGridPage', () => { const getViewProperties = () => { const { docLinks, notifications } = coreMock.createStart(); return { + getUrlForApp: (id: string) => id, docLinks: new DocumentationLinksService(docLinks), notifications, apiKeysAPIClient: apiClientMock, diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx index 9db09a34d3c3f..548ce21e30ff2 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx @@ -26,7 +26,7 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import moment from 'moment-timezone'; -import { NotificationsStart } from 'src/core/public'; +import { ApplicationStart, NotificationsStart } from 'src/core/public'; import { SectionLoading } from '../../../../../../../src/plugins/es_ui_shared/public'; import { ApiKey, ApiKeyToInvalidate } from '../../../../common/model'; import { APIKeysAPIClient } from '../api_keys_api_client'; @@ -40,6 +40,7 @@ interface Props { notifications: NotificationsStart; docLinks: DocumentationLinksService; apiKeysAPIClient: PublicMethodsOf; + getUrlForApp: ApplicationStart['getUrlForApp']; } interface State { @@ -137,7 +138,11 @@ export class APIKeysGridPage extends Component { if (!isLoadingTable && apiKeys && apiKeys.length === 0) { return ( - + ); } diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/empty_prompt.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/empty_prompt.tsx index ef1ac40ca4b32..b688a017e4540 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/empty_prompt.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/empty_prompt.tsx @@ -5,6 +5,8 @@ */ import React, { Fragment } from 'react'; +import { ApplicationStart } from 'kibana/public'; + import { EuiEmptyPrompt, EuiButton, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { DocumentationLinksService } from '../../documentation_links'; @@ -12,9 +14,14 @@ import { DocumentationLinksService } from '../../documentation_links'; interface Props { isAdmin: boolean; docLinks: DocumentationLinksService; + getUrlForApp: ApplicationStart['getUrlForApp']; } -export const EmptyPrompt: React.FunctionComponent = ({ isAdmin, docLinks }) => ( +export const EmptyPrompt: React.FunctionComponent = ({ + isAdmin, + docLinks, + getUrlForApp, +}) => ( = ({ isAdmin, docLinks } actions={ - + { }); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); - expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: '#/some-base-path', text: 'API Keys' }]); + expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: '/', text: 'API Keys' }]); expect(container).toMatchInlineSnapshot(`
Page: {"notifications":{"toasts":{}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"apiKeysAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}}} diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx index b9ec5b35b3f9d..444089c9e0f4e 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx @@ -25,18 +25,18 @@ export const apiKeysManagementApp = Object.freeze({ title: i18n.translate('xpack.security.management.apiKeysTitle', { defaultMessage: 'API Keys', }), - async mount({ basePath, element, setBreadcrumbs }) { + async mount({ basePath, element, setBreadcrumbs, history }) { setBreadcrumbs([ { text: i18n.translate('xpack.security.apiKeys.breadcrumb', { defaultMessage: 'API Keys', }), - href: `#${basePath}`, + href: `/`, }, ]); const [ - [{ docLinks, http, notifications, i18n: i18nStart }], + [{ docLinks, http, notifications, i18n: i18nStart, application }], { APIKeysGridPage }, { APIKeysAPIClient }, ] = await Promise.all([ @@ -48,6 +48,7 @@ export const apiKeysManagementApp = Object.freeze({ render( Date: Thu, 21 May 2020 18:43:06 +0300 Subject: [PATCH 26/93] Fixed routing for remote cluster --- .../remote_clusters/public/application/app.js | 21 +++++----- .../public/application/index.js | 5 +-- .../remote_cluster_add/remote_cluster_add.js | 3 +- .../remote_cluster_edit.js | 8 ++-- .../detail_panel/detail_panel.js | 23 +++++------ .../remote_cluster_list.js | 8 ++-- .../remote_cluster_table.js | 9 +++-- .../public/application/services/breadcrumb.ts | 4 +- .../public/application/services/redirect.ts | 2 +- .../public/application/services/routing.js | 39 ------------------- .../application/store/actions/add_cluster.js | 3 +- .../application/store/actions/edit_cluster.js | 3 +- 12 files changed, 41 insertions(+), 87 deletions(-) diff --git a/x-pack/plugins/remote_clusters/public/application/app.js b/x-pack/plugins/remote_clusters/public/application/app.js index dca9568eaee6c..714887b039a42 100644 --- a/x-pack/plugins/remote_clusters/public/application/app.js +++ b/x-pack/plugins/remote_clusters/public/application/app.js @@ -6,7 +6,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { Switch, Route, Redirect, withRouter } from 'react-router-dom'; +import { Switch, Route, Redirect, Router } from 'react-router-dom'; import { UIM_APP_LOAD } from './constants'; import { registerRouter, setUserHasLeftApp, trackUiMetric, METRIC_TYPE } from './services'; @@ -22,15 +22,16 @@ class AppComponent extends Component { constructor(...args) { super(...args); + setUserHasLeftApp(false); this.registerRouter(); } registerRouter() { // Share the router with the app without requiring React or context. - const { history, location } = this.props; + const { history } = this.props; registerRouter({ history, - route: { location }, + route: { location: history.location }, }); } @@ -45,18 +46,16 @@ class AppComponent extends Component { render() { return ( -
+ - - - - - + + + -
+ ); } } -export const App = withRouter(AppComponent); +export const App = AppComponent; diff --git a/x-pack/plugins/remote_clusters/public/application/index.js b/x-pack/plugins/remote_clusters/public/application/index.js index 5881e886c7384..25e171c9ef51d 100644 --- a/x-pack/plugins/remote_clusters/public/application/index.js +++ b/x-pack/plugins/remote_clusters/public/application/index.js @@ -6,7 +6,6 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { Router } from 'react-router-dom'; import { Provider } from 'react-redux'; import { App } from './app'; @@ -20,9 +19,7 @@ export const renderApp = (elem, I18nContext, appDependencies, history) => { - - - + , diff --git a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.js index 4f9c5dcd38254..757fe5f3cd688 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.js +++ b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.js @@ -10,7 +10,6 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { EuiPageContent } from '@elastic/eui'; -import { CRUD_APP_BASE_PATH } from '../../constants'; import { getRouter, redirect, extractQueryParams } from '../../services'; import { setBreadcrumbs } from '../../services/breadcrumb'; import { RemoteClusterPageTitle, RemoteClusterForm } from '../components'; @@ -49,7 +48,7 @@ export class RemoteClusterAdd extends PureComponent { const decodedRedirect = decodeURIComponent(redirectUrl); redirect(decodedRedirect); } else { - history.push(CRUD_APP_BASE_PATH); + history.push('/list'); } }; diff --git a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.js index d582fc2b0af1b..4c65a2f42f0b8 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.js +++ b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.js @@ -20,8 +20,8 @@ import { EuiTextColor, } from '@elastic/eui'; -import { CRUD_APP_BASE_PATH } from '../../constants'; -import { extractQueryParams, getRouter, getRouterLinkProps, redirect } from '../../services'; +import { reactRouterNavigate } from '../../../../../../../src/plugins/kibana_react/public'; +import { extractQueryParams, getRouter, redirect } from '../../services'; import { setBreadcrumbs } from '../../services/breadcrumb'; import { RemoteClusterPageTitle, RemoteClusterForm, ConfiguredByNodeWarning } from '../components'; @@ -89,7 +89,7 @@ export class RemoteClusterEdit extends Component { const decodedRedirect = decodeURIComponent(redirectUrl); redirect(decodedRedirect); } else { - history.push(CRUD_APP_BASE_PATH); + history.push('/list'); openDetailPanel(clusterName); } }; @@ -143,7 +143,7 @@ export class RemoteClusterEdit extends Component { diff --git a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/detail_panel/detail_panel.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/detail_panel/detail_panel.js index 94c5fd6ce7c3f..ad8d047cd8b61 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/detail_panel/detail_panel.js +++ b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/detail_panel/detail_panel.js @@ -30,12 +30,11 @@ import { EuiTextColor, EuiTitle, } from '@elastic/eui'; - -import { CRUD_APP_BASE_PATH } from '../../../constants'; +import { reactRouterNavigate } from '../../../../../../../../src/plugins/kibana_react/public'; import { PROXY_MODE } from '../../../../../common/constants'; -import { getRouterLinkProps } from '../../../services'; import { ConfiguredByNodeWarning } from '../../components'; import { ConnectionStatus, RemoveClusterButtonProvider } from '../components'; +import { getRouter } from '../../../services'; import { proxyModeUrl } from '../../../services/documentation'; export class DetailPanel extends Component { @@ -114,7 +113,8 @@ export class DetailPanel extends Component { renderClusterWithDeprecatedSettingWarning( { hasDeprecatedProxySetting, isConfiguredByNode }, - clusterName + clusterName, + history ) { if (!hasDeprecatedProxySetting) { return null; @@ -156,7 +156,7 @@ export class DetailPanel extends Component { defaultMessage="{editLink} to update the settings." values={{ editLink: ( - + {this.renderClusterConfiguredByNodeWarning(cluster)} - {this.renderClusterWithDeprecatedSettingWarning(cluster, clusterName)} + {this.renderClusterWithDeprecatedSettingWarning(cluster, clusterName, history)} {this.renderCluster(cluster)} )} @@ -465,7 +465,7 @@ export class DetailPanel extends Component { ); } - renderFlyoutFooter() { + renderFlyoutFooter(history) { const { cluster, clusterName, closeDetailPanel } = this.props; return ( @@ -507,7 +507,7 @@ export class DetailPanel extends Component { - {this.renderFlyoutBody()} + {this.renderFlyoutBody(history)} - {this.renderFlyoutFooter()} + {this.renderFlyoutFooter(history)} ); } diff --git a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.js index 207aa8045c011..6d40cbbeb82ae 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.js +++ b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.js @@ -28,8 +28,8 @@ import { EuiCallOut, } from '@elastic/eui'; -import { CRUD_APP_BASE_PATH } from '../../constants'; -import { getRouterLinkProps, extractQueryParams } from '../../services'; +import { reactRouterNavigate } from '../../../../../../../src/plugins/kibana_react/public'; +import { extractQueryParams } from '../../services'; import { setBreadcrumbs } from '../../services/breadcrumb'; import { RemoteClusterTable } from './remote_cluster_table'; @@ -99,7 +99,7 @@ export class RemoteClusterList extends Component { {isAuthorized && ( @@ -185,7 +185,7 @@ export class RemoteClusterList extends Component { } actions={ { @@ -94,6 +94,7 @@ export class RemoteClusterTable extends Component { render() { const { openDetailPanel } = this.props; const { selectedItems, filteredClusters } = this.state; + const { history } = getRouter(); const columns = [ { @@ -256,7 +257,7 @@ export class RemoteClusterTable extends Component { iconType="pencil" color="primary" isDisabled={isConfiguredByNode} - {...getRouterLinkProps(`${CRUD_APP_BASE_PATH}/edit/${name}`)} + {...reactRouterNavigate(history, `/edit/${name}`)} disabled={isConfiguredByNode} /> diff --git a/x-pack/plugins/remote_clusters/public/application/services/breadcrumb.ts b/x-pack/plugins/remote_clusters/public/application/services/breadcrumb.ts index f90a0d3456166..feec7d523e7c1 100644 --- a/x-pack/plugins/remote_clusters/public/application/services/breadcrumb.ts +++ b/x-pack/plugins/remote_clusters/public/application/services/breadcrumb.ts @@ -6,8 +6,6 @@ import { i18n } from '@kbn/i18n'; -import { CRUD_APP_BASE_PATH } from '../constants'; - interface Breadcrumb { text: string; href?: string; @@ -28,7 +26,7 @@ export function init(setGlobalBreadcrumbs: (breadcrumbs: Breadcrumb[]) => void): text: i18n.translate('xpack.remoteClusters.listBreadcrumbTitle', { defaultMessage: 'Remote Clusters', }), - href: `#${CRUD_APP_BASE_PATH}/list`, + href: `/list`, }, add: { text: i18n.translate('xpack.remoteClusters.addBreadcrumbTitle', { diff --git a/x-pack/plugins/remote_clusters/public/application/services/redirect.ts b/x-pack/plugins/remote_clusters/public/application/services/redirect.ts index 00a97fa74c5ce..1130dbc77fc75 100644 --- a/x-pack/plugins/remote_clusters/public/application/services/redirect.ts +++ b/x-pack/plugins/remote_clusters/public/application/services/redirect.ts @@ -13,5 +13,5 @@ export function init(_navigateToApp: CoreStart['application']['navigateToApp']) } export function redirect(path: string) { - navigateToApp('kibana', { path: `#${path}` }); + navigateToApp('management', { path }); } diff --git a/x-pack/plugins/remote_clusters/public/application/services/routing.js b/x-pack/plugins/remote_clusters/public/application/services/routing.js index 3b78e73c6b3af..c86c9756cfcc8 100644 --- a/x-pack/plugins/remote_clusters/public/application/services/routing.js +++ b/x-pack/plugins/remote_clusters/public/application/services/routing.js @@ -8,8 +8,6 @@ * This file based on guidance from https://github.com/elastic/eui/blob/master/wiki/react-router.md */ -import { createLocation } from 'history'; - let _userHasLeftApp = false; export function setUserHasLeftApp(userHasLeftApp) { @@ -20,11 +18,6 @@ export function getUserHasLeftApp() { return _userHasLeftApp; } -const isModifiedEvent = event => - !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); - -const isLeftClickEvent = event => event.button === 0; - let router; export function registerRouter(reactRouter) { router = reactRouter; @@ -33,35 +26,3 @@ export function registerRouter(reactRouter) { export function getRouter() { return router; } - -/** - * The logic for generating hrefs and onClick handlers from the `to` prop is largely borrowed from - * https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/Link.js. - */ -export function getRouterLinkProps(to) { - const location = - typeof to === 'string' ? createLocation(to, null, null, router.history.location) : to; - - const href = router.history.createHref(location); - - const onClick = event => { - if (event.defaultPrevented) { - return; - } - - // If target prop is set (e.g. to "_blank"), let browser handle link. - if (event.target.getAttribute('target')) { - return; - } - - if (isModifiedEvent(event) || !isLeftClickEvent(event)) { - return; - } - - // Prevent regular link behavior, which causes a browser refresh. - event.preventDefault(); - router.history.push(location); - }; - - return { href, onClick }; -} diff --git a/x-pack/plugins/remote_clusters/public/application/store/actions/add_cluster.js b/x-pack/plugins/remote_clusters/public/application/store/actions/add_cluster.js index 0b7838f48b137..de23a47e71309 100644 --- a/x-pack/plugins/remote_clusters/public/application/store/actions/add_cluster.js +++ b/x-pack/plugins/remote_clusters/public/application/store/actions/add_cluster.js @@ -6,7 +6,6 @@ import { i18n } from '@kbn/i18n'; -import { CRUD_APP_BASE_PATH } from '../../constants'; import { addCluster as sendAddClusterRequest, getRouter, @@ -108,7 +107,7 @@ export const addCluster = cluster => async dispatch => { // This will open the new job in the detail panel. Note that we're *not* showing a success toast // here, because it would partially obscure the detail panel. history.push({ - pathname: `${CRUD_APP_BASE_PATH}/list`, + pathname: `/list`, search: `?cluster=${cluster.name}`, }); } diff --git a/x-pack/plugins/remote_clusters/public/application/store/actions/edit_cluster.js b/x-pack/plugins/remote_clusters/public/application/store/actions/edit_cluster.js index 062704472521e..0f10f6c9b5e08 100644 --- a/x-pack/plugins/remote_clusters/public/application/store/actions/edit_cluster.js +++ b/x-pack/plugins/remote_clusters/public/application/store/actions/edit_cluster.js @@ -7,7 +7,6 @@ import { i18n } from '@kbn/i18n'; import { toasts, fatalError } from '../../services/notification'; -import { CRUD_APP_BASE_PATH } from '../../constants'; import { loadClusters } from './load_clusters'; import { @@ -95,7 +94,7 @@ export const editCluster = cluster => async dispatch => { // This will open the edited cluster in the detail panel. Note that we're *not* showing a success toast // here, because it would partially obscure the detail panel. history.push({ - pathname: `${CRUD_APP_BASE_PATH}/list`, + pathname: `/list`, search: `?cluster=${cluster.name}`, }); } From c3ee79448576aff0ce5cd61598f7af380e8aaaae Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 21 May 2020 19:33:52 +0300 Subject: [PATCH 27/93] [role_mapping] Partial progress --- .../public/management/management_urls.ts | 9 +++------ .../edit_role_mapping_page.tsx | 8 +++----- .../create_role_mapping_button.tsx | 14 +++++++++---- .../role_mappings_grid_page.tsx | 20 +++++++++++++------ .../role_mappings_management_app.tsx | 6 ++++-- .../role_table_display/role_table_display.tsx | 8 ++++++-- 6 files changed, 40 insertions(+), 25 deletions(-) diff --git a/x-pack/plugins/security/public/management/management_urls.ts b/x-pack/plugins/security/public/management/management_urls.ts index c7d325fd1d2d9..d113c13f63f72 100644 --- a/x-pack/plugins/security/public/management/management_urls.ts +++ b/x-pack/plugins/security/public/management/management_urls.ts @@ -11,12 +11,9 @@ export const EDIT_ROLES_PATH = `/edit`; export const CLONE_ROLES_PATH = `/clone`; export const USERS_PATH = `../users`; export const EDIT_USERS_PATH = `${USERS_PATH}/edit`; -export const ROLE_MAPPINGS_PATH = `../role_mappings`; -const CREATE_ROLE_MAPPING_PATH = `${ROLE_MAPPINGS_PATH}/edit`; -export const getEditRoleHref = (roleName: string) => `/edit/${encodeURIComponent(roleName)}`; - -export const getCreateRoleMappingHref = () => `${CREATE_ROLE_MAPPING_PATH}`; +export const getEditRoleHref = (roleName: string) => + `../roles/edit/${encodeURIComponent(roleName)}`; export const getEditRoleMappingHref = (roleMappingName: string) => - `${CREATE_ROLE_MAPPING_PATH}/${encodeURIComponent(roleMappingName)}`; + `${EDIT_ROLES_PATH}/${encodeURIComponent(roleMappingName)}`; diff --git a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx index 142b53cbb50f2..29d25dad8f98f 100644 --- a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx @@ -19,7 +19,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { NotificationsStart } from 'src/core/public'; +import { NotificationsStart, ScopedHistory } from 'src/core/public'; import { RoleMapping } from '../../../../common/model'; import { RuleEditorPanel } from './rule_editor_panel'; import { @@ -29,7 +29,6 @@ import { SectionLoading, } from '../components'; import { RolesAPIClient } from '../../roles'; -import { ROLE_MAPPINGS_PATH } from '../../management_urls'; import { validateRoleMappingForSave } from './services/role_mapping_validation'; import { MappingInfoPanel } from './mapping_info_panel'; import { DocumentationLinksService } from '../documentation_links'; @@ -55,6 +54,7 @@ interface Props { rolesAPIClient: PublicMethodsOf; notifications: NotificationsStart; docLinks: DocumentationLinksService; + history: ScopedHistory; } export class EditRoleMappingPage extends Component { @@ -342,7 +342,5 @@ export class EditRoleMappingPage extends Component { } } - private backToRoleMappingsList = () => { - window.location.hash = ROLE_MAPPINGS_PATH; - }; + private backToRoleMappingsList = () => this.props.history.push('/'); } diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx index 6fe4bcc7a0bbb..a5ce984efd06f 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx @@ -7,15 +7,21 @@ import React from 'react'; import { EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { getCreateRoleMappingHref } from '../../../management_urls'; +import { withRouter } from 'react-router-dom'; +import { EDIT_ROLES_PATH } from '../../../management_urls'; +import { reactRouterNavigate } from '../../../../../../../../src/plugins/kibana_react/public'; -export const CreateRoleMappingButton = () => { +export const CreateRoleMappingButton = withRouter(({ history }) => { return ( - + ); -}; +}); diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx index 5802c3444e85f..758b10632d36a 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx @@ -24,7 +24,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { NotificationsStart } from 'src/core/public'; +import { NotificationsStart, ScopedHistory } from 'src/core/public'; import { RoleMapping, Role } from '../../../../common/model'; import { EmptyPrompt } from './empty_prompt'; import { @@ -33,18 +33,20 @@ import { PermissionDenied, SectionLoading, } from '../components'; -import { getCreateRoleMappingHref, getEditRoleMappingHref } from '../../management_urls'; +import { EDIT_ROLES_PATH, getEditRoleMappingHref } from '../../management_urls'; import { DocumentationLinksService } from '../documentation_links'; import { RoleMappingsAPIClient } from '../role_mappings_api_client'; import { RoleTableDisplay } from '../../role_table_display'; import { RolesAPIClient } from '../../roles'; import { EnabledBadge, DisabledBadge } from '../../badges'; +import { reactRouterNavigate } from '../../../../../../../src/plugins/kibana_react/public'; interface Props { rolesAPIClient: PublicMethodsOf; roleMappingsAPI: PublicMethodsOf; notifications: NotificationsStart; docLinks: DocumentationLinksService; + history: ScopedHistory; } interface State { @@ -160,7 +162,10 @@ export class RoleMappingsGridPage extends Component { - + { render: (roleMappingName: string) => { return ( {roleMappingName} @@ -327,7 +332,7 @@ export class RoleMappingsGridPage extends Component { const role: Role | string = this.state.roles?.find(r => r.name === rolename) ?? rolename; - return ; + return ; }); return
{roleLinks}
; }, @@ -371,7 +376,10 @@ export class RoleMappingsGridPage extends Component { iconType="pencil" color="primary" data-test-subj={`editRoleMappingButton-${record.name}`} - href={getEditRoleMappingHref(record.name)} + {...reactRouterNavigate( + this.props.history, + getEditRoleMappingHref(record.name) + )} /> ); diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx index 7e3aaea93784b..d9c0f082454b6 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx @@ -26,13 +26,13 @@ export const roleMappingsManagementApp = Object.freeze({ title: i18n.translate('xpack.security.management.roleMappingsTitle', { defaultMessage: 'Role Mappings', }), - async mount({ basePath, element, setBreadcrumbs, history }) { + async mount({ element, setBreadcrumbs, history }) { const roleMappingsBreadcrumbs = [ { text: i18n.translate('xpack.security.roleMapping.breadcrumb', { defaultMessage: 'Role Mappings', }), - href: `#${basePath}`, + href: `/`, }, ]; @@ -60,6 +60,7 @@ export const roleMappingsManagementApp = Object.freeze({ rolesAPIClient={new RolesAPIClient(http)} roleMappingsAPI={roleMappingsAPIClient} docLinks={dockLinksService} + history={history} /> ); }; @@ -85,6 +86,7 @@ export const roleMappingsManagementApp = Object.freeze({ rolesAPIClient={new RolesAPIClient(http)} notifications={notifications} docLinks={dockLinksService} + history={history} /> ); }; diff --git a/x-pack/plugins/security/public/management/role_table_display/role_table_display.tsx b/x-pack/plugins/security/public/management/role_table_display/role_table_display.tsx index 28978f0090011..89097a955b5de 100644 --- a/x-pack/plugins/security/public/management/role_table_display/role_table_display.tsx +++ b/x-pack/plugins/security/public/management/role_table_display/role_table_display.tsx @@ -6,14 +6,17 @@ import React from 'react'; import { EuiLink, EuiToolTip, EuiIcon } from '@elastic/eui'; +import { ScopedHistory } from 'kibana/public'; import { Role, isRoleDeprecated, getExtendedRoleDeprecationNotice } from '../../../common/model'; import { getEditRoleHref } from '../management_urls'; +import { reactRouterNavigate } from '../../../../../../src/plugins/kibana_react/public'; interface Props { role: Role | string; + history: ScopedHistory; } -export const RoleTableDisplay = ({ role }: Props) => { +export const RoleTableDisplay = ({ role, history }: Props) => { let content; let href; if (typeof role === 'string') { @@ -35,5 +38,6 @@ export const RoleTableDisplay = ({ role }: Props) => { content =
{role.name}
; href = getEditRoleHref(role.name); } - return {content}; + + return {content}; }; From 6f3d7ce0bdf90c7db9b64c2f17392056414998ba Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 22 May 2020 12:23:45 +0300 Subject: [PATCH 28/93] [users] partial progress --- .../users/edit_user/edit_user_page.tsx | 24 +++++++++++-------- .../users/users_grid/users_grid_page.tsx | 19 +++++++++++---- .../management/users/users_management_app.tsx | 6 +++-- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx index 49da4c66a7630..b845c6bc60059 100644 --- a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx +++ b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx @@ -30,7 +30,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { NotificationsStart } from 'src/core/public'; +import { NotificationsStart, ScopedHistory } from 'src/core/public'; import { User, EditUser, Role, isRoleDeprecated } from '../../../../common/model'; import { AuthenticationServiceSetup } from '../../../authentication'; import { USERS_PATH } from '../../management_urls'; @@ -47,6 +47,7 @@ interface Props { rolesAPIClient: PublicMethodsOf; authc: AuthenticationServiceSetup; notifications: NotificationsStart; + history: ScopedHistory; } interface State { @@ -61,10 +62,6 @@ interface State { formError: UserValidationResult | null; } -function backToUserList() { - window.location.hash = USERS_PATH; -} - export class EditUserPage extends Component { private validator: UserValidator; @@ -102,6 +99,10 @@ export class EditUserPage extends Component { } } + private backToUserList() { + this.props.history.push('/'); + } + private async setCurrentUser() { const { username, userAPIClient, rolesAPIClient, notifications, authc } = this.props; let { user, currentUser } = this.state; @@ -120,7 +121,7 @@ export class EditUserPage extends Component { }), text: get(err, 'body.message') || err.message, }); - return backToUserList(); + return this.backToUserList(); } } @@ -148,7 +149,7 @@ export class EditUserPage extends Component { private handleDelete = (usernames: string[], errors: string[]) => { if (errors.length === 0) { - backToUserList(); + this.backToUserList(); } }; @@ -184,7 +185,7 @@ export class EditUserPage extends Component { ) ); - backToUserList(); + this.backToUserList(); } catch (e) { this.props.notifications.toasts.addDanger( i18n.translate('xpack.security.management.users.editUser.savingUserErrorMessage', { @@ -549,7 +550,7 @@ export class EditUserPage extends Component { {reserved && ( - + this.backToUserList()}> {
- + this.backToUserList()} + > ; rolesAPIClient: PublicMethodsOf; notifications: NotificationsStart; + history: ScopedHistory; } interface State { @@ -70,6 +72,7 @@ export class UsersGridPage extends Component { public render() { const { users, roles, permissionDenied, showDeleteConfirmation, selection } = this.state; + if (permissionDenied) { return ( @@ -107,7 +110,10 @@ export class UsersGridPage extends Component { sortable: true, truncateText: true, render: (username: string) => ( - + {username} ), @@ -144,7 +150,9 @@ export class UsersGridPage extends Component { render: (rolenames: string[]) => { const roleLinks = rolenames.map((rolename, index) => { const roleDefinition = roles?.find((role) => role.name === rolename) ?? rolename; - return ; + return ( + + ); }); return
{roleLinks}
; }, @@ -219,7 +227,10 @@ export class UsersGridPage extends Component { - + ); }; @@ -66,7 +67,7 @@ export const usersManagementApp = Object.freeze({ setBreadcrumbs([ ...usersBreadcrumbs, username - ? { text: username, href: `#${basePath}/edit/${encodeURIComponent(username)}` } + ? { text: username, href: `/edit/${encodeURIComponent(username)}` } : { text: i18n.translate('xpack.security.users.createBreadcrumb', { defaultMessage: 'Create', @@ -81,6 +82,7 @@ export const usersManagementApp = Object.freeze({ rolesAPIClient={new RolesAPIClient(http)} notifications={notifications} username={username} + history={history} /> ); }; From 01256378a02dd09886a5c4a4cfa0c9cfe8b35c49 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 22 May 2020 13:03:59 +0300 Subject: [PATCH 29/93] [watcher] partial progress --- x-pack/plugins/watcher/public/application/app.tsx | 11 +++++++++-- .../watcher/public/application/lib/breadcrumbs.ts | 2 +- .../watcher/public/application/lib/navigation.ts | 7 +++---- .../monitoring_watch_edit/monitoring_watch_edit.tsx | 9 ++++++--- .../sections/watch_list/components/watch_list.tsx | 7 +++++-- x-pack/plugins/watcher/public/plugin.ts | 3 ++- x-pack/test/functional/apps/security/role_mappings.ts | 6 +++--- 7 files changed, 29 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/watcher/public/application/app.tsx b/x-pack/plugins/watcher/public/application/app.tsx index ca4371045c45d..555440f9fbbec 100644 --- a/x-pack/plugins/watcher/public/application/app.tsx +++ b/x-pack/plugins/watcher/public/application/app.tsx @@ -6,7 +6,13 @@ import React, { useEffect, useState } from 'react'; import { Observable } from 'rxjs'; -import { DocLinksStart, HttpSetup, ToastsSetup, IUiSettingsClient } from 'kibana/public'; +import { + DocLinksStart, + HttpSetup, + ToastsSetup, + IUiSettingsClient, + ApplicationStart, +} from 'kibana/public'; import { Router, Switch, Route, Redirect, withRouter, RouteComponentProps } from 'react-router-dom'; @@ -42,6 +48,7 @@ export interface AppDeps { licenseStatus$: Observable; setBreadcrumbs: Parameters[0]['setBreadcrumbs']; history: ManagementAppMountParams['history']; + getUrlForApp: ApplicationStart['getUrlForApp']; } export const App = (deps: AppDeps) => { @@ -65,7 +72,7 @@ export const App = (deps: AppDeps) => { iconType="help" > {message}{' '} - + { router = aRouter; }; export const goToWatchList = () => { - router.history.push({ pathname: `${BASE_PATH}watches` }); + router.history.push({ pathname: `/watches` }); }; export const goToCreateThresholdAlert = () => { - router.history.push({ pathname: `${BASE_PATH}watches/new-watch/threshold` }); + router.history.push({ pathname: `/watches/new-watch/threshold` }); }; export const goToCreateAdvancedWatch = () => { - router.history.push({ pathname: `${BASE_PATH}watches/new-watch/json` }); + router.history.push({ pathname: `/watches/new-watch/json` }); }; diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx index 156a6f2eda890..27b510e839563 100644 --- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx @@ -15,12 +15,17 @@ import { EuiCallOut, EuiText, EuiLink, + EuiButtonIcon, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { WatchContext } from '../../watch_context'; +import { useAppContext } from '../../../../app_context'; + +import { reactRouterNavigate } from '../../../../../../../../../src/plugins/kibana_react/public'; export const MonitoringWatchEdit = ({ pageTitle }: { pageTitle: string }) => { const { watch } = useContext(WatchContext); + const { history } = useAppContext(); const systemWatchTitle = ( { values={{ watchName: watch.name, watchStatusLink: ( - + { // hooks const { setBreadcrumbs, + history, links: { watcherGettingStartedUrl }, } = useAppContext(); const [selection, setSelection] = useState([]); @@ -242,7 +245,7 @@ export const WatchList = () => { return ( {id} @@ -326,7 +329,7 @@ export const WatchList = () => { )} iconType="pencil" color="primary" - href={`#/management/insightsAndAlerting/watcher/watches/watch/${watch.id}/edit`} + {...reactRouterNavigate(history, `/watches/watch/${watch.id}/edit`)} data-test-subj="editWatchButton" /> diff --git a/x-pack/plugins/watcher/public/plugin.ts b/x-pack/plugins/watcher/public/plugin.ts index a8df9d6dbce29..80f8503af67ce 100644 --- a/x-pack/plugins/watcher/public/plugin.ts +++ b/x-pack/plugins/watcher/public/plugin.ts @@ -40,7 +40,7 @@ export class WatcherUIPlugin implements Plugin { order: 3, mount: async ({ element, setBreadcrumbs, history }) => { const [core] = await getStartServices(); - const { i18n: i18nDep, docLinks, savedObjects } = core; + const { i18n: i18nDep, docLinks, savedObjects, application } = core; const { boot } = await import('./application/boot'); const { TimeBuckets } = await import('./legacy'); @@ -59,6 +59,7 @@ export class WatcherUIPlugin implements Plugin { I18nContext: i18nDep.Context, createTimeBuckets: () => new TimeBuckets(uiSettings, data), history, + getUrlForApp: application.getUrlForApp, }); }, }); diff --git a/x-pack/test/functional/apps/security/role_mappings.ts b/x-pack/test/functional/apps/security/role_mappings.ts index 16d8fdd4b3c1e..dcd411e75232d 100644 --- a/x-pack/test/functional/apps/security/role_mappings.ts +++ b/x-pack/test/functional/apps/security/role_mappings.ts @@ -84,8 +84,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('displays an error and returns to the listing page when navigating to a role mapping which does not exist', async () => { await pageObjects.common.navigateToActualUrl( - 'kibana', - '#/management/security/role_mappings/edit/i-do-not-exist', + 'management', + 'security/role_mappings/edit/i-do-not-exist', { ensureCurrentUrl: false } ); @@ -93,7 +93,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const url = parse(await browser.getCurrentUrl()); - expect(url.hash).to.eql('#/management/security/role_mappings'); + expect(url.pathname).to.eql('/management/security/role_mappings'); }); describe('with role mappings', () => { From 3d147a8b6836700b5fd9d810b6efc75752fb2f30 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 22 May 2020 14:08:00 +0300 Subject: [PATCH 30/93] fix eslint issues --- .../public/components/management_app/management_app.tsx | 6 +++--- .../management_app_wrapper/management_app_wrapper.tsx | 2 +- .../management_sidebar_nav/management_sidebar_nav.tsx | 8 ++++---- .../management/public/management_sections_service.ts | 2 +- src/plugins/management/public/utils/management_section.ts | 4 ++-- .../apm/public/components/app/Main/route_config/index.tsx | 2 +- .../remote_clusters/public/application/services/index.js | 8 +------- .../security/public/management/management_service.test.ts | 2 +- 8 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/plugins/management/public/components/management_app/management_app.tsx b/src/plugins/management/public/components/management_app/management_app.tsx index 0e85333af3546..165d478c8954e 100644 --- a/src/plugins/management/public/components/management_app/management_app.tsx +++ b/src/plugins/management/public/components/management_app/management_app.tsx @@ -67,7 +67,7 @@ export const ManagementApp = ({ context, dependencies, history }: ManagementAppP context.core.chrome.setBreadcrumbs([ wrapBreadcrumb(MANAGEMENT_BREADCRUMB, history), - ...crumbs.map(item => wrapBreadcrumb(item, appHistory || history)), + ...crumbs.map((item) => wrapBreadcrumb(item, appHistory || history)), ]); }, [context.core.chrome, history] @@ -88,8 +88,8 @@ export const ManagementApp = ({ context, dependencies, history }: ManagementAppP - {sections.map(section => - section.apps.map(app => ( + {sections.map((section) => + section.apps.map((app) => ( ( diff --git a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx index 41546651e2684..ecf90260c3eaa 100644 --- a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx +++ b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx @@ -54,7 +54,7 @@ export const ManagementAppWrapper = ({ onAppMounted(app.id); if (mountResult instanceof Promise) { - mountResult.then(um => { + mountResult.then((um) => { unmount.current = um; }); } else { diff --git a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx index b880fd465a885..d4bba784c38aa 100644 --- a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx +++ b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx @@ -54,8 +54,8 @@ export const ManagementSidebarNav = ({ const sectionsToNavItems = (managementSections: ManagementSection[]) => { return managementSections - .filter(section => section.getAppsEnabled()) - .map(section => ({ + .filter((section) => section.getAppsEnabled()) + .map((section) => ({ ...createNavItem(section, { items: appsToNavItems(section.apps), }), @@ -64,8 +64,8 @@ export const ManagementSidebarNav = ({ const appsToNavItems = (managementApps: ManagementApp[]) => { return managementApps - .filter(app => app.enabled) - .map(app => ({ + .filter((app) => app.enabled) + .map((app) => ({ ...createNavItem(app, { ...reactRouterNavigate(history, app.basePath), }), diff --git a/src/plugins/management/public/management_sections_service.ts b/src/plugins/management/public/management_sections_service.ts index 4fc041df340ce..85aa73de7b5bb 100644 --- a/src/plugins/management/public/management_sections_service.ts +++ b/src/plugins/management/public/management_sections_service.ts @@ -61,7 +61,7 @@ export class ManagementSectionsService { getAllSections: this.getAllSections, getSectionsEnabled: () => this.getAllSections() - .filter(section => section.enabled && section.apps.length) + .filter((section) => section.enabled && section.apps.length) .sort((a, b) => a.order - b.order), }; } diff --git a/src/plugins/management/public/utils/management_section.ts b/src/plugins/management/public/utils/management_section.ts index e00c2b942e0c4..970a4d5ac05c8 100644 --- a/src/plugins/management/public/utils/management_section.ts +++ b/src/plugins/management/public/utils/management_section.ts @@ -49,10 +49,10 @@ export class ManagementSection extends ManagementItem { } getApp(id: ManagementApp['id']) { - return this.apps.find(app => app.id === id); + return this.apps.find((app) => app.id === id); } getAppsEnabled() { - return this.apps.filter(app => app.enabled).sort((a, b) => a.order - b.order); + return this.apps.filter((app) => app.enabled).sort((a, b) => a.order - b.order); } } diff --git a/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx b/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx index 206cee00d2daa..0eaeeaa20aa57 100644 --- a/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx @@ -53,7 +53,7 @@ export const routes: BreadcrumbRoute[] = [ path: '', render: renderAsRedirectTo('/services'), breadcrumb: 'APM', - name: RouteName.HOME + name: RouteName.HOME, }, { exact: true, diff --git a/x-pack/plugins/remote_clusters/public/application/services/index.js b/x-pack/plugins/remote_clusters/public/application/services/index.js index 387a04b6e5d8c..ce8d06b6e2278 100644 --- a/x-pack/plugins/remote_clusters/public/application/services/index.js +++ b/x-pack/plugins/remote_clusters/public/application/services/index.js @@ -14,12 +14,6 @@ export { isAddressValid, isPortValid } from './validate_address'; export { extractQueryParams } from './query_params'; -export { - setUserHasLeftApp, - getUserHasLeftApp, - registerRouter, - getRouter, - getRouterLinkProps, -} from './routing'; +export { setUserHasLeftApp, getUserHasLeftApp, registerRouter, getRouter } from './routing'; export { trackUiMetric, METRIC_TYPE } from './ui_metric'; diff --git a/x-pack/plugins/security/public/management/management_service.test.ts b/x-pack/plugins/security/public/management/management_service.test.ts index 78dcda411191a..c707206569bf5 100644 --- a/x-pack/plugins/security/public/management/management_service.test.ts +++ b/x-pack/plugins/security/public/management/management_service.test.ts @@ -127,7 +127,7 @@ describe('ManagementService', () => { sections: { getSection: jest .fn() - .mockReturnValue({ getApp: jest.fn().mockImplementation(id => mockApps.get(id)) }), + .mockReturnValue({ getApp: jest.fn().mockImplementation((id) => mockApps.get(id)) }), getAllSections: jest.fn(), getSectionsEnabled: jest.fn(), }, From 821984e0de63889053c005b3542b4878b301737e Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 22 May 2020 15:19:18 +0300 Subject: [PATCH 31/93] [snapshot_restore] partial progress --- .../public/application/app_context.tsx | 3 +- .../policy_form/steps/step_logistics.tsx | 6 ++- .../public/application/constants/index.ts | 2 +- .../public/application/index.tsx | 10 +++-- .../application/mount_management_section.ts | 3 +- .../policy_details/policy_details.tsx | 15 +++++--- .../policy_details/tabs/tab_history.tsx | 10 ++++- .../policy_details/tabs/tab_summary.tsx | 12 ++++-- .../sections/home/policy_list/policy_list.tsx | 4 +- .../policy_list/policy_table/policy_table.tsx | 11 ++++-- .../repository_details/repository_details.tsx | 18 +++++++-- .../home/repository_list/repository_list.tsx | 4 +- .../repository_table/repository_table.tsx | 11 ++++-- .../home/restore_list/restore_list.tsx | 6 ++- .../snapshot_details/snapshot_details.tsx | 14 +++++-- .../snapshot_details/tabs/tab_summary.tsx | 9 ++++- .../home/snapshot_list/snapshot_list.tsx | 12 +++--- .../snapshot_table/snapshot_table.tsx | 20 +++++++--- .../application/services/navigation/links.ts | 38 ++++++++----------- 19 files changed, 138 insertions(+), 70 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/app_context.tsx b/x-pack/plugins/snapshot_restore/public/application/app_context.tsx index 8ad05b3de5e98..d50f051c37fc0 100644 --- a/x-pack/plugins/snapshot_restore/public/application/app_context.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/app_context.tsx @@ -7,7 +7,7 @@ import React, { createContext, useContext } from 'react'; import { i18n } from '@kbn/i18n'; -import { CoreStart } from '../../../../../src/core/public'; +import { CoreStart, ScopedHistory } from '../../../../../src/core/public'; import { ClientConfigType } from '../types'; import { HttpService, UiMetricService } from './services'; @@ -19,6 +19,7 @@ export interface AppDependencies { httpService: HttpService; uiMetricService: UiMetricService; i18n: typeof i18n; + history: ScopedHistory; }; config: ClientConfigType; } diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_logistics.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_logistics.tsx index 21e6bc6530707..8a7338f4db4e7 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_logistics.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_logistics.tsx @@ -30,6 +30,8 @@ import { documentationLinksService } from '../../../services/documentation'; import { SectionLoading } from '../../'; import { StepProps } from './'; +import { reactRouterNavigate } from '../../../../../../../../src/plugins/kibana_react/public'; + export const PolicyStepLogistics: React.FunctionComponent = ({ policy, updatePolicy, @@ -50,7 +52,7 @@ export const PolicyStepLogistics: React.FunctionComponent = ({ sendRequest: reloadRepositories, } = useLoadRepositories(); - const { i18n } = useServices(); + const { i18n, history } = useServices(); // State for touched inputs const [touched, setTouched] = useState({ @@ -226,7 +228,7 @@ export const PolicyStepLogistics: React.FunctionComponent = ({ }} actions={ ( +interface AppWithRouterProps { + history: ScopedHistory; +} + +const AppWithRouter = ({ history }: AppWithRouterProps) => ( ); -export const renderApp = (elem: Element, dependencies: AppDependencies, history: ScopedHistory) => { +export const renderApp = (elem: Element, dependencies: AppDependencies) => { render( - + , elem ); diff --git a/x-pack/plugins/snapshot_restore/public/application/mount_management_section.ts b/x-pack/plugins/snapshot_restore/public/application/mount_management_section.ts index 87a9170307ea6..3f28e78c6028c 100644 --- a/x-pack/plugins/snapshot_restore/public/application/mount_management_section.ts +++ b/x-pack/plugins/snapshot_restore/public/application/mount_management_section.ts @@ -41,8 +41,9 @@ export async function mountManagementSection( httpService, uiMetricService: services.uiMetricService, i18n, + history, }, }; - return renderApp(element, appDependencies, history); + return renderApp(element, appDependencies); } diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/policy_details.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/policy_details.tsx index e1c20a76ba07c..5959ad6441f5d 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/policy_details.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/policy_details.tsx @@ -41,6 +41,8 @@ import { } from '../../../../components'; import { TabSummary, TabHistory } from './tabs'; +import { reactRouterNavigate } from '../../../../../../../../../src/plugins/kibana_react/public'; + interface Props { policyName: SlmPolicy['name']; onClose: () => void; @@ -62,7 +64,7 @@ export const PolicyDetails: React.FunctionComponent = ({ onPolicyDeleted, onPolicyExecuted, }) => { - const { i18n, uiMetricService } = useServices(); + const { i18n, uiMetricService, history } = useServices(); const { error, data: policyDetails, sendRequest: reload } = useLoadPolicy(policyName); const [activeTab, setActiveTab] = useState(TAB_SUMMARY); const [isPopoverOpen, setIsPopoverOpen] = useState(false); @@ -258,7 +260,7 @@ export const PolicyDetails: React.FunctionComponent = ({ } ), icon: 'pencil', - href: linkToEditPolicy(policyName), + ...reactRouterNavigate(history, linkToEditPolicy(policyName)), }, { name: i18n.translate( @@ -317,9 +319,12 @@ export const PolicyDetails: React.FunctionComponent = ({ diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/tabs/tab_history.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/tabs/tab_history.tsx index 22c37241348e7..d6f379045a472 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/tabs/tab_history.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/tabs/tab_history.tsx @@ -23,6 +23,9 @@ import { import { SlmPolicy } from '../../../../../../../common/types'; import { FormattedDateTime } from '../../../../../components'; import { linkToSnapshot } from '../../../../../services/navigation'; +import { useServices } from '../../../../../app_context'; + +import { reactRouterNavigate } from '../../../../../../../../../../src/plugins/kibana_react/public'; interface Props { policy: SlmPolicy; @@ -30,6 +33,7 @@ interface Props { export const TabHistory: React.FunctionComponent = ({ policy }) => { const { lastSuccess, lastFailure, nextExecutionMillis, name, repository } = policy; + const { history } = useServices(); const renderLastSuccess = () => { if (!lastSuccess) { @@ -73,7 +77,11 @@ export const TabHistory: React.FunctionComponent = ({ policy }) => { - {snapshotName} + + {snapshotName} +
diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/tabs/tab_summary.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/tabs/tab_summary.tsx index 053c4dc108e72..7bcee4f5f6621 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/tabs/tab_summary.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/tabs/tab_summary.tsx @@ -25,12 +25,14 @@ import { useServices } from '../../../../../app_context'; import { FormattedDateTime, CollapsibleIndicesList } from '../../../../../components'; import { linkToSnapshots, linkToRepository } from '../../../../../services/navigation'; +import { reactRouterNavigate } from '../../../../../../../../../../src/plugins/kibana_react/public'; + interface Props { policy: SlmPolicy; } export const TabSummary: React.FunctionComponent = ({ policy }) => { - const { i18n } = useServices(); + const { i18n, history } = useServices(); const { version, @@ -180,7 +182,9 @@ export const TabSummary: React.FunctionComponent = ({ policy }) => { - {snapshotName} + + {snapshotName} + @@ -193,7 +197,9 @@ export const TabSummary: React.FunctionComponent = ({ policy }) => { - {repository} + + {repository} + diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_list.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_list.tsx index 050274f1319b5..39ef66eb0658c 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_list.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_list.tsx @@ -28,6 +28,8 @@ import { PolicyDetails } from './policy_details'; import { PolicyTable } from './policy_table'; import { PolicyRetentionSchedule } from './policy_retention_schedule'; +import { reactRouterNavigate } from '../../../../../../../../src/plugins/kibana_react/public'; + interface MatchParams { policyName?: SlmPolicy['name']; } @@ -130,7 +132,7 @@ export const PolicyList: React.FunctionComponent Promise>; @@ -47,7 +49,7 @@ export const PolicyTable: React.FunctionComponent = ({ onPolicyDeleted, onPolicyExecuted, }) => { - const { i18n, uiMetricService } = useServices(); + const { i18n, uiMetricService, history } = useServices(); const [selectedItems, setSelectedItems] = useState([]); const columns = [ @@ -64,8 +66,9 @@ export const PolicyTable: React.FunctionComponent = ({ {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} uiMetricService.trackUiMetric(UIM_POLICY_SHOW_DETAILS_CLICK)} - href={openPolicyDetailsUrl(name)} data-test-subj="policyLink" > {name} @@ -249,7 +252,7 @@ export const PolicyTable: React.FunctionComponent = ({ )} iconType="pencil" color="primary" - href={linkToEditPolicy(name)} + {...reactRouterNavigate(history, linkToEditPolicy(name))} data-test-subj="editPolicyButton" /> @@ -373,7 +376,7 @@ export const PolicyTable: React.FunctionComponent = ({ , void; @@ -62,7 +68,7 @@ export const RepositoryDetails: React.FunctionComponent = ({ onClose, onRepositoryDeleted, }) => { - const { i18n } = useServices(); + const { i18n, history } = useServices(); const { error, data: repositoryDetails } = useLoadRepository(repositoryName); const [verification, setVerification] = useState(undefined); const [cleanup, setCleanup] = useState(undefined); @@ -162,7 +168,7 @@ export const RepositoryDetails: React.FunctionComponent = ({ ); } return ( - + = ({ - + = ({ openRepositoryDetailsUrl, onRepositoryDeleted, }) => { - const { i18n, uiMetricService } = useServices(); + const { i18n, uiMetricService, history } = useServices(); const [selectedItems, setSelectedItems] = useState([]); const columns = [ @@ -55,8 +57,9 @@ export const RepositoryTable: React.FunctionComponent = ({ {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} uiMetricService.trackUiMetric(UIM_REPOSITORY_SHOW_DETAILS_CLICK)} - href={openRepositoryDetailsUrl(name)} data-test-subj="repositoryLink" > {name} @@ -116,7 +119,7 @@ export const RepositoryTable: React.FunctionComponent = ({ )} iconType="pencil" color="primary" - href={linkToEditRepository(name)} + {...reactRouterNavigate(history, linkToEditRepository(name))} data-test-subj="editRepositoryButton" /> @@ -247,7 +250,7 @@ export const RepositoryTable: React.FunctionComponent = ({ , { currentInterval ); - const { uiMetricService } = useServices(); + const { uiMetricService, history } = useServices(); // Track component loaded useEffect(() => { @@ -110,7 +112,7 @@ export const RestoreList: React.FunctionComponent = () => { defaultMessage="Go to {snapshotsLink} to start a restore." values={{ snapshotsLink: ( - + = ({ onClose, onSnapshotDeleted, }) => { - const { i18n, uiMetricService } = useServices(); + const { i18n, uiMetricService, history } = useServices(); const { error, data: snapshotDetails } = useLoadSnapshot(repositoryName, snapshotId); const [activeTab, setActiveTab] = useState(TAB_SUMMARY); @@ -221,7 +223,10 @@ export const SnapshotDetails: React.FunctionComponent = ({ = ({

- + = ({ snapshotDetails }) => { policyName, } = snapshotDetails; + const { history } = useServices(); + return ( @@ -201,7 +206,9 @@ export const TabSummary: React.FC = ({ snapshotDetails }) => { - {policyName} + + {policyName} + ) : null} diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_list.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_list.tsx index 43bdd973f3d45..b3c9858159e88 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_list.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_list.tsx @@ -27,6 +27,8 @@ import { useServices } from '../../../app_context'; import { SnapshotDetails } from './snapshot_details'; import { SnapshotTable } from './snapshot_table'; +import { reactRouterNavigate } from '../../../../../../../../src/plugins/kibana_react/public'; + interface MatchParams { repositoryName?: string; snapshotId?: string; @@ -141,7 +143,7 @@ export const SnapshotList: React.FunctionComponent +

{policies.length === 0 ? ( ) : ( + = ({ repositoryFilter, policyFilter, }) => { - const { i18n, uiMetricService } = useServices(); + const { i18n, uiMetricService, history } = useServices(); const [selectedItems, setSelectedItems] = useState([]); const lastSuccessfulManagedSnapshot = getLastSuccessfulManagedSnapshot(snapshots); @@ -74,8 +80,9 @@ export const SnapshotTable: React.FunctionComponent = ({ render: (snapshotId: string, snapshot: SnapshotDetails) => ( /* eslint-disable-next-line @elastic/eui/href-or-on-click */ uiMetricService.trackUiMetric(UIM_SNAPSHOT_SHOW_DETAILS_CLICK)} - href={openSnapshotDetailsUrl(snapshot.repository, snapshotId)} data-test-subj="snapshotLink" > {snapshotId} @@ -90,7 +97,10 @@ export const SnapshotTable: React.FunctionComponent = ({ truncateText: true, sortable: true, render: (repositoryName: string) => ( - + {repositoryName} ), @@ -199,7 +209,7 @@ export const SnapshotTable: React.FunctionComponent = ({ iconType="importAction" color="primary" data-test-subj="srsnapshotListRestoreActionButton" - href={linkToRestoreSnapshot(repository, snapshot)} + {...reactRouterNavigate(history, linkToRestoreSnapshot(repository, snapshot))} isDisabled={!canRestore} /> diff --git a/x-pack/plugins/snapshot_restore/public/application/services/navigation/links.ts b/x-pack/plugins/snapshot_restore/public/application/services/navigation/links.ts index 6f95000726106..503704c6fe820 100644 --- a/x-pack/plugins/snapshot_restore/public/application/services/navigation/links.ts +++ b/x-pack/plugins/snapshot_restore/public/application/services/navigation/links.ts @@ -4,68 +4,60 @@ * you may not use this file except in compliance with the Elastic License. */ -import { BASE_PATH } from '../../constants'; - export function linkToHome() { - return `#${BASE_PATH}`; + return `/`; } export function linkToRepositories() { - return `#${BASE_PATH}/repositories`; + return `/repositories`; } export function linkToRepository(repositoryName: string) { - return `#${BASE_PATH}/repositories/${encodeURIComponent(repositoryName)}`; + return `/repositories/${encodeURIComponent(repositoryName)}`; } export function linkToEditRepository(repositoryName: string) { - return `#${BASE_PATH}/edit_repository/${encodeURIComponent(repositoryName)}`; + return `/edit_repository/${encodeURIComponent(repositoryName)}`; } export function linkToAddRepository(redirect?: string) { - return `#${BASE_PATH}/add_repository${ - redirect ? `?redirect=${encodeURIComponent(redirect)}` : '' - }`; + return `/add_repository${redirect ? `?redirect=${encodeURIComponent(redirect)}` : ''}`; } export function linkToSnapshots(repositoryName?: string, policyName?: string) { if (repositoryName) { - return `#${BASE_PATH}/snapshots?repository=${encodeURIComponent(repositoryName)}`; + return `/snapshots?repository=${encodeURIComponent(repositoryName)}`; } if (policyName) { - return `#${BASE_PATH}/snapshots?policy=${encodeURIComponent(policyName)}`; + return `/snapshots?policy=${encodeURIComponent(policyName)}`; } - return `#${BASE_PATH}/snapshots`; + return `/snapshots`; } export function linkToSnapshot(repositoryName: string, snapshotName: string) { - return `#${BASE_PATH}/snapshots/${encodeURIComponent(repositoryName)}/${encodeURIComponent( - snapshotName - )}`; + return `/snapshots/${encodeURIComponent(repositoryName)}/${encodeURIComponent(snapshotName)}`; } export function linkToRestoreSnapshot(repositoryName: string, snapshotName: string) { - return `#${BASE_PATH}/restore/${encodeURIComponent(repositoryName)}/${encodeURIComponent( - snapshotName - )}`; + return `/restore/${encodeURIComponent(repositoryName)}/${encodeURIComponent(snapshotName)}`; } export function linkToPolicies() { - return `#${BASE_PATH}/policies`; + return `/policies`; } export function linkToPolicy(policyName: string) { - return `#${BASE_PATH}/policies/${encodeURIComponent(policyName)}`; + return `/policies/${encodeURIComponent(policyName)}`; } export function linkToEditPolicy(policyName: string) { - return `#${BASE_PATH}/edit_policy/${encodeURIComponent(policyName)}`; + return `/edit_policy/${encodeURIComponent(policyName)}`; } export function linkToAddPolicy() { - return `#${BASE_PATH}/add_policy`; + return `/add_policy`; } export function linkToRestoreStatus() { - return `#${BASE_PATH}/restore_status`; + return `/restore_status`; } From 9c9f2d22fb185e752c13090aa3ad56e3f75d21d4 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 22 May 2020 16:03:59 +0300 Subject: [PATCH 32/93] [rollup_jobs] partial progress --- x-pack/plugins/rollup/public/application.tsx | 20 +++++++++---------- .../rollup/public/crud_app/constants/index.js | 2 -- .../rollup/public/crud_app/constants/paths.js | 7 ------- .../crud_app/sections/job_list/job_list.js | 5 ++--- .../public/crud_app/services/breadcrumbs.js | 3 +-- .../crud_app/store/actions/create_job.js | 3 +-- .../crud_app/store/middleware/clone_job.js | 3 +-- 7 files changed, 15 insertions(+), 28 deletions(-) delete mode 100644 x-pack/plugins/rollup/public/crud_app/constants/paths.js diff --git a/x-pack/plugins/rollup/public/application.tsx b/x-pack/plugins/rollup/public/application.tsx index 1bdf940d746b2..2bd8bd8738213 100644 --- a/x-pack/plugins/rollup/public/application.tsx +++ b/x-pack/plugins/rollup/public/application.tsx @@ -16,28 +16,28 @@ import { App } from './crud_app/app'; import './index.scss'; +import { ManagementAppMountParams } from '../../../../src/plugins/management/public'; + /** * This module will be loaded asynchronously to reduce the bundle size of your plugin's main bundle. */ export const renderApp = async ( core: CoreSetup, - { - element, - setBreadcrumbs, - }: { element: HTMLElement; setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void } + { history, element, setBreadcrumbs }: ManagementAppMountParams ) => { const [coreStart] = await core.getStartServices(); const I18nContext = coreStart.i18n.Context; + const services = { + history, + setBreadcrumbs, + }; + render( - + - + , diff --git a/x-pack/plugins/rollup/public/crud_app/constants/index.js b/x-pack/plugins/rollup/public/crud_app/constants/index.js index f3a218fc3b493..132affafea87d 100644 --- a/x-pack/plugins/rollup/public/crud_app/constants/index.js +++ b/x-pack/plugins/rollup/public/crud_app/constants/index.js @@ -4,6 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { CRUD_APP_BASE_PATH } from './paths'; - export { METRICS_CONFIG } from './metrics_config'; diff --git a/x-pack/plugins/rollup/public/crud_app/constants/paths.js b/x-pack/plugins/rollup/public/crud_app/constants/paths.js deleted file mode 100644 index 44829f38e79cd..0000000000000 --- a/x-pack/plugins/rollup/public/crud_app/constants/paths.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export const CRUD_APP_BASE_PATH = '/management/data/rollup_jobs'; diff --git a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js index 011becded148c..85cd6e742d27f 100644 --- a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js @@ -27,7 +27,6 @@ import { import { withKibana } from '../../../../../../../src/plugins/kibana_react/public'; -import { CRUD_APP_BASE_PATH } from '../../constants'; import { getRouterLinkProps, extractQueryParams, listBreadcrumb } from '../../services'; import { JobTable } from './job_table'; @@ -166,7 +165,7 @@ export class JobListUi extends Component { actions={ @@ -210,7 +209,7 @@ export class JobListUi extends Component { {this.getHeaderSection()} - + async (dispatch) => { // This will open the new job in the detail panel. Note that we're *not* showing a success toast // here, because it would partially obscure the detail panel. getRouter().history.push({ - pathname: `${CRUD_APP_BASE_PATH}/job_list`, + pathname: `/job_list`, search: `?job=${jobConfig.id}`, }); }; diff --git a/x-pack/plugins/rollup/public/crud_app/store/middleware/clone_job.js b/x-pack/plugins/rollup/public/crud_app/store/middleware/clone_job.js index 2012ec2248fbd..b8495a1c95a8e 100644 --- a/x-pack/plugins/rollup/public/crud_app/store/middleware/clone_job.js +++ b/x-pack/plugins/rollup/public/crud_app/store/middleware/clone_job.js @@ -6,7 +6,6 @@ import { getRouter, getUserHasLeftApp } from '../../services'; import { CLONE_JOB_START } from '../action_types'; -import { CRUD_APP_BASE_PATH } from '../../constants'; export const cloneJob = () => (next) => (action) => { const { type } = action; @@ -14,7 +13,7 @@ export const cloneJob = () => (next) => (action) => { if (type === CLONE_JOB_START) { if (!getUserHasLeftApp()) { getRouter().history.push({ - pathname: `${CRUD_APP_BASE_PATH}/create`, + pathname: `/create`, }); } } From 09cd254d7447a6d9c7cabfc0d2f5b1f34f0ada11 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Fri, 22 May 2020 17:11:10 +0300 Subject: [PATCH 33/93] Fixed routing for cross cluster replications (partial progress). Enhanced reactRouterNavigate --- .../react_router_navigate.tsx | 20 ++++-- .../common/constants/index.ts | 2 +- .../public/app/app.tsx | 24 +++---- .../auto_follow_pattern_action_menu.tsx | 2 +- .../follower_index_resume_provider.js | 10 ++- .../components/remote_clusters_form_field.js | 23 +++---- .../public/app/index.tsx | 14 ++--- .../auto_follow_pattern_add.js | 2 +- .../auto_follow_pattern_edit.js | 6 +- .../follower_index_add/follower_index_add.js | 2 +- .../follower_index_edit.js | 6 +- .../auto_follow_pattern_list.js | 8 +-- .../auto_follow_pattern_table.js | 2 +- .../components/context_menu/context_menu.js | 2 +- .../follower_indices_table.js | 2 +- .../follower_indices_list.js | 8 +-- .../public/app/sections/home/home.js | 12 ++-- .../public/app/services/breadcrumbs.ts | 14 ++--- .../public/app/services/routing.js | 62 +++---------------- .../app/store/actions/auto_follow_pattern.js | 2 +- .../app/store/actions/follower_index.js | 2 +- .../public/plugin.ts | 2 + .../public/application/sections/home/home.tsx | 6 +- .../template_table/template_table.tsx | 10 ++- 24 files changed, 110 insertions(+), 133 deletions(-) diff --git a/src/plugins/kibana_react/public/react_router_navigate/react_router_navigate.tsx b/src/plugins/kibana_react/public/react_router_navigate/react_router_navigate.tsx index 2de3c569dd6cd..0dd5bda91cccb 100644 --- a/src/plugins/kibana_react/public/react_router_navigate/react_router_navigate.tsx +++ b/src/plugins/kibana_react/public/react_router_navigate/react_router_navigate.tsx @@ -33,14 +33,24 @@ const isLeftClickEvent = (event: any) => event.button === 0; export const toLocationObject = (to: string | LocationObject) => typeof to === 'string' ? { pathname: to } : to; -export const reactRouterNavigate = (history: ScopedHistory, to: string | LocationObject) => ({ +export const reactRouterNavigate = ( + history: ScopedHistory, + to: string | LocationObject, + onClickCallback?: Function +) => ({ href: history.createHref(toLocationObject(to)), - onClick: reactRouterOnClickHandler(history, toLocationObject(to)), + onClick: reactRouterOnClickHandler(history, toLocationObject(to), onClickCallback), }); -export const reactRouterOnClickHandler = (history: ScopedHistory, to: string | LocationObject) => ( - event: any -) => { +export const reactRouterOnClickHandler = ( + history: ScopedHistory, + to: string | LocationObject, + onClickCallback?: Function +) => (event: any) => { + if (onClickCallback) { + onClickCallback(event); + } + if (event.defaultPrevented) { return; } diff --git a/x-pack/plugins/cross_cluster_replication/common/constants/index.ts b/x-pack/plugins/cross_cluster_replication/common/constants/index.ts index 96884cf4bead8..73185e6fa1b8d 100644 --- a/x-pack/plugins/cross_cluster_replication/common/constants/index.ts +++ b/x-pack/plugins/cross_cluster_replication/common/constants/index.ts @@ -25,7 +25,7 @@ export const APPS = { export const MANAGEMENT_ID = 'cross_cluster_replication'; export const BASE_PATH = `/management/data/${MANAGEMENT_ID}`; -export const BASE_PATH_REMOTE_CLUSTERS = '/management/data/remote_clusters'; +export const BASE_PATH_REMOTE_CLUSTERS = 'data/remote_clusters'; export const API_BASE_PATH = '/api/cross_cluster_replication'; export const API_REMOTE_CLUSTERS_BASE_PATH = '/api/remote_clusters'; export const API_INDEX_MANAGEMENT_BASE_PATH = '/api/index_management'; diff --git a/x-pack/plugins/cross_cluster_replication/public/app/app.tsx b/x-pack/plugins/cross_cluster_replication/public/app/app.tsx index 8245f2dd2c3fe..288da20c353d2 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/app.tsx +++ b/x-pack/plugins/cross_cluster_replication/public/app/app.tsx @@ -5,8 +5,8 @@ */ import React, { Component, Fragment } from 'react'; -import { Route, Switch, Redirect, withRouter, RouteComponentProps } from 'react-router-dom'; -import { History } from 'history'; +import { Route, Switch, Router, Redirect } from 'react-router-dom'; +import { ScopedHistory, ApplicationStart } from 'kibana/public'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -36,8 +36,8 @@ import { } from './sections'; interface AppProps { - history: History; - location: any; + history: ScopedHistory; + getUrlForApp: ApplicationStart['getUrlForApp']; } interface AppState { @@ -47,7 +47,7 @@ interface AppState { missingClusterPrivileges: any[]; } -class AppComponent extends Component { +class AppComponent extends Component { constructor(props: any) { super(props); this.registerRouter(); @@ -98,12 +98,13 @@ class AppComponent extends Component { } registerRouter() { - const { history, location } = this.props; + const { history, getUrlForApp } = this.props; routing.reactRouter = { history, route: { - location, + location: history.location, }, + getUrlForApp, }; } @@ -188,19 +189,18 @@ class AppComponent extends Component { } return ( -

+ - - + -
+ ); } } -export const App = withRouter(AppComponent); +export const App = AppComponent; diff --git a/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_action_menu/auto_follow_pattern_action_menu.tsx b/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_action_menu/auto_follow_pattern_action_menu.tsx index 5474708f313c8..1d8f8bacc8c84 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_action_menu/auto_follow_pattern_action_menu.tsx +++ b/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_action_menu/auto_follow_pattern_action_menu.tsx @@ -99,7 +99,7 @@ const AutoFollowPatternActionMenuUI: FunctionComponent = ({ }), icon: , onClick: () => { - window.location.hash = routing.getAutoFollowPatternPath(patterns[0].name); + routing.navigate(routing.getAutoFollowPatternPath(patterns[0].name)); }, } : null, diff --git a/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_resume_provider.js b/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_resume_provider.js index 6e4c019dab85c..4c264b9b3e708 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_resume_provider.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_resume_provider.js @@ -10,7 +10,7 @@ import { connect } from 'react-redux'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiConfirmModal, EuiLink, EuiOverlayMask } from '@elastic/eui'; - +import { reactRouterNavigate } from '../../../../../../src/plugins/kibana_react/public'; import { routing } from '../services/routing'; import { resumeFollowerIndex } from '../store/actions'; import { arrify } from '../../../common/services/utils'; @@ -97,7 +97,13 @@ class FollowerIndexResumeProviderUi extends PureComponent { custom advanced settings, {editLink}." values={{ editLink: ( - + ( @@ -152,10 +151,9 @@ export class RemoteClustersFormField extends PureComponent { {' '} {/* Break out of EuiFormRow's flexbox layout */} {this.errorMessages.noClusterFound()}

{description}

{this.errorMessages.remoteClusterDoesNotExist(name)}

{ render( - - - + , element @@ -41,6 +39,7 @@ export async function mountApp({ ELASTIC_WEBSITE_URL, DOC_LINK_VERSION, history, + getUrlForApp, }: { element: Element; setBreadcrumbs: SetBreadcrumbs; @@ -48,11 +47,12 @@ export async function mountApp({ ELASTIC_WEBSITE_URL: string; DOC_LINK_VERSION: string; history: ScopedHistory; + getUrlForApp: ApplicationStart['getUrlForApp']; }): Promise { // Import and initialize additional services here instead of in plugin.ts to reduce the size of the // initial bundle as much as possible. initBreadcrumbs(setBreadcrumbs); initDocumentation(`${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`); - return renderApp(element, I18nContext, history); + return renderApp(element, I18nContext, history, getUrlForApp); } diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/auto_follow_pattern_add/auto_follow_pattern_add.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/auto_follow_pattern_add/auto_follow_pattern_add.js index 60a6cc79376e5..76fdf6e2fd766 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/auto_follow_pattern_add/auto_follow_pattern_add.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/auto_follow_pattern_add/auto_follow_pattern_add.js @@ -27,7 +27,7 @@ export class AutoFollowPatternAdd extends PureComponent { }; componentDidMount() { - setBreadcrumbs([listBreadcrumb, addBreadcrumb]); + setBreadcrumbs([listBreadcrumb('/auto_follow_patterns'), addBreadcrumb]); } componentWillUnmount() { diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/auto_follow_pattern_edit/auto_follow_pattern_edit.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/auto_follow_pattern_edit/auto_follow_pattern_edit.js index 387d7817a0357..d89e3adb531ab 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/auto_follow_pattern_edit/auto_follow_pattern_edit.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/auto_follow_pattern_edit/auto_follow_pattern_edit.js @@ -12,7 +12,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiPageContent, EuiSpacer } from '@elastic/eui'; import { listBreadcrumb, editBreadcrumb, setBreadcrumbs } from '../../services/breadcrumbs'; -import { routing } from '../../services/routing'; +import { reactRouterNavigate } from '../../../../../../../src/plugins/kibana_react/public'; import { AutoFollowPatternForm, AutoFollowPatternPageTitle, @@ -54,7 +54,7 @@ export class AutoFollowPatternEdit extends PureComponent { selectAutoFollowPattern(decodedId); - setBreadcrumbs([listBreadcrumb, editBreadcrumb]); + setBreadcrumbs([listBreadcrumb('/auto_follow_patterns'), editBreadcrumb]); } componentDidUpdate(prevProps, prevState) { @@ -108,7 +108,7 @@ export class AutoFollowPatternEdit extends PureComponent { @@ -122,7 +122,7 @@ export class AutoFollowPatternList extends PureComponent { {isAuthorized && ( (window.location.hash = routing.getAutoFollowPatternPath(name))} + onClick={() => routing.navigate(routing.getAutoFollowPatternPath(name))} data-test-subj="contextMenuEditButton" > diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/context_menu/context_menu.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/context_menu/context_menu.js index 6549905013025..3d79e0cb4fa56 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/context_menu/context_menu.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/context_menu/context_menu.js @@ -48,7 +48,7 @@ export class ContextMenu extends PureComponent { }; editFollowerIndex = (id) => { - const uri = routing.getFollowerIndexPath(id, '/edit', false); + const uri = routing.getFollowerIndexPath(id); routing.navigate(uri); }; diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/follower_indices_table/follower_indices_table.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/follower_indices_table/follower_indices_table.js index ea4a35de2282a..183609355fdfd 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/follower_indices_table/follower_indices_table.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/follower_indices_table/follower_indices_table.js @@ -97,7 +97,7 @@ export class FollowerIndicesTable extends PureComponent { }; editFollowerIndex = (id) => { - const uri = routing.getFollowerIndexPath(id, '/edit', false); + const uri = routing.getFollowerIndexPath(id); routing.navigate(uri); }; diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/follower_indices_list.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/follower_indices_list.js index 7b843d08cefd3..4d4cbbf6825ec 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/follower_indices_list.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/follower_indices_list.js @@ -17,7 +17,7 @@ import { EuiSpacer, } from '@elastic/eui'; -import { routing } from '../../../services/routing'; +import { reactRouterNavigate } from '../../../../../../../../src/plugins/kibana_react/public'; import { extractQueryParams } from '../../../services/query_params'; import { trackUiMetric, METRIC_TYPE } from '../../../services/track_ui_metric'; import { API_STATUS, UIM_FOLLOWER_INDEX_LIST_LOAD } from '../../../constants'; @@ -94,7 +94,7 @@ export class FollowerIndicesList extends PureComponent { } renderHeader() { - const { isAuthorized } = this.props; + const { isAuthorized, history } = this.props; return ( @@ -113,7 +113,7 @@ export class FollowerIndicesList extends PureComponent { {isAuthorized && ( { + setBreadcrumbs([listBreadcrumb(`/${section}`)]); routing.navigate(`/${section}`); }; @@ -94,12 +94,8 @@ export class CrossClusterReplicationHome extends PureComponent { - - + + diff --git a/x-pack/plugins/cross_cluster_replication/public/app/services/breadcrumbs.ts b/x-pack/plugins/cross_cluster_replication/public/app/services/breadcrumbs.ts index 84ac9356462ad..c3ca893e6182b 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/services/breadcrumbs.ts +++ b/x-pack/plugins/cross_cluster_replication/public/app/services/breadcrumbs.ts @@ -9,8 +9,6 @@ import { ChromeBreadcrumb } from 'src/core/public'; import { ManagementAppMountParams } from '../../../../../../src/plugins/management/public'; -import { BASE_PATH } from '../../../common/constants'; - export type SetBreadcrumbs = ManagementAppMountParams['setBreadcrumbs']; let setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; @@ -19,11 +17,13 @@ export const init = (_setBreadcrumbs: SetBreadcrumbs): void => { setBreadcrumbs = _setBreadcrumbs; }; -export const listBreadcrumb = { - text: i18n.translate('xpack.crossClusterReplication.homeBreadcrumbTitle', { - defaultMessage: 'Cross-Cluster Replication', - }), - href: `#${BASE_PATH}`, +export const listBreadcrumb = (section?: string) => { + return { + text: i18n.translate('xpack.crossClusterReplication.homeBreadcrumbTitle', { + defaultMessage: 'Cross-Cluster Replication', + }), + href: section || '/', + }; }; export const addBreadcrumb = { diff --git a/x-pack/plugins/cross_cluster_replication/public/app/services/routing.js b/x-pack/plugins/cross_cluster_replication/public/app/services/routing.js index 1a488cc951c49..59210272534b9 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/services/routing.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/services/routing.js @@ -8,14 +8,8 @@ * This file based on guidance from https://github.com/elastic/eui/blob/master/wiki/react-router.md */ -import { createLocation } from 'history'; import { stringify } from 'query-string'; -import { APPS, BASE_PATH, BASE_PATH_REMOTE_CLUSTERS } from '../../../common/constants'; - -const isModifiedEvent = (event) => - !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); - -const isLeftClickEvent = (event) => event.button === 0; +import { BASE_PATH_REMOTE_CLUSTERS } from '../../../common/constants'; const queryParamsFromObject = (params, encodeParams = false) => { if (!params) { @@ -26,67 +20,31 @@ const queryParamsFromObject = (params, encodeParams = false) => { return `?${paramsStr}`; }; -const appToBasePathMap = { - [APPS.CCR_APP]: BASE_PATH, - [APPS.REMOTE_CLUSTER_APP]: BASE_PATH_REMOTE_CLUSTERS, -}; - class Routing { _reactRouter = null; - /** - * The logic for generating hrefs and onClick handlers from the `to` prop is largely borrowed from - * https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/Link.js. - * - * @param {*} to URL to navigate to - */ - getRouterLinkProps(to, base = BASE_PATH, params = {}, encodeParams = false) { + getHrefToRemoteClusters(route = '/', params, encodeParams = false) { const search = queryParamsFromObject(params, encodeParams) || ''; - const location = - typeof to === 'string' - ? createLocation(base + to + search, null, null, this._reactRouter.history.location) - : to; - const href = this._reactRouter.history.createHref(location); - - const onClick = (event) => { - if (event.defaultPrevented) { - return; - } - - // If target prop is set (e.g. to "_blank"), let browser handle link. - if (event.target.getAttribute('target')) { - return; - } - - if (isModifiedEvent(event) || !isLeftClickEvent(event)) { - return; - } - - // Prevent regular link behavior, which causes a browser refresh. - event.preventDefault(); - this._reactRouter.history.push(location); - }; - - return { href, onClick }; + return this._reactRouter.getUrlForApp('management', { + path: `${BASE_PATH_REMOTE_CLUSTERS}${route}${search}`, + }); } - navigate(route = '/home', app = APPS.CCR_APP, params, encodeParams = false) { + navigate(route = '/home', params, encodeParams = false) { const search = queryParamsFromObject(params, encodeParams); this._reactRouter.history.push({ - pathname: encodeURI(appToBasePathMap[app] + route), + pathname: encodeURI(route), search, }); } getAutoFollowPatternPath = (name, section = '/edit') => { - return encodeURI(`#${BASE_PATH}/auto_follow_patterns${section}/${encodeURIComponent(name)}`); + return encodeURI(`/auto_follow_patterns${section}/${encodeURIComponent(name)}`); }; - getFollowerIndexPath = (name, section = '/edit', withBase = true) => { - return withBase - ? encodeURI(`#${BASE_PATH}/follower_indices${section}/${encodeURIComponent(name)}`) - : encodeURI(`/follower_indices${section}/${encodeURIComponent(name)}`); + getFollowerIndexPath = (name, section = '/edit') => { + return encodeURI(`/follower_indices${section}/${encodeURIComponent(name)}`); }; get reactRouter() { diff --git a/x-pack/plugins/cross_cluster_replication/public/app/store/actions/auto_follow_pattern.js b/x-pack/plugins/cross_cluster_replication/public/app/store/actions/auto_follow_pattern.js index ea6801b55458d..6503333924951 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/store/actions/auto_follow_pattern.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/store/actions/auto_follow_pattern.js @@ -76,7 +76,7 @@ export const saveAutoFollowPattern = (id, autoFollowPattern, isUpdating = false) ); getToasts().addSuccess(successMessage); - routing.navigate(`/auto_follow_patterns`, undefined, { + routing.navigate(`/auto_follow_patterns`, { pattern: encodeURIComponent(id), }); }, diff --git a/x-pack/plugins/cross_cluster_replication/public/app/store/actions/follower_index.js b/x-pack/plugins/cross_cluster_replication/public/app/store/actions/follower_index.js index 61d0ed1d51c72..1af5a95a29b98 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/store/actions/follower_index.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/store/actions/follower_index.js @@ -77,7 +77,7 @@ export const saveFollowerIndex = (name, followerIndex, isUpdating = false) => ); getToasts().addSuccess(successMessage); - routing.navigate(`/follower_indices`, undefined, { + routing.navigate(`/follower_indices`, { name: encodeURIComponent(name), }); }, diff --git a/x-pack/plugins/cross_cluster_replication/public/plugin.ts b/x-pack/plugins/cross_cluster_replication/public/plugin.ts index 4da9e20ec5c78..b87801c3b0c76 100644 --- a/x-pack/plugins/cross_cluster_replication/public/plugin.ts +++ b/x-pack/plugins/cross_cluster_replication/public/plugin.ts @@ -48,6 +48,7 @@ export class CrossClusterReplicationPlugin implements Plugin { const { i18n: { Context: I18nContext }, docLinks: { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION }, + application: { getUrlForApp }, } = coreStart; return mountApp({ @@ -57,6 +58,7 @@ export class CrossClusterReplicationPlugin implements Plugin { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION, history, + getUrlForApp, }); }, }); diff --git a/x-pack/plugins/index_management/public/application/sections/home/home.tsx b/x-pack/plugins/index_management/public/application/sections/home/home.tsx index 91303ee23798e..9d4331d742a25 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/home.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/home.tsx @@ -108,7 +108,11 @@ export const IndexManagementHome: React.FunctionComponent - + diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx index f870794d7e88a..f51f3d31826fc 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx @@ -50,9 +50,15 @@ export const TemplateTable: React.FunctionComponent = ({ return ( /* eslint-disable-next-line @elastic/eui/href-or-on-click */ uiMetricService.trackMetric('click', UIM_TEMPLATE_SHOW_DETAILS_CLICK) + )} data-test-subj="templateDetailsLink" - onClick={() => uiMetricService.trackMetric('click', UIM_TEMPLATE_SHOW_DETAILS_CLICK)} > {name} From 5dd58fe04329ced0394512d29eaf0704f4901c28 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 22 May 2020 17:40:58 +0300 Subject: [PATCH 34/93] Perf optimization: fix extra re-rendering --- .../management_app/management_app.tsx | 48 +++---------- .../management_app/management_router.tsx | 70 +++++++++++++++++++ .../management_app_wrapper.tsx | 66 ++++++++--------- 3 files changed, 112 insertions(+), 72 deletions(-) create mode 100644 src/plugins/management/public/components/management_app/management_router.tsx diff --git a/src/plugins/management/public/components/management_app/management_app.tsx b/src/plugins/management/public/components/management_app/management_app.tsx index 165d478c8954e..78e878e7925da 100644 --- a/src/plugins/management/public/components/management_app/management_app.tsx +++ b/src/plugins/management/public/components/management_app/management_app.tsx @@ -17,7 +17,6 @@ * under the License. */ import React, { useState, useEffect, useCallback } from 'react'; -import { Route, Router, Switch } from 'react-router-dom'; import { AppMountContext, AppMountParameters, @@ -29,10 +28,8 @@ import { EuiPage, EuiPageBody } from '@elastic/eui'; import { ManagementStart } from '../../types'; import { ManagementSection, MANAGEMENT_BREADCRUMB } from '../../utils'; -import { ManagementLandingPage } from '../langing'; +import { ManagementRouter } from './management_router'; import { ManagementSidebarNav } from '../management_sidebar_nav'; -import { ManagementAppWrapper } from '../management_app_wrapper'; - import { reactRouterNavigate } from '../../../../kibana_react/public'; import './_management_app.scss'; @@ -83,39 +80,16 @@ export const ManagementApp = ({ context, dependencies, history }: ManagementAppP return ( - - - - - - {sections.map((section) => - section.apps.map((app) => ( - ( - - )} - /> - )) - )} - ( - - )} - /> - - - - + + + + ); }; diff --git a/src/plugins/management/public/components/management_app/management_router.tsx b/src/plugins/management/public/components/management_app/management_router.tsx new file mode 100644 index 0000000000000..518793eb615fe --- /dev/null +++ b/src/plugins/management/public/components/management_app/management_router.tsx @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { memo } from 'react'; +import { Route, Router, Switch } from 'react-router-dom'; +import { EuiPageBody } from '@elastic/eui'; +import { AppMountParameters, ChromeBreadcrumb, ScopedHistory } from 'kibana/public'; +import { ManagementAppWrapper } from '../management_app_wrapper'; +import { ManagementLandingPage } from '../langing'; +import { ManagementAppDependencies } from './management_app'; +import { ManagementSection } from '../../utils'; + +interface ManagementRouterProps { + history: AppMountParameters['history']; + dependencies: ManagementAppDependencies; + setBreadcrumbs: (crumbs: ChromeBreadcrumb[], appHistory?: ScopedHistory) => void; + onAppMounted: (id: string) => void; + sections: ManagementSection[]; +} + +export const ManagementRouter = memo( + ({ dependencies, history, setBreadcrumbs, onAppMounted, sections }: ManagementRouterProps) => ( + + + + {sections.map((section) => + section.apps.map((app) => ( + ( + + )} + /> + )) + )} + ( + + )} + /> + + + + ) +); diff --git a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx index ecf90260c3eaa..8954d40f73bb2 100644 --- a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx +++ b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx @@ -17,7 +17,7 @@ * under the License. */ -import React, { useEffect, createRef, useRef, RefObject } from 'react'; +import React, { createRef, Component } from 'react'; import { ChromeBreadcrumb, AppMountParameters, ScopedHistory } from 'kibana/public'; import { ManagementApp } from '../../utils'; @@ -30,43 +30,39 @@ interface ManagementSectionWrapperProps { history: AppMountParameters['history']; } -export const ManagementAppWrapper = ({ - app, - setBreadcrumbs, - onAppMounted, - history, -}: ManagementSectionWrapperProps) => { - const mountElementRef = useRef>(); - const { mount, basePath } = app; - const unmount = useRef(); +export class ManagementAppWrapper extends Component { + private unmount: Unmount; + private mountElementRef = createRef(); - mountElementRef.current = createRef(); + componentDidMount() { + const { setBreadcrumbs, app, onAppMounted, history, selectedId } = this.props; + const { mount, basePath } = app; - useEffect(() => { - if (mount && basePath) { - const mountResult = mount({ - basePath, - setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => setBreadcrumbs(crumbs, history), - element: mountElementRef.current!.current, - history, - }); + const mountResult = mount({ + basePath, + setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => setBreadcrumbs(crumbs, history), + element: this.mountElementRef.current, + history: history.createSubHistory(app.basePath), + }); - onAppMounted(app.id); + onAppMounted(app.id); - if (mountResult instanceof Promise) { - mountResult.then((um) => { - unmount.current = um; - }); - } else { - unmount.current = mountResult; - } - return () => { - if (unmount.current) { - unmount.current(); - } - }; + if (mountResult instanceof Promise) { + mountResult.then((um) => { + this.unmount = um; + }); + } else { + this.unmount = mountResult; } - }, [app.id, basePath, history, mount, onAppMounted, setBreadcrumbs]); + } - return
; -}; + async componentWillUnmount() { + if (this.unmount) { + await this.unmount(); + } + } + + render() { + return
; + } +} From 61c113c24ddab6e8124829ede878120ecf080dcc Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 22 May 2020 18:44:26 +0300 Subject: [PATCH 35/93] fix TS errors --- .../react_router_navigate.tsx | 5 +++-- .../components/management_app/management_app.tsx | 2 +- .../management_app/management_router.tsx | 2 +- .../management_app_wrapper.tsx | 11 ++++++----- .../template_table/template_table.tsx | 1 - x-pack/plugins/rollup/public/application.tsx | 2 +- .../test/client_integration/job_list_clone.test.js | 5 ++--- .../edit_role_mapping_page.test.tsx | 14 +++++++++++++- .../role_mappings_grid_page.test.tsx | 12 +++++++++++- .../users/edit_user/edit_user_page.test.tsx | 9 ++++++++- .../users/users_grid/users_grid_page.test.tsx | 12 ++++++++++-- .../users/users_grid/users_grid_page.tsx | 1 - .../repository_details/repository_details.tsx | 6 +----- .../sections/home/snapshot_list/snapshot_list.tsx | 2 +- .../snapshot_table/snapshot_table.tsx | 6 +----- .../helpers/app_context.mock.tsx | 1 + .../monitoring_watch_edit.tsx | 1 - 17 files changed, 60 insertions(+), 32 deletions(-) diff --git a/src/plugins/kibana_react/public/react_router_navigate/react_router_navigate.tsx b/src/plugins/kibana_react/public/react_router_navigate/react_router_navigate.tsx index 0dd5bda91cccb..7a9fe19273324 100644 --- a/src/plugins/kibana_react/public/react_router_navigate/react_router_navigate.tsx +++ b/src/plugins/kibana_react/public/react_router_navigate/react_router_navigate.tsx @@ -18,6 +18,7 @@ */ import { ScopedHistory } from 'kibana/public'; +import { History } from 'history'; interface LocationObject { pathname?: string; @@ -34,7 +35,7 @@ export const toLocationObject = (to: string | LocationObject) => typeof to === 'string' ? { pathname: to } : to; export const reactRouterNavigate = ( - history: ScopedHistory, + history: ScopedHistory | History, to: string | LocationObject, onClickCallback?: Function ) => ({ @@ -43,7 +44,7 @@ export const reactRouterNavigate = ( }); export const reactRouterOnClickHandler = ( - history: ScopedHistory, + history: ScopedHistory | History, to: string | LocationObject, onClickCallback?: Function ) => (event: any) => { diff --git a/src/plugins/management/public/components/management_app/management_app.tsx b/src/plugins/management/public/components/management_app/management_app.tsx index 78e878e7925da..b5fb8e7f2a01b 100644 --- a/src/plugins/management/public/components/management_app/management_app.tsx +++ b/src/plugins/management/public/components/management_app/management_app.tsx @@ -24,7 +24,7 @@ import { ScopedHistory, } from 'kibana/public'; import { I18nProvider } from '@kbn/i18n/react'; -import { EuiPage, EuiPageBody } from '@elastic/eui'; +import { EuiPage } from '@elastic/eui'; import { ManagementStart } from '../../types'; import { ManagementSection, MANAGEMENT_BREADCRUMB } from '../../utils'; diff --git a/src/plugins/management/public/components/management_app/management_router.tsx b/src/plugins/management/public/components/management_app/management_router.tsx index 518793eb615fe..12aed3d115a76 100644 --- a/src/plugins/management/public/components/management_app/management_router.tsx +++ b/src/plugins/management/public/components/management_app/management_router.tsx @@ -29,7 +29,7 @@ import { ManagementSection } from '../../utils'; interface ManagementRouterProps { history: AppMountParameters['history']; dependencies: ManagementAppDependencies; - setBreadcrumbs: (crumbs: ChromeBreadcrumb[], appHistory?: ScopedHistory) => void; + setBreadcrumbs: (crumbs?: ChromeBreadcrumb[], appHistory?: ScopedHistory) => void; onAppMounted: (id: string) => void; sections: ManagementSection[]; } diff --git a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx index 8954d40f73bb2..02da2a46540c2 100644 --- a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx +++ b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx @@ -31,18 +31,19 @@ interface ManagementSectionWrapperProps { } export class ManagementAppWrapper extends Component { - private unmount: Unmount; + private unmount?: Unmount; private mountElementRef = createRef(); componentDidMount() { - const { setBreadcrumbs, app, onAppMounted, history, selectedId } = this.props; + const { setBreadcrumbs, app, onAppMounted, history } = this.props; const { mount, basePath } = app; + const appHistory = history.createSubHistory(app.basePath); const mountResult = mount({ basePath, - setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => setBreadcrumbs(crumbs, history), - element: this.mountElementRef.current, - history: history.createSubHistory(app.basePath), + setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => setBreadcrumbs(crumbs, appHistory), + element: this.mountElementRef.current!, + history: appHistory, }); onAppMounted(app.id); diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx index f51f3d31826fc..1c487158c2022 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx @@ -13,7 +13,6 @@ import { TemplateListItem, IndexTemplateFormatVersion } from '../../../../../../ import { UIM_TEMPLATE_SHOW_DETAILS_CLICK } from '../../../../../../common/constants'; import { TemplateDeleteModal } from '../../../../components'; import { useServices } from '../../../../app_context'; -import { getTemplateDetailsLink } from '../../../../services/routing'; import { SendRequestResponse } from '../../../../../shared_imports'; import { reactRouterNavigate } from '../../../../../../../../../src/plugins/kibana_react/public'; diff --git a/x-pack/plugins/rollup/public/application.tsx b/x-pack/plugins/rollup/public/application.tsx index 2bd8bd8738213..16a0312341118 100644 --- a/x-pack/plugins/rollup/public/application.tsx +++ b/x-pack/plugins/rollup/public/application.tsx @@ -5,7 +5,7 @@ */ import React from 'react'; -import { ChromeBreadcrumb, CoreSetup } from 'kibana/public'; +import { CoreSetup } from 'kibana/public'; import { render, unmountComponentAtNode } from 'react-dom'; import { Provider } from 'react-redux'; import { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public'; diff --git a/x-pack/plugins/rollup/public/test/client_integration/job_list_clone.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_list_clone.test.js index 380275df05ba8..53a3af38f3235 100644 --- a/x-pack/plugins/rollup/public/test/client_integration/job_list_clone.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_list_clone.test.js @@ -8,7 +8,6 @@ import { mockHttpRequest, pageHelpers, nextTick } from './helpers'; import { JOB_TO_CLONE, JOB_CLONE_INDEX_PATTERN_CHECK } from './helpers/constants'; import { getRouter } from '../../crud_app/services/routing'; import { setHttp } from '../../crud_app/services'; -import { CRUD_APP_BASE_PATH } from '../../crud_app/constants'; import { coreMock } from '../../../../../../src/core/public/mocks'; jest.mock('lodash/function/debounce', () => (fn) => fn); @@ -65,8 +64,8 @@ describe('Smoke test cloning an existing rollup job from job list', () => { find('jobActionMenuButton').simulate('click'); - expect(router.history.location.pathname).not.toBe(`${CRUD_APP_BASE_PATH}/create`); + expect(router.history.location.pathname).not.toBe(`/create`); find('jobCloneActionContextMenu').simulate('click'); - expect(router.history.location.pathname).toBe(`${CRUD_APP_BASE_PATH}/create`); + expect(router.history.location.pathname).toBe(`/create`); }); }); diff --git a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.test.tsx index eea6bbef94306..b4e755507f8c5 100644 --- a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.test.tsx @@ -12,6 +12,7 @@ import { findTestSubject } from 'test_utils/find_test_subject'; // This is not required for the tests to pass, but it rather suppresses lengthy // warnings in the console which adds unnecessary noise to the test output. import 'test_utils/stub_web_worker'; +import { ScopedHistory } from 'kibana/public'; import { EditRoleMappingPage } from '.'; import { NoCompatibleRealms, SectionLoading, PermissionDenied } from '../components'; @@ -21,13 +22,15 @@ import { RolesAPIClient } from '../../roles'; import { Role } from '../../../../common/model'; import { DocumentationLinksService } from '../documentation_links'; -import { coreMock } from '../../../../../../../src/core/public/mocks'; +import { coreMock, scopedHistoryMock } from '../../../../../../../src/core/public/mocks'; import { roleMappingsAPIClientMock } from '../role_mappings_api_client.mock'; import { rolesAPIClientMock } from '../../roles/roles_api_client.mock'; import { RoleComboBox } from '../../role_combo_box'; describe('EditRoleMappingPage', () => { + const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; let rolesAPI: PublicMethodsOf; + beforeEach(() => { rolesAPI = rolesAPIClientMock.create(); (rolesAPI as jest.Mocked).getRoles.mockResolvedValue([ @@ -54,6 +57,7 @@ describe('EditRoleMappingPage', () => { rolesAPIClient={rolesAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); @@ -116,6 +120,7 @@ describe('EditRoleMappingPage', () => { rolesAPIClient={rolesAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); @@ -163,6 +168,7 @@ describe('EditRoleMappingPage', () => { rolesAPIClient={rolesAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); expect(wrapper.find(SectionLoading)).toHaveLength(1); @@ -190,6 +196,7 @@ describe('EditRoleMappingPage', () => { rolesAPIClient={rolesAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); expect(wrapper.find(SectionLoading)).toHaveLength(1); @@ -227,6 +234,7 @@ describe('EditRoleMappingPage', () => { rolesAPIClient={rolesAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); @@ -267,6 +275,7 @@ describe('EditRoleMappingPage', () => { rolesAPIClient={rolesAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); @@ -309,6 +318,7 @@ describe('EditRoleMappingPage', () => { rolesAPIClient={rolesAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); @@ -363,6 +373,7 @@ describe('EditRoleMappingPage', () => { rolesAPIClient={rolesAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); @@ -418,6 +429,7 @@ describe('EditRoleMappingPage', () => { rolesAPIClient={rolesAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx index 2318384650e78..96fd881566a80 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx @@ -5,6 +5,7 @@ */ import React from 'react'; +import { ScopedHistory } from 'kibana/public'; import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; import { RoleMappingsGridPage } from '.'; import { SectionLoading, PermissionDenied, NoCompatibleRealms } from '../components'; @@ -14,11 +15,13 @@ import { EuiLink } from '@elastic/eui'; import { act } from '@testing-library/react'; import { DocumentationLinksService } from '../documentation_links'; -import { coreMock } from '../../../../../../../src/core/public/mocks'; +import { coreMock, scopedHistoryMock } from '../../../../../../../src/core/public/mocks'; import { roleMappingsAPIClientMock } from '../role_mappings_api_client.mock'; import { rolesAPIClientMock } from '../../roles/index.mock'; describe('RoleMappingsGridPage', () => { + const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; + it('renders an empty prompt when no role mappings exist', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); roleMappingsAPI.getRoleMappings.mockResolvedValue([]); @@ -34,6 +37,7 @@ describe('RoleMappingsGridPage', () => { roleMappingsAPI={roleMappingsAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); expect(wrapper.find(SectionLoading)).toHaveLength(1); @@ -61,6 +65,7 @@ describe('RoleMappingsGridPage', () => { roleMappingsAPI={roleMappingsAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); expect(wrapper.find(SectionLoading)).toHaveLength(1); @@ -96,6 +101,7 @@ describe('RoleMappingsGridPage', () => { roleMappingsAPI={roleMappingsAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); expect(wrapper.find(SectionLoading)).toHaveLength(1); @@ -130,6 +136,7 @@ describe('RoleMappingsGridPage', () => { roleMappingsAPI={roleMappingsAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); await nextTick(); @@ -164,6 +171,7 @@ describe('RoleMappingsGridPage', () => { roleMappingsAPI={roleMappingsAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); await nextTick(); @@ -202,6 +210,7 @@ describe('RoleMappingsGridPage', () => { roleMappingsAPI={roleMappingsAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); await nextTick(); @@ -263,6 +272,7 @@ describe('RoleMappingsGridPage', () => { roleMappingsAPI={roleMappingsAPI} notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} + history={history} /> ); await nextTick(); diff --git a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx index a97781ba25ea6..37c6caedb209b 100644 --- a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx +++ b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx @@ -5,12 +5,13 @@ */ import { act } from '@testing-library/react'; +import { ScopedHistory } from 'kibana/public'; import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; import { EditUserPage } from './edit_user_page'; import React from 'react'; import { User, Role } from '../../../../common/model'; import { ReactWrapper } from 'enzyme'; -import { coreMock } from '../../../../../../../src/core/public/mocks'; +import { coreMock, scopedHistoryMock } from '../../../../../../../src/core/public/mocks'; import { mockAuthenticatedUser } from '../../../../common/model/authenticated_user.mock'; import { securityMock } from '../../../mocks'; import { rolesAPIClientMock } from '../../roles/index.mock'; @@ -103,6 +104,8 @@ function expectMissingSaveButton(wrapper: ReactWrapper) { } describe('EditUserPage', () => { + const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; + it('allows reserved users to be viewed', async () => { const user = createUser('reserved_user'); const { apiClient, rolesAPIClient } = buildClients(user); @@ -114,6 +117,7 @@ describe('EditUserPage', () => { rolesAPIClient={rolesAPIClient} authc={securitySetup.authc} notifications={coreMock.createStart().notifications} + history={history} /> ); @@ -136,6 +140,7 @@ describe('EditUserPage', () => { rolesAPIClient={rolesAPIClient} authc={securitySetup.authc} notifications={coreMock.createStart().notifications} + history={history} /> ); @@ -182,6 +187,7 @@ describe('EditUserPage', () => { rolesAPIClient={rolesAPIClient} authc={securitySetup.authc} notifications={coreMock.createStart().notifications} + history={history} /> ); @@ -204,6 +210,7 @@ describe('EditUserPage', () => { rolesAPIClient={rolesAPIClient} authc={securitySetup.authc} notifications={coreMock.createStart().notifications} + history={history} /> ); diff --git a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx index d3b85b83ff6a4..831ea18efe3a5 100644 --- a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { ScopedHistory } from 'kibana/public'; import { User } from '../../../../common/model'; import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; @@ -10,12 +11,14 @@ import { UsersGridPage } from './users_grid_page'; import React from 'react'; import { ReactWrapper } from 'enzyme'; import { userAPIClientMock } from '../index.mock'; -import { coreMock } from '../../../../../../../src/core/public/mocks'; +import { coreMock, scopedHistoryMock } from '../../../../../../../src/core/public/mocks'; import { rolesAPIClientMock } from '../../roles/index.mock'; import { findTestSubject } from 'test_utils/find_test_subject'; import { EuiBasicTable } from '@elastic/eui'; describe('UsersGridPage', () => { + const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; + it('renders the list of users', async () => { const apiClientMock = userAPIClientMock.create(); apiClientMock.getUsers.mockImplementation(() => { @@ -45,6 +48,7 @@ describe('UsersGridPage', () => { userAPIClient={apiClientMock} rolesAPIClient={rolesAPIClientMock.create()} notifications={coreMock.createStart().notifications} + history={history} /> ); @@ -65,6 +69,7 @@ describe('UsersGridPage', () => { userAPIClient={apiClient} rolesAPIClient={rolesAPIClientMock.create()} notifications={coreMock.createStart().notifications} + history={history} /> ); @@ -94,6 +99,7 @@ describe('UsersGridPage', () => { userAPIClient={apiClientMock} rolesAPIClient={rolesAPIClientMock.create()} notifications={coreMock.createStart().notifications} + history={history} /> ); @@ -126,6 +132,7 @@ describe('UsersGridPage', () => { userAPIClient={apiClientMock} rolesAPIClient={rolesAPIClientMock.create()} notifications={coreMock.createStart().notifications} + history={history} /> ); @@ -174,6 +181,7 @@ describe('UsersGridPage', () => { userAPIClient={apiClientMock} rolesAPIClient={roleAPIClientMock} notifications={coreMock.createStart().notifications} + history={history} /> ); @@ -185,7 +193,7 @@ describe('UsersGridPage', () => { Object { "children":
kibana_user - + { ); } - const path = '/'; const columns: Array> = [ { field: 'username', diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/repository_list/repository_details/repository_details.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/home/repository_list/repository_details/repository_details.tsx index d19a9814453b7..7a3a17f50a6c3 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/repository_list/repository_details/repository_details.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/repository_list/repository_details/repository_details.tsx @@ -35,11 +35,7 @@ import { cleanupRepository as cleanupRepositoryRequest, } from '../../../../services/http'; import { textService } from '../../../../services/text'; -import { - linkToSnapshots, - linkToEditRepository, - linkToAddRepository, -} from '../../../../services/navigation'; +import { linkToSnapshots, linkToEditRepository } from '../../../../services/navigation'; import { REPOSITORY_TYPES } from '../../../../../../common'; diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_list.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_list.tsx index b3c9858159e88..794bd98238a02 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_list.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_list.tsx @@ -307,7 +307,7 @@ export const SnapshotList: React.FunctionComponent + ) => (props: any) => { diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx index 27b510e839563..b3fc8af81c94a 100644 --- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx @@ -15,7 +15,6 @@ import { EuiCallOut, EuiText, EuiLink, - EuiButtonIcon, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { WatchContext } from '../../watch_context'; From 02bd88091e89821c45fc16ad522f5ae66958b9fb Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 22 May 2020 18:51:17 +0300 Subject: [PATCH 36/93] x-pack fix config for functional tests --- .../users/edit_user/edit_user_page.test.tsx | 1 + .../users/edit_user/edit_user_page.tsx | 1 - .../users/users_grid/users_grid_page.test.tsx | 1 + .../home/snapshot_list/snapshot_list.tsx | 2 +- x-pack/test/functional/config.js | 42 +++++++------------ 5 files changed, 17 insertions(+), 30 deletions(-) diff --git a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx index 37c6caedb209b..7ee33357b9af4 100644 --- a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx +++ b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx @@ -163,6 +163,7 @@ describe('EditUserPage', () => { rolesAPIClient={rolesAPIClient} authc={securitySetup.authc} notifications={coreMock.createStart().notifications} + history={history} /> ); diff --git a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx index b845c6bc60059..eea7edd62fbfa 100644 --- a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx +++ b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx @@ -33,7 +33,6 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { NotificationsStart, ScopedHistory } from 'src/core/public'; import { User, EditUser, Role, isRoleDeprecated } from '../../../../common/model'; import { AuthenticationServiceSetup } from '../../../authentication'; -import { USERS_PATH } from '../../management_urls'; import { RolesAPIClient } from '../../roles'; import { ConfirmDeleteUsers, ChangePasswordForm } from '../components'; import { UserValidator, UserValidationResult } from './validate_user'; diff --git a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx index 831ea18efe3a5..a3e9070cfa972 100644 --- a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx @@ -240,6 +240,7 @@ describe('UsersGridPage', () => { userAPIClient={apiClientMock} rolesAPIClient={roleAPIClientMock} notifications={coreMock.createStart().notifications} + history={history} /> ); diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_list.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_list.tsx index 794bd98238a02..2b8df7294c374 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_list.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_list.tsx @@ -307,7 +307,7 @@ export const SnapshotList: React.FunctionComponent + Date: Fri, 22 May 2020 19:14:19 +0300 Subject: [PATCH 37/93] Fixed routing for index lifecycle management --- .../public/application/app.tsx | 17 +++++++++++++---- .../public/application/index.tsx | 7 ++++--- .../sections/edit_policy/edit_policy.js | 3 +-- .../components/policy_table/policy_table.js | 14 ++++++++------ .../public/application/services/navigation.ts | 8 +------- .../components/add_lifecycle_confirm_modal.js | 9 ++++++--- .../components/index_lifecycle_summary.js | 10 +++++++++- .../public/extend_index_management/index.js | 7 ++++--- .../public/plugin.tsx | 3 ++- .../public/application/app_context.tsx | 1 + .../application/mount_management_section.ts | 3 ++- .../index_list/detail_panel/summary/summary.js | 11 +++++++---- .../index_actions_context_menu.js | 3 ++- 13 files changed, 60 insertions(+), 36 deletions(-) diff --git a/x-pack/plugins/index_lifecycle_management/public/application/app.tsx b/x-pack/plugins/index_lifecycle_management/public/application/app.tsx index 0358a5f67cd8b..11cd5d181f4ad 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/app.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/app.tsx @@ -6,7 +6,7 @@ import React, { useEffect } from 'react'; import { Router, Switch, Route, Redirect } from 'react-router-dom'; -import { ScopedHistory } from 'kibana/public'; +import { ScopedHistory, ApplicationStart } from 'kibana/public'; import { METRIC_TYPE } from '@kbn/analytics'; import { UIM_APP_LOAD } from './constants'; @@ -14,15 +14,24 @@ import { EditPolicy } from './sections/edit_policy'; import { PolicyTable } from './sections/policy_table'; import { trackUiMetric } from './services/ui_metric'; -export const App = ({ history }: { history: ScopedHistory }) => { +export const App = ({ + history, + navigateToApp, +}: { + history: ScopedHistory; + navigateToApp: ApplicationStart['navigateToApp']; +}) => { useEffect(() => trackUiMetric(METRIC_TYPE.LOADED, UIM_APP_LOAD), []); return ( - - + } + /> diff --git a/x-pack/plugins/index_lifecycle_management/public/application/index.tsx b/x-pack/plugins/index_lifecycle_management/public/application/index.tsx index b0a7101a236db..eddbb5528ad84 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/index.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/index.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { Provider } from 'react-redux'; -import { I18nStart, ScopedHistory } from 'kibana/public'; +import { I18nStart, ScopedHistory, ApplicationStart } from 'kibana/public'; import { UnmountCallback } from 'src/core/public'; import { App } from './app'; @@ -16,12 +16,13 @@ import { indexLifecycleManagementStore } from './store'; export const renderApp = ( element: Element, I18nContext: I18nStart['Context'], - history: ScopedHistory + history: ScopedHistory, + navigateToApp: ApplicationStart['navigateToApp'] ): UnmountCallback => { render( - + , element diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.js index 94186b7fc79d7..998143929afef 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.js @@ -36,7 +36,6 @@ import { } from '../../constants'; import { toasts } from '../../services/notification'; -import { goToPolicyList } from '../../services/navigation'; import { findFirstError } from '../../services/find_errors'; import { LearnMoreLink } from '../components'; import { NodeAttrsDetails } from './components/node_attrs_details'; @@ -100,7 +99,7 @@ export class EditPolicy extends Component { backToPolicyList = () => { this.props.setSelectedPolicy(null); - goToPolicyList(); + this.props.history.push('/policies'); }; submit = async () => { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/policy_table/policy_table.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/policy_table/policy_table.js index d9d74becf9e5d..dad259681eb7a 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/policy_table/policy_table.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/policy_table/policy_table.js @@ -36,9 +36,8 @@ import { } from '@elastic/eui'; import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services'; - +import { reactRouterNavigate } from '../../../../../../../../../src/plugins/kibana_react/public'; import { getIndexListUri } from '../../../../../../../index_management/public'; -import { BASE_PATH } from '../../../../../../common/constants'; import { UIM_EDIT_CLICK } from '../../../../constants'; import { getPolicyPath } from '../../../../services/navigation'; import { flattenPanelTree } from '../../../../services/flatten_panel_tree'; @@ -181,8 +180,9 @@ export class PolicyTable extends Component { /* eslint-disable-next-line @elastic/eui/href-or-on-click */ trackUiMetric('click', UIM_EDIT_CLICK)} + {...reactRouterNavigate(this.props.history, getPolicyPath(value), () => + trackUiMetric('click', UIM_EDIT_CLICK) + )} > {value} @@ -201,7 +201,7 @@ export class PolicyTable extends Component { renderCreatePolicyButton() { return ( { - window.location.hash = getIndexListUri(`ilm.policy:${policy.name}`); + this.props.navigateToApp('management', { + path: `/data/index_management${getIndexListUri(`ilm.policy:${policy.name}`)}`, + }); }, }); } diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/navigation.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/navigation.ts index 2d518ebb3015e..72e9d51d8fdeb 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/navigation.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/navigation.ts @@ -4,12 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { BASE_PATH } from '../../../common/constants'; - -export const goToPolicyList = () => { - window.location.hash = `${BASE_PATH}policies`; -}; - export const getPolicyPath = (policyName: string): string => { - return encodeURI(`#${BASE_PATH}policies/edit/${encodeURIComponent(policyName)}`); + return encodeURI(`/policies/edit/${encodeURIComponent(policyName)}`); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/add_lifecycle_confirm_modal.js b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/add_lifecycle_confirm_modal.js index 110998a7e9354..0bd313c9a9f8d 100644 --- a/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/add_lifecycle_confirm_modal.js +++ b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/add_lifecycle_confirm_modal.js @@ -23,7 +23,6 @@ import { EuiModalHeaderTitle, } from '@elastic/eui'; -import { BASE_PATH } from '../../../common/constants'; import { loadPolicies, addLifecyclePolicyToIndex } from '../../application/services/api'; import { showApiError } from '../../application/services/api_errors'; import { toasts } from '../../application/services/notification'; @@ -216,7 +215,7 @@ export class AddLifecyclePolicyConfirmModal extends Component { } render() { const { policies } = this.state; - const { indexName, closeModal } = this.props; + const { indexName, closeModal, getUrlForApp } = this.props; const title = (

- + {value}; + content = ( + + {value} + + ); } else { content = value; } diff --git a/x-pack/plugins/index_lifecycle_management/public/extend_index_management/index.js b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/index.js index 43f8332f4b6bd..e7afc8f12859c 100644 --- a/x-pack/plugins/index_lifecycle_management/public/extend_index_management/index.js +++ b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/index.js @@ -67,7 +67,7 @@ export const removeLifecyclePolicyActionExtension = ({ indices, reloadIndices }) }; }; -export const addLifecyclePolicyActionExtension = ({ indices, reloadIndices }) => { +export const addLifecyclePolicyActionExtension = ({ indices, reloadIndices, getUrlForApp }) => { if (indices.length !== 1) { return null; } @@ -86,6 +86,7 @@ export const addLifecyclePolicyActionExtension = ({ indices, reloadIndices }) => closeModal={closeModal} index={index} reloadIndices={reloadIndices} + getUrlForApp={getUrlForApp} /> ); }, @@ -123,8 +124,8 @@ export const ilmBannerExtension = (indices) => { }; }; -export const ilmSummaryExtension = (index) => { - return ; +export const ilmSummaryExtension = (index, getUrlForApp) => { + return ; }; export const ilmFilterExtension = (indices) => { diff --git a/x-pack/plugins/index_lifecycle_management/public/plugin.tsx b/x-pack/plugins/index_lifecycle_management/public/plugin.tsx index 3f8d7d7f88487..49856dee47fba 100644 --- a/x-pack/plugins/index_lifecycle_management/public/plugin.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/plugin.tsx @@ -47,6 +47,7 @@ export class IndexLifecycleManagementPlugin { const { i18n: { Context: I18nContext }, docLinks: { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION }, + application: { navigateToApp }, } = coreStart; // Initialize additional services. @@ -55,7 +56,7 @@ export class IndexLifecycleManagementPlugin { ); const { renderApp } = await import('./application'); - return renderApp(element, I18nContext, history); + return renderApp(element, I18nContext, history, navigateToApp); }, }); diff --git a/x-pack/plugins/index_management/public/application/app_context.tsx b/x-pack/plugins/index_management/public/application/app_context.tsx index ad934c18c18e3..84938de416941 100644 --- a/x-pack/plugins/index_management/public/application/app_context.tsx +++ b/x-pack/plugins/index_management/public/application/app_context.tsx @@ -18,6 +18,7 @@ const AppContext = createContext(undefined); export interface AppDependencies { core: { fatalErrors: CoreStart['fatalErrors']; + getUrlForApp: CoreStart['application']['getUrlForApp']; }; plugins: { usageCollection: UsageCollectionSetup; diff --git a/x-pack/plugins/index_management/public/application/mount_management_section.ts b/x-pack/plugins/index_management/public/application/mount_management_section.ts index 5e8282fcdcdf8..e8b6f200fb349 100644 --- a/x-pack/plugins/index_management/public/application/mount_management_section.ts +++ b/x-pack/plugins/index_management/public/application/mount_management_section.ts @@ -32,7 +32,7 @@ export async function mountManagementSection( ) { const { element, setBreadcrumbs, history } = params; const [core] = await coreSetup.getStartServices(); - const { docLinks, fatalErrors } = core; + const { docLinks, fatalErrors, application } = core; breadcrumbService.setup(setBreadcrumbs); documentationService.setup(docLinks); @@ -40,6 +40,7 @@ export async function mountManagementSection( const appDependencies: AppDependencies = { core: { fatalErrors, + getUrlForApp: application.getUrlForApp, }, plugins: { usageCollection, diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/summary.js b/x-pack/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/summary.js index e49b3c353931e..2fda71035fb58 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/summary.js +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/summary.js @@ -54,14 +54,14 @@ const getHeaders = () => { }; export class Summary extends React.PureComponent { - getAdditionalContent(extensionsService) { + getAdditionalContent(extensionsService, getUrlForApp) { const { index } = this.props; const extensions = extensionsService.summaries; return extensions.map((summaryExtension, i) => { return ( - {summaryExtension(index)} + {summaryExtension(index, getUrlForApp)} ); }); @@ -103,9 +103,12 @@ export class Summary extends React.PureComponent { render() { return ( - {({ services }) => { + {({ services, core }) => { const { left, right } = this.buildRows(); - const additionalContent = this.getAdditionalContent(services.extensionsService); + const additionalContent = this.getAdditionalContent( + services.extensionsService, + core.getUrlForApp + ); return ( diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js index effd80c39f0d1..1931884cf7306 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js @@ -46,7 +46,7 @@ export class IndexActionsContextMenu extends Component { confirmAction = (isActionConfirmed) => { this.setState({ isActionConfirmed }); }; - panels({ services: { extensionsService } }) { + panels({ services: { extensionsService }, core: { getUrlForApp } }) { const { closeIndices, openIndices, @@ -214,6 +214,7 @@ export class IndexActionsContextMenu extends Component { const actionExtensionDefinition = actionExtension({ indices, reloadIndices, + getUrlForApp, }); if (actionExtensionDefinition) { const { From 1b928278681dcb7cbdac2637c8ac3f7e524268ad Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Sat, 23 May 2020 22:36:08 +0300 Subject: [PATCH 38/93] fix some broken CI tests --- .../management/public/components/langing/landing.tsx | 6 +++--- .../test_suites/core_plugins/applications.ts | 3 ++- x-pack/plugins/rollup/public/plugin.ts | 4 +--- .../ml_popover/__snapshots__/upgrade_contents.test.tsx.snap | 2 +- x-pack/plugins/translations/translations/ja-JP.json | 5 ++--- x-pack/plugins/translations/translations/zh-CN.json | 5 ++--- .../ml/__tests__/__snapshots__/license_info.test.tsx.snap | 4 ++-- .../ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap | 2 +- 8 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/plugins/management/public/components/langing/landing.tsx b/src/plugins/management/public/components/langing/landing.tsx index c35f8b10b8163..f15374173e5f3 100644 --- a/src/plugins/management/public/components/langing/landing.tsx +++ b/src/plugins/management/public/components/langing/landing.tsx @@ -46,7 +46,7 @@ export const ManagementLandingPage = ({ version, setBreadcrumbs }: ManagementLan

@@ -54,7 +54,7 @@ export const ManagementLandingPage = ({ version, setBreadcrumbs }: ManagementLan @@ -65,7 +65,7 @@ export const ManagementLandingPage = ({ version, setBreadcrumbs }: ManagementLan

diff --git a/test/plugin_functional/test_suites/core_plugins/applications.ts b/test/plugin_functional/test_suites/core_plugins/applications.ts index 64d27103e59e2..6d31889a9cbe4 100644 --- a/test/plugin_functional/test_suites/core_plugins/applications.ts +++ b/test/plugin_functional/test_suites/core_plugins/applications.ts @@ -135,7 +135,8 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide expect(wrapperHeight).to.be.below(windowHeight); }); - it('can navigate from NP apps to legacy apps', async () => { + // Not sure if we need this test or not. If yes, we need to find another legacy app + it.skip('can navigate from NP apps to legacy apps', async () => { await appsMenu.clickLink('Stack Management'); await testSubjects.existOrFail('managementNav'); }); diff --git a/x-pack/plugins/rollup/public/plugin.ts b/x-pack/plugins/rollup/public/plugin.ts index b2e793d7e75e9..b55760c5cc5aa 100644 --- a/x-pack/plugins/rollup/public/plugin.ts +++ b/x-pack/plugins/rollup/public/plugin.ts @@ -16,8 +16,6 @@ import { FeatureCatalogueCategory, HomePublicPluginSetup, } from '../../../../src/plugins/home/public'; -// @ts-ignore -import { CRUD_APP_BASE_PATH } from './crud_app/constants'; import { ManagementSetup, ManagementSectionId } from '../../../../src/plugins/management/public'; import { IndexManagementPluginSetup } from '../../index_management/public'; import { IndexPatternManagementSetup } from '../../../../src/plugins/index_pattern_management/public'; @@ -71,7 +69,7 @@ export class RollupPlugin implements Plugin { 'Summarize and store historical data in a smaller index for future analysis.', }), icon: 'indexRollupApp', - path: `#${CRUD_APP_BASE_PATH}/job_list`, + path: `/app/management/data/rollup_jobs/job_list`, showOnHomePage: true, category: FeatureCatalogueCategory.ADMIN, }); diff --git a/x-pack/plugins/siem/public/common/components/ml_popover/__snapshots__/upgrade_contents.test.tsx.snap b/x-pack/plugins/siem/public/common/components/ml_popover/__snapshots__/upgrade_contents.test.tsx.snap index 87cf9fb18adf3..546fa78babe22 100644 --- a/x-pack/plugins/siem/public/common/components/ml_popover/__snapshots__/upgrade_contents.test.tsx.snap +++ b/x-pack/plugins/siem/public/common/components/ml_popover/__snapshots__/upgrade_contents.test.tsx.snap @@ -50,7 +50,7 @@ exports[`JobsTableFilters renders correctly against snapshot 1`] = ` grow={false} > diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 94b5ce719ccaa..27b5f1e06bf65 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -2363,9 +2363,8 @@ "indexPatternManagement.indexPatterns.listBreadcrumb": "インデックスパターン", "indexPatternManagement.indexPatternTable.createBtn": "インデックスパターンの作成", "indexPatternManagement.indexPatternTable.title": "インデックスパターン", - "kbn.management.landing.subhead": "インデックス、インデックスパターン、保存されたオブジェクト、Kibana の設定、その他を管理します。", - "kbn.management.landing.text": "すべてのツールの一覧は、左のメニューにあります。", - "kbn.managementTitle": "管理", + "management.landing.subhead": "インデックス、インデックスパターン、保存されたオブジェクト、Kibana の設定、その他を管理します。", + "management.landing.text": "すべてのツールの一覧は、左のメニューにあります。", "savedObjectsManagement.indexPattern.confirmOverwriteButton": "上書き", "savedObjectsManagement.indexPattern.confirmOverwriteLabel": "「{title}」に上書きしてよろしいですか?", "savedObjectsManagement.indexPattern.confirmOverwriteTitle": "{type} を上書きしますか?", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 06701fa2f0213..d7b5661322989 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -2364,9 +2364,8 @@ "indexPatternManagement.indexPatterns.listBreadcrumb": "索引模式", "indexPatternManagement.indexPatternTable.createBtn": "创建索引模式", "indexPatternManagement.indexPatternTable.title": "索引模式", - "kbn.management.landing.subhead": "管理您的索引、索引模式、已保存对象、Kibana 设置等等。", - "kbn.management.landing.text": "应用的完整列表位于左侧菜单中。", - "kbn.managementTitle": "管理", + "management.landing.subhead": "管理您的索引、索引模式、已保存对象、Kibana 设置等等。", + "management.landing.text": "应用的完整列表位于左侧菜单中。", "savedObjectsManagement.indexPattern.confirmOverwriteButton": "覆盖", "savedObjectsManagement.indexPattern.confirmOverwriteLabel": "确定要覆盖 “{title}”?", "savedObjectsManagement.indexPattern.confirmOverwriteTitle": "覆盖“{type}”?", diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/license_info.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/license_info.test.tsx.snap index 5ae90a1613575..2ba4eda82a391 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/license_info.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/license_info.test.tsx.snap @@ -28,7 +28,7 @@ Array [

@@ -64,7 +64,7 @@ exports[`ShowLicenseInfo shallow renders without errors 1`] = `

Start free 14-day trial diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap index df9de8c2ad03d..3a056e6621f58 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap @@ -160,7 +160,7 @@ exports[`ML Flyout component shows license info if no ml available 1`] = `

From 40f75605385b885d9a482a6a36312832c0289241 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Sat, 23 May 2020 22:57:38 +0300 Subject: [PATCH 39/93] fix PR comment --- .../management_sidebar_nav/management_sidebar_nav.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx index d4bba784c38aa..613c43109bf71 100644 --- a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx +++ b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { EuiIcon, EuiSideNav, EuiScreenReaderOnly } from '@elastic/eui'; +import { EuiIcon, EuiSideNav, EuiScreenReaderOnly, EuiSideNavItemType } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useState } from 'react'; import { AppMountParameters } from 'kibana/public'; @@ -74,7 +74,7 @@ export const ManagementSidebarNav = ({ const createNavItem = ( item: T, - customParams: Record = {} + customParams: Partial> = {} ) => { const iconType = item.euiIconType || item.icon; From ce54146ce4283798f90db982189d0ca513a3a659 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Sat, 23 May 2020 23:01:28 +0300 Subject: [PATCH 40/93] [snapshot_restore] move onClick into reactRouterNavigate --- .../home/policy_list/policy_table/policy_table.tsx | 6 +++--- .../repository_list/repository_table/repository_table.tsx | 6 +++--- .../home/snapshot_list/snapshot_table/snapshot_table.tsx | 8 +++++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_table/policy_table.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_table/policy_table.tsx index 380c9383ecf61..5f0a208348785 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_table/policy_table.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_table/policy_table.tsx @@ -66,9 +66,9 @@ export const PolicyTable: React.FunctionComponent = ({ {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} uiMetricService.trackUiMetric(UIM_POLICY_SHOW_DETAILS_CLICK)} + {...reactRouterNavigate(history, openPolicyDetailsUrl(name), () => + uiMetricService.trackUiMetric(UIM_POLICY_SHOW_DETAILS_CLICK) + )} data-test-subj="policyLink" > {name} diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/repository_list/repository_table/repository_table.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/home/repository_list/repository_table/repository_table.tsx index 3eaab47940f9f..70d83846cd74e 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/repository_list/repository_table/repository_table.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/repository_list/repository_table/repository_table.tsx @@ -57,9 +57,9 @@ export const RepositoryTable: React.FunctionComponent = ({ {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} uiMetricService.trackUiMetric(UIM_REPOSITORY_SHOW_DETAILS_CLICK)} + {...reactRouterNavigate(history, openRepositoryDetailsUrl(name), () => + uiMetricService.trackUiMetric(UIM_REPOSITORY_SHOW_DETAILS_CLICK) + )} data-test-subj="repositoryLink" > {name} diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_table/snapshot_table.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_table/snapshot_table.tsx index d467965dadb72..4910bf909ce3a 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_table/snapshot_table.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_table/snapshot_table.tsx @@ -76,9 +76,11 @@ export const SnapshotTable: React.FunctionComponent = ({ render: (snapshotId: string, snapshot: SnapshotDetails) => ( /* eslint-disable-next-line @elastic/eui/href-or-on-click */ uiMetricService.trackUiMetric(UIM_SNAPSHOT_SHOW_DETAILS_CLICK)} + {...reactRouterNavigate( + history, + openSnapshotDetailsUrl(snapshot.repository, snapshotId), + () => uiMetricService.trackUiMetric(UIM_SNAPSHOT_SHOW_DETAILS_CLICK) + )} data-test-subj="snapshotLink" > {snapshotId} From 240c0f6929a5c1ea14b7102d94f9c3169c4ac24b Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Sun, 24 May 2020 22:08:13 +0300 Subject: [PATCH 41/93] fix some jest --- .../components/__snapshots__/add_data.test.js.snap | 8 ++++---- .../components/__snapshots__/welcome.test.tsx.snap | 6 +++--- .../components/__snapshots__/relationships.test.tsx.snap | 2 +- .../__snapshots__/opted_in_notice_banner.test.tsx.snap | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap b/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap index 924de9bbd0994..3b3f86e579f1a 100644 --- a/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap +++ b/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap @@ -277,7 +277,7 @@ exports[`apmUiEnabled 1`] = ` /> Date: Sun, 24 May 2020 22:28:44 +0300 Subject: [PATCH 42/93] fix some functional tests --- .../saved_objects_management/edit_saved_object.ts | 6 +++--- .../test_suites/management/management_plugin.js | 7 ++----- .../feature_controls/advanced_settings_security.ts | 2 +- .../feature_controls/advanced_settings_spaces.ts | 4 ++-- .../feature_controls/index_patterns_security.ts | 2 +- .../feature_controls/index_patterns_spaces.ts | 2 +- .../saved_objects_management_security.ts | 10 +++++----- .../test/functional/apps/security/role_mappings.ts | 4 ++-- .../apps/spaces/feature_controls/spaces_security.ts | 12 ++++++------ 9 files changed, 23 insertions(+), 26 deletions(-) diff --git a/test/functional/apps/saved_objects_management/edit_saved_object.ts b/test/functional/apps/saved_objects_management/edit_saved_object.ts index 06b2e86dd1af9..caad9558687f4 100644 --- a/test/functional/apps/saved_objects_management/edit_saved_object.ts +++ b/test/functional/apps/saved_objects_management/edit_saved_object.ts @@ -139,7 +139,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const objects = await PageObjects.settings.getSavedObjectsInTable(); expect(objects.includes('A Pie')).to.be(true); - await PageObjects.common.navigateToActualUrl('kibana', testVisualizationUrl); + await PageObjects.common.navigateToActualUrl(testVisualizationUrl); await testSubjects.existOrFail('savedObjectEditSave'); @@ -151,7 +151,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.settings.getSavedObjectsInTable(); - await PageObjects.common.navigateToActualUrl('kibana', testVisualizationUrl); + await PageObjects.common.navigateToActualUrl(testVisualizationUrl); // Parsing to avoid random keys ordering issues in raw string comparison expect(JSON.parse(await getAceEditorFieldValue('references'))).to.eql(visualizationRefs); @@ -162,7 +162,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.settings.getSavedObjectsInTable(); - await PageObjects.common.navigateToActualUrl('kibana', testVisualizationUrl); + await PageObjects.common.navigateToActualUrl(testVisualizationUrl); displayedReferencesValue = await getAceEditorFieldValue('references'); diff --git a/test/plugin_functional/test_suites/management/management_plugin.js b/test/plugin_functional/test_suites/management/management_plugin.js index 87542c97a3f5d..4dea719535a43 100644 --- a/test/plugin_functional/test_suites/management/management_plugin.js +++ b/test/plugin_functional/test_suites/management/management_plugin.js @@ -23,7 +23,7 @@ export default function ({ getService, getPageObjects }) { describe('management plugin', function describeIndexTests() { before(async () => { - await PageObjects.common.navigateToActualUrl('kibana', 'management'); + await PageObjects.common.navigateToActualUrl('management'); }); it('should be able to navigate to management test app', async () => { @@ -38,10 +38,7 @@ export default function ({ getService, getPageObjects }) { }); it('should redirect when app is disabled', async () => { - await PageObjects.common.navigateToActualUrl( - 'kibana', - 'management/data/test-management-disabled' - ); + await PageObjects.common.navigateToActualUrl('management/data/test-management-disabled'); await testSubjects.existOrFail('management-landing'); }); }); diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts index b64db5eaeffac..b5bea917457d9 100644 --- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts +++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts @@ -182,7 +182,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it(`does not allow navigation to advanced settings; redirects to management home`, async () => { - await PageObjects.common.navigateToActualUrl('kibana', 'management/kibana/settings', { + await PageObjects.common.navigateToActualUrl('management/kibana/settings', undefined, { ensureCurrentUrl: false, shouldLoginIfPrompted: false, }); diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts index 7e4aa6e375aef..af2c8c8f5d064 100644 --- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts +++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts @@ -47,7 +47,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it(`allows settings to be changed`, async () => { - await PageObjects.common.navigateToActualUrl('kibana', 'management/kibana/settings', { + await PageObjects.common.navigateToActualUrl('management/kibana/settings', undefined, { basePath: `/s/custom_space`, ensureCurrentUrl: false, shouldLoginIfPrompted: false, @@ -77,7 +77,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it(`redirects to management home`, async () => { - await PageObjects.common.navigateToActualUrl('kibana', 'management/kibana/settings', { + await PageObjects.common.navigateToActualUrl('management/kibana/settings', undefined, { basePath: `/s/custom_space`, ensureCurrentUrl: false, shouldLoginIfPrompted: false, diff --git a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts index 1d45d00cbc894..70f8cddbbafeb 100644 --- a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts +++ b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts @@ -187,7 +187,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it(`does not allow navigation to Index Patterns; redirects to management home`, async () => { - await PageObjects.common.navigateToActualUrl('kibana', 'management/kibana/indexPatterns', { + await PageObjects.common.navigateToActualUrl('management/kibana/indexPatterns', undefined, { ensureCurrentUrl: false, shouldLoginIfPrompted: false, }); diff --git a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts index 7e82dfab1d7a3..78407f66b0e12 100644 --- a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts +++ b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts @@ -70,7 +70,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it(`redirects to management home`, async () => { - await PageObjects.common.navigateToActualUrl('kibana', 'management/kibana/indexPatterns', { + await PageObjects.common.navigateToActualUrl('management/kibana/indexPatterns', undefined, { basePath: `/s/custom_space`, ensureCurrentUrl: false, shouldLoginIfPrompted: false, diff --git a/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts b/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts index 383f97cb2ce43..0d0153110346f 100644 --- a/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts +++ b/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts @@ -112,8 +112,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { describe('edit visualization', () => { before(async () => { await PageObjects.common.navigateToActualUrl( - 'kibana', '/management/kibana/objects/savedVisualizations/75c3e060-1e7c-11e9-8488-65449e65d0ed', + undefined, { shouldLoginIfPrompted: false, } @@ -230,8 +230,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { describe('edit visualization', () => { before(async () => { await PageObjects.common.navigateToActualUrl( - 'kibana', '/management/kibana/objects/savedVisualizations/75c3e060-1e7c-11e9-8488-65449e65d0ed', + undefined, { shouldLoginIfPrompted: false, } @@ -302,7 +302,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { describe('listing', () => { it('redirects to Kibana home', async () => { - await PageObjects.common.navigateToActualUrl('kibana', 'management/kibana/objects', { + await PageObjects.common.navigateToActualUrl('management/kibana/objects', undefined, { ensureCurrentUrl: false, shouldLoginIfPrompted: false, }); @@ -314,8 +314,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { describe('edit visualization', () => { it('redirects to Kibana home', async () => { await PageObjects.common.navigateToActualUrl( - 'kibana', - '/management/kibana/objects/savedVisualizations/75c3e060-1e7c-11e9-8488-65449e65d0ed', + 'management/kibana/objects/savedVisualizations/75c3e060-1e7c-11e9-8488-65449e65d0ed', + undefined, { shouldLoginIfPrompted: false, ensureCurrentUrl: false, diff --git a/x-pack/test/functional/apps/security/role_mappings.ts b/x-pack/test/functional/apps/security/role_mappings.ts index dcd411e75232d..f252026405f7a 100644 --- a/x-pack/test/functional/apps/security/role_mappings.ts +++ b/x-pack/test/functional/apps/security/role_mappings.ts @@ -84,8 +84,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('displays an error and returns to the listing page when navigating to a role mapping which does not exist', async () => { await pageObjects.common.navigateToActualUrl( - 'management', - 'security/role_mappings/edit/i-do-not-exist', + 'management/security/role_mappings/edit/i-do-not-exist', + undefined, { ensureCurrentUrl: false } ); diff --git a/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts b/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts index d43d56ae22e36..3c96620943c4a 100644 --- a/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts +++ b/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts @@ -65,7 +65,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it(`can navigate to spaces grid page`, async () => { - await PageObjects.common.navigateToActualUrl('kibana', 'management/kibana/spaces', { + await PageObjects.common.navigateToActualUrl('management/kibana/spaces', undefined, { ensureCurrentUrl: false, shouldLoginIfPrompted: false, }); @@ -74,7 +74,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it(`can navigate to create new space page`, async () => { - await PageObjects.common.navigateToActualUrl('kibana', 'management/kibana/spaces/create', { + await PageObjects.common.navigateToActualUrl('management/kibana/spaces/create', undefined, { ensureCurrentUrl: false, shouldLoginIfPrompted: false, }); @@ -84,8 +84,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it(`can navigate to edit space page`, async () => { await PageObjects.common.navigateToActualUrl( - 'kibana', 'management/kibana/spaces/edit/default', + undefined, { ensureCurrentUrl: false, shouldLoginIfPrompted: false, @@ -144,7 +144,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it(`can't navigate to spaces grid page`, async () => { - await PageObjects.common.navigateToActualUrl('kibana', 'management/kibana/spaces', { + await PageObjects.common.navigateToActualUrl('management/kibana/spaces', undefined, { ensureCurrentUrl: false, shouldLoginIfPrompted: false, }); @@ -153,7 +153,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it(`can't navigate to create new space page`, async () => { - await PageObjects.common.navigateToActualUrl('kibana', 'management/kibana/spaces/create', { + await PageObjects.common.navigateToActualUrl('management/kibana/spaces/create', undefined, { ensureCurrentUrl: false, shouldLoginIfPrompted: false, }); @@ -163,8 +163,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it(`can't navigate to edit space page`, async () => { await PageObjects.common.navigateToActualUrl( - 'kibana', 'management/kibana/spaces/edit/default', + undefined, { ensureCurrentUrl: false, shouldLoginIfPrompted: false, From c1f2f20da18374f38759eff6ed0ca6b04695d90c Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 25 May 2020 11:45:55 +0300 Subject: [PATCH 43/93] fix functiona test: management scripted fields testing regression for issue --- .../create_edit_field/create_edit_field.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx index fb5c27774f506..5c6822d539a8a 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx @@ -94,7 +94,9 @@ export const CreateEditField = withRouter( services.docTitle.change([docFieldName, indexPattern.title]); const redirectAway = () => { - history.push(`${url}?_a=(tab:${field?.scripted ? TAB_SCRIPTED_FIELDS : TAB_INDEXED_FIELDS})`); + history.push( + `${url}#/?_a=(tab:${field?.scripted ? TAB_SCRIPTED_FIELDS : TAB_INDEXED_FIELDS})` + ); }; if (field) { From 21391a50c9e2908ab465b936ab1086000b99ee34 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 25 May 2020 13:01:59 +0300 Subject: [PATCH 44/93] fix some functional tests --- .../management_app/management_router.tsx | 28 +++++------ test/functional/config.js | 4 ++ test/functional/page_objects/common_page.ts | 10 +++- .../management_test_plugin/public/plugin.tsx | 16 +++---- .../management/management_plugin.js | 8 +++- .../advanced_settings_security.ts | 3 +- .../advanced_settings_spaces.ts | 6 ++- .../index_patterns_security.ts | 3 +- .../feature_controls/index_patterns_spaces.ts | 3 +- .../saved_objects_management_security.ts | 24 ++++++---- .../functional/apps/security/role_mappings.ts | 8 ++-- .../feature_controls/spaces_security.ts | 46 +++++++++---------- 12 files changed, 91 insertions(+), 68 deletions(-) diff --git a/src/plugins/management/public/components/management_app/management_router.tsx b/src/plugins/management/public/components/management_app/management_router.tsx index 12aed3d115a76..da16a869558bc 100644 --- a/src/plugins/management/public/components/management_app/management_router.tsx +++ b/src/plugins/management/public/components/management_app/management_router.tsx @@ -40,19 +40,21 @@ export const ManagementRouter = memo( {sections.map((section) => - section.apps.map((app) => ( - ( - - )} - /> - )) + section + .getAppsEnabled() + .map((app) => ( + ( + + )} + /> + )) )} +

Hello from management test plugin

- - - Link to /one - - - + Link to basePath + + + Link to /one + +
, params.element diff --git a/test/plugin_functional/test_suites/management/management_plugin.js b/test/plugin_functional/test_suites/management/management_plugin.js index 4dea719535a43..8d879cfa67d7a 100644 --- a/test/plugin_functional/test_suites/management/management_plugin.js +++ b/test/plugin_functional/test_suites/management/management_plugin.js @@ -38,8 +38,12 @@ export default function ({ getService, getPageObjects }) { }); it('should redirect when app is disabled', async () => { - await PageObjects.common.navigateToActualUrl('management/data/test-management-disabled'); - await testSubjects.existOrFail('management-landing'); + await PageObjects.common.navigateToUrl('management', 'data/test-management-disabled', { + useActualUrl: true, + shouldUseHashForSubUrl: false, + }); + + await testSubjects.existOrFail('managementHome'); }); }); } diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts index b5bea917457d9..cbf1f3e1af2df 100644 --- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts +++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts @@ -182,9 +182,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it(`does not allow navigation to advanced settings; redirects to management home`, async () => { - await PageObjects.common.navigateToActualUrl('management/kibana/settings', undefined, { + await PageObjects.common.navigateToUrl('management', 'kibana/settings', { ensureCurrentUrl: false, shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, }); await testSubjects.existOrFail('managementHome', { timeout: config.get('timeouts.waitFor'), diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts index af2c8c8f5d064..f7991e62fdaa9 100644 --- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts +++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts @@ -47,10 +47,11 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it(`allows settings to be changed`, async () => { - await PageObjects.common.navigateToActualUrl('management/kibana/settings', undefined, { + await PageObjects.common.navigateToUrl('management', 'kibana/settings', { basePath: `/s/custom_space`, ensureCurrentUrl: false, shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, }); await PageObjects.settings.setAdvancedSettingsSelect('dateFormat:tz', 'America/Phoenix'); const advancedSetting = await PageObjects.settings.getAdvancedSettings('dateFormat:tz'); @@ -77,10 +78,11 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it(`redirects to management home`, async () => { - await PageObjects.common.navigateToActualUrl('management/kibana/settings', undefined, { + await PageObjects.common.navigateToUrl('management', 'kibana/settings', { basePath: `/s/custom_space`, ensureCurrentUrl: false, shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, }); await testSubjects.existOrFail('managementHome', { timeout: config.get('timeouts.waitFor'), diff --git a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts index 70f8cddbbafeb..cd892c4424290 100644 --- a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts +++ b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts @@ -187,9 +187,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it(`does not allow navigation to Index Patterns; redirects to management home`, async () => { - await PageObjects.common.navigateToActualUrl('management/kibana/indexPatterns', undefined, { + await PageObjects.common.navigateToUrl('management', 'kibana/indexPatterns', { ensureCurrentUrl: false, shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, }); await testSubjects.existOrFail('managementHome', { timeout: config.get('timeouts.waitFor'), diff --git a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts index 78407f66b0e12..29929a978c8d8 100644 --- a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts +++ b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts @@ -70,10 +70,11 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it(`redirects to management home`, async () => { - await PageObjects.common.navigateToActualUrl('management/kibana/indexPatterns', undefined, { + await PageObjects.common.navigateToUrl('management', 'kibana/indexPatterns', { basePath: `/s/custom_space`, ensureCurrentUrl: false, shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, }); await testSubjects.existOrFail('managementHome', { timeout: config.get('timeouts.waitFor'), diff --git a/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts b/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts index 0d0153110346f..9969608bd2a45 100644 --- a/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts +++ b/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts @@ -111,11 +111,12 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { describe('edit visualization', () => { before(async () => { - await PageObjects.common.navigateToActualUrl( - '/management/kibana/objects/savedVisualizations/75c3e060-1e7c-11e9-8488-65449e65d0ed', - undefined, + await PageObjects.common.navigateToUrl( + 'management', + 'kibana/objects/savedVisualizations/75c3e060-1e7c-11e9-8488-65449e65d0ed', { shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, } ); }); @@ -229,11 +230,12 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { describe('edit visualization', () => { before(async () => { - await PageObjects.common.navigateToActualUrl( - '/management/kibana/objects/savedVisualizations/75c3e060-1e7c-11e9-8488-65449e65d0ed', - undefined, + await PageObjects.common.navigateToUrl( + 'management', + 'kibana/objects/savedVisualizations/75c3e060-1e7c-11e9-8488-65449e65d0ed', { shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, } ); await testSubjects.existOrFail('savedObjectsEdit'); @@ -302,9 +304,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { describe('listing', () => { it('redirects to Kibana home', async () => { - await PageObjects.common.navigateToActualUrl('management/kibana/objects', undefined, { + await PageObjects.common.navigateToUrl('management', 'kibana/objects', { ensureCurrentUrl: false, shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, }); await PageObjects.header.waitUntilLoadingHasFinished(); await testSubjects.existOrFail('homeApp'); @@ -313,12 +316,13 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { describe('edit visualization', () => { it('redirects to Kibana home', async () => { - await PageObjects.common.navigateToActualUrl( - 'management/kibana/objects/savedVisualizations/75c3e060-1e7c-11e9-8488-65449e65d0ed', - undefined, + await PageObjects.common.navigateToUrl( + 'management', + 'kibana/objects/savedVisualizations/75c3e060-1e7c-11e9-8488-65449e65d0ed', { shouldLoginIfPrompted: false, ensureCurrentUrl: false, + shouldUseHashForSubUrl: false, } ); await PageObjects.header.waitUntilLoadingHasFinished(); diff --git a/x-pack/test/functional/apps/security/role_mappings.ts b/x-pack/test/functional/apps/security/role_mappings.ts index f252026405f7a..dd953769c3ce6 100644 --- a/x-pack/test/functional/apps/security/role_mappings.ts +++ b/x-pack/test/functional/apps/security/role_mappings.ts @@ -83,10 +83,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('displays an error and returns to the listing page when navigating to a role mapping which does not exist', async () => { - await pageObjects.common.navigateToActualUrl( - 'management/security/role_mappings/edit/i-do-not-exist', - undefined, - { ensureCurrentUrl: false } + await pageObjects.common.navigateToUrl( + 'management', + 'security/role_mappings/edit/i-do-not-exist', + { ensureCurrentUrl: false, shouldUseHashForSubUrl: false } ); await testSubjects.existOrFail('errorLoadingRoleMappingEditorToast'); diff --git a/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts b/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts index 3c96620943c4a..d904c407b060b 100644 --- a/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts +++ b/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts @@ -65,32 +65,31 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it(`can navigate to spaces grid page`, async () => { - await PageObjects.common.navigateToActualUrl('management/kibana/spaces', undefined, { + await PageObjects.common.navigateToUrl('management', 'kibana/spaces', { ensureCurrentUrl: false, shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, }); await testSubjects.existOrFail('spaces-grid-page'); }); it(`can navigate to create new space page`, async () => { - await PageObjects.common.navigateToActualUrl('management/kibana/spaces/create', undefined, { + await PageObjects.common.navigateToUrl('management', 'kibana/spaces/create', { ensureCurrentUrl: false, shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, }); await testSubjects.existOrFail('spaces-edit-page'); }); it(`can navigate to edit space page`, async () => { - await PageObjects.common.navigateToActualUrl( - 'management/kibana/spaces/edit/default', - undefined, - { - ensureCurrentUrl: false, - shouldLoginIfPrompted: false, - } - ); + await PageObjects.common.navigateToUrl('management', 'kibana/spaces/edit/default', { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, + }); await testSubjects.existOrFail('spaces-edit-page'); }); @@ -139,39 +138,38 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it(`doesn't display Spaces management section`, async () => { await PageObjects.settings.navigateTo(); - await testSubjects.existOrFail('management-landing'); // this ensures we've gotten to the management page + await testSubjects.existOrFail('managementHome'); // this ensures we've gotten to the management page await testSubjects.missingOrFail('spaces'); }); it(`can't navigate to spaces grid page`, async () => { - await PageObjects.common.navigateToActualUrl('management/kibana/spaces', undefined, { + await PageObjects.common.navigateToUrl('management', 'kibana/spaces', { ensureCurrentUrl: false, shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, }); - await testSubjects.existOrFail('management-landing'); + await testSubjects.existOrFail('managementHome'); }); it(`can't navigate to create new space page`, async () => { - await PageObjects.common.navigateToActualUrl('management/kibana/spaces/create', undefined, { + await PageObjects.common.navigateToUrl('management', 'kibana/spaces/create', { ensureCurrentUrl: false, shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, }); - await testSubjects.existOrFail('management-landing'); + await testSubjects.existOrFail('managementHome'); }); it(`can't navigate to edit space page`, async () => { - await PageObjects.common.navigateToActualUrl( - 'management/kibana/spaces/edit/default', - undefined, - { - ensureCurrentUrl: false, - shouldLoginIfPrompted: false, - } - ); + await PageObjects.common.navigateToUrl('management', 'kibana/spaces/edit/default', { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, + }); - await testSubjects.existOrFail('management-landing'); + await testSubjects.existOrFail('managementHome'); }); }); }); From c8d3d7745517927baa5b2ac061fa8d059b488069 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 25 May 2020 14:07:36 +0300 Subject: [PATCH 45/93] [licence_management] partial progress --- .../__jest__/upload_license.test.tsx | 6 ++---- .../common/constants/base_path.ts | 2 -- .../license_management/common/constants/index.ts | 2 +- .../license_management/public/application/app.js | 2 +- .../public/application/app_providers.tsx | 5 +---- .../public/application/breadcrumbs.ts | 3 +-- .../license_dashboard/add_license/add_license.js | 13 ++++++++++--- .../sections/upload_license/upload_license.js | 7 ++++--- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/license_management/__jest__/upload_license.test.tsx b/x-pack/plugins/license_management/__jest__/upload_license.test.tsx index ad2fbd288e9f4..8f85e09de6c6c 100644 --- a/x-pack/plugins/license_management/__jest__/upload_license.test.tsx +++ b/x-pack/plugins/license_management/__jest__/upload_license.test.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { Provider } from 'react-redux'; -import { httpServiceMock } from '../../../../src/core/public/mocks'; +import { httpServiceMock, scopedHistoryMock } from '../../../../src/core/public/mocks'; import { mountWithIntl } from '../../../test_utils/enzyme_helpers'; // @ts-ignore @@ -44,9 +44,7 @@ const appDependencies = { const thunkServices = { http: httpServiceMock.createSetupContract(), - history: { - replace: jest.fn(), - }, + history: scopedHistoryMock.create(), breadcrumbService: { setBreadcrumbs() {}, }, diff --git a/x-pack/plugins/license_management/common/constants/base_path.ts b/x-pack/plugins/license_management/common/constants/base_path.ts index 6ed03a0428096..ffb470e931921 100644 --- a/x-pack/plugins/license_management/common/constants/base_path.ts +++ b/x-pack/plugins/license_management/common/constants/base_path.ts @@ -4,6 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export const BASE_PATH = '/management/stack/license_management/'; - export const API_BASE_PATH = '/api/license'; diff --git a/x-pack/plugins/license_management/common/constants/index.ts b/x-pack/plugins/license_management/common/constants/index.ts index ec411fea4b7a9..a531ba08401f8 100644 --- a/x-pack/plugins/license_management/common/constants/index.ts +++ b/x-pack/plugins/license_management/common/constants/index.ts @@ -5,6 +5,6 @@ */ export { PLUGIN } from './plugin'; -export { BASE_PATH, API_BASE_PATH } from './base_path'; +export { API_BASE_PATH } from './base_path'; export { EXTERNAL_LINKS } from './external_links'; export { APP_PERMISSION } from './permissions'; diff --git a/x-pack/plugins/license_management/public/application/app.js b/x-pack/plugins/license_management/public/application/app.js index e0c590c4f09ca..6885a249be01c 100644 --- a/x-pack/plugins/license_management/public/application/app.js +++ b/x-pack/plugins/license_management/public/application/app.js @@ -90,7 +90,7 @@ export class App extends Component { - + ); diff --git a/x-pack/plugins/license_management/public/application/app_providers.tsx b/x-pack/plugins/license_management/public/application/app_providers.tsx index 9f9fd2a8275df..139290f2c46ce 100644 --- a/x-pack/plugins/license_management/public/application/app_providers.tsx +++ b/x-pack/plugins/license_management/public/application/app_providers.tsx @@ -4,10 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ import React from 'react'; -import * as history from 'history'; import { Provider } from 'react-redux'; -import { BASE_PATH } from '../../common/constants'; import { AppContextProvider, AppDependencies } from './app_context'; // @ts-ignore import { licenseManagementStore } from './store'; @@ -33,8 +31,7 @@ export const AppProviders = ({ appDependencies, children }: Props) => { // Setup Redux store const thunkServices = { - // So we can imperatively control the hash route - history: history.createHashHistory({ basename: BASE_PATH }), + history: appDependencies.services.history, toasts, http, telemetry: plugins.telemetry, diff --git a/x-pack/plugins/license_management/public/application/breadcrumbs.ts b/x-pack/plugins/license_management/public/application/breadcrumbs.ts index b1773a10f01ba..d3a69f55c4347 100644 --- a/x-pack/plugins/license_management/public/application/breadcrumbs.ts +++ b/x-pack/plugins/license_management/public/application/breadcrumbs.ts @@ -7,7 +7,6 @@ import { i18n } from '@kbn/i18n'; import { ManagementAppMountParams } from '../../../../../src/plugins/management/public'; -import { BASE_PATH } from '../../common/constants'; type SetBreadcrumbs = ManagementAppMountParams['setBreadcrumbs']; @@ -32,7 +31,7 @@ export class BreadcrumbService { text: i18n.translate('xpack.licenseMgmt.dashboard.breadcrumb', { defaultMessage: 'License management', }), - href: `#${BASE_PATH}home`, + href: `/`, }, ]; diff --git a/x-pack/plugins/license_management/public/application/sections/license_dashboard/add_license/add_license.js b/x-pack/plugins/license_management/public/application/sections/license_dashboard/add_license/add_license.js index 158702e1286ae..d13a3bc34a7f2 100644 --- a/x-pack/plugins/license_management/public/application/sections/license_dashboard/add_license/add_license.js +++ b/x-pack/plugins/license_management/public/application/sections/license_dashboard/add_license/add_license.js @@ -5,12 +5,16 @@ */ import React from 'react'; -import { BASE_PATH } from '../../../../../common/constants'; import { EuiCard, EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import { useAppContext } from '../../../app_context'; + +import { reactRouterNavigate } from '../../../../../../../../src/plugins/kibana_react/public'; + +export const AddLicense = ({ uploadPath = `/upload_license` }) => { + const { services } = useAppContext(); -export const AddLicense = ({ uploadPath = `#${BASE_PATH}upload_license` }) => { return ( { /> } footer={ - + @@ -189,7 +190,7 @@ export class UploadLicense extends React.PureComponent { - + Date: Mon, 25 May 2020 16:28:06 +0300 Subject: [PATCH 46/93] Fixed x-pack jest tests --- .../common/constants/index.ts | 1 - .../auto_follow_pattern_add.helpers.js | 6 ++- .../auto_follow_pattern_edit.helpers.js | 6 ++- .../helpers/follower_index_add.helpers.js | 6 ++- .../helpers/follower_index_edit.helpers.js | 6 ++- .../helpers/follower_index_list.helpers.js | 6 ++- .../helpers/home.helpers.js | 5 +- .../follower_index_resume_provider.js | 2 +- .../extend_index_management.test.js.snap | 10 ++-- .../__snapshots__/policy_table.test.js.snap | 7 ++- .../__jest__/components/policy_table.test.js | 5 +- .../__jest__/extend_index_management.test.js | 17 ++++-- .../helpers/home.helpers.ts | 5 +- .../helpers/setup_environment.tsx | 10 +++- .../create_role_mapping_button.tsx | 10 ++-- .../empty_prompt/empty_prompt.tsx | 9 +++- .../role_mappings_grid_page.test.tsx | 14 ++++- .../role_mappings_grid_page.tsx | 14 +++-- .../role_mappings_management_app.test.tsx | 41 ++++++-------- .../role_mappings_management_app.tsx | 2 + .../role_table_display/role_table_display.tsx | 21 +++++--- .../roles/roles_management_app.test.tsx | 54 +++++++------------ .../users/users_grid/users_grid_page.test.tsx | 15 +++++- .../users/users_grid/users_grid_page.tsx | 10 +++- .../users/users_management_app.test.tsx | 43 ++++++--------- .../management/users/users_management_app.tsx | 2 + .../helpers/setup_environment.tsx | 10 +++- .../management/spaces_management_app.test.tsx | 32 +++++------ .../helpers/app_context.mock.tsx | 9 +++- .../client_integration/watch_list.test.ts | 2 +- 30 files changed, 218 insertions(+), 162 deletions(-) diff --git a/x-pack/plugins/cross_cluster_replication/common/constants/index.ts b/x-pack/plugins/cross_cluster_replication/common/constants/index.ts index 73185e6fa1b8d..0574cb9b2dd6d 100644 --- a/x-pack/plugins/cross_cluster_replication/common/constants/index.ts +++ b/x-pack/plugins/cross_cluster_replication/common/constants/index.ts @@ -24,7 +24,6 @@ export const APPS = { }; export const MANAGEMENT_ID = 'cross_cluster_replication'; -export const BASE_PATH = `/management/data/${MANAGEMENT_ID}`; export const BASE_PATH_REMOTE_CLUSTERS = 'data/remote_clusters'; export const API_BASE_PATH = '/api/cross_cluster_replication'; export const API_REMOTE_CLUSTERS_BASE_PATH = '/api/remote_clusters'; diff --git a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_add.helpers.js b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_add.helpers.js index e240b5b304c33..a4edee7268a23 100644 --- a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_add.helpers.js +++ b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_add.helpers.js @@ -12,7 +12,11 @@ import { routing } from '../../../app/services/routing'; const testBedConfig = { store: ccrStore, memoryRouter: { - onRouter: (router) => (routing.reactRouter = router), + onRouter: (router) => + (routing.reactRouter = { + ...router, + getUrlForApp: () => '', + }), }, }; diff --git a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_edit.helpers.js b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_edit.helpers.js index c32f6a54114c7..ea372d534d817 100644 --- a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_edit.helpers.js +++ b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_edit.helpers.js @@ -14,7 +14,11 @@ import { AUTO_FOLLOW_PATTERN_EDIT_NAME } from './constants'; const testBedConfig = { store: ccrStore, memoryRouter: { - onRouter: (router) => (routing.reactRouter = router), + onRouter: (router) => + (routing.reactRouter = { + ...router, + getUrlForApp: () => '', + }), // The auto-follow pattern id to fetch is read from the router ":id" param // so we first set it in our initial entries initialEntries: [`/${AUTO_FOLLOW_PATTERN_EDIT_NAME}`], diff --git a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_add.helpers.js b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_add.helpers.js index 9778b595111a2..31f3844f57fb5 100644 --- a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_add.helpers.js +++ b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_add.helpers.js @@ -12,7 +12,11 @@ import { routing } from '../../../app/services/routing'; const testBedConfig = { store: ccrStore, memoryRouter: { - onRouter: (router) => (routing.reactRouter = router), + onRouter: (router) => + (routing.reactRouter = { + ...router, + getUrlForApp: () => '', + }), }, }; diff --git a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_edit.helpers.js b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_edit.helpers.js index 993cde86ada22..8fc2811e58cdb 100644 --- a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_edit.helpers.js +++ b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_edit.helpers.js @@ -14,7 +14,11 @@ import { FOLLOWER_INDEX_EDIT_NAME } from './constants'; const testBedConfig = { store: ccrStore, memoryRouter: { - onRouter: (router) => (routing.reactRouter = router), + onRouter: (router) => + (routing.reactRouter = { + ...router, + getUrlForApp: () => '', + }), // The follower index id to fetch is read from the router ":id" param // so we first set it in our initial entries initialEntries: [`/${FOLLOWER_INDEX_EDIT_NAME}`], diff --git a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_list.helpers.js b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_list.helpers.js index 16a4fa9cd3f3e..c147a3984190b 100644 --- a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_list.helpers.js +++ b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_list.helpers.js @@ -12,7 +12,11 @@ import { routing } from '../../../app/services/routing'; const testBedConfig = { store: ccrStore, memoryRouter: { - onRouter: (router) => (routing.reactRouter = router), + onRouter: (router) => + (routing.reactRouter = { + ...router, + getUrlForApp: () => '', + }), }, }; diff --git a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/home.helpers.js b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/home.helpers.js index 26a0d86cdcbca..e51c444a6b370 100644 --- a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/home.helpers.js +++ b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/home.helpers.js @@ -5,7 +5,6 @@ */ import { registerTestBed } from '../../../../../../test_utils'; -import { BASE_PATH } from '../../../../common/constants'; import { CrossClusterReplicationHome } from '../../../app/sections/home/home'; import { ccrStore } from '../../../app/store'; import { routing } from '../../../app/services/routing'; @@ -13,8 +12,8 @@ import { routing } from '../../../app/services/routing'; const testBedConfig = { store: ccrStore, memoryRouter: { - initialEntries: [`${BASE_PATH}/follower_indices`], - componentRoutePath: `${BASE_PATH}/:section`, + initialEntries: [`/follower_indices`], + componentRoutePath: `/:section`, onRouter: (router) => (routing.reactRouter = router), }, }; diff --git a/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_resume_provider.js b/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_resume_provider.js index 4c264b9b3e708..101e3df6bf710 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_resume_provider.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_resume_provider.js @@ -99,7 +99,7 @@ class FollowerIndexResumeProviderUi extends PureComponent { editLink: (
testy @@ -564,6 +565,7 @@ exports[`extend index management ilm summary extension should return extension w exports[`extend index management ilm summary extension should return extension when index has lifecycle policy 1`] = ` testy diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/components/__snapshots__/policy_table.test.js.snap b/x-pack/plugins/index_lifecycle_management/__jest__/components/__snapshots__/policy_table.test.js.snap index 857a63826505e..5edc5a9343fc3 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/components/__snapshots__/policy_table.test.js.snap +++ b/x-pack/plugins/index_lifecycle_management/__jest__/components/__snapshots__/policy_table.test.js.snap @@ -91,11 +91,10 @@ exports[`policy table should show empty state when there are not any policies 1`
{ store = indexLifecycleManagementStore(); component = ( - + {}} /> ); store.dispatch(fetchedPolicies(policies)); @@ -90,7 +91,7 @@ describe('policy table', () => { store = indexLifecycleManagementStore(); component = ( - + {}} /> ); const rendered = mountWithIntl(component); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js b/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js index b5d9b91e8c412..4fa1838115840 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js +++ b/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js @@ -115,6 +115,10 @@ const indexWithLifecycleError = { moment.tz.setDefault('utc'); +const getUrlForApp = (appId, options) => { + return appId + '/' + (options ? options.path : ''); +}; + describe('extend index management', () => { describe('retry lifecycle action extension', () => { test('should return null when no indices have index lifecycle policy', () => { @@ -171,13 +175,17 @@ describe('extend index management', () => { describe('add lifecycle policy action extension', () => { test('should return null when index has index lifecycle policy', () => { - const extension = addLifecyclePolicyActionExtension({ indices: [indexWithLifecyclePolicy] }); + const extension = addLifecyclePolicyActionExtension( + { indices: [indexWithLifecyclePolicy] }, + getUrlForApp + ); expect(extension).toBeNull(); }); test('should return null when more than one index is passed', () => { const extension = addLifecyclePolicyActionExtension({ indices: [indexWithoutLifecyclePolicy, indexWithoutLifecyclePolicy], + getUrlForApp, }); expect(extension).toBeNull(); }); @@ -185,6 +193,7 @@ describe('extend index management', () => { test('should return extension when one index is passed and it does not have lifecycle policy', () => { const extension = addLifecyclePolicyActionExtension({ indices: [indexWithoutLifecyclePolicy], + getUrlForApp, }); expect(extension.renderConfirmModal).toBeDefined; const component = extension.renderConfirmModal(jest.fn()); @@ -220,20 +229,20 @@ describe('extend index management', () => { describe('ilm summary extension', () => { test('should render null when index has no index lifecycle policy', () => { - const extension = ilmSummaryExtension(indexWithoutLifecyclePolicy); + const extension = ilmSummaryExtension(indexWithoutLifecyclePolicy, getUrlForApp); const rendered = mountWithIntl(extension); expect(rendered.isEmptyRender()).toBeTruthy(); }); test('should return extension when index has lifecycle policy', () => { - const extension = ilmSummaryExtension(indexWithLifecyclePolicy); + const extension = ilmSummaryExtension(indexWithLifecyclePolicy, getUrlForApp); expect(extension).toBeDefined(); const rendered = mountWithIntl(extension); expect(rendered).toMatchSnapshot(); }); test('should return extension when index has lifecycle error', () => { - const extension = ilmSummaryExtension(indexWithLifecycleError); + const extension = ilmSummaryExtension(indexWithLifecycleError, getUrlForApp); expect(extension).toBeDefined(); const rendered = mountWithIntl(extension); expect(rendered).toMatchSnapshot(); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/home.helpers.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/home.helpers.ts index 57b925b8c6fc1..36d8e1d343b5e 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/home.helpers.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/home.helpers.ts @@ -14,7 +14,6 @@ import { nextTick, } from '../../../../../test_utils'; import { IndexManagementHome } from '../../../public/application/sections/home'; // eslint-disable-line @kbn/eslint/no-restricted-paths -import { BASE_PATH } from '../../../common/constants'; import { indexManagementStore } from '../../../public/application/store'; // eslint-disable-line @kbn/eslint/no-restricted-paths import { TemplateDeserialized } from '../../../common'; import { WithAppDependencies, services } from './setup_environment'; @@ -22,8 +21,8 @@ import { WithAppDependencies, services } from './setup_environment'; const testBedConfig: TestBedConfig = { store: () => indexManagementStore(services as any), memoryRouter: { - initialEntries: [`${BASE_PATH}indices?includeHidden=true`], - componentRoutePath: `${BASE_PATH}:section(indices|templates)`, + initialEntries: [`/indices?includeHidden=true`], + componentRoutePath: `/:section(indices|templates)`, }, doMountAsync: true, }; diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/setup_environment.tsx index 3243d665832f2..fa8c4f82c1b68 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/setup_environment.tsx @@ -5,13 +5,15 @@ */ /* eslint-disable @kbn/eslint/no-restricted-paths */ import React from 'react'; - +import { LocationDescriptorObject } from 'history'; +import { ScopedHistory } from 'kibana/public'; import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public'; import { notificationServiceMock, fatalErrorsServiceMock, docLinksServiceMock, injectedMetadataServiceMock, + scopedHistoryMock, } from '../../../../../../src/core/public/mocks'; import { usageCollectionPluginMock } from '../../../../../../src/plugins/usage_collection/public/mocks'; @@ -33,12 +35,18 @@ const httpServiceSetupMock = new HttpService().setup({ fatalErrors: fatalErrorsServiceMock.createSetupContract(), }); +const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; +history.createHref = (location: LocationDescriptorObject) => { + return `${location.pathname}?${location.search}`; +}; + const appServices = { breadcrumbs: breadcrumbService, metric: uiMetricService, documentation: documentationService, api: apiService, notifications: notificationServiceMock.createSetupContract(), + history, }; export const setupEnvironment = () => { diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx index a5ce984efd06f..6726ee1bdac29 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx @@ -7,11 +7,15 @@ import React from 'react'; import { EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { withRouter } from 'react-router-dom'; +import { ScopedHistory } from 'kibana/public'; import { EDIT_ROLES_PATH } from '../../../management_urls'; import { reactRouterNavigate } from '../../../../../../../../src/plugins/kibana_react/public'; -export const CreateRoleMappingButton = withRouter(({ history }) => { +interface CreateRoleMappingButtonProps { + history: ScopedHistory; +} + +export const CreateRoleMappingButton = ({ history }: CreateRoleMappingButtonProps) => { return ( { /> ); -}); +}; diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/empty_prompt/empty_prompt.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/empty_prompt/empty_prompt.tsx index 1919d3fbf4785..37ab4445d6b26 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/empty_prompt/empty_prompt.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/empty_prompt/empty_prompt.tsx @@ -7,9 +7,14 @@ import React, { Fragment } from 'react'; import { EuiEmptyPrompt } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import { ScopedHistory } from 'kibana/public'; import { CreateRoleMappingButton } from '../create_role_mapping_button'; -export const EmptyPrompt: React.FunctionComponent<{}> = () => ( +interface EmptyPromptProps { + history: ScopedHistory; +} + +export const EmptyPrompt: React.FunctionComponent = ({ history }) => ( = () => (

} - actions={} + actions={} data-test-subj="roleMappingsEmptyPrompt" /> ); diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx index 96fd881566a80..47717574a75b4 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx @@ -21,6 +21,9 @@ import { rolesAPIClientMock } from '../../roles/index.mock'; describe('RoleMappingsGridPage', () => { const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; + const getUrlForApp = (appId: string, options?: { path: string }) => { + return appId + '/' + (options ? options.path : ''); + }; it('renders an empty prompt when no role mappings exist', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); @@ -38,6 +41,7 @@ describe('RoleMappingsGridPage', () => { notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} history={history} + getUrlForApp={getUrlForApp} /> ); expect(wrapper.find(SectionLoading)).toHaveLength(1); @@ -66,6 +70,7 @@ describe('RoleMappingsGridPage', () => { notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} history={history} + getUrlForApp={getUrlForApp} /> ); expect(wrapper.find(SectionLoading)).toHaveLength(1); @@ -102,6 +107,7 @@ describe('RoleMappingsGridPage', () => { notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} history={history} + getUrlForApp={getUrlForApp} /> ); expect(wrapper.find(SectionLoading)).toHaveLength(1); @@ -137,6 +143,7 @@ describe('RoleMappingsGridPage', () => { notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} history={history} + getUrlForApp={getUrlForApp} /> ); await nextTick(); @@ -145,7 +152,7 @@ describe('RoleMappingsGridPage', () => { const links = findTestSubject(wrapper, 'roleMappingRoles').find(EuiLink); expect(links).toHaveLength(1); expect(links.at(0).props()).toMatchObject({ - href: '/edit/superuser', + href: 'management/security/roles/edit/superuser', }); }); @@ -172,6 +179,7 @@ describe('RoleMappingsGridPage', () => { notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} history={history} + getUrlForApp={getUrlForApp} /> ); await nextTick(); @@ -211,6 +219,7 @@ describe('RoleMappingsGridPage', () => { notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} history={history} + getUrlForApp={getUrlForApp} /> ); await nextTick(); @@ -273,6 +282,7 @@ describe('RoleMappingsGridPage', () => { notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} history={history} + getUrlForApp={getUrlForApp} /> ); await nextTick(); @@ -284,7 +294,7 @@ describe('RoleMappingsGridPage', () => { Object { "children":
kibana_user - + { if (loadState === 'finished' && roleMappings && roleMappings.length === 0) { return ( - + ); } @@ -328,7 +329,14 @@ export class RoleMappingsGridPage extends Component { const role: Role | string = this.state.roles?.find((r) => r.name === rolename) ?? rolename; - return ; + return ( + + ); }); return
{roleLinks}
; }, diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx index 16c41377ca1c3..c95d78f90f51a 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx @@ -16,7 +16,7 @@ import { ScopedHistory } from 'src/core/public'; import { roleMappingsManagementApp } from './role_mappings_management_app'; import { coreMock, scopedHistoryMock } from '../../../../../../src/core/public/mocks'; -async function mountApp(basePath: string) { +async function mountApp(basePath: string, pathname: string) { const container = document.createElement('div'); const setBreadcrumbs = jest.fn(); @@ -26,7 +26,7 @@ async function mountApp(basePath: string) { basePath, element: container, setBreadcrumbs, - history: (scopedHistoryMock.create() as unknown) as ScopedHistory, + history: (scopedHistoryMock.create({ pathname }) as unknown) as ScopedHistory, }); return { unmount, container, setBreadcrumbs }; @@ -49,16 +49,13 @@ describe('roleMappingsManagementApp', () => { }); it('mount() works for the `grid` page', async () => { - const basePath = '/some-base-path/role_mappings'; - window.location.hash = basePath; - - const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + const { setBreadcrumbs, container, unmount } = await mountApp('/', '/'); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); - expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `#${basePath}`, text: 'Role Mappings' }]); + expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `/`, text: 'Role Mappings' }]); expect(container).toMatchInlineSnapshot(`
- Role Mappings Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"}} + Role Mappings Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}}}
`); @@ -68,19 +65,16 @@ describe('roleMappingsManagementApp', () => { }); it('mount() works for the `create role mapping` page', async () => { - const basePath = '/some-base-path/role_mappings'; - window.location.hash = `${basePath}/edit`; - - const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + const { setBreadcrumbs, container, unmount } = await mountApp('/', '/edit'); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); expect(setBreadcrumbs).toHaveBeenCalledWith([ - { href: `#${basePath}`, text: 'Role Mappings' }, + { href: `/`, text: 'Role Mappings' }, { text: 'Create' }, ]); expect(container).toMatchInlineSnapshot(`
- Role Mapping Edit Page: {"roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"}} + Role Mapping Edit Page: {"roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit","search":"","hash":""}}}
`); @@ -90,20 +84,18 @@ describe('roleMappingsManagementApp', () => { }); it('mount() works for the `edit role mapping` page', async () => { - const basePath = '/some-base-path/role_mappings'; const roleMappingName = 'someRoleMappingName'; - window.location.hash = `${basePath}/edit/${roleMappingName}`; - const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + const { setBreadcrumbs, container, unmount } = await mountApp('/', `/edit/${roleMappingName}`); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); expect(setBreadcrumbs).toHaveBeenCalledWith([ - { href: `#${basePath}`, text: 'Role Mappings' }, - { href: `#/some-base-path/role_mappings/edit/${roleMappingName}`, text: roleMappingName }, + { href: `/`, text: 'Role Mappings' }, + { href: `/edit/${roleMappingName}`, text: roleMappingName }, ]); expect(container).toMatchInlineSnapshot(`
- Role Mapping Edit Page: {"name":"someRoleMappingName","roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"}} + Role Mapping Edit Page: {"name":"someRoleMappingName","roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/someRoleMappingName","search":"","hash":""}}}
`); @@ -113,18 +105,15 @@ describe('roleMappingsManagementApp', () => { }); it('mount() properly encodes role mapping name in `edit role mapping` page link in breadcrumbs', async () => { - const basePath = '/some-base-path/role_mappings'; const roleMappingName = 'some 安全性 role mapping'; - window.location.hash = `${basePath}/edit/${roleMappingName}`; - const { setBreadcrumbs } = await mountApp(basePath); + const { setBreadcrumbs } = await mountApp('/', `/edit/${roleMappingName}`); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); expect(setBreadcrumbs).toHaveBeenCalledWith([ - { href: `#${basePath}`, text: 'Role Mappings' }, + { href: `/`, text: 'Role Mappings' }, { - href: - '#/some-base-path/role_mappings/edit/some%20%E5%AE%89%E5%85%A8%E6%80%A7%20role%20mapping', + href: '/edit/some%20%E5%AE%89%E5%85%A8%E6%80%A7%20role%20mapping', text: roleMappingName, }, ]); diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx index d9c0f082454b6..18aa8e80595ad 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx @@ -27,6 +27,7 @@ export const roleMappingsManagementApp = Object.freeze({ defaultMessage: 'Role Mappings', }), async mount({ element, setBreadcrumbs, history }) { + const [coreStart] = await getStartServices(); const roleMappingsBreadcrumbs = [ { text: i18n.translate('xpack.security.roleMapping.breadcrumb', { @@ -61,6 +62,7 @@ export const roleMappingsManagementApp = Object.freeze({ roleMappingsAPI={roleMappingsAPIClient} docLinks={dockLinksService} history={history} + getUrlForApp={coreStart.application.getUrlForApp} /> ); }; diff --git a/x-pack/plugins/security/public/management/role_table_display/role_table_display.tsx b/x-pack/plugins/security/public/management/role_table_display/role_table_display.tsx index 89097a955b5de..d94a6045df74b 100644 --- a/x-pack/plugins/security/public/management/role_table_display/role_table_display.tsx +++ b/x-pack/plugins/security/public/management/role_table_display/role_table_display.tsx @@ -6,22 +6,23 @@ import React from 'react'; import { EuiLink, EuiToolTip, EuiIcon } from '@elastic/eui'; -import { ScopedHistory } from 'kibana/public'; +import { ScopedHistory, ApplicationStart } from 'kibana/public'; import { Role, isRoleDeprecated, getExtendedRoleDeprecationNotice } from '../../../common/model'; -import { getEditRoleHref } from '../management_urls'; -import { reactRouterNavigate } from '../../../../../../src/plugins/kibana_react/public'; interface Props { role: Role | string; history: ScopedHistory; + getUrlForApp: ApplicationStart['getUrlForApp']; } -export const RoleTableDisplay = ({ role, history }: Props) => { +export const RoleTableDisplay = ({ role, history, getUrlForApp }: Props) => { let content; let href; if (typeof role === 'string') { content =
{role}
; - href = getEditRoleHref(role); + href = getUrlForApp('management', { + path: `security/roles/edit/${encodeURIComponent(role)}`, + }); } else if (isRoleDeprecated(role)) { content = ( {
); - href = getEditRoleHref(role.name); + href = getUrlForApp('management', { + path: `security/roles/edit/${encodeURIComponent(role.name)}`, + }); } else { content =
{role.name}
; - href = getEditRoleHref(role.name); + href = getUrlForApp('management', { + path: `security/roles/edit/${encodeURIComponent(role.name)}`, + }); } - return {content}; + return {content}; }; diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx index 850dcce278185..e7f38c86b045e 100644 --- a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx @@ -21,7 +21,7 @@ import { rolesManagementApp } from './roles_management_app'; import { coreMock, scopedHistoryMock } from '../../../../../../src/core/public/mocks'; import { featuresPluginMock } from '../../../../features/public/mocks'; -async function mountApp(basePath: string) { +async function mountApp(basePath: string, pathname: string) { const { fatalErrors } = coreMock.createSetup(); const container = document.createElement('div'); const setBreadcrumbs = jest.fn(); @@ -40,7 +40,7 @@ async function mountApp(basePath: string) { basePath, element: container, setBreadcrumbs, - history: (scopedHistoryMock.create() as unknown) as ScopedHistory, + history: (scopedHistoryMock.create({ pathname }) as unknown) as ScopedHistory, }); return { unmount, container, setBreadcrumbs }; @@ -67,16 +67,13 @@ describe('rolesManagementApp', () => { }); it('mount() works for the `grid` page', async () => { - const basePath = '/some-base-path/roles'; - window.location.hash = basePath; - - const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + const { setBreadcrumbs, container, unmount } = await mountApp('/', '/'); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); - expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `#${basePath}`, text: 'Roles' }]); + expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `/`, text: 'Roles' }]); expect(container).toMatchInlineSnapshot(`
- Roles Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}}} + Roles Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}}}
`); @@ -86,19 +83,13 @@ describe('rolesManagementApp', () => { }); it('mount() works for the `create role` page', async () => { - const basePath = '/some-base-path/roles'; - window.location.hash = `${basePath}/edit`; - - const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + const { setBreadcrumbs, container, unmount } = await mountApp('/', '/edit'); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); - expect(setBreadcrumbs).toHaveBeenCalledWith([ - { href: `#${basePath}`, text: 'Roles' }, - { text: 'Create' }, - ]); + expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `/`, text: 'Roles' }, { text: 'Create' }]); expect(container).toMatchInlineSnapshot(`
- Role Edit Page: {"action":"edit","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"indicesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}}} + Role Edit Page: {"action":"edit","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"indicesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit","search":"","hash":""}}}
`); @@ -108,20 +99,18 @@ describe('rolesManagementApp', () => { }); it('mount() works for the `edit role` page', async () => { - const basePath = '/some-base-path/roles'; const roleName = 'someRoleName'; - window.location.hash = `${basePath}/edit/${roleName}`; - const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + const { setBreadcrumbs, container, unmount } = await mountApp('/', `/edit/${roleName}`); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); expect(setBreadcrumbs).toHaveBeenCalledWith([ - { href: `#${basePath}`, text: 'Roles' }, - { href: `#/some-base-path/roles/edit/${roleName}`, text: roleName }, + { href: `/`, text: 'Roles' }, + { href: `/edit/${roleName}`, text: roleName }, ]); expect(container).toMatchInlineSnapshot(`
- Role Edit Page: {"action":"edit","roleName":"someRoleName","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"indicesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}}} + Role Edit Page: {"action":"edit","roleName":"someRoleName","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"indicesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/someRoleName","search":"","hash":""}}}
`); @@ -131,20 +120,15 @@ describe('rolesManagementApp', () => { }); it('mount() works for the `clone role` page', async () => { - const basePath = '/some-base-path/roles'; const roleName = 'someRoleName'; - window.location.hash = `${basePath}/clone/${roleName}`; - const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + const { setBreadcrumbs, container, unmount } = await mountApp('/', `/clone/${roleName}`); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); - expect(setBreadcrumbs).toHaveBeenCalledWith([ - { href: `#${basePath}`, text: 'Roles' }, - { text: 'Create' }, - ]); + expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `/`, text: 'Roles' }, { text: 'Create' }]); expect(container).toMatchInlineSnapshot(`
- Role Edit Page: {"action":"clone","roleName":"someRoleName","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"indicesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}}} + Role Edit Page: {"action":"clone","roleName":"someRoleName","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"indicesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/clone/someRoleName","search":"","hash":""}}}
`); @@ -154,17 +138,15 @@ describe('rolesManagementApp', () => { }); it('mount() properly encodes role name in `edit role` page link in breadcrumbs', async () => { - const basePath = '/some-base-path/roles'; const roleName = 'some 安全性 role'; - window.location.hash = `${basePath}/edit/${roleName}`; - const { setBreadcrumbs } = await mountApp(basePath); + const { setBreadcrumbs } = await mountApp('/', `/edit/${roleName}`); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); expect(setBreadcrumbs).toHaveBeenCalledWith([ - { href: `#${basePath}`, text: 'Roles' }, + { href: `/`, text: 'Roles' }, { - href: '#/some-base-path/roles/edit/some%20%E5%AE%89%E5%85%A8%E6%80%A7%20role', + href: '/edit/some%20%E5%AE%89%E5%85%A8%E6%80%A7%20role', text: roleName, }, ]); diff --git a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx index a3e9070cfa972..8f27511330efd 100644 --- a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { LocationDescriptorObject } from 'history'; import { ScopedHistory } from 'kibana/public'; import { User } from '../../../../common/model'; @@ -18,6 +19,12 @@ import { EuiBasicTable } from '@elastic/eui'; describe('UsersGridPage', () => { const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; + history.createHref = (location: LocationDescriptorObject) => { + return `${location.pathname}${location.search ? '?' + location.search : ''}`; + }; + const getUrlForApp = (appId: string, options?: { path: string }) => { + return appId + '/' + (options ? options.path : ''); + }; it('renders the list of users', async () => { const apiClientMock = userAPIClientMock.create(); @@ -49,6 +56,7 @@ describe('UsersGridPage', () => { rolesAPIClient={rolesAPIClientMock.create()} notifications={coreMock.createStart().notifications} history={history} + getUrlForApp={getUrlForApp} /> ); @@ -70,6 +78,7 @@ describe('UsersGridPage', () => { rolesAPIClient={rolesAPIClientMock.create()} notifications={coreMock.createStart().notifications} history={history} + getUrlForApp={getUrlForApp} /> ); @@ -100,6 +109,7 @@ describe('UsersGridPage', () => { rolesAPIClient={rolesAPIClientMock.create()} notifications={coreMock.createStart().notifications} history={history} + getUrlForApp={getUrlForApp} /> ); @@ -133,6 +143,7 @@ describe('UsersGridPage', () => { rolesAPIClient={rolesAPIClientMock.create()} notifications={coreMock.createStart().notifications} history={history} + getUrlForApp={getUrlForApp} /> ); @@ -182,6 +193,7 @@ describe('UsersGridPage', () => { rolesAPIClient={roleAPIClientMock} notifications={coreMock.createStart().notifications} history={history} + getUrlForApp={getUrlForApp} /> ); @@ -193,7 +205,7 @@ describe('UsersGridPage', () => { Object { "children":
kibana_user - + { rolesAPIClient={roleAPIClientMock} notifications={coreMock.createStart().notifications} history={history} + getUrlForApp={getUrlForApp} /> ); diff --git a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx index f0489a66b4c1a..6b2f98e9263ec 100644 --- a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx +++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx @@ -23,7 +23,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { NotificationsStart, ScopedHistory } from 'src/core/public'; +import { NotificationsStart, ApplicationStart, ScopedHistory } from 'src/core/public'; import { User, Role } from '../../../../common/model'; import { ConfirmDeleteUsers } from '../components'; import { isUserReserved, getExtendedUserDeprecationNotice, isUserDeprecated } from '../user_utils'; @@ -38,6 +38,7 @@ interface Props { rolesAPIClient: PublicMethodsOf; notifications: NotificationsStart; history: ScopedHistory; + getUrlForApp: ApplicationStart['getUrlForApp']; } interface State { @@ -150,7 +151,12 @@ export class UsersGridPage extends Component { const roleLinks = rolenames.map((rolename, index) => { const roleDefinition = roles?.find((role) => role.name === rolename) ?? rolename; return ( - + ); }); return
{roleLinks}
; diff --git a/x-pack/plugins/security/public/management/users/users_management_app.test.tsx b/x-pack/plugins/security/public/management/users/users_management_app.test.tsx index 0741250823bba..98906f560e6cb 100644 --- a/x-pack/plugins/security/public/management/users/users_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/users/users_management_app.test.tsx @@ -18,7 +18,7 @@ import { usersManagementApp } from './users_management_app'; import { coreMock, scopedHistoryMock } from '../../../../../../src/core/public/mocks'; import { securityMock } from '../../mocks'; -async function mountApp(basePath: string) { +async function mountApp(basePath: string, pathname: string) { const container = document.createElement('div'); const setBreadcrumbs = jest.fn(); @@ -31,7 +31,7 @@ async function mountApp(basePath: string) { basePath, element: container, setBreadcrumbs, - history: (scopedHistoryMock.create() as unknown) as ScopedHistory, + history: (scopedHistoryMock.create({ pathname }) as unknown) as ScopedHistory, }); return { unmount, container, setBreadcrumbs }; @@ -55,16 +55,13 @@ describe('usersManagementApp', () => { }); it('mount() works for the `grid` page', async () => { - const basePath = '/some-base-path/users'; - window.location.hash = basePath; - - const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + const { setBreadcrumbs, container, unmount } = await mountApp('/', '/'); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); - expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `#${basePath}`, text: 'Users' }]); + expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `/`, text: 'Users' }]); expect(container).toMatchInlineSnapshot(`
- Users Page: {"notifications":{"toasts":{}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}}} + Users Page: {"notifications":{"toasts":{}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}}}
`); @@ -74,19 +71,13 @@ describe('usersManagementApp', () => { }); it('mount() works for the `create user` page', async () => { - const basePath = '/some-base-path/users'; - window.location.hash = `${basePath}/edit`; - - const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + const { setBreadcrumbs, container, unmount } = await mountApp('/', '/edit'); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); - expect(setBreadcrumbs).toHaveBeenCalledWith([ - { href: `#${basePath}`, text: 'Users' }, - { text: 'Create' }, - ]); + expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `/`, text: 'Users' }, { text: 'Create' }]); expect(container).toMatchInlineSnapshot(`
- User Edit Page: {"authc":{},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}}} + User Edit Page: {"authc":{},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit","search":"","hash":""}}}
`); @@ -96,20 +87,18 @@ describe('usersManagementApp', () => { }); it('mount() works for the `edit user` page', async () => { - const basePath = '/some-base-path/users'; const userName = 'someUserName'; - window.location.hash = `${basePath}/edit/${userName}`; - const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + const { setBreadcrumbs, container, unmount } = await mountApp('/', `/edit/${userName}`); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); expect(setBreadcrumbs).toHaveBeenCalledWith([ - { href: `#${basePath}`, text: 'Users' }, - { href: `#/some-base-path/users/edit/${userName}`, text: userName }, + { href: `/`, text: 'Users' }, + { href: `/edit/${userName}`, text: userName }, ]); expect(container).toMatchInlineSnapshot(`
- User Edit Page: {"authc":{},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}},"username":"someUserName"} + User Edit Page: {"authc":{},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}},"username":"someUserName","history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/someUserName","search":"","hash":""}}}
`); @@ -119,17 +108,15 @@ describe('usersManagementApp', () => { }); it('mount() properly encodes user name in `edit user` page link in breadcrumbs', async () => { - const basePath = '/some-base-path/users'; const username = 'some 安全性 user'; - window.location.hash = `${basePath}/edit/${username}`; - const { setBreadcrumbs } = await mountApp(basePath); + const { setBreadcrumbs } = await mountApp('/', `/edit/${username}`); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); expect(setBreadcrumbs).toHaveBeenCalledWith([ - { href: `#${basePath}`, text: 'Users' }, + { href: `/`, text: 'Users' }, { - href: '#/some-base-path/users/edit/some%20%E5%AE%89%E5%85%A8%E6%80%A7%20user', + href: '/edit/some%20%E5%AE%89%E5%85%A8%E6%80%A7%20user', text: username, }, ]); diff --git a/x-pack/plugins/security/public/management/users/users_management_app.tsx b/x-pack/plugins/security/public/management/users/users_management_app.tsx index 02398f271e259..a166deca26eb0 100644 --- a/x-pack/plugins/security/public/management/users/users_management_app.tsx +++ b/x-pack/plugins/security/public/management/users/users_management_app.tsx @@ -26,6 +26,7 @@ export const usersManagementApp = Object.freeze({ order: 10, title: i18n.translate('xpack.security.management.usersTitle', { defaultMessage: 'Users' }), async mount({ basePath, element, setBreadcrumbs, history }) { + const [coreStart] = await getStartServices(); const usersBreadcrumbs = [ { text: i18n.translate('xpack.security.users.breadcrumb', { defaultMessage: 'Users' }), @@ -57,6 +58,7 @@ export const usersManagementApp = Object.freeze({ userAPIClient={userAPIClient} rolesAPIClient={rolesAPIClient} history={history} + getUrlForApp={coreStart.application.getUrlForApp} /> ); }; diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx index 827fea7021eb4..c4f4876b8a1cd 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx @@ -8,8 +8,10 @@ import React from 'react'; import axios from 'axios'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; import { i18n } from '@kbn/i18n'; +import { LocationDescriptorObject } from 'history'; +import { ScopedHistory } from 'kibana/public'; -import { coreMock } from 'src/core/public/mocks'; +import { coreMock, scopedHistoryMock } from 'src/core/public/mocks'; import { setUiMetricService, httpService } from '../../../public/application/services/http'; import { breadcrumbService, @@ -23,10 +25,16 @@ import { documentationLinksService } from '../../../public/application/services/ const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); +const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; +history.createHref = (location: LocationDescriptorObject) => { + return `${location.pathname}?${location.search}`; +}; + export const services = { uiMetricService: new UiMetricService('snapshot_restore'), httpService, i18n, + history, }; setUiMetricService(services.uiMetricService); diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx index a2eba568e9a41..834bfb73d8f46 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx @@ -27,7 +27,7 @@ import { SecurityLicenseFeatures } from '../../../security/public'; import { featuresPluginMock } from '../../../features/public/mocks'; import { PluginsStart } from '../plugin'; -async function mountApp(basePath: string, spaceId?: string) { +async function mountApp(basePath: string, pathname: string, spaceId?: string) { const container = document.createElement('div'); const setBreadcrumbs = jest.fn(); @@ -58,7 +58,7 @@ async function mountApp(basePath: string, spaceId?: string) { basePath, element: container, setBreadcrumbs, - history: (scopedHistoryMock.create() as unknown) as ScopedHistory, + history: (scopedHistoryMock.create({ pathname }) as unknown) as ScopedHistory, }); return { unmount, container, setBreadcrumbs }; @@ -83,16 +83,13 @@ describe('spacesManagementApp', () => { }); it('mount() works for the `grid` page', async () => { - const basePath = '/some-base-path/spaces'; - window.location.hash = basePath; - - const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + const { setBreadcrumbs, container, unmount } = await mountApp('/', '/'); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); - expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `#${basePath}`, text: 'Spaces' }]); + expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `/`, text: 'Spaces' }]); expect(container).toMatchInlineSnapshot(`
- Spaces Page: {"capabilities":{"catalogue":{},"management":{},"navLinks":{}},"notifications":{"toasts":{}},"spacesManager":{"onActiveSpaceChange$":{"_isScalar":false}},"securityEnabled":true} + Spaces Page: {"capabilities":{"catalogue":{},"management":{},"navLinks":{}},"notifications":{"toasts":{}},"spacesManager":{"onActiveSpaceChange$":{"_isScalar":false}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}},"securityEnabled":true}
`); @@ -102,19 +99,16 @@ describe('spacesManagementApp', () => { }); it('mount() works for the `create space` page', async () => { - const basePath = '/some-base-path/spaces'; - window.location.hash = `${basePath}/create`; - - const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + const { setBreadcrumbs, container, unmount } = await mountApp('/', '/create'); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); expect(setBreadcrumbs).toHaveBeenCalledWith([ - { href: `#${basePath}`, text: 'Spaces' }, + { href: `/`, text: 'Spaces' }, { text: 'Create' }, ]); expect(container).toMatchInlineSnapshot(`
- Spaces Edit Page: {"capabilities":{"catalogue":{},"management":{},"navLinks":{}},"notifications":{"toasts":{}},"spacesManager":{"onActiveSpaceChange$":{"_isScalar":false}},"securityEnabled":true} + Spaces Edit Page: {"capabilities":{"catalogue":{},"management":{},"navLinks":{}},"notifications":{"toasts":{}},"spacesManager":{"onActiveSpaceChange$":{"_isScalar":false}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/create","search":"","hash":""}},"securityEnabled":true}
`); @@ -124,20 +118,18 @@ describe('spacesManagementApp', () => { }); it('mount() works for the `edit space` page', async () => { - const basePath = '/some-base-path/spaces'; const spaceId = 'some-space'; - window.location.hash = `${basePath}/edit/${spaceId}`; - const { setBreadcrumbs, container, unmount } = await mountApp(basePath, spaceId); + const { setBreadcrumbs, container, unmount } = await mountApp('/', `/edit/${spaceId}`, spaceId); expect(setBreadcrumbs).toHaveBeenCalledTimes(1); expect(setBreadcrumbs).toHaveBeenCalledWith([ - { href: `#${basePath}`, text: 'Spaces' }, - { href: `#/some-base-path/spaces/edit/${spaceId}`, text: `space with id some-space` }, + { href: `/`, text: 'Spaces' }, + { href: `/edit/${spaceId}`, text: `space with id some-space` }, ]); expect(container).toMatchInlineSnapshot(`
- Spaces Edit Page: {"capabilities":{"catalogue":{},"management":{},"navLinks":{}},"notifications":{"toasts":{}},"spacesManager":{"onActiveSpaceChange$":{"_isScalar":false}},"spaceId":"some-space","securityEnabled":true} + Spaces Edit Page: {"capabilities":{"catalogue":{},"management":{},"navLinks":{}},"notifications":{"toasts":{}},"spacesManager":{"onActiveSpaceChange$":{"_isScalar":false}},"spaceId":"some-space","history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/some-space","search":"","hash":""}},"securityEnabled":true}
`); diff --git a/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx b/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx index 0440e3f07b565..142504ee163b7 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx +++ b/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { of } from 'rxjs'; import { ComponentType } from 'enzyme'; +import { LocationDescriptorObject } from 'history'; import { ScopedHistory } from 'src/core/public'; import { docLinksServiceMock, @@ -29,6 +30,12 @@ class MockTimeBuckets { }; } } + +const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; +history.createHref = (location: LocationDescriptorObject) => { + return `${location.pathname}${location.search ? '?' + location.search : ''}`; +}; + export const mockContextValue = { licenseStatus$: of({ valid: true }), docLinks: docLinksServiceMock.createStartContract(), @@ -41,7 +48,7 @@ export const mockContextValue = { } as any, // For our test harness, we don't use this mocked out http service http: httpServiceMock.createSetupContract(), - history: (scopedHistoryMock.create() as unknown) as ScopedHistory, + history, getUrlForApp: jest.fn(), }; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts index 0436ed1d6bb06..e436971edbb69 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts @@ -131,7 +131,7 @@ describe('', () => { expect(findTestSubject(idColumn, `watchIdColumn-${watch1.id}`).length).toBe(1); expect(findTestSubject(idColumn, `watchIdColumn-${watch1.id}`).props().href).toEqual( - `#/management/insightsAndAlerting/watcher/watches/watch/${watch1.id}/status` + `/watches/watch/${watch1.id}/status` ); }); From e470a4712dfb7d03d000508513fcd7f7a6695b90 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 25 May 2020 16:41:56 +0300 Subject: [PATCH 47/93] [saved_object_management] partial progress --- .../index_pattern_table.tsx | 5 +-- .../management_section/mount_section.tsx | 1 + .../object_view/saved_object_view.tsx | 4 +- .../saved_objects_table.test.tsx.snap | 8 ++-- .../components/relationships.test.tsx | 8 ++-- .../saved_objects_table.test.tsx | 10 ++--- .../saved_objects_edition_page.tsx | 7 +++- .../saved_objects_table_page.tsx | 4 +- .../edit_saved_object.ts | 41 +++++++++++++------ 9 files changed, 53 insertions(+), 35 deletions(-) diff --git a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx index 3cef6e1a6c5f7..ae09f624251c0 100644 --- a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx +++ b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx @@ -125,10 +125,7 @@ export const IndexPatternTable = ({ canSave, history }: Props) => { }>; } ) => ( - + {name} {index.tags && index.tags.map(({ key: tagKey, name: tagName }) => ( diff --git a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx index 3ca0c3772a243..f835503d4efbf 100644 --- a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx +++ b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx @@ -62,6 +62,7 @@ export const mountManagementSection = async ({ coreStart={coreStart} serviceRegistry={serviceRegistry} setBreadcrumbs={setBreadcrumbs} + history={history} /> diff --git a/src/plugins/saved_objects_management/public/management_section/object_view/saved_object_view.tsx b/src/plugins/saved_objects_management/public/management_section/object_view/saved_object_view.tsx index 83644e6404c81..1572ef9164700 100644 --- a/src/plugins/saved_objects_management/public/management_section/object_view/saved_object_view.tsx +++ b/src/plugins/saved_objects_management/public/management_section/object_view/saved_object_view.tsx @@ -26,6 +26,7 @@ import { OverlayStart, NotificationsStart, SimpleSavedObject, + ScopedHistory, } from '../../../../../core/public'; import { ISavedObjectsManagementServiceRegistry } from '../../services'; import { Header, NotFoundErrors, Intro, Form } from './components'; @@ -41,6 +42,7 @@ interface SavedObjectEditionProps { notifications: NotificationsStart; notFoundType?: string; savedObjectsClient: SavedObjectsClientContract; + history: ScopedHistory; } interface SavedObjectEditionState { @@ -171,6 +173,6 @@ export class SavedObjectEdition extends Component< }; redirectToListing() { - window.location.hash = '/management/kibana/objects'; + this.props.history.push('/'); } } diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap index 78af61c20c828..26ddb0809d24b 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap @@ -314,7 +314,7 @@ exports[`SavedObjectsTable relationships should show the flyout 1`] = ` Object { "id": "2", "meta": Object { - "editUrl": "#/management/kibana/objects/savedSearches/2", + "editUrl": "/management/kibana/objects/savedSearches/2", "icon": "search", "inAppUrl": Object { "path": "/discover/2", @@ -404,7 +404,7 @@ exports[`SavedObjectsTable should render normally 1`] = ` Object { "id": "2", "meta": Object { - "editUrl": "#/management/kibana/objects/savedSearches/2", + "editUrl": "/management/kibana/objects/savedSearches/2", "icon": "search", "inAppUrl": Object { "path": "/discover/2", @@ -417,7 +417,7 @@ exports[`SavedObjectsTable should render normally 1`] = ` Object { "id": "3", "meta": Object { - "editUrl": "#/management/kibana/objects/savedDashboards/3", + "editUrl": "/management/kibana/objects/savedDashboards/3", "icon": "dashboardApp", "inAppUrl": Object { "path": "/dashboard/3", @@ -430,7 +430,7 @@ exports[`SavedObjectsTable should render normally 1`] = ` Object { "id": "4", "meta": Object { - "editUrl": "#/management/kibana/objects/savedVisualizations/4", + "editUrl": "/management/kibana/objects/savedVisualizations/4", "icon": "visualizeApp", "inAppUrl": Object { "path": "/edit/4", diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx index aaae53f809896..9277d9b00305b 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx @@ -141,7 +141,7 @@ describe('Relationships', () => { meta: { title: 'MySearch', icon: 'search', - editUrl: '#/management/kibana/objects/savedSearches/1', + editUrl: '/management/kibana/objects/savedSearches/1', inAppUrl: { path: '/discover/1', uiCapabilitiesPath: 'discover.show', @@ -208,7 +208,7 @@ describe('Relationships', () => { meta: { title: 'MyViz', icon: 'visualizeApp', - editUrl: '#/management/kibana/objects/savedVisualizations/1', + editUrl: '/management/kibana/objects/savedVisualizations/1', inAppUrl: { path: '/edit/1', uiCapabilitiesPath: 'visualize.show', @@ -275,7 +275,7 @@ describe('Relationships', () => { meta: { title: 'MyDashboard', icon: 'dashboardApp', - editUrl: '#/management/kibana/objects/savedDashboards/1', + editUrl: '/management/kibana/objects/savedDashboards/1', inAppUrl: { path: '/dashboard/1', uiCapabilitiesPath: 'dashboard.show', @@ -315,7 +315,7 @@ describe('Relationships', () => { meta: { title: 'MyDashboard', icon: 'dashboardApp', - editUrl: '#/management/kibana/objects/savedDashboards/1', + editUrl: '/management/kibana/objects/savedDashboards/1', inAppUrl: { path: '/dashboard/1', uiCapabilitiesPath: 'dashboard.show', diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx index b46bc8dd1b4ee..191bde8b192fd 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx @@ -168,7 +168,7 @@ describe('SavedObjectsTable', () => { meta: { title: `MySearch`, icon: 'search', - editUrl: '#/management/kibana/objects/savedSearches/2', + editUrl: '/management/kibana/objects/savedSearches/2', inAppUrl: { path: '/discover/2', uiCapabilitiesPath: 'discover.show', @@ -181,7 +181,7 @@ describe('SavedObjectsTable', () => { meta: { title: `MyDashboard`, icon: 'dashboardApp', - editUrl: '#/management/kibana/objects/savedDashboards/3', + editUrl: '/management/kibana/objects/savedDashboards/3', inAppUrl: { path: '/dashboard/3', uiCapabilitiesPath: 'dashboard.show', @@ -194,7 +194,7 @@ describe('SavedObjectsTable', () => { meta: { title: `MyViz`, icon: 'visualizeApp', - editUrl: '#/management/kibana/objects/savedVisualizations/4', + editUrl: '/management/kibana/objects/savedVisualizations/4', inAppUrl: { path: '/edit/4', uiCapabilitiesPath: 'visualize.show', @@ -441,7 +441,7 @@ describe('SavedObjectsTable', () => { meta: { title: `MySearch`, icon: 'search', - editUrl: '#/management/kibana/objects/savedSearches/2', + editUrl: '/management/kibana/objects/savedSearches/2', inAppUrl: { path: '/discover/2', uiCapabilitiesPath: 'discover.show', @@ -456,7 +456,7 @@ describe('SavedObjectsTable', () => { type: 'search', meta: { title: 'MySearch', - editUrl: '#/management/kibana/objects/savedSearches/2', + editUrl: '/management/kibana/objects/savedSearches/2', icon: 'search', inAppUrl: { path: '/discover/2', diff --git a/src/plugins/saved_objects_management/public/management_section/saved_objects_edition_page.tsx b/src/plugins/saved_objects_management/public/management_section/saved_objects_edition_page.tsx index 5ac6e8e103c47..52c4485b4f375 100644 --- a/src/plugins/saved_objects_management/public/management_section/saved_objects_edition_page.tsx +++ b/src/plugins/saved_objects_management/public/management_section/saved_objects_edition_page.tsx @@ -21,7 +21,7 @@ import React, { useEffect } from 'react'; import { useParams, useLocation } from 'react-router-dom'; import { parse } from 'query-string'; import { i18n } from '@kbn/i18n'; -import { CoreStart, ChromeBreadcrumb } from 'src/core/public'; +import { CoreStart, ChromeBreadcrumb, ScopedHistory } from 'src/core/public'; import { ISavedObjectsManagementServiceRegistry } from '../services'; import { SavedObjectEdition } from './object_view'; @@ -29,10 +29,12 @@ const SavedObjectsEditionPage = ({ coreStart, serviceRegistry, setBreadcrumbs, + history, }: { coreStart: CoreStart; serviceRegistry: ISavedObjectsManagementServiceRegistry; setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; + history: ScopedHistory; }) => { const { service: serviceName, id } = useParams<{ service: string; id: string }>(); const capabilities = coreStart.application.capabilities; @@ -47,7 +49,7 @@ const SavedObjectsEditionPage = ({ text: i18n.translate('savedObjectsManagement.breadcrumb.index', { defaultMessage: 'Saved objects', }), - href: '#/management/kibana/objects', + href: '/', }, { text: i18n.translate('savedObjectsManagement.breadcrumb.edit', { @@ -68,6 +70,7 @@ const SavedObjectsEditionPage = ({ notifications={coreStart.notifications} capabilities={capabilities} notFoundType={query.notFound as string} + history={history} /> ); }; diff --git a/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx b/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx index 4e8418d7406b5..ade9e82f28a36 100644 --- a/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx +++ b/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx @@ -20,7 +20,7 @@ import React, { useEffect } from 'react'; import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { CoreStart, ChromeBreadcrumb } from 'src/core/public'; +import { CoreStart, ChromeBreadcrumb, ScopedHistory } from 'src/core/public'; import { DataPublicPluginStart } from '../../../data/public'; import { ISavedObjectsManagementServiceRegistry, @@ -52,7 +52,7 @@ const SavedObjectsTablePage = ({ text: i18n.translate('savedObjectsManagement.breadcrumb.index', { defaultMessage: 'Saved objects', }), - href: '#/management/kibana/objects', + href: '/', }, ]); }, [setBreadcrumbs]); diff --git a/test/functional/apps/saved_objects_management/edit_saved_object.ts b/test/functional/apps/saved_objects_management/edit_saved_object.ts index caad9558687f4..6e4b820879ed3 100644 --- a/test/functional/apps/saved_objects_management/edit_saved_object.ts +++ b/test/functional/apps/saved_objects_management/edit_saved_object.ts @@ -82,9 +82,12 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { let objects = await PageObjects.settings.getSavedObjectsInTable(); expect(objects.includes('A Dashboard')).to.be(true); - await PageObjects.common.navigateToActualUrl( - 'kibana', - '/management/kibana/objects/savedDashboards/i-exist' + await PageObjects.common.navigateToUrl( + 'management', + 'kibana/objects/savedDashboards/i-exist', + { + shouldUseHashForSubUrl: false, + } ); await testSubjects.existOrFail('savedObjectEditSave'); @@ -100,9 +103,12 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(objects.includes('A Dashboard')).to.be(false); expect(objects.includes('Edited Dashboard')).to.be(true); - await PageObjects.common.navigateToActualUrl( - 'kibana', - '/management/kibana/objects/savedDashboards/i-exist' + await PageObjects.common.navigateToUrl( + 'management', + 'kibana/objects/savedDashboards/i-exist', + { + shouldUseHashForSubUrl: false, + } ); expect(await getFieldValue('title')).to.eql('Edited Dashboard'); @@ -110,9 +116,12 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it('allows to delete a saved object', async () => { - await PageObjects.common.navigateToActualUrl( - 'kibana', - '/management/kibana/objects/savedDashboards/i-exist' + await PageObjects.common.navigateToUrl( + 'management', + 'kibana/objects/savedDashboards/i-exist', + { + shouldUseHashForSubUrl: false, + } ); await focusAndClickButton('savedObjectEditDelete'); @@ -124,7 +133,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('preserves the object references when saving', async () => { const testVisualizationUrl = - '/management/kibana/objects/savedVisualizations/75c3e060-1e7c-11e9-8488-65449e65d0ed'; + 'kibana/objects/savedVisualizations/75c3e060-1e7c-11e9-8488-65449e65d0ed'; const visualizationRefs = [ { name: 'kibanaSavedObjectMeta.searchSourceJSON.index', @@ -139,7 +148,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const objects = await PageObjects.settings.getSavedObjectsInTable(); expect(objects.includes('A Pie')).to.be(true); - await PageObjects.common.navigateToActualUrl(testVisualizationUrl); + await PageObjects.common.navigateToUrl('management', testVisualizationUrl, { + shouldUseHashForSubUrl: false, + }); await testSubjects.existOrFail('savedObjectEditSave'); @@ -151,7 +162,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.settings.getSavedObjectsInTable(); - await PageObjects.common.navigateToActualUrl(testVisualizationUrl); + await PageObjects.common.navigateToUrl('management', testVisualizationUrl, { + shouldUseHashForSubUrl: false, + }); // Parsing to avoid random keys ordering issues in raw string comparison expect(JSON.parse(await getAceEditorFieldValue('references'))).to.eql(visualizationRefs); @@ -162,7 +175,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.settings.getSavedObjectsInTable(); - await PageObjects.common.navigateToActualUrl(testVisualizationUrl); + await PageObjects.common.navigateToUrl('management', testVisualizationUrl, { + shouldUseHashForSubUrl: false, + }); displayedReferencesValue = await getAceEditorFieldValue('references'); From 8299e039e9c0f4790c3441a5c8185818469165a6 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Mon, 25 May 2020 17:26:46 +0300 Subject: [PATCH 48/93] Fixed some tests --- .../top_nav/__snapshots__/open_search_panel.test.js.snap | 2 +- .../application/components/top_nav/open_search_panel.test.js | 1 + .../scripted_fields_table/components/header/header.test.tsx | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/discover/public/application/components/top_nav/__snapshots__/open_search_panel.test.js.snap b/src/plugins/discover/public/application/components/top_nav/__snapshots__/open_search_panel.test.js.snap index 3204252c808ac..42cd8613b1de0 100644 --- a/src/plugins/discover/public/application/components/top_nav/__snapshots__/open_search_panel.test.js.snap +++ b/src/plugins/discover/public/application/components/top_nav/__snapshots__/open_search_panel.test.js.snap @@ -53,7 +53,7 @@ exports[`render 1`] = ` > { return { getServices: () => ({ core: { uiSettings: {}, savedObjects: {} }, + addBasePath: (path) => path, }), }; }); diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx index 75a3baad11b30..a0d6a43d6f776 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx @@ -21,6 +21,7 @@ import React from 'react'; import { render } from 'enzyme'; import { RouteComponentProps } from 'react-router-dom'; import { ScopedHistory } from 'kibana/public'; +import { scopedHistoryMock } from '../../../../../../../../core/public/mocks'; import { Header } from './header'; @@ -29,7 +30,7 @@ describe('Header', () => { const component = render( From d4ee16378e6bcad1f755003c46c1c72ed10ce758 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 25 May 2020 17:48:28 +0300 Subject: [PATCH 49/93] fix functional test: should add new role myroleEast --- .../public/management/roles/edit_role/edit_role_page.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx index ede86c79720b4..58b45a7f1e95e 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx @@ -265,11 +265,6 @@ function useFeatures( return features; } -function backToRoleList() { - // todo: window.location.hash = ROLES_PATH; - // window.location.hash = ''; -} - export const EditRolePage: FunctionComponent = ({ userAPIClient, indexPatterns, @@ -318,6 +313,8 @@ export const EditRolePage: FunctionComponent = ({ const [kibanaPrivileges, builtInESPrivileges] = privileges; + const backToRoleList = () => history.push('/'); + const getFormTitle = () => { let titleText; const props: HTMLProps = { From 7ed4271346b821df57265f74f7e4e04acd529fec Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Mon, 25 May 2020 18:28:05 +0300 Subject: [PATCH 50/93] Reverted part of changes for ml --- x-pack/plugins/ml/public/application/app.tsx | 9 ++------- x-pack/plugins/ml/public/application/routing/router.tsx | 7 +++---- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/ml/public/application/app.tsx b/x-pack/plugins/ml/public/application/app.tsx index 9170df2570cc6..b3dc9eff95c34 100644 --- a/x-pack/plugins/ml/public/application/app.tsx +++ b/x-pack/plugins/ml/public/application/app.tsx @@ -23,17 +23,15 @@ type MlDependencies = MlSetupDependencies & MlStartDependencies; interface AppProps { coreStart: CoreStart; deps: MlDependencies; - history: ScopedHistory; } const localStorage = new Storage(window.localStorage); -const App: FC = ({ coreStart, deps, history }) => { +const App: FC = ({ coreStart, deps }) => { const pageDeps = { indexPatterns: deps.data.indexPatterns, config: coreStart.uiSettings!, setBreadcrumbs: coreStart.chrome!.setBreadcrumbs, - history, }; const services = { appName: 'ML', @@ -82,10 +80,7 @@ export const renderApp = ( appMountParams.onAppLeave((actions) => actions.default()); - ReactDOM.render( - , - appMountParams.element - ); + ReactDOM.render(, appMountParams.element); return () => { mlLicense.unsubscribe(); diff --git a/x-pack/plugins/ml/public/application/routing/router.tsx b/x-pack/plugins/ml/public/application/routing/router.tsx index 2851f41e3a97f..7b276da19c0b5 100644 --- a/x-pack/plugins/ml/public/application/routing/router.tsx +++ b/x-pack/plugins/ml/public/application/routing/router.tsx @@ -5,7 +5,7 @@ */ import React, { FC } from 'react'; -import { Router, Route, RouteProps } from 'react-router-dom'; +import { HashRouter, Route, RouteProps } from 'react-router-dom'; import { Location } from 'history'; import { IUiSettingsClient, ChromeStart, ScopedHistory } from 'kibana/public'; @@ -35,7 +35,6 @@ interface PageDependencies { setBreadcrumbs: ChromeStart['setBreadcrumbs']; indexPatterns: IndexPatternsContract; config: IUiSettingsClient; - history: ScopedHistory; } export const PageLoader: FC<{ context: MlContextValue }> = ({ context, children }) => { @@ -48,7 +47,7 @@ export const MlRouter: FC<{ pageDeps: PageDependencies }> = ({ pageDeps }) => { const setBreadcrumbs = pageDeps.setBreadcrumbs; return ( - +
{Object.entries(routes).map(([name, route]) => ( = ({ pageDeps }) => { /> ))}
-
+ ); }; From 86795ad6330dc9f07a2ee8d8f26784435c3a7aaa Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 25 May 2020 18:41:35 +0300 Subject: [PATCH 51/93] [transforms] partial progress --- .../management_section/saved_objects_table_page.tsx | 2 +- .../management/roles/edit_role/edit_role_page.tsx | 13 ++++++++----- x-pack/plugins/transform/public/app/app.tsx | 6 ++---- .../transform/public/app/common/navigation.tsx | 8 +++----- .../plugins/transform/public/app/constants/index.ts | 2 -- .../components/transform_list/action_clone.tsx | 4 ++-- .../public/app/services/navigation/breadcrumb.ts | 3 +-- .../public/app/services/navigation/index.ts | 1 - .../public/app/services/navigation/links.ts | 11 ----------- 9 files changed, 17 insertions(+), 33 deletions(-) delete mode 100644 x-pack/plugins/transform/public/app/services/navigation/links.ts diff --git a/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx b/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx index ade9e82f28a36..7db9de4f1bc0d 100644 --- a/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx +++ b/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx @@ -20,7 +20,7 @@ import React, { useEffect } from 'react'; import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { CoreStart, ChromeBreadcrumb, ScopedHistory } from 'src/core/public'; +import { CoreStart, ChromeBreadcrumb } from 'src/core/public'; import { DataPublicPluginStart } from '../../../data/public'; import { ISavedObjectsManagementServiceRegistry, diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx index 58b45a7f1e95e..0cbc430de09c2 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx @@ -26,6 +26,7 @@ import React, { Fragment, FunctionComponent, HTMLProps, + useCallback, useEffect, useRef, useState, @@ -158,7 +159,8 @@ function useRole( notifications: NotificationsStart, license: SecurityLicense, action: string, - roleName?: string + roleName?: string, + backToRoleList: () => void ) { const [role, setRole] = useState(null); useEffect(() => { @@ -218,7 +220,7 @@ function useRole( fatalErrors.add(err); } }); - }, [roleName, action, fatalErrors, rolesAPIClient, notifications, license]); + }, [roleName, action, fatalErrors, rolesAPIClient, notifications, license, backToRoleList]); return [role, setRole] as [Role | null, typeof setRole]; } @@ -283,6 +285,8 @@ export const EditRolePage: FunctionComponent = ({ notifications, history, }) => { + const backToRoleList = useCallback(() => history.push('/'), [history]); + // We should keep the same mutable instance of Validator for every re-render since we'll // eventually enable validation after the first time user tries to save a role. const { current: validator } = useRef(new RoleValidator({ shouldValidate: false })); @@ -299,7 +303,8 @@ export const EditRolePage: FunctionComponent = ({ notifications, license, action, - roleName + roleName, + backToRoleList ); if (!role || !runAsUsers || !indexPatternsTitles || !privileges || !spaces || !features) { @@ -313,8 +318,6 @@ export const EditRolePage: FunctionComponent = ({ const [kibanaPrivileges, builtInESPrivileges] = privileges; - const backToRoleList = () => history.push('/'); - const getFormTitle = () => { let titleText; const props: HTMLProps = { diff --git a/x-pack/plugins/transform/public/app/app.tsx b/x-pack/plugins/transform/public/app/app.tsx index c9a8cb3f8539c..ccfdc8b0942fa 100644 --- a/x-pack/plugins/transform/public/app/app.tsx +++ b/x-pack/plugins/transform/public/app/app.tsx @@ -6,7 +6,7 @@ import React, { useContext, FC } from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { Router, Redirect, Route, Switch } from 'react-router-dom'; +import { Router, Route, Switch } from 'react-router-dom'; import { ScopedHistory } from 'kibana/public'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -52,9 +52,7 @@ export const App: FC<{ history: ScopedHistory }> = ({ history }) => { path={`/${SECTION_SLUG.CREATE_TRANSFORM}/:savedObjectId`} component={CreateTransformSection} /> - - - +
diff --git a/x-pack/plugins/transform/public/app/common/navigation.tsx b/x-pack/plugins/transform/public/app/common/navigation.tsx index 15966a93e1f42..67c44c54a3ed8 100644 --- a/x-pack/plugins/transform/public/app/common/navigation.tsx +++ b/x-pack/plugins/transform/public/app/common/navigation.tsx @@ -8,7 +8,7 @@ import React, { FC } from 'react'; import { Redirect } from 'react-router-dom'; import rison from 'rison-node'; -import { CLIENT_BASE_PATH, SECTION_SLUG } from '../constants'; +import { SECTION_SLUG } from '../constants'; /** * Gets a url for navigating to Discover page. @@ -28,10 +28,8 @@ export function getDiscoverUrl(indexPatternId: string, baseUrl: string): string return `${baseUrl}${hash}`; } -export const RedirectToTransformManagement: FC = () => ( - -); +export const RedirectToTransformManagement: FC = () => ; export const RedirectToCreateTransform: FC<{ savedObjectId: string }> = ({ savedObjectId }) => ( - + ); diff --git a/x-pack/plugins/transform/public/app/constants/index.ts b/x-pack/plugins/transform/public/app/constants/index.ts index 3156fae7545b1..299007d84768f 100644 --- a/x-pack/plugins/transform/public/app/constants/index.ts +++ b/x-pack/plugins/transform/public/app/constants/index.ts @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -export const CLIENT_BASE_PATH = '/management/data/transform/'; - export enum SECTION_SLUG { HOME = 'transform_management', CLONE_TRANSFORM = 'clone_transform', diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_clone.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_clone.tsx index 4b333f73f048c..48188fd70bd7e 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_clone.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_clone.tsx @@ -14,7 +14,7 @@ import { AuthorizationContext, } from '../../../../lib/authorization'; -import { CLIENT_BASE_PATH, SECTION_SLUG } from '../../../../constants'; +import { SECTION_SLUG } from '../../../../constants'; interface CloneActionProps { itemId: string; @@ -30,7 +30,7 @@ export const CloneAction: FC = ({ itemId }) => { }); function clickHandler() { - history.push(`${CLIENT_BASE_PATH}${SECTION_SLUG.CLONE_TRANSFORM}/${itemId}`); + history.push(`/${SECTION_SLUG.CLONE_TRANSFORM}/${itemId}`); } const cloneButton = ( diff --git a/x-pack/plugins/transform/public/app/services/navigation/breadcrumb.ts b/x-pack/plugins/transform/public/app/services/navigation/breadcrumb.ts index 6637b8a39cd56..7d4ab5d8163e1 100644 --- a/x-pack/plugins/transform/public/app/services/navigation/breadcrumb.ts +++ b/x-pack/plugins/transform/public/app/services/navigation/breadcrumb.ts @@ -5,7 +5,6 @@ */ import { textService } from '../text'; -import { linkToHome } from './links'; import { ManagementAppMountParams } from '../../../../../../../src/plugins/management/public'; @@ -41,7 +40,7 @@ class BreadcrumbService { this.breadcrumbs.home = [ { text: textService.breadcrumbs.home, - href: linkToHome(), + href: '/', }, ]; this.breadcrumbs.cloneTransform = [ diff --git a/x-pack/plugins/transform/public/app/services/navigation/index.ts b/x-pack/plugins/transform/public/app/services/navigation/index.ts index 40a6d6d9fbdc4..f1bd864f538ad 100644 --- a/x-pack/plugins/transform/public/app/services/navigation/index.ts +++ b/x-pack/plugins/transform/public/app/services/navigation/index.ts @@ -6,4 +6,3 @@ export { breadcrumbService, BREADCRUMB_SECTION } from './breadcrumb'; export { docTitleService } from './doc_title'; -export * from './links'; diff --git a/x-pack/plugins/transform/public/app/services/navigation/links.ts b/x-pack/plugins/transform/public/app/services/navigation/links.ts deleted file mode 100644 index 85088c3a4a69d..0000000000000 --- a/x-pack/plugins/transform/public/app/services/navigation/links.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { CLIENT_BASE_PATH } from '../../constants'; - -export function linkToHome() { - return `#${CLIENT_BASE_PATH}`; -} From 3c1c19f25ce900877623257b2cd9f4f6a0fb4e24 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 25 May 2020 21:43:27 +0300 Subject: [PATCH 52/93] fix TS errors --- x-pack/plugins/ml/public/application/app.tsx | 2 +- x-pack/plugins/ml/public/application/routing/router.tsx | 2 +- .../public/management/roles/edit_role/edit_role_page.tsx | 8 ++++---- x-pack/test/functional/apps/security/role_mappings.ts | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/ml/public/application/app.tsx b/x-pack/plugins/ml/public/application/app.tsx index b3dc9eff95c34..4b6ff8c64822b 100644 --- a/x-pack/plugins/ml/public/application/app.tsx +++ b/x-pack/plugins/ml/public/application/app.tsx @@ -7,7 +7,7 @@ import React, { FC } from 'react'; import ReactDOM from 'react-dom'; -import { AppMountParameters, CoreStart, ScopedHistory } from 'kibana/public'; +import { AppMountParameters, CoreStart } from 'kibana/public'; import { Storage } from '../../../../../src/plugins/kibana_utils/public'; diff --git a/x-pack/plugins/ml/public/application/routing/router.tsx b/x-pack/plugins/ml/public/application/routing/router.tsx index 7b276da19c0b5..281493c4e31b7 100644 --- a/x-pack/plugins/ml/public/application/routing/router.tsx +++ b/x-pack/plugins/ml/public/application/routing/router.tsx @@ -8,7 +8,7 @@ import React, { FC } from 'react'; import { HashRouter, Route, RouteProps } from 'react-router-dom'; import { Location } from 'history'; -import { IUiSettingsClient, ChromeStart, ScopedHistory } from 'kibana/public'; +import { IUiSettingsClient, ChromeStart } from 'kibana/public'; import { ChromeBreadcrumb } from 'kibana/public'; import { IndexPatternsContract } from 'src/plugins/data/public'; import { MlContext, MlContextValue } from '../contexts/ml'; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx index 0cbc430de09c2..77f4455d813c6 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx @@ -159,8 +159,8 @@ function useRole( notifications: NotificationsStart, license: SecurityLicense, action: string, - roleName?: string, - backToRoleList: () => void + backToRoleList: () => void, + roleName?: string ) { const [role, setRole] = useState(null); useEffect(() => { @@ -303,8 +303,8 @@ export const EditRolePage: FunctionComponent = ({ notifications, license, action, - roleName, - backToRoleList + backToRoleList, + roleName ); if (!role || !runAsUsers || !indexPatternsTitles || !privileges || !spaces || !features) { diff --git a/x-pack/test/functional/apps/security/role_mappings.ts b/x-pack/test/functional/apps/security/role_mappings.ts index dd953769c3ce6..f5ad92a700531 100644 --- a/x-pack/test/functional/apps/security/role_mappings.ts +++ b/x-pack/test/functional/apps/security/role_mappings.ts @@ -93,7 +93,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const url = parse(await browser.getCurrentUrl()); - expect(url.pathname).to.eql('/management/security/role_mappings'); + expect(url.pathname).to.eql('/management/security/role_mappings/'); }); describe('with role mappings', () => { From 1d2878e902d093bbfa3717687309fc14734cbae8 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 25 May 2020 23:18:29 +0300 Subject: [PATCH 53/93] fix functional: redirects to Kibana home --- .../management/public/management_sections_service.ts | 2 +- .../public/management_section/saved_objects_table_page.tsx | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/plugins/management/public/management_sections_service.ts b/src/plugins/management/public/management_sections_service.ts index 85aa73de7b5bb..1d6441eea13ff 100644 --- a/src/plugins/management/public/management_sections_service.ts +++ b/src/plugins/management/public/management_sections_service.ts @@ -61,7 +61,7 @@ export class ManagementSectionsService { getAllSections: this.getAllSections, getSectionsEnabled: () => this.getAllSections() - .filter((section) => section.enabled && section.apps.length) + .filter((section) => section.enabled && section.getAppsEnabled().length) .sort((a, b) => a.order - b.order), }; } diff --git a/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx b/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx index 7db9de4f1bc0d..75692777f08bb 100644 --- a/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx +++ b/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx @@ -73,11 +73,7 @@ const SavedObjectsTablePage = ({ goInspectObject={(savedObject) => { const { editUrl } = savedObject.meta; if (editUrl) { - // previously, kbnUrl.change(object.meta.editUrl); was used. - // using direct access to location.hash seems the only option for now, - // as using react-router-dom will prefix the url with the router's basename - // which should be ignored there. - window.location.hash = editUrl; + return coreStart.application.navigateToUrl('/app' + editUrl); } }} canGoInApp={(savedObject) => { From 0b3cd49e25784ba7c24fa3b0b0729ccb081e4831 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 26 May 2020 13:14:31 +0300 Subject: [PATCH 54/93] add support of Backward compatibility --- src/legacy/core_plugins/kibana/public/kibana.js | 5 +++++ test/common/services/security/test_user.ts | 4 ++-- .../functional/apps/dashboard_mode/dashboard_view_mode.js | 6 +++++- x-pack/test/functional/apps/security/role_mappings.ts | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/kibana.js b/src/legacy/core_plugins/kibana/public/kibana.js index 610ae4d452384..51dedcc629c76 100644 --- a/src/legacy/core_plugins/kibana/public/kibana.js +++ b/src/legacy/core_plugins/kibana/public/kibana.js @@ -44,11 +44,16 @@ import { localApplicationService } from './local_application_service'; npSetup.plugins.kibanaLegacy.registerLegacyAppAlias('doc', 'discover', { keepPrefix: true }); npSetup.plugins.kibanaLegacy.registerLegacyAppAlias('context', 'discover', { keepPrefix: true }); +npSetup.plugins.kibanaLegacy.forwardApp('management', 'management', (path) => { + return path.replace('/management', ''); +}); + localApplicationService.attachToAngular(routes); routes.enable(); const { config } = npSetup.plugins.kibanaLegacy; + routes.otherwise({ redirectTo: `/${config.defaultAppId || 'discover'}`, }); diff --git a/test/common/services/security/test_user.ts b/test/common/services/security/test_user.ts index e72ded3a6f2fd..c0abf236e3412 100644 --- a/test/common/services/security/test_user.ts +++ b/test/common/services/security/test_user.ts @@ -71,7 +71,7 @@ export async function createTestUserService( } } - async setRoles(roles: string[]) { + async setRoles(roles: string[], shouldRefreshBrowser: boolean = true) { if (isEnabled()) { log.debug(`set roles = ${roles}`); await user.create('test_user', { @@ -80,7 +80,7 @@ export async function createTestUserService( full_name: 'test user', }); - if (browser && testSubjects) { + if (browser && testSubjects && shouldRefreshBrowser) { if (await testSubjects.exists('kibanaChrome', { allowHidden: true })) { await browser.refresh(); await testSubjects.find('kibanaChrome', config.get('timeouts.find') * 10); diff --git a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js index 612556b0c4728..00183113a4d59 100644 --- a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js +++ b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js @@ -115,7 +115,11 @@ export default function ({ getService, getPageObjects }) { }); it('shows only the dashboard app link', async () => { - await security.testUser.setRoles(['test_logstash_reader', 'kibana_dashboard_only_user']); + await security.testUser.setRoles( + ['test_logstash_reader', 'kibana_dashboard_only_user'], + false + ); + await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.security.forceLogout(); await PageObjects.security.login('test_user', 'changeme'); diff --git a/x-pack/test/functional/apps/security/role_mappings.ts b/x-pack/test/functional/apps/security/role_mappings.ts index f5ad92a700531..60c166d837933 100644 --- a/x-pack/test/functional/apps/security/role_mappings.ts +++ b/x-pack/test/functional/apps/security/role_mappings.ts @@ -93,7 +93,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const url = parse(await browser.getCurrentUrl()); - expect(url.pathname).to.eql('/management/security/role_mappings/'); + expect(url.pathname).to.eql('/app/management/security/role_mappings/'); }); describe('with role mappings', () => { From 4d164e58d79b627d6ac9ecf0d292ba101ed555bd Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 26 May 2020 13:54:55 +0300 Subject: [PATCH 55/93] fix functional: Saved objects management feature controls saved objects management global visualize all privileges listing redirects to Kibana home --- .../management_section/mount_section.tsx | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx index f835503d4efbf..0eb37c56117ee 100644 --- a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx +++ b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx @@ -51,6 +51,16 @@ export const mountManagementSection = async ({ const capabilities = coreStart.application.capabilities; + const RedirectToHomeIfUnauthorized: React.FunctionComponent = ({ children }) => { + const allowed = capabilities?.management?.kibana?.objects ?? false; + + if (!allowed) { + coreStart.application.navigateToApp('home'); + return null; + } + return children! as React.ReactElement; + }; + ReactDOM.render( @@ -91,14 +101,3 @@ export const mountManagementSection = async ({ ReactDOM.unmountComponentAtNode(element); }; }; - -const RedirectToHomeIfUnauthorized: React.FunctionComponent<{ - capabilities: Capabilities; -}> = ({ children, capabilities }) => { - const allowed = capabilities?.management?.kibana?.objects ?? false; - if (!allowed) { - window.location.hash = '/home'; - return null; - } - return children! as React.ReactElement; -}; From 219cd555968bafb2c6ab23e84ce39a752e1f6b4d Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 26 May 2020 13:57:22 +0300 Subject: [PATCH 56/93] fix PR comment --- .../index_patterns/ensure_default_index_pattern.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/data/public/index_patterns/index_patterns/ensure_default_index_pattern.tsx b/src/plugins/data/public/index_patterns/index_patterns/ensure_default_index_pattern.tsx index 2ee6965bb4125..2088bd8c925df 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/ensure_default_index_pattern.tsx +++ b/src/plugins/data/public/index_patterns/index_patterns/ensure_default_index_pattern.tsx @@ -91,9 +91,9 @@ export const createEnsureDefaultIndexPattern = (core: CoreStart) => { if (redirectTarget === '/home') { core.application.navigateToApp('home'); } else { - window.location.href = core.http.basePath.prepend( - `/app/management/kibana/indexPatterns?bannerMessage=${bannerMessage}` - ); + core.application.navigateToApp('management', { + path: `/kibana/indexPatterns?bannerMessage=${bannerMessage}`, + }); } // return never-resolving promise to stop resolving and wait for the url change From d5a9731bded167cee47c979cd26dabaa65680ba5 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 26 May 2020 14:10:26 +0300 Subject: [PATCH 57/93] fix TS issues --- .../public/management_section/mount_section.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx index 0eb37c56117ee..9cfe99fd3bbf8 100644 --- a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx +++ b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx @@ -22,7 +22,7 @@ import ReactDOM from 'react-dom'; import { Router, Switch, Route } from 'react-router-dom'; import { I18nProvider } from '@kbn/i18n/react'; import { EuiLoadingSpinner } from '@elastic/eui'; -import { CoreSetup, Capabilities } from 'src/core/public'; +import { CoreSetup } from 'src/core/public'; import { ManagementAppMountParams } from '../../../management/public'; import { StartDependencies, SavedObjectsManagementPluginStart } from '../plugin'; import { ISavedObjectsManagementServiceRegistry } from '../services'; @@ -66,7 +66,7 @@ export const mountManagementSection = async ({ - + }> - + }> Date: Tue, 26 May 2020 14:36:18 +0300 Subject: [PATCH 58/93] Fixed x-pack jest tests --- .../__snapshots__/add_license.test.js.snap | 4 +- .../upload_license.test.tsx.snap | 909 +++++++++++++++++- .../__jest__/upload_license.test.tsx | 12 +- .../license_management/__jest__/util/util.js | 11 +- .../connector_add_flyout.test.tsx | 2 +- 5 files changed, 917 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/license_management/__jest__/__snapshots__/add_license.test.js.snap b/x-pack/plugins/license_management/__jest__/__snapshots__/add_license.test.js.snap index e4411807dfa56..28ce3c6c07501 100644 --- a/x-pack/plugins/license_management/__jest__/__snapshots__/add_license.test.js.snap +++ b/x-pack/plugins/license_management/__jest__/__snapshots__/add_license.test.js.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`AddLicense component when license is active should display correct verbiage 1`] = `"
Update your license

If you already have a new license, upload it now.

"`; +exports[`AddLicense component when license is active should display correct verbiage 1`] = `"
Update your license

If you already have a new license, upload it now.

"`; -exports[`AddLicense component when license is expired should display with correct verbiage 1`] = `"
Update your license

If you already have a new license, upload it now.

"`; +exports[`AddLicense component when license is expired should display with correct verbiage 1`] = `"
Update your license

If you already have a new license, upload it now.

"`; diff --git a/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.tsx.snap b/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.tsx.snap index b621e89efbee3..cc8cbfe679eff 100644 --- a/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.tsx.snap +++ b/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.tsx.snap @@ -112,6 +112,42 @@ exports[`UploadLicense should display a modal when license requires acknowledgem "refresh": [MockFunction], }, }, + "services": Object { + "history": Object { + "action": "PUSH", + "block": [MockFunction], + "createHref": [MockFunction] { + "calls": Array [ + Array [ + Object { + "pathname": "/home", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": "/home", + }, + ], + }, + "createSubHistory": [MockFunction], + "go": [MockFunction], + "goBack": [MockFunction], + "goForward": [MockFunction], + "length": 1, + "listen": [MockFunction], + "location": Object { + "hash": "", + "key": undefined, + "pathname": "/", + "search": "", + "state": undefined, + }, + "push": [MockFunction], + "replace": [MockFunction], + }, + }, } } > @@ -126,12 +162,85 @@ exports[`UploadLicense should display a modal when license requires acknowledgem } } > - + @@ -1162,12 +1336,139 @@ exports[`UploadLicense should display an error when ES says license is expired 1 } } > - + @@ -1628,12 +1994,139 @@ exports[`UploadLicense should display an error when ES says license is invalid 1 } } > - + @@ -2094,12 +2652,139 @@ exports[`UploadLicense should display an error when submitting invalid JSON 1`] } } > - + @@ -2560,12 +3310,139 @@ exports[`UploadLicense should display error when ES returns error 1`] = ` } } > - + {}; let store: any = null; let component: any = null; +const history = scopedHistoryMock.create(); +history.createHref.mockImplementation((location: LocationDescriptorObject) => { + return `${location.pathname}${location.search ? '?' + location.search : ''}`; +}); const appDependencies = { plugins: { @@ -39,12 +44,15 @@ const appDependencies = { refresh: jest.fn(), }, }, + services: { + history, + }, docLinks: {}, }; const thunkServices = { http: httpServiceMock.createSetupContract(), - history: scopedHistoryMock.create(), + history, breadcrumbService: { setBreadcrumbs() {}, }, @@ -57,7 +65,7 @@ describe('UploadLicense', () => { component = ( - + ); diff --git a/x-pack/plugins/license_management/__jest__/util/util.js b/x-pack/plugins/license_management/__jest__/util/util.js index 5a7e49c8c3315..c13dcdb7fdbfa 100644 --- a/x-pack/plugins/license_management/__jest__/util/util.js +++ b/x-pack/plugins/license_management/__jest__/util/util.js @@ -9,14 +9,22 @@ import React from 'react'; import { Provider } from 'react-redux'; import { mountWithIntl } from '../../../../test_utils/enzyme_helpers'; -import { httpServiceMock } from '../../../../../src/core/public/mocks'; +import { httpServiceMock, scopedHistoryMock } from '../../../../../src/core/public/mocks'; import { licenseManagementStore } from '../../public/application/store/store'; import { AppContextProvider } from '../../public/application/app_context'; const highExpirationMillis = new Date('October 13, 2099 00:00:00Z').getTime(); +const history = scopedHistoryMock.create(); +history.createHref.mockImplementation((location) => { + return `${location.pathname}${location.search ? '?' + location.search : ''}`; +}); + const appDependencies = { docLinks: {}, + services: { + history, + }, }; export const createMockLicense = (type, expiryDateInMillis = highExpirationMillis) => { @@ -30,6 +38,7 @@ export const createMockLicense = (type, expiryDateInMillis = highExpirationMilli export const getComponent = (initialState, Component) => { const services = { http: httpServiceMock.createSetupContract(), + history, }; const store = licenseManagementStore(initialState, services); return mountWithIntl( diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.test.tsx index a96abfe312663..f60199bc47f4b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.test.tsx @@ -127,7 +127,7 @@ describe('connector_add_flyout', () => { const manageLink = callout.find('EuiButton'); expect(manageLink).toHaveLength(1); expect(manageLink.getElements()[0].props.href).toMatchInlineSnapshot( - `"/app//management/stack/license_management/"` + `"/app/management/stack/license_management"` ); const subscriptionLink = callout.find('EuiButtonEmpty'); From 9d0c162db511946a07e1669279b6b4bd6669c249 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 26 May 2020 14:46:25 +0300 Subject: [PATCH 59/93] fix oss JEST --- .../url/kbn_url_storage.test.ts | 48 +++++++------------ .../state_management/url/kbn_url_storage.ts | 8 ++-- 2 files changed, 22 insertions(+), 34 deletions(-) diff --git a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.test.ts b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.test.ts index b8c06c8479926..a8c3aab2202d1 100644 --- a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.test.ts +++ b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.test.ts @@ -35,7 +35,7 @@ import { ScopedHistory } from '../../../../../core/public'; describe('kbn_url_storage', () => { describe('getStateFromUrl & setStateToUrl', () => { - const url = 'http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id'; + const url = 'http://localhost:5601/oxf/app/kibana#/yourApp'; const state1 = { testStr: '123', testNumber: 0, @@ -50,14 +50,14 @@ describe('kbn_url_storage', () => { it('should set expanded state to url', () => { let newUrl = setStateToKbnUrl('_s', state1, { useHash: false }, url); expect(newUrl).toMatchInlineSnapshot( - `"http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_s=(testArray:!(1,2,()),testNull:!n,testNumber:0,testObj:(test:'123'),testStr:'123')"` + `"http://localhost:5601/oxf/app/kibana#/yourApp?_s=(testArray:!(1,2,()),testNull:!n,testNumber:0,testObj:(test:'123'),testStr:'123')"` ); const retrievedState1 = getStateFromKbnUrl('_s', newUrl); expect(retrievedState1).toEqual(state1); newUrl = setStateToKbnUrl('_s', state2, { useHash: false }, newUrl); expect(newUrl).toMatchInlineSnapshot( - `"http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_s=(test:'123')"` + `"http://localhost:5601/oxf/app/kibana#/yourApp?_s=(test:'123')"` ); const retrievedState2 = getStateFromKbnUrl('_s', newUrl); expect(retrievedState2).toEqual(state2); @@ -66,14 +66,14 @@ describe('kbn_url_storage', () => { it('should set hashed state to url', () => { let newUrl = setStateToKbnUrl('_s', state1, { useHash: true }, url); expect(newUrl).toMatchInlineSnapshot( - `"http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_s=h@a897fac"` + `"http://localhost:5601/oxf/app/kibana#/yourApp?_s=h@a897fac"` ); const retrievedState1 = getStateFromKbnUrl('_s', newUrl); expect(retrievedState1).toEqual(state1); newUrl = setStateToKbnUrl('_s', state2, { useHash: true }, newUrl); expect(newUrl).toMatchInlineSnapshot( - `"http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_s=h@40f94d5"` + `"http://localhost:5601/oxf/app/kibana#/yourApp?_s=h@40f94d5"` ); const retrievedState2 = getStateFromKbnUrl('_s', newUrl); expect(retrievedState2).toEqual(state2); @@ -244,67 +244,55 @@ describe('kbn_url_storage', () => { it('should extract path relative to browser history without basename', () => { const history = createBrowserHistory(); const url = - "http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "http://localhost:5601/oxf/app/kibana#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const relativePath = getRelativeToHistoryPath(url, history); expect(relativePath).toEqual( - "/oxf/app/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" + "/oxf/app/kibana#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" ); }); it('should extract path relative to browser history with basename', () => { const url = - "http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "http://localhost:5601/oxf/app/kibana#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const history1 = createBrowserHistory({ basename: '/oxf/app/' }); const relativePath1 = getRelativeToHistoryPath(url, history1); expect(relativePath1).toEqual( - "/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" + "/kibana#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" ); const history2 = createBrowserHistory({ basename: '/oxf/app/kibana/' }); const relativePath2 = getRelativeToHistoryPath(url, history2); - expect(relativePath2).toEqual( - "#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" - ); + expect(relativePath2).toEqual("#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"); }); it('should extract path relative to browser history with basename from relative url', () => { const history = createBrowserHistory({ basename: '/oxf/app/' }); - const url = - "/oxf/app/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + const url = "/oxf/app/kibana#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const relativePath = getRelativeToHistoryPath(url, history); - expect(relativePath).toEqual( - "/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" - ); + expect(relativePath).toEqual("/kibana#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"); }); it('should extract path relative to hash history without basename', () => { const history = createHashHistory(); const url = - "http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "http://localhost:5601/oxf/app/kibana#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const relativePath = getRelativeToHistoryPath(url, history); - expect(relativePath).toEqual( - "/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" - ); + expect(relativePath).toEqual("/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"); }); it('should extract path relative to hash history with basename', () => { const history = createHashHistory({ basename: 'management' }); const url = - "http://localhost:5601/oxf/app/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + "http://localhost:5601/oxf/app/kibana#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const relativePath = getRelativeToHistoryPath(url, history); - expect(relativePath).toEqual( - "/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" - ); + expect(relativePath).toEqual("/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"); }); it('should extract path relative to hash history with basename from relative url', () => { const history = createHashHistory({ basename: 'management' }); - const url = - "/oxf/app/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; + const url = "/oxf/app/kibana#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"; const relativePath = getRelativeToHistoryPath(url, history); - expect(relativePath).toEqual( - "/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')" - ); + expect(relativePath).toEqual("/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')"); }); }); }); diff --git a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts index 20816c08c550e..d9149095a2fa2 100644 --- a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts +++ b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts @@ -31,7 +31,7 @@ import { url as urlUtils } from '../../../common'; * e.g.: * * given an url: - * http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'') + * http://localhost:5601/oxf/app/kibana#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'') * will return object: * {_a: {tab: 'indexedFields'}, _b: {f: 'test', i: '', l: ''}}; */ @@ -57,7 +57,7 @@ export function getStatesFromKbnUrl( * e.g.: * * given an url: - * http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'') + * http://localhost:5601/oxf/app/kibana#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'') * and key '_a' * will return object: * {tab: 'indexedFields'} @@ -74,12 +74,12 @@ export function getStateFromKbnUrl( * Doesn't actually updates history * * e.g.: - * given a url: http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'') + * given a url: http://localhost:5601/oxf/app/kibana#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'') * key: '_a' * and state: {tab: 'other'} * * will return url: - * http://localhost:5601/oxf/app/kibana#/management/kibana/indexPatterns/patterns/id?_a=(tab:other)&_b=(f:test,i:'',l:'') + * http://localhost:5601/oxf/app/kibana#/yourApp?_a=(tab:other)&_b=(f:test,i:'',l:'') */ export function setStateToKbnUrl( key: string, From 96ec2a9682bba9c45aede5152597d6e627a7dcec Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Tue, 26 May 2020 16:52:49 +0300 Subject: [PATCH 60/93] Fixed functional test --- x-pack/test/functional/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index 2980d8a002363..9aed489a9ffdb 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -176,7 +176,7 @@ export default async function ({ readConfigFile }) { pathname: '/app/management/data/cross_cluster_replication', }, remoteClusters: { - pathname: '/app/management/data/remote_cluster', + pathname: '/app/management/data/remote_clusters', }, apm: { pathname: '/app/apm', From de9be15184a63c3245b185bebfdad90c11fb0a6f Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 26 May 2020 19:04:27 +0300 Subject: [PATCH 61/93] fix functional test --- .../apps/security/trial_license/login_selector.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/x-pack/test/functional/apps/security/trial_license/login_selector.ts b/x-pack/test/functional/apps/security/trial_license/login_selector.ts index 95e68eb9a1f6e..67ece8d4a4049 100644 --- a/x-pack/test/functional/apps/security/trial_license/login_selector.ts +++ b/x-pack/test/functional/apps/security/trial_license/login_selector.ts @@ -6,7 +6,6 @@ import expect from '@kbn/expect'; import { parse } from 'url'; -import { USERS_PATH } from '../../../../../plugins/security/public/management/management_urls'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { @@ -42,9 +41,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('can login with Login Form preserving original URL', async () => { - await PageObjects.common.navigateToActualUrl('kibana', USERS_PATH, { + await PageObjects.common.navigateToUrl('management', 'security/users', { ensureCurrentUrl: false, shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, }); await PageObjects.common.waitUntilUrlIncludes('next='); @@ -52,14 +52,15 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // We need to make sure that both path and hash are respected. const currentURL = parse(await browser.getCurrentUrl()); - expect(currentURL.pathname).to.eql('/app/kibana'); - expect(currentURL.hash).to.eql(`#${USERS_PATH}`); + + expect(currentURL.pathname).to.eql('/app/management/security/users/'); }); it('can login with SSO preserving original URL', async () => { - await PageObjects.common.navigateToActualUrl('kibana', USERS_PATH, { + await PageObjects.common.navigateToUrl('management', 'security/users', { ensureCurrentUrl: false, shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, }); await PageObjects.common.waitUntilUrlIncludes('next='); @@ -67,8 +68,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // We need to make sure that both path and hash are respected. const currentURL = parse(await browser.getCurrentUrl()); - expect(currentURL.pathname).to.eql('/app/kibana'); - expect(currentURL.hash).to.eql(`#${USERS_PATH}`); + expect(currentURL.pathname).to.eql('/app/management/security/users/'); }); it('should show toast with error if SSO fails', async () => { From c0d6210f93eed94abf36c7ba2851e34fbcc80d0b Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 26 May 2020 22:13:00 +0300 Subject: [PATCH 62/93] fix PR comment --- x-pack/plugins/apm/public/application/index.tsx | 1 - .../functional/apps/security/trial_license/login_selector.ts | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/apm/public/application/index.tsx b/x-pack/plugins/apm/public/application/index.tsx index 6882d4c9c1117..d91ac460277ba 100644 --- a/x-pack/plugins/apm/public/application/index.tsx +++ b/x-pack/plugins/apm/public/application/index.tsx @@ -25,7 +25,6 @@ import { UpdateBreadcrumbs } from '../components/app/Main/UpdateBreadcrumbs'; import { APMIndicesPermission } from '../components/app/APMIndicesPermission'; import { ScrollToTopOnPathChange } from '../components/app/Main/ScrollToTopOnPathChange'; import { routes } from '../components/app/Main/route_config'; -// import { history, resetHistory } from '../utils/history'; import { ConfigSchema } from '..'; import 'react-vis/dist/style.css'; diff --git a/x-pack/test/functional/apps/security/trial_license/login_selector.ts b/x-pack/test/functional/apps/security/trial_license/login_selector.ts index 67ece8d4a4049..e0b776cd123c1 100644 --- a/x-pack/test/functional/apps/security/trial_license/login_selector.ts +++ b/x-pack/test/functional/apps/security/trial_license/login_selector.ts @@ -53,7 +53,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // We need to make sure that both path and hash are respected. const currentURL = parse(await browser.getCurrentUrl()); - expect(currentURL.pathname).to.eql('/app/management/security/users/'); + expect(currentURL.pathname).to.eql('/app/management/security/users'); }); it('can login with SSO preserving original URL', async () => { @@ -68,7 +68,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // We need to make sure that both path and hash are respected. const currentURL = parse(await browser.getCurrentUrl()); - expect(currentURL.pathname).to.eql('/app/management/security/users/'); + expect(currentURL.pathname).to.eql('/app/management/security/users'); }); it('should show toast with error if SSO fails', async () => { From ac265f5958da0e5c61cb7a7f6d619246d9f52246 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Wed, 27 May 2020 13:56:05 +0300 Subject: [PATCH 63/93] Fixed i18n --- x-pack/plugins/translations/translations/ja-JP.json | 2 -- x-pack/plugins/translations/translations/zh-CN.json | 2 -- 2 files changed, 4 deletions(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 6c3dfa2e31cb6..f5799dfaa1721 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -168,7 +168,6 @@ "common.ui.flotCharts.thuLabel": "木", "common.ui.flotCharts.tueLabel": "火", "common.ui.flotCharts.wedLabel": "水", - "common.ui.stackManagement.breadcrumb": "スタック管理", "common.ui.stateManagement.unableToParseUrlErrorMessage": "URL をパースできません", "common.ui.stateManagement.unableToRestoreUrlErrorMessage": "URL を完全に復元できません。共有機能を使用していることを確認してください。", "common.ui.stateManagement.unableToStoreHistoryInSessionErrorMessage": "セッションがいっぱいで安全に削除できるアイテムが見つからないため、Kibana は履歴アイテムを保存できません。\n\nこれは大抵新規タブに移動することで解決されますが、より大きな問題が原因である可能性もあります。このメッセージが定期的に表示される場合は、{gitHubIssuesUrl} で問題を報告してください。", @@ -2220,7 +2219,6 @@ "kibana-react.tableListView.listing.table.editActionName": "編集", "kibana-react.tableListView.listing.unableToDeleteDangerMessage": "{entityName} を削除できません", "management.breadcrumb": "スタック管理", - "management.displayName": "スタック管理", "management.nav.label": "管理", "management.nav.menu": "管理メニュー", "management.landing.header": "Stack Management {version}へようこそ", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 7ab71b1d9d70b..7626db752b6ff 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -168,7 +168,6 @@ "common.ui.flotCharts.thuLabel": "周四", "common.ui.flotCharts.tueLabel": "周二", "common.ui.flotCharts.wedLabel": "周三", - "common.ui.stackManagement.breadcrumb": "Stack Management", "common.ui.stateManagement.unableToParseUrlErrorMessage": "无法解析 URL", "common.ui.stateManagement.unableToRestoreUrlErrorMessage": "无法完整还原 URL,确保使用共享功能。", "common.ui.stateManagement.unableToStoreHistoryInSessionErrorMessage": "Kibana 无法将历史记录项存储在您的会话中,因为其已满,并且似乎没有任何可安全删除的项。\n\n通常可通过移至新的标签页来解决此问题,但这会导致更大的问题。如果您有规律地看到此消息,请在 {gitHubIssuesUrl} 提交问题。", @@ -2223,7 +2222,6 @@ "kibana-react.tableListView.listing.table.editActionName": "编辑", "kibana-react.tableListView.listing.unableToDeleteDangerMessage": "无法删除{entityName}", "management.breadcrumb": "Stack Management", - "management.displayName": "Stack Management", "management.nav.label": "管理", "management.nav.menu": "管理菜单", "management.landing.header": "欢迎使用 Stack Management {version}", From 22634b2d91f1f5fe3bfba4ed48b7e0d025764e71 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 28 May 2020 12:02:16 +0300 Subject: [PATCH 64/93] fix typo --- .../management/public/components/{langing => landing}/index.ts | 0 .../public/components/{langing => landing}/landing.tsx | 0 .../public/components/management_app/management_router.tsx | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename src/plugins/management/public/components/{langing => landing}/index.ts (100%) rename src/plugins/management/public/components/{langing => landing}/landing.tsx (100%) diff --git a/src/plugins/management/public/components/langing/index.ts b/src/plugins/management/public/components/landing/index.ts similarity index 100% rename from src/plugins/management/public/components/langing/index.ts rename to src/plugins/management/public/components/landing/index.ts diff --git a/src/plugins/management/public/components/langing/landing.tsx b/src/plugins/management/public/components/landing/landing.tsx similarity index 100% rename from src/plugins/management/public/components/langing/landing.tsx rename to src/plugins/management/public/components/landing/landing.tsx diff --git a/src/plugins/management/public/components/management_app/management_router.tsx b/src/plugins/management/public/components/management_app/management_router.tsx index da16a869558bc..fc614ea517c96 100644 --- a/src/plugins/management/public/components/management_app/management_router.tsx +++ b/src/plugins/management/public/components/management_app/management_router.tsx @@ -22,7 +22,7 @@ import { Route, Router, Switch } from 'react-router-dom'; import { EuiPageBody } from '@elastic/eui'; import { AppMountParameters, ChromeBreadcrumb, ScopedHistory } from 'kibana/public'; import { ManagementAppWrapper } from '../management_app_wrapper'; -import { ManagementLandingPage } from '../langing'; +import { ManagementLandingPage } from '../landing'; import { ManagementAppDependencies } from './management_app'; import { ManagementSection } from '../../utils'; From fe060ab6a138b3b770e0c12c0de4af91952912df Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 28 May 2020 13:10:31 +0300 Subject: [PATCH 65/93] fix Styles --- .../kibana/public/management/_hacks.scss | 5 ----- .../management_app/_management_app.scss | 20 +++---------------- .../management_app/management_router.tsx | 2 +- .../management_sidebar_nav/_index.scss | 1 - .../management_sidebar_nav/_sidebar_nav.scss | 1 + .../management_sidebar_nav.tsx | 2 +- 6 files changed, 6 insertions(+), 25 deletions(-) delete mode 100644 src/plugins/management/public/components/management_sidebar_nav/_index.scss diff --git a/src/legacy/core_plugins/kibana/public/management/_hacks.scss b/src/legacy/core_plugins/kibana/public/management/_hacks.scss index 59af9c9617a30..99555b74f03ca 100644 --- a/src/legacy/core_plugins/kibana/public/management/_hacks.scss +++ b/src/legacy/core_plugins/kibana/public/management/_hacks.scss @@ -22,8 +22,3 @@ kbn-management-objects-view { kbn-management-objects-view { .ace_editor { height: 300px; } } - -// Hack because the management wrapper is flat HTML and needs a class -.mgtPage__body { - max-width: map-get($euiBreakpoints, 'xl'); -} diff --git a/src/plugins/management/public/components/management_app/_management_app.scss b/src/plugins/management/public/components/management_app/_management_app.scss index 6eaf82ba8283d..5b068819d3815 100644 --- a/src/plugins/management/public/components/management_app/_management_app.scss +++ b/src/plugins/management/public/components/management_app/_management_app.scss @@ -1,19 +1,5 @@ -.mgtPanel { - margin-bottom: $euiSize; - background: $euiColorEmptyShade; -} - -/** - * 1. Override kuiPanelBody styles to accommodate padding of items within the panel body.. - */ -.mgtPanel__body { - padding: 5px 10px; /* 1 */ -} -/** - * 1. Create vertical space between items when they wrap. - */ -.mgtPanel__item { - padding: 5px 15px; /* 1 */ +// Hack because the management wrapper is flat HTML and needs a class +.mgtPage__body { + max-width: map-get($euiBreakpoints, 'xl'); } - diff --git a/src/plugins/management/public/components/management_app/management_router.tsx b/src/plugins/management/public/components/management_app/management_router.tsx index fc614ea517c96..3f934fa68c6ba 100644 --- a/src/plugins/management/public/components/management_app/management_router.tsx +++ b/src/plugins/management/public/components/management_app/management_router.tsx @@ -37,7 +37,7 @@ interface ManagementRouterProps { export const ManagementRouter = memo( ({ dependencies, history, setBreadcrumbs, onAppMounted, sections }: ManagementRouterProps) => ( - + {sections.map((section) => section diff --git a/src/plugins/management/public/components/management_sidebar_nav/_index.scss b/src/plugins/management/public/components/management_sidebar_nav/_index.scss deleted file mode 100644 index 0a48807344abd..0000000000000 --- a/src/plugins/management/public/components/management_sidebar_nav/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './sidebar_nav'; \ No newline at end of file diff --git a/src/plugins/management/public/components/management_sidebar_nav/_sidebar_nav.scss b/src/plugins/management/public/components/management_sidebar_nav/_sidebar_nav.scss index 5302bd200de3f..a148c1e141e8d 100644 --- a/src/plugins/management/public/components/management_sidebar_nav/_sidebar_nav.scss +++ b/src/plugins/management/public/components/management_sidebar_nav/_sidebar_nav.scss @@ -1,5 +1,6 @@ .mgtSideBarNav { width: 210px; + margin-right: $euiSize; } @include euiBreakpoint('xs','s') { diff --git a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx index 613c43109bf71..b986ab4ffa1c3 100644 --- a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx +++ b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx @@ -23,7 +23,7 @@ import React, { useState } from 'react'; import { AppMountParameters } from 'kibana/public'; import { ManagementApp, ManagementSection } from '../../utils'; -import './_index.scss'; +import './_sidebar_nav.scss'; import { ManagementItem } from '../../utils/management_item'; import { reactRouterNavigate } from '../../../../kibana_react/public'; From ce4454b43f7b9d442de824527cd11c7a35dadcae Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Thu, 28 May 2020 14:21:05 +0300 Subject: [PATCH 66/93] Fixed paths for cross_cluster_replication --- .../components/detail_panel/detail_panel.js | 8 +++++++- .../components/detail_panel/detail_panel.js | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js index 3f2ed82420ff1..6b2ee01bff8df 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js @@ -31,6 +31,7 @@ import { EuiTitle, } from '@elastic/eui'; +import { routing } from '../../../../../services/routing'; import { AutoFollowPatternIndicesPreview, AutoFollowPatternActionMenu, @@ -296,7 +297,12 @@ export class DetailPanel extends Component { - + - + Date: Thu, 28 May 2020 14:29:54 +0300 Subject: [PATCH 67/93] fix wrong link --- .../management_section/objects_table/saved_objects_table.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index d9b856a79b496..c24f5d29f3870 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -457,8 +457,8 @@ export class SavedObjectsTable extends Component Date: Thu, 28 May 2020 16:21:57 +0300 Subject: [PATCH 68/93] Fixed jest --- .../helpers/auto_follow_pattern_list.helpers.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_list.helpers.js b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_list.helpers.js index 87cf6a13ba011..f9d4e98c6be56 100644 --- a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_list.helpers.js +++ b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_list.helpers.js @@ -12,7 +12,11 @@ import { routing } from '../../../app/services/routing'; const testBedConfig = { store: ccrStore, memoryRouter: { - onRouter: (router) => (routing.reactRouter = router), + onRouter: (router) => + (routing.reactRouter = { + ...router, + getUrlForApp: () => '', + }), }, }; From 2e86461320b5dd73a393651247a0bc9bcb2049a0 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Fri, 29 May 2020 12:56:06 +0300 Subject: [PATCH 69/93] Fixed some comments --- .../kibana/public/management/_hacks.scss | 24 ------------------- ...anagement_app.scss => management_app.scss} | 1 + .../management_app/management_app.tsx | 2 +- ...r_nav.scss => management_sidebar_nav.scss} | 0 .../management_sidebar_nav.tsx | 2 +- .../components/detail_panel/detail_panel.js | 8 ++++--- .../components/detail_panel/detail_panel.js | 8 ++++--- .../common/constants/index.ts | 2 -- .../public/app/common/navigation.tsx | 4 ++-- .../components/wizard/wizard.tsx | 15 +++++++++--- 10 files changed, 27 insertions(+), 39 deletions(-) delete mode 100644 src/legacy/core_plugins/kibana/public/management/_hacks.scss rename src/plugins/management/public/components/management_app/{_management_app.scss => management_app.scss} (88%) rename src/plugins/management/public/components/management_sidebar_nav/{_sidebar_nav.scss => management_sidebar_nav.scss} (100%) diff --git a/src/legacy/core_plugins/kibana/public/management/_hacks.scss b/src/legacy/core_plugins/kibana/public/management/_hacks.scss deleted file mode 100644 index 99555b74f03ca..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/_hacks.scss +++ /dev/null @@ -1,24 +0,0 @@ -// SASSTODO: figure out why this is needed -kbn-management-app, -kbn-management-landing, -kbn-management-indices, -kbn-management-indices-edit, -kbn-management-indices-create, -kbn-management-advanced, -kbn-management-objects, -kbn-management-objects-view { - display: block; -} - -#management-landing { - display: flex; -} - -.kbn-management-tab:first-letter { - text-transform: capitalize; -} - -// SASSTODO: Remove when this is replaced with EuiCode -kbn-management-objects-view { - .ace_editor { height: 300px; } -} diff --git a/src/plugins/management/public/components/management_app/_management_app.scss b/src/plugins/management/public/components/management_app/management_app.scss similarity index 88% rename from src/plugins/management/public/components/management_app/_management_app.scss rename to src/plugins/management/public/components/management_app/management_app.scss index 5b068819d3815..00b3e51fb53ee 100644 --- a/src/plugins/management/public/components/management_app/_management_app.scss +++ b/src/plugins/management/public/components/management_app/management_app.scss @@ -2,4 +2,5 @@ // Hack because the management wrapper is flat HTML and needs a class .mgtPage__body { max-width: map-get($euiBreakpoints, 'xl'); + margin: 0 auto; } diff --git a/src/plugins/management/public/components/management_app/management_app.tsx b/src/plugins/management/public/components/management_app/management_app.tsx index b5fb8e7f2a01b..fc5a8924c95d6 100644 --- a/src/plugins/management/public/components/management_app/management_app.tsx +++ b/src/plugins/management/public/components/management_app/management_app.tsx @@ -32,7 +32,7 @@ import { ManagementRouter } from './management_router'; import { ManagementSidebarNav } from '../management_sidebar_nav'; import { reactRouterNavigate } from '../../../../kibana_react/public'; -import './_management_app.scss'; +import './management_app.scss'; interface ManagementAppProps { appBasePath: string; diff --git a/src/plugins/management/public/components/management_sidebar_nav/_sidebar_nav.scss b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.scss similarity index 100% rename from src/plugins/management/public/components/management_sidebar_nav/_sidebar_nav.scss rename to src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.scss diff --git a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx index b986ab4ffa1c3..e25dfaa93a6c2 100644 --- a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx +++ b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx @@ -23,7 +23,7 @@ import React, { useState } from 'react'; import { AppMountParameters } from 'kibana/public'; import { ManagementApp, ManagementSection } from '../../utils'; -import './_sidebar_nav.scss'; +import './management_sidebar_nav.scss'; import { ManagementItem } from '../../utils/management_item'; import { reactRouterNavigate } from '../../../../kibana_react/public'; diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js index 6b2ee01bff8df..8f8b3c5c39aab 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js @@ -9,6 +9,7 @@ import PropTypes from 'prop-types'; import { FormattedMessage } from '@kbn/i18n/react'; import moment from 'moment'; +import { reactRouterNavigate } from '../../../../../../../../../../src/plugins/kibana_react/public'; import { getIndexListUri } from '../../../../../../../../../plugins/index_management/public'; import { @@ -298,9 +299,10 @@ export class DetailPanel extends Component { ; diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx b/x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx index 3fcfd77ba54cd..69fcf822de5d2 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx @@ -120,14 +120,23 @@ export const Wizard: FC = React.memo(({ cloneConfig, searchItems }) // as it was when transforms were part of the ML plugin. This will be revisited // to come up with an approach that's more in line with the overall layout // of the Kibana management section. - const managementBody = document.getElementsByClassName( + let managementBody = document.getElementsByClassName( KBN_MANAGEMENT_PAGE_CLASSNAME.DEFAULT_BODY ); if (managementBody.length > 0) { - managementBody[0].classList.add(KBN_MANAGEMENT_PAGE_CLASSNAME.TRANSFORM_BODY_MODIFIER); + managementBody[0].classList.replace( + KBN_MANAGEMENT_PAGE_CLASSNAME.DEFAULT_BODY, + KBN_MANAGEMENT_PAGE_CLASSNAME.TRANSFORM_BODY_MODIFIER + ); return () => { - managementBody[0].classList.remove(KBN_MANAGEMENT_PAGE_CLASSNAME.TRANSFORM_BODY_MODIFIER); + managementBody = document.getElementsByClassName( + KBN_MANAGEMENT_PAGE_CLASSNAME.TRANSFORM_BODY_MODIFIER + ); + managementBody[0].classList.replace( + KBN_MANAGEMENT_PAGE_CLASSNAME.TRANSFORM_BODY_MODIFIER, + KBN_MANAGEMENT_PAGE_CLASSNAME.DEFAULT_BODY + ); }; } }, []); From 89e843236057600c950ac6c8880ebc56e7328ae0 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 29 May 2020 12:55:05 +0300 Subject: [PATCH 70/93] fix sorting --- .../management_sidebar_nav.tsx | 43 +++++++++++-------- .../management_sections_service.test.ts | 6 +-- .../public/management_sections_service.ts | 5 +-- .../public/utils/management_section.ts | 2 +- 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx index e25dfaa93a6c2..055dda5ed84a1 100644 --- a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx +++ b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.tsx @@ -17,9 +17,11 @@ * under the License. */ -import { EuiIcon, EuiSideNav, EuiScreenReaderOnly, EuiSideNavItemType } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import React, { useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { sortBy } from 'lodash'; + +import { EuiIcon, EuiSideNav, EuiScreenReaderOnly, EuiSideNavItemType } from '@elastic/eui'; import { AppMountParameters } from 'kibana/public'; import { ManagementApp, ManagementSection } from '../../utils'; @@ -53,25 +55,30 @@ export const ManagementSidebarNav = ({ const toggleOpenOnMobile = () => setIsSideNavOpenOnMobile(!isSideNavOpenOnMobile); const sectionsToNavItems = (managementSections: ManagementSection[]) => { - return managementSections - .filter((section) => section.getAppsEnabled()) - .map((section) => ({ - ...createNavItem(section, { - items: appsToNavItems(section.apps), - }), - })); - }; + const sortedManagementSections = sortBy(managementSections, 'order'); + + return sortedManagementSections.reduce>>((acc, section) => { + const apps = sortBy(section.getAppsEnabled(), 'order'); - const appsToNavItems = (managementApps: ManagementApp[]) => { - return managementApps - .filter((app) => app.enabled) - .map((app) => ({ - ...createNavItem(app, { - ...reactRouterNavigate(history, app.basePath), - }), - })); + if (apps.length) { + acc.push({ + ...createNavItem(section, { + items: appsToNavItems(apps), + }), + }); + } + + return acc; + }, []); }; + const appsToNavItems = (managementApps: ManagementApp[]) => + managementApps.map((app) => ({ + ...createNavItem(app, { + ...reactRouterNavigate(history, app.basePath), + }), + })); + const createNavItem = ( item: T, customParams: Partial> = {} diff --git a/src/plugins/management/public/management_sections_service.test.ts b/src/plugins/management/public/management_sections_service.test.ts index 27bff646117aa..0e040c3cab055 100644 --- a/src/plugins/management/public/management_sections_service.test.ts +++ b/src/plugins/management/public/management_sections_service.test.ts @@ -58,10 +58,10 @@ describe('ManagementService', () => { // Start phase: const start = managementService.start(); - expect(start.getSectionsEnabled().length).toEqual(1); + expect(start.getSectionsEnabled().length).toEqual(7); - testApp.disable(); + testSection.disable(); - expect(start.getSectionsEnabled().length).toEqual(0); + expect(start.getSectionsEnabled().length).toEqual(6); }); }); diff --git a/src/plugins/management/public/management_sections_service.ts b/src/plugins/management/public/management_sections_service.ts index 1d6441eea13ff..08a87b3e89f2b 100644 --- a/src/plugins/management/public/management_sections_service.ts +++ b/src/plugins/management/public/management_sections_service.ts @@ -59,10 +59,7 @@ export class ManagementSectionsService { return { getSection: this.getSection, getAllSections: this.getAllSections, - getSectionsEnabled: () => - this.getAllSections() - .filter((section) => section.enabled && section.getAppsEnabled().length) - .sort((a, b) => a.order - b.order), + getSectionsEnabled: () => this.getAllSections().filter((section) => section.enabled), }; } } diff --git a/src/plugins/management/public/utils/management_section.ts b/src/plugins/management/public/utils/management_section.ts index 970a4d5ac05c8..d226825e39d19 100644 --- a/src/plugins/management/public/utils/management_section.ts +++ b/src/plugins/management/public/utils/management_section.ts @@ -53,6 +53,6 @@ export class ManagementSection extends ManagementItem { } getAppsEnabled() { - return this.apps.filter((app) => app.enabled).sort((a, b) => a.order - b.order); + return this.apps.filter((app) => app.enabled); } } From e9e0456b850ce0ec54ed276f5ac2b6d7fae2e22d Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 29 May 2020 14:01:17 +0300 Subject: [PATCH 71/93] fix type check --- .../management/public/management_sections_service.test.ts | 8 -------- x-pack/test/functional/config.js | 6 +++--- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/plugins/management/public/management_sections_service.test.ts b/src/plugins/management/public/management_sections_service.test.ts index 0e040c3cab055..2c5d04883235c 100644 --- a/src/plugins/management/public/management_sections_service.test.ts +++ b/src/plugins/management/public/management_sections_service.test.ts @@ -47,14 +47,6 @@ describe('ManagementService', () => { expect(setup.getSection('test-section')).not.toBeUndefined(); - const testApp = testSection.registerApp({ - id: 'test-app', - title: 'Test App', - mount: () => () => {}, - }); - - expect(testSection.getApp('test-app')).not.toBeUndefined(); - // Start phase: const start = managementService.start(); diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index 057ec7a99ed9f..bcc7c978ca237 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -172,12 +172,12 @@ export default async function ({ readConfigFile }) { snapshotRestore: { pathname: '/app/management/data/snapshot_restore', }, - crossClusterReplication: { - pathname: '/app/management/data/cross_cluster_replication', - }, remoteClusters: { pathname: '/app/management/data/remote_clusters', }, + crossClusterReplication: { + pathname: '/app/management/data/cross_cluster_replication', + }, apm: { pathname: '/app/apm', }, From 14c9e5f126ac3bbfa8e8f6eaa46aea0b437c279d Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Fri, 29 May 2020 14:11:34 +0300 Subject: [PATCH 72/93] fixed x-pack jest --- .../helpers/auto_follow_pattern_list.helpers.js | 7 +++++++ .../helpers/follower_index_list.helpers.js | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_list.helpers.js b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_list.helpers.js index f9d4e98c6be56..550e178a1c733 100644 --- a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_list.helpers.js +++ b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/auto_follow_pattern_list.helpers.js @@ -15,6 +15,13 @@ const testBedConfig = { onRouter: (router) => (routing.reactRouter = { ...router, + history: { + ...router.history, + parentHistory: { + createHref: () => '', + push: () => {}, + }, + }, getUrlForApp: () => '', }), }, diff --git a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_list.helpers.js b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_list.helpers.js index c147a3984190b..65be10b9d272e 100644 --- a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_list.helpers.js +++ b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/follower_index_list.helpers.js @@ -14,7 +14,13 @@ const testBedConfig = { memoryRouter: { onRouter: (router) => (routing.reactRouter = { - ...router, + history: { + ...router.history, + parentHistory: { + createHref: () => '', + push: () => {}, + }, + }, getUrlForApp: () => '', }), }, From e9182da7806bf448e601f3b163af5e1070e964ec Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Fri, 29 May 2020 16:00:04 +0300 Subject: [PATCH 73/93] fixed x-pack jest --- x-pack/plugins/transform/public/app/common/navigation.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/transform/public/app/common/navigation.test.tsx b/x-pack/plugins/transform/public/app/common/navigation.test.tsx index 97cb5b4d5d236..4fd4376a021fc 100644 --- a/x-pack/plugins/transform/public/app/common/navigation.test.tsx +++ b/x-pack/plugins/transform/public/app/common/navigation.test.tsx @@ -9,7 +9,7 @@ import { getDiscoverUrl } from './navigation'; describe('navigation', () => { test('getDiscoverUrl should provide encoded url to Discover page', () => { expect(getDiscoverUrl('farequote-airline', 'http://example.com')).toBe( - 'http://example.com#/discover?_g=()&_a=(index:farequote-airline)' + 'http://example.com/app/discover#?_g=()&_a=(index:farequote-airline)' ); }); }); From 4f7eb18f9bf95ce768a2fdf7112785621c25c138 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Fri, 29 May 2020 18:42:19 +0300 Subject: [PATCH 74/93] reverted using of parentHistory --- .../components/detail_panel/detail_panel.js | 8 +++----- .../components/detail_panel/detail_panel.js | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js index 8f8b3c5c39aab..6b2ee01bff8df 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js @@ -9,7 +9,6 @@ import PropTypes from 'prop-types'; import { FormattedMessage } from '@kbn/i18n/react'; import moment from 'moment'; -import { reactRouterNavigate } from '../../../../../../../../../../src/plugins/kibana_react/public'; import { getIndexListUri } from '../../../../../../../../../plugins/index_management/public'; import { @@ -299,10 +298,9 @@ export class DetailPanel extends Component { Date: Fri, 29 May 2020 11:28:43 -0700 Subject: [PATCH 75/93] Add debugging toasts to CCR. --- x-pack/plugins/cross_cluster_replication/public/plugin.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/cross_cluster_replication/public/plugin.ts b/x-pack/plugins/cross_cluster_replication/public/plugin.ts index b87801c3b0c76..22ec8c9d81ded 100644 --- a/x-pack/plugins/cross_cluster_replication/public/plugin.ts +++ b/x-pack/plugins/cross_cluster_replication/public/plugin.ts @@ -65,14 +65,17 @@ export class CrossClusterReplicationPlugin implements Plugin { ccrApp.disable(); + const config = this.initializerContext.config.get(); + + toasts.addSuccess(`Enabled: ${config.ui.enable}. RC UI enabled: ${remoteClusters.isUiEnabled}`); + licensing.license$ .pipe(first()) .toPromise() .then((license) => { const licenseStatus = license.check(PLUGIN.ID, PLUGIN.minimumLicenseType); const isLicenseOk = licenseStatus.state === 'valid'; - const config = this.initializerContext.config.get(); - + toasts.addSuccess(`License OK: ${isLicenseOk}`); // remoteClusters.isUiEnabled is driven by the xpack.remote_clusters.ui.enabled setting. // The CCR UI depends upon the Remote Clusters UI (e.g. by cross-linking to it), so if // the Remote Clusters UI is disabled we can't show the CCR UI. From 933d765161f28329c7aa26397adc772d6b253281 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Fri, 29 May 2020 11:39:25 -0700 Subject: [PATCH 76/93] Comment out non-CCR functional tests. --- x-pack/test/functional/config.js | 62 ++++++++++++++++---------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index bcc7c978ca237..cda9d6fa99d72 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -24,37 +24,37 @@ export default async function ({ readConfigFile }) { return { // list paths to the files that contain your plugins tests testFiles: [ - resolve(__dirname, './apps/advanced_settings'), - resolve(__dirname, './apps/canvas'), - resolve(__dirname, './apps/graph'), - resolve(__dirname, './apps/monitoring'), - resolve(__dirname, './apps/watcher'), - resolve(__dirname, './apps/dashboard'), - resolve(__dirname, './apps/dashboard_mode'), - resolve(__dirname, './apps/discover'), - resolve(__dirname, './apps/security'), - resolve(__dirname, './apps/spaces'), - resolve(__dirname, './apps/lens'), - resolve(__dirname, './apps/logstash'), - resolve(__dirname, './apps/grok_debugger'), - resolve(__dirname, './apps/infra'), - resolve(__dirname, './apps/ml'), - resolve(__dirname, './apps/rollup_job'), - resolve(__dirname, './apps/maps'), - resolve(__dirname, './apps/status_page'), - resolve(__dirname, './apps/timelion'), - resolve(__dirname, './apps/upgrade_assistant'), - resolve(__dirname, './apps/visualize'), - resolve(__dirname, './apps/uptime'), - resolve(__dirname, './apps/saved_objects_management'), - resolve(__dirname, './apps/dev_tools'), - resolve(__dirname, './apps/apm'), - resolve(__dirname, './apps/api_keys'), - resolve(__dirname, './apps/index_patterns'), - resolve(__dirname, './apps/index_management'), - resolve(__dirname, './apps/index_lifecycle_management'), - resolve(__dirname, './apps/ingest_pipelines'), - resolve(__dirname, './apps/snapshot_restore'), + // resolve(__dirname, './apps/advanced_settings'), + // resolve(__dirname, './apps/canvas'), + // resolve(__dirname, './apps/graph'), + // resolve(__dirname, './apps/monitoring'), + // resolve(__dirname, './apps/watcher'), + // resolve(__dirname, './apps/dashboard'), + // resolve(__dirname, './apps/dashboard_mode'), + // resolve(__dirname, './apps/discover'), + // resolve(__dirname, './apps/security'), + // resolve(__dirname, './apps/spaces'), + // resolve(__dirname, './apps/lens'), + // resolve(__dirname, './apps/logstash'), + // resolve(__dirname, './apps/grok_debugger'), + // resolve(__dirname, './apps/infra'), + // resolve(__dirname, './apps/ml'), + // resolve(__dirname, './apps/rollup_job'), + // resolve(__dirname, './apps/maps'), + // resolve(__dirname, './apps/status_page'), + // resolve(__dirname, './apps/timelion'), + // resolve(__dirname, './apps/upgrade_assistant'), + // resolve(__dirname, './apps/visualize'), + // resolve(__dirname, './apps/uptime'), + // resolve(__dirname, './apps/saved_objects_management'), + // resolve(__dirname, './apps/dev_tools'), + // resolve(__dirname, './apps/apm'), + // resolve(__dirname, './apps/api_keys'), + // resolve(__dirname, './apps/index_patterns'), + // resolve(__dirname, './apps/index_management'), + // resolve(__dirname, './apps/index_lifecycle_management'), + // resolve(__dirname, './apps/ingest_pipelines'), + // resolve(__dirname, './apps/snapshot_restore'), resolve(__dirname, './apps/cross_cluster_replication'), resolve(__dirname, './apps/remote_clusters'), resolve(__dirname, './apps/transform'), From 7fcec23409c905292391f684bceb43b50e18070e Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Fri, 29 May 2020 13:01:48 -0700 Subject: [PATCH 77/93] Fix typo. --- x-pack/plugins/cross_cluster_replication/public/plugin.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/cross_cluster_replication/public/plugin.ts b/x-pack/plugins/cross_cluster_replication/public/plugin.ts index 22ec8c9d81ded..85ce8993342a5 100644 --- a/x-pack/plugins/cross_cluster_replication/public/plugin.ts +++ b/x-pack/plugins/cross_cluster_replication/public/plugin.ts @@ -67,7 +67,9 @@ export class CrossClusterReplicationPlugin implements Plugin { const config = this.initializerContext.config.get(); - toasts.addSuccess(`Enabled: ${config.ui.enable}. RC UI enabled: ${remoteClusters.isUiEnabled}`); + toasts.addSuccess( + `Enabled: ${config.ui.enabled}. RC UI enabled: ${remoteClusters.isUiEnabled}` + ); licensing.license$ .pipe(first()) From e496bb0614af92e0367ab69177ff86feb316b49f Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Fri, 29 May 2020 14:45:22 -0700 Subject: [PATCH 78/93] Uncomment non-CCR functional tests. --- x-pack/test/functional/config.js | 62 ++++++++++++++++---------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index cda9d6fa99d72..bcc7c978ca237 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -24,37 +24,37 @@ export default async function ({ readConfigFile }) { return { // list paths to the files that contain your plugins tests testFiles: [ - // resolve(__dirname, './apps/advanced_settings'), - // resolve(__dirname, './apps/canvas'), - // resolve(__dirname, './apps/graph'), - // resolve(__dirname, './apps/monitoring'), - // resolve(__dirname, './apps/watcher'), - // resolve(__dirname, './apps/dashboard'), - // resolve(__dirname, './apps/dashboard_mode'), - // resolve(__dirname, './apps/discover'), - // resolve(__dirname, './apps/security'), - // resolve(__dirname, './apps/spaces'), - // resolve(__dirname, './apps/lens'), - // resolve(__dirname, './apps/logstash'), - // resolve(__dirname, './apps/grok_debugger'), - // resolve(__dirname, './apps/infra'), - // resolve(__dirname, './apps/ml'), - // resolve(__dirname, './apps/rollup_job'), - // resolve(__dirname, './apps/maps'), - // resolve(__dirname, './apps/status_page'), - // resolve(__dirname, './apps/timelion'), - // resolve(__dirname, './apps/upgrade_assistant'), - // resolve(__dirname, './apps/visualize'), - // resolve(__dirname, './apps/uptime'), - // resolve(__dirname, './apps/saved_objects_management'), - // resolve(__dirname, './apps/dev_tools'), - // resolve(__dirname, './apps/apm'), - // resolve(__dirname, './apps/api_keys'), - // resolve(__dirname, './apps/index_patterns'), - // resolve(__dirname, './apps/index_management'), - // resolve(__dirname, './apps/index_lifecycle_management'), - // resolve(__dirname, './apps/ingest_pipelines'), - // resolve(__dirname, './apps/snapshot_restore'), + resolve(__dirname, './apps/advanced_settings'), + resolve(__dirname, './apps/canvas'), + resolve(__dirname, './apps/graph'), + resolve(__dirname, './apps/monitoring'), + resolve(__dirname, './apps/watcher'), + resolve(__dirname, './apps/dashboard'), + resolve(__dirname, './apps/dashboard_mode'), + resolve(__dirname, './apps/discover'), + resolve(__dirname, './apps/security'), + resolve(__dirname, './apps/spaces'), + resolve(__dirname, './apps/lens'), + resolve(__dirname, './apps/logstash'), + resolve(__dirname, './apps/grok_debugger'), + resolve(__dirname, './apps/infra'), + resolve(__dirname, './apps/ml'), + resolve(__dirname, './apps/rollup_job'), + resolve(__dirname, './apps/maps'), + resolve(__dirname, './apps/status_page'), + resolve(__dirname, './apps/timelion'), + resolve(__dirname, './apps/upgrade_assistant'), + resolve(__dirname, './apps/visualize'), + resolve(__dirname, './apps/uptime'), + resolve(__dirname, './apps/saved_objects_management'), + resolve(__dirname, './apps/dev_tools'), + resolve(__dirname, './apps/apm'), + resolve(__dirname, './apps/api_keys'), + resolve(__dirname, './apps/index_patterns'), + resolve(__dirname, './apps/index_management'), + resolve(__dirname, './apps/index_lifecycle_management'), + resolve(__dirname, './apps/ingest_pipelines'), + resolve(__dirname, './apps/snapshot_restore'), resolve(__dirname, './apps/cross_cluster_replication'), resolve(__dirname, './apps/remote_clusters'), resolve(__dirname, './apps/transform'), From 3390711ad89cf19c1cd2fbe29b711c0ebd5508ee Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Sat, 30 May 2020 20:59:37 -0700 Subject: [PATCH 79/93] Enable CCR. --- .../plugins/cross_cluster_replication/public/plugin.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/cross_cluster_replication/public/plugin.ts b/x-pack/plugins/cross_cluster_replication/public/plugin.ts index 85ce8993342a5..3712b5cdef40f 100644 --- a/x-pack/plugins/cross_cluster_replication/public/plugin.ts +++ b/x-pack/plugins/cross_cluster_replication/public/plugin.ts @@ -63,14 +63,10 @@ export class CrossClusterReplicationPlugin implements Plugin { }, }); - ccrApp.disable(); + ccrApp.enable(); const config = this.initializerContext.config.get(); - toasts.addSuccess( - `Enabled: ${config.ui.enabled}. RC UI enabled: ${remoteClusters.isUiEnabled}` - ); - licensing.license$ .pipe(first()) .toPromise() @@ -78,6 +74,9 @@ export class CrossClusterReplicationPlugin implements Plugin { const licenseStatus = license.check(PLUGIN.ID, PLUGIN.minimumLicenseType); const isLicenseOk = licenseStatus.state === 'valid'; toasts.addSuccess(`License OK: ${isLicenseOk}`); + toasts.addSuccess( + `Enabled: ${config.ui.enabled}. RC UI enabled: ${remoteClusters.isUiEnabled}` + ); // remoteClusters.isUiEnabled is driven by the xpack.remote_clusters.ui.enabled setting. // The CCR UI depends upon the Remote Clusters UI (e.g. by cross-linking to it), so if // the Remote Clusters UI is disabled we can't show the CCR UI. From 2c83f8c23acc2210731897a284f36de8fca4e4b7 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Sun, 31 May 2020 12:10:23 +0300 Subject: [PATCH 80/93] fix CI --- .../plugins/cross_cluster_replication/public/plugin.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/cross_cluster_replication/public/plugin.ts b/x-pack/plugins/cross_cluster_replication/public/plugin.ts index 3712b5cdef40f..5f96849c5c161 100644 --- a/x-pack/plugins/cross_cluster_replication/public/plugin.ts +++ b/x-pack/plugins/cross_cluster_replication/public/plugin.ts @@ -63,8 +63,6 @@ export class CrossClusterReplicationPlugin implements Plugin { }, }); - ccrApp.enable(); - const config = this.initializerContext.config.get(); licensing.license$ @@ -73,18 +71,12 @@ export class CrossClusterReplicationPlugin implements Plugin { .then((license) => { const licenseStatus = license.check(PLUGIN.ID, PLUGIN.minimumLicenseType); const isLicenseOk = licenseStatus.state === 'valid'; - toasts.addSuccess(`License OK: ${isLicenseOk}`); - toasts.addSuccess( - `Enabled: ${config.ui.enabled}. RC UI enabled: ${remoteClusters.isUiEnabled}` - ); // remoteClusters.isUiEnabled is driven by the xpack.remote_clusters.ui.enabled setting. // The CCR UI depends upon the Remote Clusters UI (e.g. by cross-linking to it), so if // the Remote Clusters UI is disabled we can't show the CCR UI. const isCcrUiEnabled = config.ui.enabled && remoteClusters.isUiEnabled; if (isLicenseOk && isCcrUiEnabled) { - ccrApp.enable(); - if (indexManagement) { const propertyPath = 'isFollowerIndex'; @@ -101,6 +93,8 @@ export class CrossClusterReplicationPlugin implements Plugin { indexManagement.extensionsService.addBadge(followerBadgeExtension); } + } else { + ccrApp.disable(); } }); } From cb656127164e1be8f553468339def2314291e498 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Sun, 31 May 2020 06:08:40 -0700 Subject: [PATCH 81/93] Add comment to explain why CCR is enabled by default and move config variable back to original location in CCR plugin. --- x-pack/plugins/cross_cluster_replication/public/plugin.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/cross_cluster_replication/public/plugin.ts b/x-pack/plugins/cross_cluster_replication/public/plugin.ts index 5f96849c5c161..8bf0d519e685d 100644 --- a/x-pack/plugins/cross_cluster_replication/public/plugin.ts +++ b/x-pack/plugins/cross_cluster_replication/public/plugin.ts @@ -63,14 +63,16 @@ export class CrossClusterReplicationPlugin implements Plugin { }, }); - const config = this.initializerContext.config.get(); - + // NOTE: We enable the plugin by default instead of disabling it by default because this + // creates a race condition that causes functional tests to fail on CI (see #66781). licensing.license$ .pipe(first()) .toPromise() .then((license) => { const licenseStatus = license.check(PLUGIN.ID, PLUGIN.minimumLicenseType); const isLicenseOk = licenseStatus.state === 'valid'; + const config = this.initializerContext.config.get(); + // remoteClusters.isUiEnabled is driven by the xpack.remote_clusters.ui.enabled setting. // The CCR UI depends upon the Remote Clusters UI (e.g. by cross-linking to it), so if // the Remote Clusters UI is disabled we can't show the CCR UI. From 2efa4db3394c6dcb034c3189815213b9a230cdb4 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 1 Jun 2020 20:43:10 +0300 Subject: [PATCH 82/93] revert some changes in APM --- x-pack/plugins/apm/public/application/index.tsx | 7 ++++--- .../apm/public/components/app/Main/route_config/index.tsx | 7 ------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/apm/public/application/index.tsx b/x-pack/plugins/apm/public/application/index.tsx index d91ac460277ba..cb8600ed2c214 100644 --- a/x-pack/plugins/apm/public/application/index.tsx +++ b/x-pack/plugins/apm/public/application/index.tsx @@ -9,7 +9,6 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { Route, Router, Switch } from 'react-router-dom'; import styled from 'styled-components'; -import { ScopedHistory } from 'kibana/public'; import { CoreStart, AppMountParameters } from '../../../../../src/core/public'; import { ApmPluginSetupDeps } from '../plugin'; import { ApmPluginContext } from '../context/ApmPluginContext'; @@ -25,6 +24,7 @@ import { UpdateBreadcrumbs } from '../components/app/Main/UpdateBreadcrumbs'; import { APMIndicesPermission } from '../components/app/APMIndicesPermission'; import { ScrollToTopOnPathChange } from '../components/app/Main/ScrollToTopOnPathChange'; import { routes } from '../components/app/Main/route_config'; +import { history, resetHistory } from '../utils/history'; import { ConfigSchema } from '..'; import 'react-vis/dist/style.css'; @@ -58,7 +58,7 @@ const ApmAppRoot = ({ }: { core: CoreStart; deps: ApmPluginSetupDeps; - routerHistory: ScopedHistory; + routerHistory: typeof history; config: ConfigSchema; }) => { const i18nCore = core.i18n; @@ -108,9 +108,10 @@ const ApmAppRoot = ({ export const renderApp = ( core: CoreStart, deps: ApmPluginSetupDeps, - { element, history }: AppMountParameters, + { element }: AppMountParameters, config: ConfigSchema ) => { + resetHistory(); ReactDOM.render( { }; export const routes: BreadcrumbRoute[] = [ - { - exact: true, - path: '', - render: renderAsRedirectTo('/services'), - breadcrumb: 'APM', - name: RouteName.HOME, - }, { exact: true, path: '/', From 66f795fe9b4076ded59e8cde000b2639f002a83b Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 2 Jun 2020 15:26:37 +0300 Subject: [PATCH 83/93] add space between index pattern name and tags --- .../index_pattern_table.tsx | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx index ae09f624251c0..947882b8df495 100644 --- a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx +++ b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx @@ -27,6 +27,7 @@ import { EuiPanel, EuiSpacer, EuiText, + EuiBadgeGroup, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { withRouter, RouteComponentProps } from 'react-router-dom'; @@ -125,15 +126,19 @@ export const IndexPatternTable = ({ canSave, history }: Props) => { }>; } ) => ( - - {name} - {index.tags && - index.tags.map(({ key: tagKey, name: tagName }) => ( - - {tagName} - - ))} - + <> + + {name} + + + {index.tags && + index.tags.map(({ key: tagKey, name: tagName }) => ( + + {tagName} + + ))} + + ), dataType: 'string' as const, sortable: ({ sort }: { sort: string }) => sort, From 6f1f56035d0560fd0ed446a21da884f0d78ec39f Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 2 Jun 2020 18:38:56 +0300 Subject: [PATCH 84/93] fix function test --- test/functional/page_objects/settings_page.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/functional/page_objects/settings_page.ts b/test/functional/page_objects/settings_page.ts index 9cf7a48cb3d88..f5b4eb7ad5de8 100644 --- a/test/functional/page_objects/settings_page.ts +++ b/test/functional/page_objects/settings_page.ts @@ -300,7 +300,9 @@ export function SettingsPageProvider({ getService, getPageObjects }: FtrProvider async getIndexPatternList() { await testSubjects.existOrFail('indexPatternTable', { timeout: 5000 }); - return await find.allByCssSelector('[data-test-subj="indexPatternTable"] .euiTable a'); + return await find.allByCssSelector( + '[data-test-subj="indexPatternTable"] .euiTable .euiTableRow' + ); } async isIndexPatternListEmpty() { From 7129133a534727bdcc2094ddc18b1e656666b498 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 3 Jun 2020 09:30:41 +0300 Subject: [PATCH 85/93] Update x-pack/plugins/security/public/management/management_urls.ts Co-authored-by: Joe Portner <5295965+jportner@users.noreply.github.com> --- x-pack/plugins/security/public/management/management_urls.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/x-pack/plugins/security/public/management/management_urls.ts b/x-pack/plugins/security/public/management/management_urls.ts index d113c13f63f72..e278f34acacfe 100644 --- a/x-pack/plugins/security/public/management/management_urls.ts +++ b/x-pack/plugins/security/public/management/management_urls.ts @@ -4,9 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -// const MANAGEMENT_PATH = '/management'; -// const SECURITY_PATH = `${MANAGEMENT_PATH}/security`; -// export const ROLES_PATH = `/roles`; export const EDIT_ROLES_PATH = `/edit`; export const CLONE_ROLES_PATH = `/clone`; export const USERS_PATH = `../users`; From 88c584dbba4b6d3b26ea0d1d03997f8391fe4575 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 3 Jun 2020 09:30:58 +0300 Subject: [PATCH 86/93] Update x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx Co-authored-by: Joe Portner <5295965+jportner@users.noreply.github.com> --- .../public/management/api_keys/api_keys_management_app.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx index 444089c9e0f4e..5f2f860fa73da 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx @@ -25,7 +25,7 @@ export const apiKeysManagementApp = Object.freeze({ title: i18n.translate('xpack.security.management.apiKeysTitle', { defaultMessage: 'API Keys', }), - async mount({ basePath, element, setBreadcrumbs, history }) { + async mount({ element, setBreadcrumbs }) { setBreadcrumbs([ { text: i18n.translate('xpack.security.apiKeys.breadcrumb', { From 573017682c91fc4350dd864fd77c6383c52989eb Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 3 Jun 2020 09:31:56 +0300 Subject: [PATCH 87/93] Update x-pack/plugins/spaces/public/management/spaces_management_app.tsx Co-authored-by: Joe Portner <5295965+jportner@users.noreply.github.com> --- .../plugins/spaces/public/management/spaces_management_app.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx index 050babdbc7b19..5b8b993d96adc 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx @@ -32,7 +32,7 @@ export const spacesManagementApp = Object.freeze({ title: i18n.translate('xpack.spaces.displayName', { defaultMessage: 'Spaces', }), - async mount({ basePath, element, setBreadcrumbs, history }) { + async mount({ element, setBreadcrumbs, history }) { const [ { notifications, i18n: i18nStart, application }, { features }, From 6ee39a888018a44ad1f99ed101ddb6190aa80633 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 3 Jun 2020 09:32:15 +0300 Subject: [PATCH 88/93] Update x-pack/plugins/security/public/management/roles/roles_management_app.tsx Co-authored-by: Joe Portner <5295965+jportner@users.noreply.github.com> --- .../security/public/management/roles/roles_management_app.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.tsx index 596f95a78bdfd..8891809d0b934 100644 --- a/x-pack/plugins/security/public/management/roles/roles_management_app.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_management_app.tsx @@ -27,7 +27,7 @@ export const rolesManagementApp = Object.freeze({ id: this.id, order: 20, title: i18n.translate('xpack.security.management.rolesTitle', { defaultMessage: 'Roles' }), - async mount({ basePath, element, setBreadcrumbs, history }) { + async mount({ element, setBreadcrumbs, history }) { const rolesBreadcrumbs = [ { text: i18n.translate('xpack.security.roles.breadcrumb', { defaultMessage: 'Roles' }), From 88b168d68cd69c4e868b22f5b5620adfb2be4b82 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 3 Jun 2020 09:32:41 +0300 Subject: [PATCH 89/93] Update x-pack/plugins/security/public/management/users/users_management_app.tsx Co-authored-by: Joe Portner <5295965+jportner@users.noreply.github.com> --- .../security/public/management/users/users_management_app.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security/public/management/users/users_management_app.tsx b/x-pack/plugins/security/public/management/users/users_management_app.tsx index a166deca26eb0..f73a419ed75f5 100644 --- a/x-pack/plugins/security/public/management/users/users_management_app.tsx +++ b/x-pack/plugins/security/public/management/users/users_management_app.tsx @@ -25,7 +25,7 @@ export const usersManagementApp = Object.freeze({ id: this.id, order: 10, title: i18n.translate('xpack.security.management.usersTitle', { defaultMessage: 'Users' }), - async mount({ basePath, element, setBreadcrumbs, history }) { + async mount({ element, setBreadcrumbs, history }) { const [coreStart] = await getStartServices(); const usersBreadcrumbs = [ { From 09f8ce614a67e913e921656a62af0185f898e032 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 3 Jun 2020 09:33:30 +0300 Subject: [PATCH 90/93] Update x-pack/plugins/security/public/management/management_urls.ts Co-authored-by: Joe Portner <5295965+jportner@users.noreply.github.com> --- x-pack/plugins/security/public/management/management_urls.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/security/public/management/management_urls.ts b/x-pack/plugins/security/public/management/management_urls.ts index e278f34acacfe..503b447b13969 100644 --- a/x-pack/plugins/security/public/management/management_urls.ts +++ b/x-pack/plugins/security/public/management/management_urls.ts @@ -9,7 +9,6 @@ export const CLONE_ROLES_PATH = `/clone`; export const USERS_PATH = `../users`; export const EDIT_USERS_PATH = `${USERS_PATH}/edit`; -export const getEditRoleHref = (roleName: string) => `../roles/edit/${encodeURIComponent(roleName)}`; export const getEditRoleMappingHref = (roleMappingName: string) => From 0f6774ffd2f58906197345db4f6eec1e541368b3 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 3 Jun 2020 10:58:16 +0300 Subject: [PATCH 91/93] Update x-pack/plugins/security/public/management/management_urls.ts Co-authored-by: Joe Portner <5295965+jportner@users.noreply.github.com> --- x-pack/plugins/security/public/management/management_urls.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/x-pack/plugins/security/public/management/management_urls.ts b/x-pack/plugins/security/public/management/management_urls.ts index 503b447b13969..713f4096c6023 100644 --- a/x-pack/plugins/security/public/management/management_urls.ts +++ b/x-pack/plugins/security/public/management/management_urls.ts @@ -9,7 +9,5 @@ export const CLONE_ROLES_PATH = `/clone`; export const USERS_PATH = `../users`; export const EDIT_USERS_PATH = `${USERS_PATH}/edit`; - `../roles/edit/${encodeURIComponent(roleName)}`; - export const getEditRoleMappingHref = (roleMappingName: string) => `${EDIT_ROLES_PATH}/${encodeURIComponent(roleMappingName)}`; From 2d37347c4069a01214994de087dfd01585934843 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 3 Jun 2020 12:57:03 +0300 Subject: [PATCH 92/93] [security] getUrlForApp -> navigateToApp --- .../api_keys_grid/api_keys_grid_page.test.tsx | 6 ++- .../api_keys_grid/api_keys_grid_page.tsx | 4 +- .../empty_prompt/empty_prompt.tsx | 10 +++-- .../api_keys/api_keys_management_app.tsx | 2 +- .../public/management/management_urls.ts | 7 +-- .../create_role_mapping_button.tsx | 4 +- .../role_mappings_grid_page.test.tsx | 31 ++++++------- .../role_mappings_grid_page.tsx | 9 ++-- .../role_mappings_management_app.tsx | 2 +- .../role_table_display/role_table_display.tsx | 23 ++++------ .../users/users_grid/users_grid_page.test.tsx | 43 ++++++++++--------- .../users/users_grid/users_grid_page.tsx | 5 +-- .../management/users/users_management_app.tsx | 2 +- .../functional/apps/security/management.js | 14 +++--- 14 files changed, 80 insertions(+), 82 deletions(-) diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx index 4a1fa75c5ec7a..94f9de010cc2a 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx @@ -64,11 +64,13 @@ describe('APIKeysGridPage', () => { }); }); + const coreStart = coreMock.createStart(); + const getViewProperties = () => { - const { docLinks, notifications } = coreMock.createStart(); + const { docLinks, notifications, application } = coreStart; return { - getUrlForApp: (id: string) => id, docLinks: new DocumentationLinksService(docLinks), + navigateToApp: application.navigateToApp, notifications, apiKeysAPIClient: apiClientMock, }; diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx index fe1e10b68d0fe..1ee1adf41a156 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx @@ -40,7 +40,7 @@ interface Props { notifications: NotificationsStart; docLinks: DocumentationLinksService; apiKeysAPIClient: PublicMethodsOf; - getUrlForApp: ApplicationStart['getUrlForApp']; + navigateToApp: ApplicationStart['navigateToApp']; } interface State { @@ -141,7 +141,7 @@ export class APIKeysGridPage extends Component { ); diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/empty_prompt.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/empty_prompt.tsx index b688a017e4540..9b2ccfcb99ef3 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/empty_prompt.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/empty_prompt.tsx @@ -14,13 +14,13 @@ import { DocumentationLinksService } from '../../documentation_links'; interface Props { isAdmin: boolean; docLinks: DocumentationLinksService; - getUrlForApp: ApplicationStart['getUrlForApp']; + navigateToApp: ApplicationStart['navigateToApp']; } export const EmptyPrompt: React.FunctionComponent = ({ isAdmin, docLinks, - getUrlForApp, + navigateToApp, }) => ( = ({ } actions={ - + navigateToApp('dev_tools')} + data-test-subj="goToConsoleButton" + > - `${EDIT_ROLES_PATH}/${encodeURIComponent(roleMappingName)}`; + `${EDIT_ROLE_MAPPING_PATH}/${encodeURIComponent(roleMappingName)}`; diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx index 6726ee1bdac29..7330dba968162 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { ScopedHistory } from 'kibana/public'; -import { EDIT_ROLES_PATH } from '../../../management_urls'; +import { EDIT_ROLE_MAPPING_PATH } from '../../../management_urls'; import { reactRouterNavigate } from '../../../../../../../../src/plugins/kibana_react/public'; interface CreateRoleMappingButtonProps { @@ -19,7 +19,7 @@ export const CreateRoleMappingButton = ({ history }: CreateRoleMappingButtonProp return ( { - const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; - const getUrlForApp = (appId: string, options?: { path: string }) => { - return appId + '/' + (options ? options.path : ''); - }; + let history: ScopedHistory; + let coreStart: CoreStart; + + beforeEach(() => { + history = (scopedHistoryMock.create() as unknown) as ScopedHistory; + coreStart = coreMock.createStart(); + }); it('renders an empty prompt when no role mappings exist', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); @@ -41,7 +44,7 @@ describe('RoleMappingsGridPage', () => { notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} history={history} - getUrlForApp={getUrlForApp} + navigateToApp={coreStart.application.navigateToApp} /> ); expect(wrapper.find(SectionLoading)).toHaveLength(1); @@ -70,7 +73,7 @@ describe('RoleMappingsGridPage', () => { notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} history={history} - getUrlForApp={getUrlForApp} + navigateToApp={coreStart.application.navigateToApp} /> ); expect(wrapper.find(SectionLoading)).toHaveLength(1); @@ -107,7 +110,7 @@ describe('RoleMappingsGridPage', () => { notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} history={history} - getUrlForApp={getUrlForApp} + navigateToApp={coreStart.application.navigateToApp} /> ); expect(wrapper.find(SectionLoading)).toHaveLength(1); @@ -143,7 +146,7 @@ describe('RoleMappingsGridPage', () => { notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} history={history} - getUrlForApp={getUrlForApp} + navigateToApp={coreStart.application.navigateToApp} /> ); await nextTick(); @@ -151,9 +154,7 @@ describe('RoleMappingsGridPage', () => { const links = findTestSubject(wrapper, 'roleMappingRoles').find(EuiLink); expect(links).toHaveLength(1); - expect(links.at(0).props()).toMatchObject({ - href: 'management/security/roles/edit/superuser', - }); + expect(links.at(0).props().onClick).toBeDefined(); }); it('describes the number of mapped role templates', async () => { @@ -179,7 +180,7 @@ describe('RoleMappingsGridPage', () => { notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} history={history} - getUrlForApp={getUrlForApp} + navigateToApp={coreStart.application.navigateToApp} /> ); await nextTick(); @@ -219,7 +220,7 @@ describe('RoleMappingsGridPage', () => { notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} history={history} - getUrlForApp={getUrlForApp} + navigateToApp={coreStart.application.navigateToApp} /> ); await nextTick(); @@ -282,7 +283,7 @@ describe('RoleMappingsGridPage', () => { notifications={notifications} docLinks={new DocumentationLinksService(docLinks)} history={history} - getUrlForApp={getUrlForApp} + navigateToApp={coreStart.application.navigateToApp} /> ); await nextTick(); diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx index a6dabb963871d..757e59a4e0583 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx @@ -33,7 +33,7 @@ import { PermissionDenied, SectionLoading, } from '../components'; -import { EDIT_ROLES_PATH, getEditRoleMappingHref } from '../../management_urls'; +import { EDIT_ROLE_MAPPING_PATH, getEditRoleMappingHref } from '../../management_urls'; import { DocumentationLinksService } from '../documentation_links'; import { RoleMappingsAPIClient } from '../role_mappings_api_client'; import { RoleTableDisplay } from '../../role_table_display'; @@ -47,7 +47,7 @@ interface Props { notifications: NotificationsStart; docLinks: DocumentationLinksService; history: ScopedHistory; - getUrlForApp: ApplicationStart['getUrlForApp']; + navigateToApp: ApplicationStart['navigateToApp']; } interface State { @@ -165,7 +165,7 @@ export class RoleMappingsGridPage extends Component { { ); }); diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx index 18aa8e80595ad..bca3a070e64f9 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx @@ -62,7 +62,7 @@ export const roleMappingsManagementApp = Object.freeze({ roleMappingsAPI={roleMappingsAPIClient} docLinks={dockLinksService} history={history} - getUrlForApp={coreStart.application.getUrlForApp} + navigateToApp={coreStart.application.navigateToApp} /> ); }; diff --git a/x-pack/plugins/security/public/management/role_table_display/role_table_display.tsx b/x-pack/plugins/security/public/management/role_table_display/role_table_display.tsx index d94a6045df74b..c1349eba9cddc 100644 --- a/x-pack/plugins/security/public/management/role_table_display/role_table_display.tsx +++ b/x-pack/plugins/security/public/management/role_table_display/role_table_display.tsx @@ -6,23 +6,20 @@ import React from 'react'; import { EuiLink, EuiToolTip, EuiIcon } from '@elastic/eui'; -import { ScopedHistory, ApplicationStart } from 'kibana/public'; +import { ApplicationStart } from 'kibana/public'; import { Role, isRoleDeprecated, getExtendedRoleDeprecationNotice } from '../../../common/model'; interface Props { role: Role | string; - history: ScopedHistory; - getUrlForApp: ApplicationStart['getUrlForApp']; + navigateToApp: ApplicationStart['navigateToApp']; } -export const RoleTableDisplay = ({ role, history, getUrlForApp }: Props) => { +export const RoleTableDisplay = ({ role, navigateToApp }: Props) => { let content; - let href; + let path: string; if (typeof role === 'string') { content =
{role}
; - href = getUrlForApp('management', { - path: `security/roles/edit/${encodeURIComponent(role)}`, - }); + path = `security/roles/edit/${encodeURIComponent(role)}`; } else if (isRoleDeprecated(role)) { content = ( {
); - href = getUrlForApp('management', { - path: `security/roles/edit/${encodeURIComponent(role.name)}`, - }); + path = `security/roles/edit/${encodeURIComponent(role.name)}`; } else { content =
{role.name}
; - href = getUrlForApp('management', { - path: `security/roles/edit/${encodeURIComponent(role.name)}`, - }); + path = `security/roles/edit/${encodeURIComponent(role.name)}`; } - return {content}; + return navigateToApp('management', { path })}>{content}; }; diff --git a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx index 8f27511330efd..edce7409e28d5 100644 --- a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { LocationDescriptorObject } from 'history'; -import { ScopedHistory } from 'kibana/public'; +import { CoreStart, ScopedHistory } from 'kibana/public'; import { User } from '../../../../common/model'; import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; @@ -18,13 +18,16 @@ import { findTestSubject } from 'test_utils/find_test_subject'; import { EuiBasicTable } from '@elastic/eui'; describe('UsersGridPage', () => { - const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; - history.createHref = (location: LocationDescriptorObject) => { - return `${location.pathname}${location.search ? '?' + location.search : ''}`; - }; - const getUrlForApp = (appId: string, options?: { path: string }) => { - return appId + '/' + (options ? options.path : ''); - }; + let history: ScopedHistory; + let coreStart: CoreStart; + + beforeEach(() => { + history = (scopedHistoryMock.create() as unknown) as ScopedHistory; + history.createHref = (location: LocationDescriptorObject) => { + return `${location.pathname}${location.search ? '?' + location.search : ''}`; + }; + coreStart = coreMock.createStart(); + }); it('renders the list of users', async () => { const apiClientMock = userAPIClientMock.create(); @@ -54,9 +57,9 @@ describe('UsersGridPage', () => { ); @@ -76,9 +79,9 @@ describe('UsersGridPage', () => { ); @@ -107,9 +110,9 @@ describe('UsersGridPage', () => { ); @@ -141,9 +144,9 @@ describe('UsersGridPage', () => { ); @@ -191,9 +194,9 @@ describe('UsersGridPage', () => { ); @@ -251,9 +254,9 @@ describe('UsersGridPage', () => { ); diff --git a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx index 6b2f98e9263ec..50815808c4859 100644 --- a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx +++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx @@ -38,7 +38,7 @@ interface Props { rolesAPIClient: PublicMethodsOf; notifications: NotificationsStart; history: ScopedHistory; - getUrlForApp: ApplicationStart['getUrlForApp']; + navigateToApp: ApplicationStart['navigateToApp']; } interface State { @@ -154,8 +154,7 @@ export class UsersGridPage extends Component { ); }); diff --git a/x-pack/plugins/security/public/management/users/users_management_app.tsx b/x-pack/plugins/security/public/management/users/users_management_app.tsx index f73a419ed75f5..82c55d67b9026 100644 --- a/x-pack/plugins/security/public/management/users/users_management_app.tsx +++ b/x-pack/plugins/security/public/management/users/users_management_app.tsx @@ -58,7 +58,7 @@ export const usersManagementApp = Object.freeze({ userAPIClient={userAPIClient} rolesAPIClient={rolesAPIClient} history={history} - getUrlForApp={coreStart.application.getUrlForApp} + navigateToApp={coreStart.application.navigateToApp} /> ); }; diff --git a/x-pack/test/functional/apps/security/management.js b/x-pack/test/functional/apps/security/management.js index d761f4d1f785c..c263b26406857 100644 --- a/x-pack/test/functional/apps/security/management.js +++ b/x-pack/test/functional/apps/security/management.js @@ -5,13 +5,6 @@ */ import expect from '@kbn/expect'; -import { - USERS_PATH, - EDIT_USERS_PATH, - ROLES_PATH, - EDIT_ROLES_PATH, - CLONE_ROLES_PATH, -} from '../../../../plugins/security/public/management/management_urls'; export default function ({ getService, getPageObjects }) { const kibanaServer = getService('kibanaServer'); @@ -19,6 +12,13 @@ export default function ({ getService, getPageObjects }) { const browser = getService('browser'); const PageObjects = getPageObjects(['security', 'settings', 'common', 'header']); + const USERS_PATH = 'security/users'; + const EDIT_USERS_PATH = `${USERS_PATH}/edit`; + + const ROLES_PATH = 'security/roles'; + const EDIT_ROLES_PATH = `${ROLES_PATH}/edit`; + const CLONE_ROLES_PATH = `${ROLES_PATH}/clone`; + // FLAKY: https://github.com/elastic/kibana/issues/61173 describe.skip('Management', function () { this.tags(['skipFirefox']); From 155c65fef04df57a84993cd4cff968c94bafca3f Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 3 Jun 2020 14:22:34 +0300 Subject: [PATCH 93/93] [mp] fix Uncaught (in promise) undefined --- .../public/application/management/jobs_list/index.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/x-pack/plugins/ml/public/application/management/jobs_list/index.ts b/x-pack/plugins/ml/public/application/management/jobs_list/index.ts index cfe37ce14bb78..5d1fc6f0a3c92 100644 --- a/x-pack/plugins/ml/public/application/management/jobs_list/index.ts +++ b/x-pack/plugins/ml/public/application/management/jobs_list/index.ts @@ -11,12 +11,14 @@ import { ManagementAppMountParams } from '../../../../../../../src/plugins/manag import { MlStartDependencies } from '../../../plugin'; import { JobsListPage } from './components'; import { getJobsListBreadcrumbs } from '../breadcrumbs'; +import { setDependencyCache, clearCache } from '../../util/dependency_cache'; const renderApp = (element: HTMLElement, coreStart: CoreStart) => { const I18nContext = coreStart.i18n.Context; ReactDOM.render(React.createElement(JobsListPage, { I18nContext }), element); return () => { unmountComponentAtNode(element); + clearCache(); }; }; @@ -25,6 +27,15 @@ export async function mountApp( params: ManagementAppMountParams ) { const [coreStart] = await core.getStartServices(); + + setDependencyCache({ + docLinks: coreStart.docLinks!, + basePath: coreStart.http.basePath, + http: coreStart.http, + i18n: coreStart.i18n, + }); + params.setBreadcrumbs(getJobsListBreadcrumbs()); + return renderApp(params.element, coreStart); }