From 94a42b71b3004b365eb7434db1fe061bd75c44a3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Yulia=20=C4=8Cech?=
<6585477+yuliacech@users.noreply.github.com>
Date: Tue, 10 Nov 2020 11:09:37 +0100
Subject: [PATCH] Fix ilm navigation (#81664)
* Fix edit policy page navigation
* Fix edit policy page navigation
* Add links to PR for explanation
* Added more tests and linked to a github issue about navigation issues
* Fix decoding function for undefined values
* Fix type check issues
* Renamed dollar sign to percent sign, added a method for (double) encoded paths and better description in test names
* Deleted Index Management from required bundles in ILM
* Fixed merge conflicts
* Revert "Deleted Index Management from required bundles in ILM"
This reverts commit 5a735dfe
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../public/url/attempt_to_uri_decode.test.ts | 49 +++-
.../public/url/attempt_to_uri_decode.ts | 8 +-
.../client_integration/app/app.helpers.tsx | 74 +++++
.../client_integration/app/app.test.ts | 252 ++++++++++++++++++
.../edit_policy/constants.ts | 20 ++
.../edit_policy/edit_policy.test.ts | 3 +-
.../client_integration/helpers/index.ts | 3 +
.../public/application/app.tsx | 40 +--
.../public/application/index.tsx | 8 +-
.../edit_policy/edit_policy.container.tsx | 6 +-
.../sections/edit_policy/edit_policy.tsx | 2 +-
.../public/shared_imports.ts | 2 +
.../component_template_details.tsx | 2 +-
.../component_template_list.tsx | 6 +-
.../component_template_clone.tsx | 2 +-
.../component_template_edit.tsx | 2 +-
.../data_stream_list/data_stream_list.tsx | 2 +-
.../home/template_list/template_list.tsx | 2 +-
.../template_clone/template_clone.tsx | 2 +-
.../sections/template_edit/template_edit.tsx | 2 +-
.../pipelines_clone/pipelines_clone.tsx | 2 +-
.../pipelines_edit/pipelines_edit.tsx | 2 +-
22 files changed, 448 insertions(+), 43 deletions(-)
create mode 100644 x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.helpers.tsx
create mode 100644 x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.test.ts
diff --git a/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.test.ts b/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.test.ts
index 15750c7667800..6654611faa18b 100644
--- a/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.test.ts
+++ b/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.test.ts
@@ -19,14 +19,51 @@
import { attemptToURIDecode } from './attempt_to_uri_decode';
+// this function doesn't work for % with other special chars or sequence %25
+// known issue https://github.com/elastic/kibana/issues/82440
test('decodes an encoded string', () => {
- const encodedString = 'test%3F';
- expect(attemptToURIDecode(encodedString)).toBe('test?');
+ const originalName = 'test;,/?:@&=+$#';
+ const encodedName = encodeURIComponent(originalName);
+ // react router v5 automatically decodes route match params
+ const reactRouterDecoded = decodeURI(encodedName);
+
+ expect(attemptToURIDecode(encodedName)).toBe(originalName);
+ expect(attemptToURIDecode(reactRouterDecoded)).toBe(originalName);
});
-// react router partially decodes %25 sequence to % in match params
-// https://github.com/elastic/kibana/pull/81664
test('ignores the error if a string is already decoded', () => {
- const decodedString = 'test%';
- expect(attemptToURIDecode(decodedString)).toBe(decodedString);
+ const originalName = 'test%';
+
+ const encodedName = encodeURIComponent(originalName);
+ // react router v5 automatically decodes route match params
+ const reactRouterDecoded = decodeURI(encodedName);
+
+ expect(attemptToURIDecode(encodedName)).toBe(originalName);
+ expect(attemptToURIDecode(reactRouterDecoded)).toBe(originalName);
+});
+
+test('returns wrong decoded value for %25 sequence', () => {
+ const originalName = 'test%25';
+
+ const encodedName = encodeURIComponent(originalName);
+ // react router v5 automatically decodes route match params
+ const reactRouterDecoded = decodeURI(encodedName);
+
+ expect(attemptToURIDecode(encodedName)).toBe(originalName);
+ expect(attemptToURIDecode(reactRouterDecoded)).not.toBe(originalName);
+});
+
+test('returns wrong decoded value for % with other escaped characters', () => {
+ const originalName = 'test%?#';
+
+ const encodedName = encodeURIComponent(originalName);
+ // react router v5 automatically decodes route match params
+ const reactRouterDecoded = decodeURI(encodedName);
+
+ expect(attemptToURIDecode(encodedName)).toBe(originalName);
+ expect(attemptToURIDecode(reactRouterDecoded)).not.toBe(originalName);
+});
+
+test("doesn't convert undefined to a string", () => {
+ expect(attemptToURIDecode(undefined)).toBeUndefined();
});
diff --git a/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.ts b/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.ts
index 65444b83f77bb..37e4761106e44 100644
--- a/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.ts
+++ b/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.ts
@@ -19,12 +19,14 @@
/*
* Use this function with any match params coming from react router to safely decode values.
- * https://github.com/elastic/kibana/pull/81664
+ * After an update to react router v6, this functions should be deprecated.
+ * Known issue for navigation with special characters in paths
+ * https://github.com/elastic/kibana/issues/82440
*/
-export const attemptToURIDecode = (value: string) => {
+export const attemptToURIDecode = (value?: string): string | undefined => {
let result = value;
try {
- result = decodeURIComponent(value);
+ result = value ? decodeURIComponent(value) : value;
} catch (e) {
// do nothing
}
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.helpers.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.helpers.tsx
new file mode 100644
index 0000000000000..de7242a6c5ddf
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.helpers.tsx
@@ -0,0 +1,74 @@
+/*
+ * 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 React from 'react';
+import { act } from 'react-dom/test-utils';
+import { registerTestBed, TestBed, TestBedConfig } from '../../../../../test_utils';
+import { App } from '../../../public/application/app';
+import { TestSubjects } from '../helpers';
+import { createBreadcrumbsMock } from '../../../public/application/services/breadcrumbs.mock';
+import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public/context';
+
+const breadcrumbService = createBreadcrumbsMock();
+
+const AppWithContext = (props: any) => {
+ return (
+
+
+
+ );
+};
+
+const getTestBedConfig = (initialEntries: string[]): TestBedConfig => ({
+ memoryRouter: {
+ initialEntries,
+ },
+ defaultProps: {
+ getUrlForApp: () => {},
+ navigateToApp: () => {},
+ },
+});
+
+const initTestBed = (initialEntries: string[]) =>
+ registerTestBed(AppWithContext, getTestBedConfig(initialEntries))();
+
+export interface AppTestBed extends TestBed {
+ actions: {
+ clickPolicyNameLink: () => void;
+ clickCreatePolicyButton: () => void;
+ };
+}
+
+export const setup = async (initialEntries: string[]): Promise => {
+ const testBed = await initTestBed(initialEntries);
+
+ const clickPolicyNameLink = async () => {
+ const { component, find } = testBed;
+ await act(async () => {
+ find('policyTablePolicyNameLink').simulate('click', { button: 0 });
+ });
+ component.update();
+ };
+
+ const clickCreatePolicyButton = async () => {
+ const { component, find } = testBed;
+ await act(async () => {
+ find('createPolicyButton').simulate('click', { button: 0 });
+ });
+ component.update();
+ };
+
+ return {
+ ...testBed,
+ actions: { clickPolicyNameLink, clickCreatePolicyButton },
+ };
+};
+
+export const getEncodedPolicyEditPath = (policyName: string): string =>
+ `/policies/edit/${encodeURIComponent(policyName)}`;
+
+export const getDoubleEncodedPolicyEditPath = (policyName: string): string =>
+ encodeURI(getEncodedPolicyEditPath(policyName));
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.test.ts
new file mode 100644
index 0000000000000..9052cf2847baa
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.test.ts
@@ -0,0 +1,252 @@
+/*
+ * 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 {
+ AppTestBed,
+ getDoubleEncodedPolicyEditPath,
+ getEncodedPolicyEditPath,
+ setup,
+} from './app.helpers';
+import { setupEnvironment } from '../helpers/setup_environment';
+import { getDefaultHotPhasePolicy, POLICY_NAME } from '../edit_policy/constants';
+import { act } from 'react-dom/test-utils';
+
+const SPECIAL_CHARS_NAME = 'test?#$+=&@:';
+const PERCENT_SIGN_NAME = 'test%';
+// navigation doesn't work for % with other special chars or sequence %25
+// known issue https://github.com/elastic/kibana/issues/82440
+const PERCENT_SIGN_WITH_OTHER_CHARS_NAME = 'test%#';
+const PERCENT_SIGN_25_SEQUENCE = 'test%25';
+
+window.scrollTo = jest.fn();
+
+describe('', () => {
+ let testBed: AppTestBed;
+ const { server, httpRequestsMockHelpers } = setupEnvironment();
+ afterAll(() => {
+ server.restore();
+ });
+
+ describe('new policy creation', () => {
+ test('when there are no policies', async () => {
+ httpRequestsMockHelpers.setLoadPolicies([]);
+ await act(async () => {
+ testBed = await setup(['/']);
+ });
+
+ const { component, actions } = testBed;
+ component.update();
+
+ await actions.clickCreatePolicyButton();
+ component.update();
+
+ expect(testBed.find('policyTitle').text()).toBe(`Create an index lifecycle policy`);
+ expect(testBed.find('policyNameField').props().value).toBe('');
+ });
+
+ test('when there are policies', async () => {
+ httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy(POLICY_NAME)]);
+ await act(async () => {
+ testBed = await setup(['/']);
+ });
+
+ const { component, actions } = testBed;
+ component.update();
+
+ await actions.clickCreatePolicyButton();
+ component.update();
+
+ expect(testBed.find('policyTitle').text()).toBe(`Create an index lifecycle policy`);
+ expect(testBed.find('policyNameField').props().value).toBe('');
+ });
+ });
+
+ describe('navigation with special characters', () => {
+ beforeAll(async () => {
+ httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy(SPECIAL_CHARS_NAME)]);
+ });
+
+ test('clicking policy name in the table works', async () => {
+ await act(async () => {
+ testBed = await setup(['/']);
+ });
+
+ const { component, actions } = testBed;
+ component.update();
+
+ await actions.clickPolicyNameLink();
+ component.update();
+
+ expect(testBed.find('policyTitle').text()).toBe(
+ `Edit index lifecycle policy ${SPECIAL_CHARS_NAME}`
+ );
+ });
+
+ test('loading edit policy page url works', async () => {
+ await act(async () => {
+ testBed = await setup([getEncodedPolicyEditPath(SPECIAL_CHARS_NAME)]);
+ });
+
+ const { component } = testBed;
+ component.update();
+
+ expect(testBed.find('policyTitle').text()).toBe(
+ `Edit index lifecycle policy ${SPECIAL_CHARS_NAME}`
+ );
+ });
+
+ // using double encoding to counteract react-router's v5 internal decodeURI call
+ // when those links are open in a new tab, address bar contains double encoded url
+ test('loading edit policy page url with double encoding works', async () => {
+ await act(async () => {
+ testBed = await setup([getDoubleEncodedPolicyEditPath(SPECIAL_CHARS_NAME)]);
+ });
+
+ const { component } = testBed;
+ component.update();
+
+ expect(testBed.find('policyTitle').text()).toBe(
+ `Edit index lifecycle policy ${SPECIAL_CHARS_NAME}`
+ );
+ });
+ });
+
+ describe('navigation with percent sign', () => {
+ beforeAll(async () => {
+ httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy(PERCENT_SIGN_NAME)]);
+ });
+
+ test('loading edit policy page url works', async () => {
+ await act(async () => {
+ testBed = await setup([getEncodedPolicyEditPath(PERCENT_SIGN_NAME)]);
+ });
+
+ const { component } = testBed;
+ component.update();
+
+ expect(testBed.find('policyTitle').text()).toBe(
+ `Edit index lifecycle policy ${PERCENT_SIGN_NAME}`
+ );
+ });
+
+ test('loading edit policy page url with double encoding works', async () => {
+ await act(async () => {
+ testBed = await setup([getDoubleEncodedPolicyEditPath(PERCENT_SIGN_NAME)]);
+ });
+
+ const { component } = testBed;
+ component.update();
+
+ expect(testBed.find('policyTitle').text()).toBe(
+ `Edit index lifecycle policy ${PERCENT_SIGN_NAME}`
+ );
+ });
+ });
+
+ describe('navigation with percent sign with other special characters', () => {
+ beforeAll(async () => {
+ httpRequestsMockHelpers.setLoadPolicies([
+ getDefaultHotPhasePolicy(PERCENT_SIGN_WITH_OTHER_CHARS_NAME),
+ ]);
+ });
+
+ test('clicking policy name in the table works', async () => {
+ await act(async () => {
+ testBed = await setup(['/']);
+ });
+
+ const { component, actions } = testBed;
+ component.update();
+
+ await actions.clickPolicyNameLink();
+ component.update();
+
+ expect(testBed.find('policyTitle').text()).toBe(
+ `Edit index lifecycle policy ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}`
+ );
+ });
+
+ test("loading edit policy page url doesn't work", async () => {
+ await act(async () => {
+ testBed = await setup([getEncodedPolicyEditPath(PERCENT_SIGN_WITH_OTHER_CHARS_NAME)]);
+ });
+
+ const { component } = testBed;
+ component.update();
+
+ // known issue https://github.com/elastic/kibana/issues/82440
+ expect(testBed.find('policyTitle').text()).not.toBe(
+ `Edit index lifecycle policy ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}`
+ );
+ });
+
+ // using double encoding to counteract react-router's v5 internal decodeURI call
+ // when those links are open in a new tab, address bar contains double encoded url
+ test('loading edit policy page url with double encoding works', async () => {
+ await act(async () => {
+ testBed = await setup([getDoubleEncodedPolicyEditPath(PERCENT_SIGN_WITH_OTHER_CHARS_NAME)]);
+ });
+
+ const { component } = testBed;
+ component.update();
+
+ expect(testBed.find('policyTitle').text()).toBe(
+ `Edit index lifecycle policy ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}`
+ );
+ });
+ });
+
+ describe('navigation with %25 sequence', () => {
+ beforeAll(async () => {
+ httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy(PERCENT_SIGN_25_SEQUENCE)]);
+ });
+
+ test('clicking policy name in the table works correctly', async () => {
+ await act(async () => {
+ testBed = await setup(['/']);
+ });
+
+ const { component, actions } = testBed;
+ component.update();
+
+ await actions.clickPolicyNameLink();
+ component.update();
+
+ expect(testBed.find('policyTitle').text()).toBe(
+ `Edit index lifecycle policy ${PERCENT_SIGN_25_SEQUENCE}`
+ );
+ });
+
+ test("loading edit policy page url doesn't work", async () => {
+ await act(async () => {
+ testBed = await setup([getEncodedPolicyEditPath(PERCENT_SIGN_25_SEQUENCE)]);
+ });
+
+ const { component } = testBed;
+ component.update();
+
+ // known issue https://github.com/elastic/kibana/issues/82440
+ expect(testBed.find('policyTitle').text()).not.toBe(
+ `Edit index lifecycle policy ${PERCENT_SIGN_25_SEQUENCE}`
+ );
+ });
+
+ // using double encoding to counteract react-router's v5 internal decodeURI call
+ // when those links are open in a new tab, address bar contains double encoded url
+ test('loading edit policy page url with double encoding works', async () => {
+ await act(async () => {
+ testBed = await setup([getDoubleEncodedPolicyEditPath(PERCENT_SIGN_25_SEQUENCE)]);
+ });
+
+ const { component } = testBed;
+ component.update();
+
+ expect(testBed.find('policyTitle').text()).toBe(
+ `Edit index lifecycle policy ${PERCENT_SIGN_25_SEQUENCE}`
+ );
+ });
+ });
+});
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts
index 3d430cf31621e..00c7d705c1f44 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts
@@ -121,6 +121,26 @@ export const DELETE_PHASE_POLICY: PolicyFromES = {
name: POLICY_NAME,
};
+export const getDefaultHotPhasePolicy = (policyName: string): PolicyFromES => ({
+ version: 1,
+ modified_date: Date.now().toString(),
+ policy: {
+ name: policyName,
+ phases: {
+ hot: {
+ min_age: '0ms',
+ actions: {
+ rollover: {
+ max_age: '30d',
+ max_size: '50gb',
+ },
+ },
+ },
+ },
+ },
+ name: policyName,
+});
+
export const POLICY_WITH_NODE_ATTR_AND_OFF_ALLOCATION: PolicyFromES = {
version: 1,
modified_date: Date.now().toString(),
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts
index 4ee67d1ed8a19..c91ee3e2a1c06 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts
@@ -19,6 +19,7 @@ import {
POLICY_WITH_INCLUDE_EXCLUDE,
POLICY_WITH_NODE_ATTR_AND_OFF_ALLOCATION,
POLICY_WITH_NODE_ROLE_ALLOCATION,
+ getDefaultHotPhasePolicy,
} from './constants';
window.scrollTo = jest.fn();
@@ -33,7 +34,7 @@ describe('', () => {
describe('hot phase', () => {
describe('serialization', () => {
beforeEach(async () => {
- httpRequestsMockHelpers.setLoadPolicies([DEFAULT_POLICY]);
+ httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy('my_policy')]);
httpRequestsMockHelpers.setLoadSnapshotPolicies([]);
await act(async () => {
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts
index e8ebc2963d16a..aff9151da61f9 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts
@@ -17,5 +17,8 @@ export type TestSubjects =
| 'hot-selectedMaxDocuments'
| 'hot-selectedMaxAge'
| 'hot-selectedMaxAgeUnits'
+ | 'policyTablePolicyNameLink'
+ | 'policyTitle'
+ | 'createPolicyButton'
| 'freezeSwitch'
| string;
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 856981fe5c4f9..20185b02064bc 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/app.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/app.tsx
@@ -15,7 +15,7 @@ import { PolicyTable } from './sections/policy_table';
import { trackUiMetric } from './services/ui_metric';
import { ROUTES } from './services/navigation';
-export const App = ({
+export const AppWithRouter = ({
history,
navigateToApp,
getUrlForApp,
@@ -23,23 +23,33 @@ export const App = ({
history: ScopedHistory;
navigateToApp: ApplicationStart['navigateToApp'];
getUrlForApp: ApplicationStart['getUrlForApp'];
+}) => (
+
+
+
+);
+
+export const App = ({
+ navigateToApp,
+ getUrlForApp,
+}: {
+ navigateToApp: ApplicationStart['navigateToApp'];
+ getUrlForApp: ApplicationStart['getUrlForApp'];
}) => {
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 3d4cc7dbbd1d4..bb1a4810ba2d2 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/index.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/index.tsx
@@ -12,7 +12,7 @@ import { CloudSetup } from '../../../cloud/public';
import { KibanaContextProvider } from '../shared_imports';
-import { App } from './app';
+import { AppWithRouter } from './app';
import { BreadcrumbService } from './services/breadcrumbs';
@@ -28,7 +28,11 @@ export const renderApp = (
render(
-
+
,
element
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.container.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.container.tsx
index ebef80871b83d..4c0cc2c8957e1 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.container.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.container.tsx
@@ -9,7 +9,7 @@ import { RouteComponentProps } from 'react-router-dom';
import { EuiButton, EuiEmptyPrompt, EuiLoadingSpinner } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
-import { useKibana } from '../../../shared_imports';
+import { useKibana, attemptToURIDecode } from '../../../shared_imports';
import { useLoadPoliciesList } from '../../services/api';
import { getPolicyByName } from '../../lib/policies';
@@ -90,13 +90,13 @@ export const EditPolicy: React.FunctionComponent = ({ history }) => {
verticalPosition="center"
horizontalPosition="center"
>
-
+
{isNewPolicy
? i18n.translate('xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage', {
diff --git a/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts b/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts
index a127574d5bad0..a5844af0bf6dd 100644
--- a/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts
@@ -32,6 +32,8 @@ export {
TextField,
} from '../../../../src/plugins/es_ui_shared/static/forms/components';
+export { attemptToURIDecode } from '../../../../src/plugins/es_ui_shared/public';
+
export { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public';
export const useKibana = () => _useKibana();
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_details/component_template_details.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_details/component_template_details.tsx
index 6d9aa58d6c86b..2fb16874cf943 100644
--- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_details/component_template_details.tsx
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_details/component_template_details.tsx
@@ -52,7 +52,7 @@ export const ComponentTemplateDetailsFlyoutContent: React.FunctionComponent {
const { api } = useComponentTemplatesContext();
- const decodedComponentTemplateName = attemptToURIDecode(componentTemplateName);
+ const decodedComponentTemplateName = attemptToURIDecode(componentTemplateName)!;
const { data: componentTemplateDetails, isLoading, error } = api.useLoadComponentTemplate(
decodedComponentTemplateName
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx
index 00ea3ebf794ee..e8424ae46c6d2 100644
--- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx
@@ -84,7 +84,7 @@ export const ComponentTemplateList: React.FunctionComponent = ({
}),
icon: 'pencil',
handleActionClick: () =>
- goToEditComponentTemplate(attemptToURIDecode(componentTemplateName)),
+ goToEditComponentTemplate(attemptToURIDecode(componentTemplateName)!),
},
{
name: i18n.translate('xpack.idxMgmt.componentTemplateDetails.cloneActionLabel', {
@@ -92,7 +92,7 @@ export const ComponentTemplateList: React.FunctionComponent = ({
}),
icon: 'copy',
handleActionClick: () =>
- goToCloneComponentTemplate(attemptToURIDecode(componentTemplateName)),
+ goToCloneComponentTemplate(attemptToURIDecode(componentTemplateName)!),
},
{
name: i18n.translate('xpack.idxMgmt.componentTemplateDetails.deleteButtonLabel', {
@@ -103,7 +103,7 @@ export const ComponentTemplateList: React.FunctionComponent = ({
details._kbnMeta.usedBy.length > 0,
closePopoverOnClick: true,
handleActionClick: () => {
- setComponentTemplatesToDelete([attemptToURIDecode(componentTemplateName)]);
+ setComponentTemplatesToDelete([attemptToURIDecode(componentTemplateName)!]);
},
},
];
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_clone/component_template_clone.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_clone/component_template_clone.tsx
index 6c03fcf5d9972..e6b403543f4b0 100644
--- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_clone/component_template_clone.tsx
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_clone/component_template_clone.tsx
@@ -19,7 +19,7 @@ export interface Params {
export const ComponentTemplateClone: FunctionComponent> = (props) => {
const { sourceComponentTemplateName } = props.match.params;
- const decodedSourceName = attemptToURIDecode(sourceComponentTemplateName);
+ const decodedSourceName = attemptToURIDecode(sourceComponentTemplateName)!;
const { toasts, api } = useComponentTemplatesContext();
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx
index 934f86f7d7590..500c84a97d222 100644
--- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx
@@ -31,7 +31,7 @@ export const ComponentTemplateEdit: React.FunctionComponent(false);
const [saveError, setSaveError] = useState(null);
- const decodedName = attemptToURIDecode(name);
+ const decodedName = attemptToURIDecode(name)!;
const { error, data: componentTemplate, isLoading } = api.useLoadComponentTemplate(decodedName);
diff --git a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx
index ba79319b566bf..20b93d9d71d04 100644
--- a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx
+++ b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx
@@ -231,7 +231,7 @@ export const DataStreamList: React.FunctionComponent {
history.push(`/${Section.DataStreams}`);
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 f3e82223c30e6..3689a875e28b2 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
@@ -101,7 +101,7 @@ export const TemplateList: React.FunctionComponent {
- const decodedTemplateName = attemptToURIDecode(name);
+ const decodedTemplateName = attemptToURIDecode(name)!;
const isLegacy = getIsLegacyFromQueryParams(location);
const [isSaving, setIsSaving] = useState(false);
diff --git a/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx b/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx
index 3e62f7f880f74..e3cb40b3a36e1 100644
--- a/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx
+++ b/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx
@@ -27,7 +27,7 @@ export const TemplateEdit: React.FunctionComponent {
- const decodedTemplateName = attemptToURIDecode(name);
+ const decodedTemplateName = attemptToURIDecode(name)!;
const isLegacy = getIsLegacyFromQueryParams(location);
const [isSaving, setIsSaving] = useState(false);
diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_clone/pipelines_clone.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_clone/pipelines_clone.tsx
index 9465117b6b589..df60907973156 100644
--- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_clone/pipelines_clone.tsx
+++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_clone/pipelines_clone.tsx
@@ -25,7 +25,7 @@ export const PipelinesClone: FunctionComponent>
const { sourceName } = props.match.params;
const { services } = useKibana();
- const decodedSourceName = attemptToURIDecode(sourceName);
+ const decodedSourceName = attemptToURIDecode(sourceName)!;
const { error, data: pipeline, isLoading, isInitialRequest } = services.api.useLoadPipeline(
decodedSourceName
);
diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx
index 7e2e85ab23fb3..2b53fdb6a6375 100644
--- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx
+++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx
@@ -38,7 +38,7 @@ export const PipelinesEdit: React.FunctionComponent(false);
const [saveError, setSaveError] = useState(null);
- const decodedPipelineName = attemptToURIDecode(name);
+ const decodedPipelineName = attemptToURIDecode(name)!;
const { error, data: pipeline, isLoading } = services.api.useLoadPipeline(decodedPipelineName);