From f2f76e104af5d0515773c173475efda7d80c1d31 Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Mon, 9 Nov 2020 14:29:53 +0100
Subject: [PATCH] [ILM] Migrate Delete phase and name field to Form Lib
(#82834)
* remove use of legacy state system and legacy serialization
* remove legacy min_age input component and re-add missing import
* rename shared -> shared_fields for more clarity
* some more cleanup and fixing regressions on policy name for creating new policy from existing policy
* move extract policy static code to lib folder and remove "policies" dir from services
* fix jest tests and minor policy flyout inconsistency
* remove legacy helper
* fix client integration tests
* fix min for set index priority
* moved save policy function into edit policy section
* remove unused translations
* refactor form files to own edit_policy/form folder
* remove "fix errors" badge to fix UX - users can see errors in line before pressing save so the value of this badge has diminished
* fix i18n after removing phase error badge
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../edit_policy/edit_policy.helpers.tsx | 5 +
.../edit_policy/edit_policy.test.ts | 3 +-
.../__jest__/components/edit_policy.test.tsx | 242 ++++----
.../public/application/lib/policies.ts | 32 ++
.../sections/edit_policy/components/index.ts | 3 -
.../components/min_age_input_legacy.tsx | 263 ---------
.../components/phase_error_message.tsx | 19 -
.../phases/cold_phase/cold_phase.tsx | 23 +-
.../{ => delete_phase}/delete_phase.tsx | 94 +--
.../components/phases/delete_phase/index.ts | 7 +
.../components/phases/hot_phase/hot_phase.tsx | 12 +-
.../components/cloud_data_tier_callout.tsx | 0
.../components/data_tier_allocation.scss | 0
.../components/data_tier_allocation.tsx | 0
.../components/default_allocation_notice.tsx | 0
.../components/index.ts | 0
.../components/no_node_attributes_warning.tsx | 0
.../components/node_allocation.tsx | 9 +-
.../components/node_attrs_details.tsx | 0
.../components/node_data_provider.tsx | 0
.../components/types.ts | 0
.../data_tier_allocation_field.tsx | 0
.../data_tier_allocation_field/index.ts | 0
.../forcemerge_field.tsx | 6 +-
.../phases/{shared => shared_fields}/index.ts | 2 +
.../min_age_input_field/index.ts | 0
.../min_age_input_field.tsx | 0
.../min_age_input_field/util.ts | 0
.../set_priority_input.tsx | 9 +-
.../snapshot_policies_field.tsx} | 113 ++--
.../phases/warm_phase/warm_phase.tsx | 27 +-
.../components/policy_json_flyout.tsx | 22 +-
.../edit_policy/edit_policy.container.tsx | 23 +-
.../sections/edit_policy/edit_policy.tsx | 537 ++++++++----------
.../edit_policy/edit_policy_context.tsx | 12 +-
.../edit_policy/{ => form}/deserializer.ts | 21 +-
.../sections/edit_policy/form/index.ts | 13 +
.../{form_schema.ts => form/schema.ts} | 53 +-
.../edit_policy/{ => form}/serializer.ts | 24 +-
.../validations.ts} | 77 ++-
.../sections/edit_policy/i18n_texts.ts | 36 ++
.../edit_policy/save_policy.ts} | 15 +-
.../application/sections/edit_policy/types.ts | 5 +
.../services/policies/delete_phase.ts | 88 ---
.../policies/policy_serialization.test.ts | 198 -------
.../services/policies/policy_serialization.ts | 82 ---
.../services/policies/policy_validation.ts | 144 -----
.../public/shared_imports.ts | 3 +
.../translations/translations/ja-JP.json | 6 -
.../translations/translations/zh-CN.json | 6 -
50 files changed, 749 insertions(+), 1485 deletions(-)
create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/lib/policies.ts
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/min_age_input_legacy.tsx
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phase_error_message.tsx
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{ => delete_phase}/delete_phase.tsx (50%)
create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/index.ts
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/data_tier_allocation_field/components/cloud_data_tier_callout.tsx (100%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/data_tier_allocation_field/components/data_tier_allocation.scss (100%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/data_tier_allocation_field/components/data_tier_allocation.tsx (100%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/data_tier_allocation_field/components/default_allocation_notice.tsx (100%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/data_tier_allocation_field/components/index.ts (100%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/data_tier_allocation_field/components/no_node_attributes_warning.tsx (100%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/data_tier_allocation_field/components/node_allocation.tsx (90%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/data_tier_allocation_field/components/node_attrs_details.tsx (100%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/data_tier_allocation_field/components/node_data_provider.tsx (100%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/data_tier_allocation_field/components/types.ts (100%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/data_tier_allocation_field/data_tier_allocation_field.tsx (100%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/data_tier_allocation_field/index.ts (100%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/forcemerge_field.tsx (94%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/index.ts (88%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/min_age_input_field/index.ts (100%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/min_age_input_field/min_age_input_field.tsx (100%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/min_age_input_field/util.ts (100%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/{shared => shared_fields}/set_priority_input.tsx (83%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/{snapshot_policies.tsx => phases/shared_fields/snapshot_policies_field.tsx} (68%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/{ => form}/deserializer.ts (82%)
create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/index.ts
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/{form_schema.ts => form/schema.ts} (90%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/{ => form}/serializer.ts (90%)
rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/{form_validations.ts => form/validations.ts} (50%)
rename x-pack/plugins/index_lifecycle_management/public/application/{services/policies/policy_save.ts => sections/edit_policy/save_policy.ts} (84%)
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/services/policies/delete_phase.ts
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx
index 0b9f47e188d15..646978dd68153 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx
@@ -221,6 +221,11 @@ export const setup = async () => {
setFreeze,
setIndexPriority: setIndexPriority('cold'),
},
+ delete: {
+ enable: enable('delete'),
+ setMinAgeValue: setMinAgeValue('delete'),
+ setMinAgeUnits: setMinAgeUnits('delete'),
+ },
},
};
};
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 11fadf51f27f8..4ee67d1ed8a19 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
@@ -367,7 +367,6 @@ describe('', () => {
expect(testBed.find('snapshotPolicyCombobox').prop('data-currentvalue')).toEqual([
{
label: DELETE_PHASE_POLICY.policy.phases.delete?.actions.wait_for_snapshot?.policy,
- value: DELETE_PHASE_POLICY.policy.phases.delete?.actions.wait_for_snapshot?.policy,
},
]);
});
@@ -412,7 +411,7 @@ describe('', () => {
test('wait for snapshot field should delete action if field is empty', async () => {
const { actions } = testBed;
- actions.setWaitForSnapshotPolicy('');
+ await actions.setWaitForSnapshotPolicy('');
await actions.savePolicy();
const expected = {
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx
index 4a3fedfb264ac..43910583ceec9 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx
@@ -20,27 +20,27 @@ import {
notificationServiceMock,
fatalErrorsServiceMock,
} from '../../../../../src/core/public/mocks';
+
import { usageCollectionPluginMock } from '../../../../../src/plugins/usage_collection/public/mocks';
+
import { CloudSetup } from '../../../cloud/public';
import { EditPolicy } from '../../public/application/sections/edit_policy/edit_policy';
+import {
+ EditPolicyContextProvider,
+ EditPolicyContextValue,
+} from '../../public/application/sections/edit_policy/edit_policy_context';
+
import { KibanaContextProvider } from '../../public/shared_imports';
+
import { init as initHttp } from '../../public/application/services/http';
import { init as initUiMetric } from '../../public/application/services/ui_metric';
import { init as initNotification } from '../../public/application/services/notification';
import { PolicyFromES } from '../../common/types';
-import {
- positiveNumberRequiredMessage,
- policyNameRequiredMessage,
- policyNameStartsWithUnderscoreErrorMessage,
- policyNameContainsCommaErrorMessage,
- policyNameContainsSpaceErrorMessage,
- policyNameMustBeDifferentErrorMessage,
- policyNameAlreadyUsedErrorMessage,
-} from '../../public/application/services/policies/policy_validation';
import { i18nTexts } from '../../public/application/sections/edit_policy/i18n_texts';
import { editPolicyHelpers } from './helpers';
+import { defaultPolicy } from '../../public/application/constants';
// @ts-ignore
initHttp(axios.create({ adapter: axiosXhrAdapter }));
@@ -122,14 +122,11 @@ const noRollover = async (rendered: ReactWrapper) => {
const getNodeAttributeSelect = (rendered: ReactWrapper, phase: string) => {
return findTestSubject(rendered, `${phase}-selectedNodeAttrs`);
};
-const setPolicyName = (rendered: ReactWrapper, policyName: string) => {
+const setPolicyName = async (rendered: ReactWrapper, policyName: string) => {
const policyNameField = findTestSubject(rendered, 'policyNameField');
- policyNameField.simulate('change', { target: { value: policyName } });
- rendered.update();
-};
-const setPhaseAfterLegacy = (rendered: ReactWrapper, phase: string, after: string | number) => {
- const afterInput = rendered.find(`input#${phase}-selectedMinimumAge`);
- afterInput.simulate('change', { target: { value: after } });
+ await act(async () => {
+ policyNameField.simulate('change', { target: { value: policyName } });
+ });
rendered.update();
};
const setPhaseAfter = async (rendered: ReactWrapper, phase: string, after: string | number) => {
@@ -157,6 +154,32 @@ const save = async (rendered: ReactWrapper) => {
});
rendered.update();
};
+
+const MyComponent = ({
+ isCloudEnabled,
+ isNewPolicy,
+ policy: _policy,
+ existingPolicies,
+ getUrlForApp,
+ policyName,
+}: EditPolicyContextValue & { isCloudEnabled: boolean }) => {
+ return (
+
+
+
+
+
+ );
+};
+
describe('edit policy', () => {
beforeAll(() => {
jest.useFakeTimers();
@@ -179,14 +202,14 @@ describe('edit policy', () => {
beforeEach(() => {
component = (
-
-
-
+
);
({ http } = editPolicyHelpers.setup());
@@ -198,62 +221,78 @@ describe('edit policy', () => {
test('should show error when trying to save empty form', async () => {
const rendered = mountWithIntl(component);
await save(rendered);
- expectedErrorMessages(rendered, [policyNameRequiredMessage]);
+ expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.policyNameRequiredMessage]);
});
test('should show error when trying to save policy name with space', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'my policy');
- await save(rendered);
- expectedErrorMessages(rendered, [policyNameContainsSpaceErrorMessage]);
+ await setPolicyName(rendered, 'my policy');
+ waitForFormLibValidation(rendered);
+ expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.policyNameContainsInvalidChars]);
});
test('should show error when trying to save policy name that is already used', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'testy0');
- rendered.update();
- await save(rendered);
- expectedErrorMessages(rendered, [policyNameAlreadyUsedErrorMessage]);
+ await setPolicyName(rendered, 'testy0');
+ waitForFormLibValidation(rendered);
+ expectedErrorMessages(rendered, [
+ i18nTexts.editPolicy.errors.policyNameAlreadyUsedErrorMessage,
+ ]);
});
test('should show error when trying to save as new policy but using the same name', async () => {
component = (
-
);
const rendered = mountWithIntl(component);
findTestSubject(rendered, 'saveAsNewSwitch').simulate('click');
rendered.update();
- setPolicyName(rendered, 'testy0');
- await save(rendered);
- expectedErrorMessages(rendered, [policyNameMustBeDifferentErrorMessage]);
+ await setPolicyName(rendered, 'testy0');
+ waitForFormLibValidation(rendered);
+ expectedErrorMessages(rendered, [
+ i18nTexts.editPolicy.errors.policyNameAlreadyUsedErrorMessage,
+ ]);
});
test('should show error when trying to save policy name with comma', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'my,policy');
- await save(rendered);
- expectedErrorMessages(rendered, [policyNameContainsCommaErrorMessage]);
+ await setPolicyName(rendered, 'my,policy');
+ waitForFormLibValidation(rendered);
+ expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.policyNameContainsInvalidChars]);
});
test('should show error when trying to save policy name starting with underscore', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, '_mypolicy');
- await save(rendered);
- expectedErrorMessages(rendered, [policyNameStartsWithUnderscoreErrorMessage]);
+ await setPolicyName(rendered, '_mypolicy');
+ waitForFormLibValidation(rendered);
+ expectedErrorMessages(rendered, [
+ i18nTexts.editPolicy.errors.policyNameStartsWithUnderscoreErrorMessage,
+ ]);
});
test('should show correct json in policy flyout', async () => {
- const rendered = mountWithIntl(component);
+ const rendered = mountWithIntl(
+
+ );
await act(async () => {
findTestSubject(rendered, 'requestButton').simulate('click');
});
rendered.update();
+
const json = rendered.find(`code`).text();
- const expected = `PUT _ilm/policy/\n${JSON.stringify(
+ const expected = `PUT _ilm/policy/my-policy\n${JSON.stringify(
{
policy: {
phases: {
@@ -282,7 +321,7 @@ describe('edit policy', () => {
test('should show errors when trying to save with no max size and no max age', async () => {
const rendered = mountWithIntl(component);
expect(findTestSubject(rendered, 'rolloverSettingsRequired').exists()).toBeFalsy();
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
const maxSizeInput = findTestSubject(rendered, 'hot-selectedMaxSizeStored');
await act(async () => {
maxSizeInput.simulate('change', { target: { value: '' } });
@@ -298,7 +337,7 @@ describe('edit policy', () => {
});
test('should show number above 0 required error when trying to save with -1 for max size', async () => {
const rendered = mountWithIntl(component);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
const maxSizeInput = findTestSubject(rendered, 'hot-selectedMaxSizeStored');
await act(async () => {
maxSizeInput.simulate('change', { target: { value: '-1' } });
@@ -309,7 +348,7 @@ describe('edit policy', () => {
});
test('should show number above 0 required error when trying to save with 0 for max size', async () => {
const rendered = mountWithIntl(component);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
const maxSizeInput = findTestSubject(rendered, 'hot-selectedMaxSizeStored');
await act(async () => {
maxSizeInput.simulate('change', { target: { value: '-1' } });
@@ -319,7 +358,7 @@ describe('edit policy', () => {
});
test('should show number above 0 required error when trying to save with -1 for max age', async () => {
const rendered = mountWithIntl(component);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
const maxAgeInput = findTestSubject(rendered, 'hot-selectedMaxAge');
await act(async () => {
maxAgeInput.simulate('change', { target: { value: '-1' } });
@@ -329,7 +368,7 @@ describe('edit policy', () => {
});
test('should show number above 0 required error when trying to save with 0 for max age', async () => {
const rendered = mountWithIntl(component);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
const maxAgeInput = findTestSubject(rendered, 'hot-selectedMaxAge');
await act(async () => {
maxAgeInput.simulate('change', { target: { value: '0' } });
@@ -337,21 +376,21 @@ describe('edit policy', () => {
waitForFormLibValidation(rendered);
expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.numberGreatThan0Required]);
});
- test('should show forcemerge input when rollover enabled', () => {
+ test('should show forcemerge input when rollover enabled', async () => {
const rendered = mountWithIntl(component);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
expect(findTestSubject(rendered, 'hot-forceMergeSwitch').exists()).toBeTruthy();
});
test('should hide forcemerge input when rollover is disabled', async () => {
const rendered = mountWithIntl(component);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await noRollover(rendered);
waitForFormLibValidation(rendered);
expect(findTestSubject(rendered, 'hot-forceMergeSwitch').exists()).toBeFalsy();
});
test('should show positive number required above zero error when trying to save hot phase with 0 for force merge', async () => {
const rendered = mountWithIntl(component);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
act(() => {
findTestSubject(rendered, 'hot-forceMergeSwitch').simulate('click');
});
@@ -365,7 +404,7 @@ describe('edit policy', () => {
});
test('should show positive number above 0 required error when trying to save hot phase with -1 for force merge', async () => {
const rendered = mountWithIntl(component);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
findTestSubject(rendered, 'hot-forceMergeSwitch').simulate('click');
rendered.update();
const forcemergeInput = findTestSubject(rendered, 'hot-selectedForceMergeSegments');
@@ -379,7 +418,7 @@ describe('edit policy', () => {
test('should show positive number required error when trying to save with -1 for index priority', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await setPhaseIndexPriority(rendered, 'hot', '-1');
waitForFormLibValidation(rendered);
expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.nonNegativeNumberRequired]);
@@ -397,7 +436,7 @@ describe('edit policy', () => {
test('should show number required error when trying to save empty warm phase', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
await setPhaseAfter(rendered, 'warm', '');
waitForFormLibValidation(rendered);
@@ -406,7 +445,7 @@ describe('edit policy', () => {
test('should allow 0 for phase timing', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
await setPhaseAfter(rendered, 'warm', '0');
waitForFormLibValidation(rendered);
@@ -415,7 +454,7 @@ describe('edit policy', () => {
test('should show positive number required error when trying to save warm phase with -1 for after', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
await setPhaseAfter(rendered, 'warm', '-1');
waitForFormLibValidation(rendered);
@@ -424,7 +463,7 @@ describe('edit policy', () => {
test('should show positive number required error when trying to save warm phase with -1 for index priority', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
await setPhaseAfter(rendered, 'warm', '1');
await setPhaseAfter(rendered, 'warm', '-1');
@@ -434,7 +473,7 @@ describe('edit policy', () => {
test('should show positive number required above zero error when trying to save warm phase with 0 for shrink', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
act(() => {
findTestSubject(rendered, 'shrinkSwitch').simulate('click');
@@ -451,7 +490,7 @@ describe('edit policy', () => {
test('should show positive number above 0 required error when trying to save warm phase with -1 for shrink', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
await setPhaseAfter(rendered, 'warm', '1');
act(() => {
@@ -468,7 +507,7 @@ describe('edit policy', () => {
test('should show positive number required above zero error when trying to save warm phase with 0 for force merge', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
await setPhaseAfter(rendered, 'warm', '1');
act(() => {
@@ -485,7 +524,7 @@ describe('edit policy', () => {
test('should show positive number above 0 required error when trying to save warm phase with -1 for force merge', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
await setPhaseAfter(rendered, 'warm', '1');
await act(async () => {
@@ -503,7 +542,7 @@ describe('edit policy', () => {
server.respondImmediately = false;
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeTruthy();
expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy();
@@ -517,7 +556,7 @@ describe('edit policy', () => {
});
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
await openNodeAttributesSection(rendered, 'warm');
@@ -527,7 +566,7 @@ describe('edit policy', () => {
test('should show node attributes input when attributes exist', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
await openNodeAttributesSection(rendered, 'warm');
@@ -539,7 +578,7 @@ describe('edit policy', () => {
test('should show view node attributes link when attribute selected and show flyout when clicked', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
await openNodeAttributesSection(rendered, 'warm');
@@ -568,7 +607,7 @@ describe('edit policy', () => {
});
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
expect(findTestSubject(rendered, 'defaultAllocationWarning').exists()).toBeTruthy();
@@ -581,7 +620,7 @@ describe('edit policy', () => {
});
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
expect(findTestSubject(rendered, 'defaultAllocationNotice').exists()).toBeTruthy();
@@ -594,7 +633,7 @@ describe('edit policy', () => {
});
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
expect(findTestSubject(rendered, 'defaultAllocationNotice').exists()).toBeFalsy();
@@ -611,7 +650,7 @@ describe('edit policy', () => {
test('should allow 0 for phase timing', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'cold');
await setPhaseAfter(rendered, 'cold', '0');
waitForFormLibValidation(rendered);
@@ -621,7 +660,7 @@ describe('edit policy', () => {
test('should show positive number required error when trying to save cold phase with -1 for after', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'cold');
await setPhaseAfter(rendered, 'cold', '-1');
waitForFormLibValidation(rendered);
@@ -631,7 +670,7 @@ describe('edit policy', () => {
server.respondImmediately = false;
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'cold');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeTruthy();
expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy();
@@ -645,7 +684,7 @@ describe('edit policy', () => {
});
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'cold');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
await openNodeAttributesSection(rendered, 'cold');
@@ -655,7 +694,7 @@ describe('edit policy', () => {
test('should show node attributes input when attributes exist', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'cold');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
await openNodeAttributesSection(rendered, 'cold');
@@ -667,7 +706,7 @@ describe('edit policy', () => {
test('should show view node attributes link when attribute selected and show flyout when clicked', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'cold');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
await openNodeAttributesSection(rendered, 'cold');
@@ -689,7 +728,7 @@ describe('edit policy', () => {
test('should show positive number required error when trying to save with -1 for index priority', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'cold');
await setPhaseAfter(rendered, 'cold', '1');
await setPhaseIndexPriority(rendered, 'cold', '-1');
@@ -704,7 +743,7 @@ describe('edit policy', () => {
});
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'cold');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
expect(findTestSubject(rendered, 'defaultAllocationWarning').exists()).toBeTruthy();
@@ -717,7 +756,7 @@ describe('edit policy', () => {
});
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'cold');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
expect(findTestSubject(rendered, 'defaultAllocationNotice').exists()).toBeTruthy();
@@ -730,7 +769,7 @@ describe('edit policy', () => {
});
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'cold');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
expect(findTestSubject(rendered, 'defaultAllocationNotice').exists()).toBeFalsy();
@@ -740,20 +779,20 @@ describe('edit policy', () => {
test('should allow 0 for phase timing', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'delete');
- setPhaseAfterLegacy(rendered, 'delete', '0');
- await save(rendered);
+ await setPhaseAfter(rendered, 'delete', '0');
+ waitForFormLibValidation(rendered);
expectedErrorMessages(rendered, []);
});
test('should show positive number required error when trying to save delete phase with -1 for after', async () => {
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'delete');
- setPhaseAfterLegacy(rendered, 'delete', '-1');
- await save(rendered);
- expectedErrorMessages(rendered, [positiveNumberRequiredMessage]);
+ await setPhaseAfter(rendered, 'delete', '-1');
+ waitForFormLibValidation(rendered);
+ expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.nonNegativeNumberRequired]);
});
});
describe('not on cloud', () => {
@@ -768,7 +807,7 @@ describe('edit policy', () => {
});
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
@@ -782,14 +821,13 @@ describe('edit policy', () => {
describe('on cloud', () => {
beforeEach(() => {
component = (
-
-
-
+
);
({ http } = editPolicyHelpers.setup());
({ server, httpRequestsMockHelpers } = http);
@@ -808,7 +846,7 @@ describe('edit policy', () => {
});
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
@@ -829,7 +867,7 @@ describe('edit policy', () => {
});
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'warm');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
@@ -849,7 +887,7 @@ describe('edit policy', () => {
});
const rendered = mountWithIntl(component);
await noRollover(rendered);
- setPolicyName(rendered, 'mypolicy');
+ await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'cold');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
expect(findTestSubject(rendered, 'cloudDataTierCallout').exists()).toBeTruthy();
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/lib/policies.ts b/x-pack/plugins/index_lifecycle_management/public/application/lib/policies.ts
new file mode 100644
index 0000000000000..c4a91978a3765
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/lib/policies.ts
@@ -0,0 +1,32 @@
+/*
+ * 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 { PolicyFromES } from '../../../common/types';
+
+export const splitSizeAndUnits = (field: string): { size: string; units: string } => {
+ let size = '';
+ let units = '';
+
+ const result = /(\d+)(\w+)/.exec(field);
+ if (result) {
+ size = result[1];
+ units = result[2];
+ }
+
+ return {
+ size,
+ units,
+ };
+};
+
+export const getPolicyByName = (
+ policies: PolicyFromES[] | null | undefined,
+ policyName: string = ''
+): PolicyFromES | undefined => {
+ if (policies && policies.length > 0) {
+ return policies.find((policy: PolicyFromES) => policy.name === policyName);
+ }
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts
index a04608338718e..326f6ff87dc3b 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts
@@ -7,11 +7,8 @@
export { ActiveBadge } from './active_badge';
export { ErrableFormRow } from './form_errors';
export { LearnMoreLink } from './learn_more_link';
-export { MinAgeInput } from './min_age_input_legacy';
export { OptionalLabel } from './optional_label';
-export { PhaseErrorMessage } from './phase_error_message';
export { PolicyJsonFlyout } from './policy_json_flyout';
-export { SnapshotPolicies } from './snapshot_policies';
export { DescribedFormField } from './described_form_field';
export * from './phases';
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/min_age_input_legacy.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/min_age_input_legacy.tsx
deleted file mode 100644
index 6fcf35b799289..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/min_age_input_legacy.tsx
+++ /dev/null
@@ -1,263 +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 React from 'react';
-import { FormattedMessage } from '@kbn/i18n/react';
-import { i18n } from '@kbn/i18n';
-
-import { EuiFieldNumber, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiSelect } from '@elastic/eui';
-
-import { LearnMoreLink } from './learn_more_link';
-import { ErrableFormRow } from './form_errors';
-import { PhaseValidationErrors, propertyof } from '../../../services/policies/policy_validation';
-import { PhaseWithMinAge, Phases } from '../../../../../common/types';
-
-function getTimingLabelForPhase(phase: keyof Phases) {
- // NOTE: Hot phase isn't necessary, because indices begin in the hot phase.
- switch (phase) {
- case 'warm':
- return i18n.translate('xpack.indexLifecycleMgmt.editPolicy.phaseWarm.minimumAgeLabel', {
- defaultMessage: 'Timing for warm phase',
- });
-
- case 'cold':
- return i18n.translate('xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeLabel', {
- defaultMessage: 'Timing for cold phase',
- });
-
- case 'delete':
- return i18n.translate('xpack.indexLifecycleMgmt.editPolicy.phaseDelete.minimumAgeLabel', {
- defaultMessage: 'Timing for delete phase',
- });
- }
-}
-
-function getUnitsAriaLabelForPhase(phase: keyof Phases) {
- // NOTE: Hot phase isn't necessary, because indices begin in the hot phase.
- switch (phase) {
- case 'warm':
- return i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.phaseWarm.minimumAgeUnitsAriaLabel',
- {
- defaultMessage: 'Units for timing of warm phase',
- }
- );
-
- case 'cold':
- return i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeUnitsAriaLabel',
- {
- defaultMessage: 'Units for timing of cold phase',
- }
- );
-
- case 'delete':
- return i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.phaseDelete.minimumAgeUnitsAriaLabel',
- {
- defaultMessage: 'Units for timing of delete phase',
- }
- );
- }
-}
-
-interface Props {
- rolloverEnabled: boolean;
- errors?: PhaseValidationErrors;
- phase: keyof Phases & string;
- phaseData: T;
- setPhaseData: (dataKey: keyof T & string, value: string) => void;
- isShowingErrors: boolean;
-}
-
-export const MinAgeInput = ({
- rolloverEnabled,
- errors,
- phaseData,
- phase,
- setPhaseData,
- isShowingErrors,
-}: React.PropsWithChildren>): React.ReactElement => {
- let daysOptionLabel;
- let hoursOptionLabel;
- let minutesOptionLabel;
- let secondsOptionLabel;
- let millisecondsOptionLabel;
- let microsecondsOptionLabel;
- let nanosecondsOptionLabel;
-
- if (rolloverEnabled) {
- daysOptionLabel = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.rolloverDaysOptionLabel',
- {
- defaultMessage: 'days from rollover',
- }
- );
-
- hoursOptionLabel = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.rolloverHoursOptionLabel',
- {
- defaultMessage: 'hours from rollover',
- }
- );
- minutesOptionLabel = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.rolloverMinutesOptionLabel',
- {
- defaultMessage: 'minutes from rollover',
- }
- );
-
- secondsOptionLabel = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.rolloverSecondsOptionLabel',
- {
- defaultMessage: 'seconds from rollover',
- }
- );
- millisecondsOptionLabel = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.rolloverMilliSecondsOptionLabel',
- {
- defaultMessage: 'milliseconds from rollover',
- }
- );
-
- microsecondsOptionLabel = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.rolloverMicroSecondsOptionLabel',
- {
- defaultMessage: 'microseconds from rollover',
- }
- );
-
- nanosecondsOptionLabel = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.rolloverNanoSecondsOptionLabel',
- {
- defaultMessage: 'nanoseconds from rollover',
- }
- );
- } else {
- daysOptionLabel = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.creationDaysOptionLabel',
- {
- defaultMessage: 'days from index creation',
- }
- );
-
- hoursOptionLabel = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.creationHoursOptionLabel',
- {
- defaultMessage: 'hours from index creation',
- }
- );
-
- minutesOptionLabel = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.creationMinutesOptionLabel',
- {
- defaultMessage: 'minutes from index creation',
- }
- );
-
- secondsOptionLabel = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.creationSecondsOptionLabel',
- {
- defaultMessage: 'seconds from index creation',
- }
- );
-
- millisecondsOptionLabel = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.creationMilliSecondsOptionLabel',
- {
- defaultMessage: 'milliseconds from index creation',
- }
- );
-
- microsecondsOptionLabel = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.creationMicroSecondsOptionLabel',
- {
- defaultMessage: 'microseconds from index creation',
- }
- );
-
- nanosecondsOptionLabel = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.creationNanoSecondsOptionLabel',
- {
- defaultMessage: 'nanoseconds from index creation',
- }
- );
- }
-
- // check that these strings are valid properties
- const selectedMinimumAgeProperty = propertyof('selectedMinimumAge');
- const selectedMinimumAgeUnitsProperty = propertyof('selectedMinimumAgeUnits');
- return (
-
-
-
- }
- />
- }
- >
- {
- setPhaseData(selectedMinimumAgeProperty, e.target.value);
- }}
- min={0}
- />
-
-
-
-
- setPhaseData(selectedMinimumAgeUnitsProperty, e.target.value)}
- options={[
- {
- value: 'd',
- text: daysOptionLabel,
- },
- {
- value: 'h',
- text: hoursOptionLabel,
- },
- {
- value: 'm',
- text: minutesOptionLabel,
- },
- {
- value: 's',
- text: secondsOptionLabel,
- },
- {
- value: 'ms',
- text: millisecondsOptionLabel,
- },
- {
- value: 'micros',
- text: microsecondsOptionLabel,
- },
- {
- value: 'nanos',
- text: nanosecondsOptionLabel,
- },
- ]}
- />
-
-
-
- );
-};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phase_error_message.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phase_error_message.tsx
deleted file mode 100644
index 750f68543f221..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phase_error_message.tsx
+++ /dev/null
@@ -1,19 +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 React from 'react';
-import { EuiBadge } from '@elastic/eui';
-import { FormattedMessage } from '@kbn/i18n/react';
-
-export const PhaseErrorMessage = ({ isShowingErrors }: { isShowingErrors: boolean }) => {
- return isShowingErrors ? (
-
-
-
- ) : null;
-};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx
index 84e955a91ad7c..b87243bd1a9a1 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx
@@ -13,19 +13,13 @@ import { EuiDescribedFormGroup, EuiTextColor } from '@elastic/eui';
import { Phases } from '../../../../../../../common/types';
-import {
- useFormData,
- useFormContext,
- UseField,
- ToggleField,
- NumericField,
-} from '../../../../../../shared_imports';
+import { useFormData, UseField, ToggleField, NumericField } from '../../../../../../shared_imports';
import { useEditPolicyContext } from '../../../edit_policy_context';
-import { LearnMoreLink, ActiveBadge, PhaseErrorMessage, DescribedFormField } from '../../';
+import { LearnMoreLink, ActiveBadge, DescribedFormField } from '../../';
-import { MinAgeInputField, DataTierAllocationField, SetPriorityInput } from '../shared';
+import { MinAgeInputField, DataTierAllocationField, SetPriorityInput } from '../shared_fields';
const i18nTexts = {
dataTierAllocation: {
@@ -43,15 +37,13 @@ const formFieldPaths = {
};
export const ColdPhase: FunctionComponent = () => {
- const { originalPolicy } = useEditPolicyContext();
- const form = useFormContext();
+ const { policy } = useEditPolicyContext();
const [formData] = useFormData({
watch: [formFieldPaths.enabled],
});
const enabled = get(formData, formFieldPaths.enabled);
- const isShowingErrors = form.isValid === false;
return (
@@ -66,8 +58,7 @@ export const ColdPhase: FunctionComponent = () => {
defaultMessage="Cold phase"
/>
{' '}
- {enabled && !isShowingErrors ?
: null}
-
+ {enabled &&
}
}
titleSize="s"
@@ -128,9 +119,7 @@ export const ColdPhase: FunctionComponent = () => {
'xpack.indexLifecycleMgmt.editPolicy.coldPhase.numberOfReplicas.switchLabel',
{ defaultMessage: 'Set replicas' }
),
- initialValue: Boolean(
- originalPolicy.phases.cold?.actions?.allocate?.number_of_replicas
- ),
+ initialValue: Boolean(policy.phases.cold?.actions?.allocate?.number_of_replicas),
}}
fullWidth
>
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/delete_phase.tsx
similarity index 50%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase.tsx
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/delete_phase.tsx
index 78ae66327654c..37323b97edc92 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/delete_phase.tsx
@@ -7,53 +7,24 @@
import React, { FunctionComponent, Fragment } from 'react';
import { get } from 'lodash';
import { FormattedMessage } from '@kbn/i18n/react';
-import { EuiDescribedFormGroup, EuiSwitch, EuiTextColor, EuiFormRow } from '@elastic/eui';
+import { EuiDescribedFormGroup, EuiTextColor, EuiFormRow } from '@elastic/eui';
-import { DeletePhase as DeletePhaseInterface, Phases } from '../../../../../../common/types';
+import { useFormData, UseField, ToggleField } from '../../../../../../shared_imports';
-import { useFormData } from '../../../../../shared_imports';
+import { ActiveBadge, LearnMoreLink, OptionalLabel } from '../../index';
-import { PhaseValidationErrors } from '../../../../services/policies/policy_validation';
+import { MinAgeInputField, SnapshotPoliciesField } from '../shared_fields';
-import {
- ActiveBadge,
- LearnMoreLink,
- OptionalLabel,
- PhaseErrorMessage,
- MinAgeInput,
- SnapshotPolicies,
-} from '../';
-import { useRolloverPath } from './shared';
-
-const deleteProperty: keyof Phases = 'delete';
-const phaseProperty = (propertyName: keyof DeletePhaseInterface) => propertyName;
-
-interface Props {
- setPhaseData: (key: keyof DeletePhaseInterface & string, value: string | boolean) => void;
- phaseData: DeletePhaseInterface;
- isShowingErrors: boolean;
- errors?: PhaseValidationErrors;
- getUrlForApp: (
- appId: string,
- options?: {
- path?: string;
- absolute?: boolean;
- }
- ) => string;
-}
+const formFieldPaths = {
+ enabled: '_meta.delete.enabled',
+};
-export const DeletePhase: FunctionComponent = ({
- setPhaseData,
- phaseData,
- errors,
- isShowingErrors,
- getUrlForApp,
-}) => {
+export const DeletePhase: FunctionComponent = () => {
const [formData] = useFormData({
- watch: useRolloverPath,
+ watch: formFieldPaths.enabled,
});
- const hotPhaseRolloverEnabled = get(formData, useRolloverPath);
+ const enabled = get(formData, formFieldPaths.enabled);
return (
@@ -66,8 +37,7 @@ export const DeletePhase: FunctionComponent
= ({
defaultMessage="Delete phase"
/>
{' '}
- {phaseData.phaseEnabled && !isShowingErrors ? : null}
-
+ {enabled && }
}
titleSize="s"
@@ -79,39 +49,23 @@ export const DeletePhase: FunctionComponent = ({
defaultMessage="You no longer need your index. You can define when it is safe to delete it."
/>
-
- }
- id={`${deleteProperty}-${phaseProperty('phaseEnabled')}`}
- checked={phaseData.phaseEnabled}
- onChange={(e) => {
- setPhaseData(phaseProperty('phaseEnabled'), e.target.checked);
+
}
fullWidth
>
- {phaseData.phaseEnabled ? (
-
- errors={errors}
- phaseData={phaseData}
- phase={deleteProperty}
- isShowingErrors={isShowingErrors}
- setPhaseData={setPhaseData}
- rolloverEnabled={hotPhaseRolloverEnabled}
- />
- ) : (
-
- )}
+ {enabled && }
- {phaseData.phaseEnabled ? (
+ {enabled ? (
@@ -145,11 +99,7 @@ export const DeletePhase: FunctionComponent = ({
}
>
- setPhaseData(phaseProperty('waitForSnapshotPolicy'), value)}
- getUrlForApp={getUrlForApp}
- />
+
) : null}
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/index.ts
new file mode 100644
index 0000000000000..488e4e26cfce0
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/index.ts
@@ -0,0 +1,7 @@
+/*
+ * 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 { DeletePhase } from './delete_phase';
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx
index a184ddf5148b9..629c1388f61fb 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx
@@ -19,7 +19,6 @@ import {
import { Phases } from '../../../../../../../common/types';
import {
- useFormContext,
useFormData,
UseField,
SelectField,
@@ -29,26 +28,24 @@ import {
import { i18nTexts } from '../../../i18n_texts';
-import { ROLLOVER_EMPTY_VALIDATION } from '../../../form_validations';
+import { ROLLOVER_EMPTY_VALIDATION } from '../../../form';
import { ROLLOVER_FORM_PATHS } from '../../../constants';
-import { LearnMoreLink, ActiveBadge, PhaseErrorMessage } from '../../';
+import { LearnMoreLink, ActiveBadge } from '../../';
-import { Forcemerge, SetPriorityInput, useRolloverPath } from '../shared';
+import { Forcemerge, SetPriorityInput, useRolloverPath } from '../shared_fields';
import { maxSizeStoredUnits, maxAgeUnits } from './constants';
const hotProperty: keyof Phases = 'hot';
export const HotPhase: FunctionComponent = () => {
- const form = useFormContext();
const [formData] = useFormData({
watch: useRolloverPath,
});
const isRolloverEnabled = get(formData, useRolloverPath);
- const isShowingErrors = form.isValid === false;
const [showEmptyRolloverFieldsError, setShowEmptyRolloverFieldsError] = useState(false);
return (
@@ -62,8 +59,7 @@ export const HotPhase: FunctionComponent = () => {
defaultMessage="Hot phase"
/>
{' '}
- {isShowingErrors ? null : }
-
+
}
titleSize="s"
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/cloud_data_tier_callout.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/cloud_data_tier_callout.tsx
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/cloud_data_tier_callout.tsx
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/cloud_data_tier_callout.tsx
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/data_tier_allocation.scss b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/data_tier_allocation.scss
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/data_tier_allocation.scss
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/data_tier_allocation.scss
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/data_tier_allocation.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/data_tier_allocation.tsx
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/data_tier_allocation.tsx
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/data_tier_allocation.tsx
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/default_allocation_notice.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/default_allocation_notice.tsx
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/default_allocation_notice.tsx
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/default_allocation_notice.tsx
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/index.ts
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/index.ts
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/index.ts
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/no_node_attributes_warning.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/no_node_attributes_warning.tsx
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/no_node_attributes_warning.tsx
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/no_node_attributes_warning.tsx
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_allocation.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_allocation.tsx
similarity index 90%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_allocation.tsx
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_allocation.tsx
index 407bb9ea92e85..c1676d7074dbc 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_allocation.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_allocation.tsx
@@ -10,12 +10,8 @@ import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { EuiButtonEmpty, EuiText, EuiSpacer } from '@elastic/eui';
-import { PhaseWithAllocationAction } from '../../../../../../../../../common/types';
-
import { UseField, SelectField, useFormData } from '../../../../../../../../shared_imports';
-import { propertyof } from '../../../../../../../services/policies/policy_validation';
-
import { LearnMoreLink } from '../../../../learn_more_link';
import { NodeAttrsDetails } from './node_attrs_details';
@@ -61,9 +57,6 @@ export const NodeAllocation: FunctionComponent = ({ phase, nodes })
nodeOptions.sort((a, b) => a.value.localeCompare(b.value));
- // check that this string is a valid property
- const nodeAttrsProperty = propertyof('selectedNodeAttrs');
-
return (
<>
@@ -100,7 +93,7 @@ export const NodeAllocation: FunctionComponent = ({ phase, nodes })
) : undefined,
euiFieldProps: {
- 'data-test-subj': `${phase}-${nodeAttrsProperty}`,
+ 'data-test-subj': `${phase}-selectedNodeAttrs`,
options: [{ text: i18nTexts.doNotModifyAllocationOption, value: '' }].concat(
nodeOptions
),
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_attrs_details.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_attrs_details.tsx
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_attrs_details.tsx
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_attrs_details.tsx
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_data_provider.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_data_provider.tsx
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_data_provider.tsx
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_data_provider.tsx
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/types.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/types.ts
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/types.ts
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/types.ts
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/data_tier_allocation_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/data_tier_allocation_field.tsx
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/data_tier_allocation_field.tsx
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/data_tier_allocation_field.tsx
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/index.ts
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/index.ts
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/index.ts
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/forcemerge_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/forcemerge_field.tsx
similarity index 94%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/forcemerge_field.tsx
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/forcemerge_field.tsx
index b410bd0e6b3b0..b05d49be497cd 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/forcemerge_field.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/forcemerge_field.tsx
@@ -21,11 +21,11 @@ interface Props {
}
export const Forcemerge: React.FunctionComponent = ({ phase }) => {
- const { originalPolicy } = useEditPolicyContext();
+ const { policy } = useEditPolicyContext();
const initialToggleValue = useMemo(() => {
- return Boolean(originalPolicy.phases[phase]?.actions?.forcemerge);
- }, [originalPolicy, phase]);
+ return Boolean(policy.phases[phase]?.actions?.forcemerge);
+ }, [policy, phase]);
return (
= ({ phase }) => {
- const phaseIndexPriorityProperty = propertyof('phaseIndexPriority');
return (
= ({ phase }) => {
componentProps={{
fullWidth: false,
euiFieldProps: {
- 'data-test-subj': `${phase}-${phaseIndexPriorityProperty}`,
- min: 1,
+ 'data-test-subj': `${phase}-phaseIndexPriority`,
+ min: 0,
},
}}
/>
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/snapshot_policies.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/snapshot_policies_field.tsx
similarity index 68%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/snapshot_policies.tsx
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/snapshot_policies_field.tsx
index cc2849b5c8e9c..e9f9f331e410a 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/snapshot_policies.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/snapshot_policies_field.tsx
@@ -4,52 +4,39 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { Fragment } from 'react';
-
+import React from 'react';
+import { get } from 'lodash';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
-import { ApplicationStart } from 'kibana/public';
import {
EuiButtonIcon,
EuiCallOut,
- EuiComboBox,
EuiComboBoxOptionOption,
EuiLink,
EuiSpacer,
} from '@elastic/eui';
-import { useLoadSnapshotPolicies } from '../../../services/api';
+import { UseField, ComboBoxField, useFormData } from '../../../../../../shared_imports';
+import { useLoadSnapshotPolicies } from '../../../../../services/api';
+import { useEditPolicyContext } from '../../../edit_policy_context';
+
+const waitForSnapshotFormField = 'phases.delete.actions.wait_for_snapshot.policy';
-interface Props {
- value: string;
- onChange: (value: string) => void;
- getUrlForApp: ApplicationStart['getUrlForApp'];
-}
-export const SnapshotPolicies: React.FunctionComponent = ({
- value,
- onChange,
- getUrlForApp,
-}) => {
+export const SnapshotPoliciesField: React.FunctionComponent = () => {
+ const { getUrlForApp } = useEditPolicyContext();
const { error, isLoading, data, resendRequest } = useLoadSnapshotPolicies();
+ const [formData] = useFormData({
+ watch: waitForSnapshotFormField,
+ });
+
+ const selectedSnapshotPolicy = get(formData, waitForSnapshotFormField);
const policies = data.map((name: string) => ({
label: name,
value: name,
}));
- const onComboChange = (options: EuiComboBoxOptionOption[]) => {
- if (options.length > 0) {
- onChange(options[0].label);
- } else {
- onChange('');
- }
- };
-
- const onCreateOption = (newValue: string) => {
- onChange(newValue);
- };
-
const getUrlForSnapshotPolicyWizard = () => {
return getUrlForApp('management', {
path: `data/snapshot_restore/add_policy`,
@@ -59,14 +46,14 @@ export const SnapshotPolicies: React.FunctionComponent = ({
let calloutContent;
if (error) {
calloutContent = (
-
+ <>
+ <>
= ({
}
)}
/>
-
+ >
}
>
= ({
defaultMessage="Refresh this field and enter the name of an existing snapshot policy."
/>
-
+ >
);
} else if (data.length === 0) {
calloutContent = (
-
+ <>
= ({
}}
/>
-
+ >
);
- } else if (value && !data.includes(value)) {
+ } else if (selectedSnapshotPolicy && !data.includes(selectedSnapshotPolicy)) {
calloutContent = (
-
+ <>
= ({
}}
/>
-
+ >
);
}
return (
-
-
+ path={waitForSnapshotFormField}>
+ {(field) => {
+ const singleSelectionArray: [selectedSnapshot?: string] = field.value
+ ? [field.value]
+ : [];
+
+ return (
+ {
+ field.setValue(newOption);
},
- ]
- : []
- }
- onChange={onComboChange}
- noSuggestions={!!(error || data.length === 0)}
- />
+ onChange: (options: EuiComboBoxOptionOption[]) => {
+ if (options.length > 0) {
+ field.setValue(options[0].label);
+ } else {
+ field.setValue('');
+ }
+ },
+ }}
+ />
+ );
+ }}
+
{calloutContent}
-
+ >
);
};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx
index 06c16e8bdd5ab..94fd2ee9edaca 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx
@@ -17,23 +17,17 @@ import {
EuiDescribedFormGroup,
} from '@elastic/eui';
-import {
- useFormData,
- UseField,
- ToggleField,
- useFormContext,
- NumericField,
-} from '../../../../../../shared_imports';
+import { useFormData, UseField, ToggleField, NumericField } from '../../../../../../shared_imports';
import { Phases } from '../../../../../../../common/types';
-import { useRolloverPath, MinAgeInputField, Forcemerge, SetPriorityInput } from '../shared';
+import { useRolloverPath, MinAgeInputField, Forcemerge, SetPriorityInput } from '../shared_fields';
import { useEditPolicyContext } from '../../../edit_policy_context';
-import { LearnMoreLink, ActiveBadge, PhaseErrorMessage, DescribedFormField } from '../../';
+import { LearnMoreLink, ActiveBadge, DescribedFormField } from '../../';
-import { DataTierAllocationField } from '../shared';
+import { DataTierAllocationField } from '../shared_fields';
const i18nTexts = {
shrinkLabel: i18n.translate('xpack.indexLifecycleMgmt.warmPhase.shrinkIndexLabel', {
@@ -54,8 +48,7 @@ const formFieldPaths = {
};
export const WarmPhase: FunctionComponent = () => {
- const { originalPolicy } = useEditPolicyContext();
- const form = useFormContext();
+ const { policy } = useEditPolicyContext();
const [formData] = useFormData({
watch: [useRolloverPath, formFieldPaths.enabled, formFieldPaths.warmPhaseOnRollover],
});
@@ -63,7 +56,6 @@ export const WarmPhase: FunctionComponent = () => {
const enabled = get(formData, formFieldPaths.enabled);
const hotPhaseRolloverEnabled = get(formData, useRolloverPath);
const warmPhaseOnRollover = get(formData, formFieldPaths.warmPhaseOnRollover);
- const isShowingErrors = form.isValid === false;
return (
@@ -77,8 +69,7 @@ export const WarmPhase: FunctionComponent = () => {
defaultMessage="Warm phase"
/>
{' '}
- {enabled && !isShowingErrors ?
: null}
-
+ {enabled &&
}
}
titleSize="s"
@@ -161,9 +152,7 @@ export const WarmPhase: FunctionComponent = () => {
'xpack.indexLifecycleMgmt.editPolicy.warmPhase.numberOfReplicas.switchLabel',
{ defaultMessage: 'Set replicas' }
),
- initialValue: Boolean(
- originalPolicy.phases.warm?.actions?.allocate?.number_of_replicas
- ),
+ initialValue: Boolean(policy.phases.warm?.actions?.allocate?.number_of_replicas),
}}
fullWidth
>
@@ -203,7 +192,7 @@ export const WarmPhase: FunctionComponent = () => {
'data-test-subj': 'shrinkSwitch',
label: i18nTexts.shrinkLabel,
'aria-label': i18nTexts.shrinkLabel,
- initialValue: Boolean(originalPolicy.phases.warm?.actions?.shrink),
+ initialValue: Boolean(policy.phases.warm?.actions?.shrink),
}}
fullWidth
>
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/policy_json_flyout.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/policy_json_flyout.tsx
index 7098b018d6dfd..a8b1680ebde07 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/policy_json_flyout.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/policy_json_flyout.tsx
@@ -7,7 +7,6 @@
import React, { useCallback, useEffect, useState } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-
import {
EuiButtonEmpty,
EuiCodeBlock,
@@ -25,19 +24,15 @@ import {
import { SerializedPolicy } from '../../../../../common/types';
import { useFormContext, useFormData } from '../../../../shared_imports';
+
import { FormInternal } from '../types';
interface Props {
- legacyPolicy: SerializedPolicy;
close: () => void;
policyName: string;
}
-export const PolicyJsonFlyout: React.FunctionComponent = ({
- policyName,
- close,
- legacyPolicy,
-}) => {
+export const PolicyJsonFlyout: React.FunctionComponent = ({ policyName, close }) => {
/**
* policy === undefined: we are checking validity
* policy === null: we have determined the policy is invalid
@@ -51,20 +46,11 @@ export const PolicyJsonFlyout: React.FunctionComponent = ({
const updatePolicy = useCallback(async () => {
setPolicy(undefined);
if (await validateForm()) {
- const p = getFormData() as SerializedPolicy;
- setPolicy({
- ...legacyPolicy,
- phases: {
- ...legacyPolicy.phases,
- hot: p.phases.hot,
- warm: p.phases.warm,
- cold: p.phases.cold,
- },
- });
+ setPolicy(getFormData() as SerializedPolicy);
} else {
setPolicy(null);
}
- }, [setPolicy, getFormData, legacyPolicy, validateForm]);
+ }, [setPolicy, getFormData, validateForm]);
useEffect(() => {
updatePolicy();
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 c82a420b74857..ebef80871b83d 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
@@ -12,8 +12,11 @@ import { FormattedMessage } from '@kbn/i18n/react';
import { useKibana } from '../../../shared_imports';
import { useLoadPoliciesList } from '../../services/api';
+import { getPolicyByName } from '../../lib/policies';
+import { defaultPolicy } from '../../constants';
import { EditPolicy as PresentationComponent } from './edit_policy';
+import { EditPolicyContextProvider } from './edit_policy_context';
interface RouterProps {
policyName: string;
@@ -44,6 +47,7 @@ export const EditPolicy: React.FunctionComponent {
breadcrumbService.setBreadcrumbs('editPolicy');
}, [breadcrumbService]);
+
if (isLoading) {
return (
+
+
+
);
};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx
index 5397f5da2d6bb..1abbe884c2dc2 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx
@@ -4,7 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { Fragment, useEffect, useState, useCallback, useMemo } from 'react';
+import React, { Fragment, useEffect, useState, useMemo } from 'react';
+import { get } from 'lodash';
import { RouteComponentProps } from 'react-router-dom';
@@ -16,7 +17,6 @@ import {
EuiButton,
EuiButtonEmpty,
EuiDescribedFormGroup,
- EuiFieldText,
EuiFlexGroup,
EuiFlexItem,
EuiFormRow,
@@ -30,31 +30,13 @@ import {
EuiTitle,
} from '@elastic/eui';
-import { useForm, Form } from '../../../shared_imports';
+import { useForm, Form, UseField, TextField, useFormData } from '../../../shared_imports';
import { toasts } from '../../services/notification';
-import { LegacyPolicy, PolicyFromES, SerializedPolicy } from '../../../../common/types';
-
-import { defaultPolicy } from '../../constants';
-
-import {
- validatePolicy,
- ValidationErrors,
- findFirstError,
-} from '../../services/policies/policy_validation';
-
-import { savePolicy } from '../../services/policies/policy_save';
+import { savePolicy } from './save_policy';
import {
- deserializePolicy,
- getPolicyByName,
- initializeNewPolicy,
- legacySerializePolicy,
-} from '../../services/policies/policy_serialization';
-
-import {
- ErrableFormRow,
LearnMoreLink,
PolicyJsonFlyout,
ColdPhase,
@@ -63,93 +45,66 @@ import {
WarmPhase,
} from './components';
-import { schema } from './form_schema';
-import { deserializer } from './deserializer';
-import { createSerializer } from './serializer';
+import { schema, deserializer, createSerializer, createPolicyNameValidations } from './form';
-import { EditPolicyContextProvider } from './edit_policy_context';
+import { useEditPolicyContext } from './edit_policy_context';
+import { FormInternal } from './types';
export interface Props {
- policies: PolicyFromES[];
- policyName: string;
- getUrlForApp: (
- appId: string,
- options?: {
- path?: string;
- absolute?: boolean;
- }
- ) => string;
history: RouteComponentProps['history'];
}
-const mergeAllSerializedPolicies = (
- serializedPolicy: SerializedPolicy,
- legacySerializedPolicy: SerializedPolicy
-): SerializedPolicy => {
- return {
- ...legacySerializedPolicy,
- phases: {
- ...legacySerializedPolicy.phases,
- hot: serializedPolicy.phases.hot,
- warm: serializedPolicy.phases.warm,
- cold: serializedPolicy.phases.cold,
- },
- };
-};
+const policyNamePath = 'name';
-export const EditPolicy: React.FunctionComponent = ({
- policies,
- policyName,
- history,
- getUrlForApp,
-}) => {
+export const EditPolicy: React.FunctionComponent = ({ history }) => {
useEffect(() => {
window.scrollTo(0, 0);
}, []);
- const [isShowingErrors, setIsShowingErrors] = useState(false);
- const [errors, setErrors] = useState();
const [isShowingPolicyJsonFlyout, setIsShowingPolicyJsonFlyout] = useState(false);
-
- const existingPolicy = getPolicyByName(policies, policyName);
+ const {
+ isNewPolicy,
+ policy: currentPolicy,
+ existingPolicies,
+ policyName,
+ } = useEditPolicyContext();
const serializer = useMemo(() => {
- return createSerializer(existingPolicy?.policy);
- }, [existingPolicy?.policy]);
+ return createSerializer(isNewPolicy ? undefined : currentPolicy);
+ }, [isNewPolicy, currentPolicy]);
- const originalPolicy = existingPolicy?.policy ?? defaultPolicy;
+ const [saveAsNew, setSaveAsNew] = useState(isNewPolicy);
+ const originalPolicyName: string = isNewPolicy ? '' : policyName!;
const { form } = useForm({
schema,
- defaultValue: originalPolicy,
+ defaultValue: {
+ ...currentPolicy,
+ name: originalPolicyName,
+ },
deserializer,
serializer,
});
- const [policy, setPolicy] = useState(() =>
- existingPolicy ? deserializePolicy(existingPolicy) : initializeNewPolicy(policyName)
+ const [formData] = useFormData({ form, watch: policyNamePath });
+ const currentPolicyName = get(formData, policyNamePath);
+
+ const policyNameValidations = useMemo(
+ () =>
+ createPolicyNameValidations({
+ originalPolicyName,
+ policies: existingPolicies,
+ saveAsNewPolicy: saveAsNew,
+ }),
+ [originalPolicyName, existingPolicies, saveAsNew]
);
- const isNewPolicy: boolean = !Boolean(existingPolicy);
- const [saveAsNew, setSaveAsNew] = useState(isNewPolicy);
- const originalPolicyName: string = existingPolicy ? existingPolicy.name : '';
-
const backToPolicyList = () => {
history.push('/policies');
};
const submit = async () => {
- setIsShowingErrors(true);
- const { data: formLibPolicy, isValid: newIsValid } = await form.submit();
- const [legacyIsValid, validationErrors] = validatePolicy(
- saveAsNew,
- policy,
- policies,
- originalPolicyName
- );
- setErrors(validationErrors);
-
- const isValid = legacyIsValid && newIsValid;
+ const { data: policy, isValid } = await form.submit();
if (!isValid) {
toasts.addDanger(
@@ -157,22 +112,11 @@ export const EditPolicy: React.FunctionComponent = ({
defaultMessage: 'Please fix the errors on this page.',
})
);
- // This functionality will not be required for once form lib is fully adopted for this form
- // because errors are reported as fields are edited.
- if (!legacyIsValid) {
- const firstError = findFirstError(validationErrors);
- const errorRowId = `${firstError ? firstError.replace('.', '-') : ''}-row`;
- const element = document.getElementById(errorRowId);
- if (element) {
- element.scrollIntoView({ block: 'center', inline: 'nearest' });
- }
- }
} else {
- const readSerializedPolicy = () => {
- const legacySerializedPolicy = legacySerializePolicy(policy, existingPolicy?.policy);
- return mergeAllSerializedPolicies(formLibPolicy, legacySerializedPolicy);
- };
- const success = await savePolicy(readSerializedPolicy, isNewPolicy || saveAsNew);
+ const success = await savePolicy(
+ { ...policy, name: saveAsNew ? currentPolicyName : originalPolicyName },
+ isNewPolicy || saveAsNew
+ );
if (success) {
backToPolicyList();
}
@@ -183,248 +127,217 @@ export const EditPolicy: React.FunctionComponent = ({
setIsShowingPolicyJsonFlyout(!isShowingPolicyJsonFlyout);
};
- const setPhaseData = useCallback(
- (phase: keyof LegacyPolicy['phases'], key: string, value: any) => {
- setPolicy((nextPolicy) => ({
- ...nextPolicy,
- phases: {
- ...nextPolicy.phases,
- [phase]: { ...nextPolicy.phases[phase], [key]: value },
- },
- }));
- },
- [setPolicy]
- );
-
- const setDeletePhaseData = useCallback(
- (key: string, value: any) => setPhaseData('delete', key, value),
- [setPhaseData]
- );
-
return (
-
-
-
-
-
-
- {isNewPolicy
- ? i18n.translate('xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage', {
- defaultMessage: 'Create an index lifecycle policy',
- })
- : i18n.translate('xpack.indexLifecycleMgmt.editPolicy.editPolicyMessage', {
- defaultMessage: 'Edit index lifecycle policy {originalPolicyName}',
- values: { originalPolicyName },
- })}
-
-
-
-
+ }
+ titleSize="s"
+ fullWidth
+ >
+
+ path={policyNamePath}
+ config={{
+ label: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.policyNameLabel', {
+ defaultMessage: 'Policy name',
+ }),
+ helpText: i18n.translate(
+ 'xpack.indexLifecycleMgmt.editPolicy.validPolicyNameMessage',
+ {
+ defaultMessage:
+ 'A policy name cannot start with an underscore and cannot contain a question mark or a space.',
+ }
+ ),
+ validations: policyNameValidations,
+ }}
+ component={TextField}
+ componentProps={{
+ fullWidth: false,
+ euiFieldProps: {
+ 'data-test-subj': 'policyNameField',
+ },
+ }}
+ />
+
+ ) : null}
-
+
-
+
-
+
-
+
-
+
-
+
-
+
- 0
- }
- getUrlForApp={getUrlForApp}
- setPhaseData={setDeletePhaseData}
- phaseData={policy.phases.delete}
- />
+
-
-
-
-
-
-
-
- {saveAsNew ? (
-
- ) : (
-
- )}
-
-
-
-
-
+
+
+
+
+
+
+
+ {saveAsNew ? (
-
-
-
-
-
-
-
- {isShowingPolicyJsonFlyout ? (
-
- ) : (
+ ) : (
+
+ )}
+
+
+
+
+
- )}
-
-
-
-
- {isShowingPolicyJsonFlyout ? (
- setIsShowingPolicyJsonFlyout(false)}
- />
- ) : null}
-
-
-
-
-
-
+
+
+
+
+
+
+
+ {isShowingPolicyJsonFlyout ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ {isShowingPolicyJsonFlyout ? (
+ setIsShowingPolicyJsonFlyout(false)}
+ />
+ ) : null}
+
+
+
+
+
);
};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy_context.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy_context.tsx
index 4748c26d6cec1..da5f940b1b6c8 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy_context.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy_context.tsx
@@ -5,10 +5,16 @@
*/
import React, { createContext, ReactChild, useContext } from 'react';
-import { SerializedPolicy } from '../../../../common/types';
+import { ApplicationStart } from 'kibana/public';
-interface EditPolicyContextValue {
- originalPolicy: SerializedPolicy;
+import { PolicyFromES, SerializedPolicy } from '../../../../common/types';
+
+export interface EditPolicyContextValue {
+ isNewPolicy: boolean;
+ policy: SerializedPolicy;
+ existingPolicies: PolicyFromES[];
+ getUrlForApp: ApplicationStart['getUrlForApp'];
+ policyName?: string;
}
const EditPolicyContext = createContext(null as any);
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts
similarity index 82%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts
index f0294a5391d21..5af8807f2dec8 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts
@@ -6,17 +6,17 @@
import { produce } from 'immer';
-import { SerializedPolicy } from '../../../../common/types';
+import { SerializedPolicy } from '../../../../../common/types';
-import { splitSizeAndUnits } from '../../services/policies/policy_serialization';
+import { splitSizeAndUnits } from '../../../lib/policies';
-import { determineDataTierAllocationType } from '../../lib';
+import { determineDataTierAllocationType } from '../../../lib';
-import { FormInternal } from './types';
+import { FormInternal } from '../types';
export const deserializer = (policy: SerializedPolicy): FormInternal => {
const {
- phases: { hot, warm, cold },
+ phases: { hot, warm, cold, delete: deletePhase },
} = policy;
const _meta: FormInternal['_meta'] = {
@@ -37,6 +37,9 @@ export const deserializer = (policy: SerializedPolicy): FormInternal => {
dataTierAllocationType: determineDataTierAllocationType(cold?.actions),
freezeEnabled: Boolean(cold?.actions?.freeze),
},
+ delete: {
+ enabled: Boolean(deletePhase),
+ },
};
return produce(
@@ -86,6 +89,14 @@ export const deserializer = (policy: SerializedPolicy): FormInternal => {
draft._meta.cold.minAgeUnit = minAge.units;
}
}
+
+ if (draft.phases.delete) {
+ if (draft.phases.delete.min_age) {
+ const minAge = splitSizeAndUnits(draft.phases.delete.min_age);
+ draft.phases.delete.min_age = minAge.size;
+ draft._meta.delete.minAgeUnit = minAge.units;
+ }
+ }
}
);
};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/index.ts
new file mode 100644
index 0000000000000..82fa478832582
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/index.ts
@@ -0,0 +1,13 @@
+/*
+ * 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 { deserializer } from './deserializer';
+
+export { createSerializer } from './serializer';
+
+export { schema } from './schema';
+
+export * from './validations';
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts
similarity index 90%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts
index 070f03f74b954..4d20db4018740 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts
@@ -6,18 +6,19 @@
import { i18n } from '@kbn/i18n';
-import { FormSchema, fieldValidators } from '../../../shared_imports';
-import { defaultSetPriority, defaultPhaseIndexPriority } from '../../constants';
+import { FormSchema, fieldValidators } from '../../../../shared_imports';
+import { defaultSetPriority, defaultPhaseIndexPriority } from '../../../constants';
-import { FormInternal } from './types';
+import { FormInternal } from '../types';
import {
ifExistsNumberGreaterThanZero,
ifExistsNumberNonNegative,
rolloverThresholdsValidator,
-} from './form_validations';
+ minAgeValidator,
+} from './validations';
-import { i18nTexts } from './i18n_texts';
+import { i18nTexts } from '../i18n_texts';
const { emptyField, numberGreaterThanField } = fieldValidators;
@@ -97,6 +98,18 @@ export const schema: FormSchema = {
label: i18nTexts.editPolicy.allocationNodeAttributeFieldLabel,
},
},
+ delete: {
+ enabled: {
+ defaultValue: false,
+ label: i18n.translate(
+ 'xpack.indexLifecycleMgmt.editPolicy.deletePhase.activateWarmPhaseSwitchLabel',
+ { defaultMessage: 'Activate delete phase' }
+ ),
+ },
+ minAgeUnit: {
+ defaultValue: 'd',
+ },
+ },
},
phases: {
hot: {
@@ -177,15 +190,7 @@ export const schema: FormSchema = {
defaultValue: '0',
validations: [
{
- validator: (arg) =>
- numberGreaterThanField({
- than: 0,
- allowEquality: true,
- message: i18nTexts.editPolicy.errors.nonNegativeNumberRequired,
- })({
- ...arg,
- value: arg.value === '' ? -Infinity : parseInt(arg.value, 10),
- }),
+ validator: minAgeValidator,
},
],
},
@@ -256,15 +261,7 @@ export const schema: FormSchema = {
defaultValue: '0',
validations: [
{
- validator: (arg) =>
- numberGreaterThanField({
- than: 0,
- allowEquality: true,
- message: i18nTexts.editPolicy.errors.nonNegativeNumberRequired,
- })({
- ...arg,
- value: arg.value === '' ? -Infinity : parseInt(arg.value, 10),
- }),
+ validator: minAgeValidator,
},
],
},
@@ -292,5 +289,15 @@ export const schema: FormSchema = {
},
},
},
+ delete: {
+ min_age: {
+ defaultValue: '0',
+ validations: [
+ {
+ validator: minAgeValidator,
+ },
+ ],
+ },
+ },
},
};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer.ts
similarity index 90%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer.ts
index 564b5a2c4e397..2274efda426ad 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer.ts
@@ -4,12 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { isEmpty } from 'lodash';
+import { isEmpty, isNumber } from 'lodash';
-import { SerializedPolicy, SerializedActionWithAllocation } from '../../../../common/types';
+import { SerializedPolicy, SerializedActionWithAllocation } from '../../../../../common/types';
-import { FormInternal, DataAllocationMetaFields } from './types';
-import { isNumber } from '../../services/policies/policy_serialization';
+import { FormInternal, DataAllocationMetaFields } from '../types';
const serializeAllocateAction = (
{ dataTierAllocationType, allocationNodeAttribute }: DataAllocationMetaFields,
@@ -165,5 +164,22 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => (
}
}
+ /**
+ * DELETE PHASE SERIALIZATION
+ */
+ if (policy.phases.delete) {
+ if (policy.phases.delete.min_age) {
+ policy.phases.delete.min_age = `${policy.phases.delete.min_age}${_meta.delete.minAgeUnit}`;
+ }
+
+ if (originalPolicy?.phases.delete?.actions) {
+ const { wait_for_snapshot: __, ...rest } = originalPolicy.phases.delete.actions;
+ policy.phases.delete.actions = {
+ ...policy.phases.delete.actions,
+ ...rest,
+ };
+ }
+ }
+
return policy;
};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/validations.ts
similarity index 50%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/validations.ts
index 9c855ccb41624..f2e26a552efc9 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/validations.ts
@@ -4,13 +4,15 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { fieldValidators, ValidationFunc } from '../../../shared_imports';
+import { fieldValidators, ValidationFunc, ValidationConfig } from '../../../../shared_imports';
-import { ROLLOVER_FORM_PATHS } from './constants';
+import { ROLLOVER_FORM_PATHS } from '../constants';
-import { i18nTexts } from './i18n_texts';
+import { i18nTexts } from '../i18n_texts';
+import { PolicyFromES } from '../../../../../common/types';
+import { FormInternal } from '../types';
-const { numberGreaterThanField } = fieldValidators;
+const { numberGreaterThanField, containsCharsField, emptyField, startsWithField } = fieldValidators;
const createIfNumberExistsValidator = ({
than,
@@ -46,7 +48,7 @@ export const ifExistsNumberNonNegative = createIfNumberExistsValidator({
* A special validation type used to keep track of validation errors for
* the rollover threshold values not being set (e.g., age and doc count)
*/
-export const ROLLOVER_EMPTY_VALIDATION = 'EMPTY';
+export const ROLLOVER_EMPTY_VALIDATION = 'ROLLOVER_EMPTY_VALIDATION';
/**
* An ILM policy requires that for rollover a value must be set for one of the threshold values.
@@ -87,3 +89,68 @@ export const rolloverThresholdsValidator: ValidationFunc = ({ form }) => {
fields[ROLLOVER_FORM_PATHS.maxSize].clearErrors(ROLLOVER_EMPTY_VALIDATION);
}
};
+
+export const minAgeValidator: ValidationFunc = (arg) =>
+ numberGreaterThanField({
+ than: 0,
+ allowEquality: true,
+ message: i18nTexts.editPolicy.errors.nonNegativeNumberRequired,
+ })({
+ ...arg,
+ value: arg.value === '' ? -Infinity : parseInt(arg.value, 10),
+ });
+
+export const createPolicyNameValidations = ({
+ policies,
+ saveAsNewPolicy,
+ originalPolicyName,
+}: {
+ policies: PolicyFromES[];
+ saveAsNewPolicy: boolean;
+ originalPolicyName?: string;
+}): Array> => {
+ return [
+ {
+ validator: emptyField(i18nTexts.editPolicy.errors.policyNameRequiredMessage),
+ },
+ {
+ validator: startsWithField({
+ message: i18nTexts.editPolicy.errors.policyNameStartsWithUnderscoreErrorMessage,
+ char: '_',
+ }),
+ },
+ {
+ validator: containsCharsField({
+ message: i18nTexts.editPolicy.errors.policyNameContainsInvalidChars,
+ chars: [',', ' '],
+ }),
+ },
+ {
+ validator: (arg) => {
+ const policyName = arg.value;
+ if (window.TextEncoder && new window.TextEncoder().encode(policyName).length > 255) {
+ return {
+ message: i18nTexts.editPolicy.errors.policyNameTooLongErrorMessage,
+ };
+ }
+ },
+ },
+ {
+ validator: (arg) => {
+ const policyName = arg.value;
+ if (saveAsNewPolicy && policyName === originalPolicyName) {
+ return {
+ message: i18nTexts.editPolicy.errors.policyNameMustBeDifferentErrorMessage,
+ };
+ } else if (policyName !== originalPolicyName) {
+ const policyNames = policies.map((existingPolicy) => existingPolicy.name);
+ if (policyNames.includes(policyName)) {
+ return {
+ message: i18nTexts.editPolicy.errors.policyNameAlreadyUsedErrorMessage,
+ };
+ }
+ }
+ },
+ },
+ ];
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts
index 1fba69b7634ae..ccd5d3a568fe3 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts
@@ -98,6 +98,42 @@ export const i18nTexts = {
defaultMessage: 'Only non-negative numbers are allowed.',
}
),
+ policyNameContainsInvalidChars: i18n.translate(
+ 'xpack.indexLifecycleMgmt.editPolicy.errors.policyNameContainsInvalidCharsError',
+ {
+ defaultMessage: 'A policy name cannot contain spaces or commas.',
+ }
+ ),
+ policyNameAlreadyUsedErrorMessage: i18n.translate(
+ 'xpack.indexLifecycleMgmt.editPolicy.policyNameAlreadyUsedError',
+ {
+ defaultMessage: 'That policy name is already used.',
+ }
+ ),
+ policyNameMustBeDifferentErrorMessage: i18n.translate(
+ 'xpack.indexLifecycleMgmt.editPolicy.differentPolicyNameRequiredError',
+ {
+ defaultMessage: 'The policy name must be different.',
+ }
+ ),
+ policyNameRequiredMessage: i18n.translate(
+ 'xpack.indexLifecycleMgmt.editPolicy.policyNameRequiredError',
+ {
+ defaultMessage: 'A policy name is required.',
+ }
+ ),
+ policyNameStartsWithUnderscoreErrorMessage: i18n.translate(
+ 'xpack.indexLifecycleMgmt.editPolicy.policyNameStartsWithUnderscoreError',
+ {
+ defaultMessage: 'A policy name cannot start with an underscore.',
+ }
+ ),
+ policyNameTooLongErrorMessage: i18n.translate(
+ 'xpack.indexLifecycleMgmt.editPolicy.policyNameTooLongError',
+ {
+ defaultMessage: 'A policy name cannot be longer than 255 bytes.',
+ }
+ ),
},
},
};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_save.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/save_policy.ts
similarity index 84%
rename from x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_save.ts
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/save_policy.ts
index 9cf622e830cb2..e2ab6a8817ef6 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_save.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/save_policy.ts
@@ -3,23 +3,22 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-
import { i18n } from '@kbn/i18n';
import { METRIC_TYPE } from '@kbn/analytics';
import { SerializedPolicy } from '../../../../common/types';
-import { savePolicy as savePolicyApi } from '../api';
-import { showApiError } from '../api_errors';
-import { getUiMetricsForPhases, trackUiMetric } from '../ui_metric';
+
import { UIM_POLICY_CREATE, UIM_POLICY_UPDATE } from '../../constants';
-import { toasts } from '../notification';
+
+import { toasts } from '../../services/notification';
+import { savePolicy as savePolicyApi } from '../../services/api';
+import { getUiMetricsForPhases, trackUiMetric } from '../../services/ui_metric';
+import { showApiError } from '../../services/api_errors';
export const savePolicy = async (
- readSerializedPolicy: () => SerializedPolicy,
+ serializedPolicy: SerializedPolicy,
isNew: boolean
): Promise => {
- const serializedPolicy = readSerializedPolicy();
-
try {
await savePolicyApi(serializedPolicy);
} catch (err) {
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts
index 1884f8dbc0619..dc3d8a640e682 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts
@@ -38,6 +38,10 @@ interface ColdPhaseMetaFields extends DataAllocationMetaFields, MinAgeField {
freezeEnabled: boolean;
}
+interface DeletePhaseMetaFields extends MinAgeField {
+ enabled: boolean;
+}
+
/**
* Describes the shape of data after deserialization.
*/
@@ -50,5 +54,6 @@ export interface FormInternal extends SerializedPolicy {
hot: HotPhaseMetaFields;
warm: WarmPhaseMetaFields;
cold: ColdPhaseMetaFields;
+ delete: DeletePhaseMetaFields;
};
}
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/delete_phase.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/delete_phase.ts
deleted file mode 100644
index 6ada039d45cd9..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/delete_phase.ts
+++ /dev/null
@@ -1,88 +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 { DeletePhase, SerializedDeletePhase } from '../../../../common/types';
-import { serializedPhaseInitialization } from '../../constants';
-import { isNumber, splitSizeAndUnits } from './policy_serialization';
-import {
- numberRequiredMessage,
- PhaseValidationErrors,
- positiveNumberRequiredMessage,
-} from './policy_validation';
-
-const deletePhaseInitialization: DeletePhase = {
- phaseEnabled: false,
- selectedMinimumAge: '0',
- selectedMinimumAgeUnits: 'd',
- waitForSnapshotPolicy: '',
-};
-
-export const deletePhaseFromES = (phaseSerialized?: SerializedDeletePhase): DeletePhase => {
- const phase = { ...deletePhaseInitialization };
- if (phaseSerialized === undefined || phaseSerialized === null) {
- return phase;
- }
-
- phase.phaseEnabled = true;
- if (phaseSerialized.min_age) {
- const { size: minAge, units: minAgeUnits } = splitSizeAndUnits(phaseSerialized.min_age);
- phase.selectedMinimumAge = minAge;
- phase.selectedMinimumAgeUnits = minAgeUnits;
- }
-
- if (phaseSerialized.actions) {
- const actions = phaseSerialized.actions;
-
- if (actions.wait_for_snapshot) {
- phase.waitForSnapshotPolicy = actions.wait_for_snapshot.policy;
- }
- }
-
- return phase;
-};
-
-export const deletePhaseToES = (
- phase: DeletePhase,
- originalEsPhase?: SerializedDeletePhase
-): SerializedDeletePhase => {
- if (!originalEsPhase) {
- originalEsPhase = { ...serializedPhaseInitialization };
- }
- const esPhase = { ...originalEsPhase };
-
- if (isNumber(phase.selectedMinimumAge)) {
- esPhase.min_age = `${phase.selectedMinimumAge}${phase.selectedMinimumAgeUnits}`;
- }
-
- esPhase.actions = esPhase.actions ? { ...esPhase.actions } : {};
-
- if (phase.waitForSnapshotPolicy) {
- esPhase.actions.wait_for_snapshot = {
- policy: phase.waitForSnapshotPolicy,
- };
- } else {
- delete esPhase.actions.wait_for_snapshot;
- }
-
- return esPhase;
-};
-
-export const validateDeletePhase = (phase: DeletePhase): PhaseValidationErrors => {
- if (!phase.phaseEnabled) {
- return {};
- }
-
- const phaseErrors = {} as PhaseValidationErrors;
-
- // min age needs to be a positive number
- if (!isNumber(phase.selectedMinimumAge)) {
- phaseErrors.selectedMinimumAge = [numberRequiredMessage];
- } else if (parseInt(phase.selectedMinimumAge, 10) < 0) {
- phaseErrors.selectedMinimumAge = [positiveNumberRequiredMessage];
- }
-
- return { ...phaseErrors };
-};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts
deleted file mode 100644
index 19481b39a2c80..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts
+++ /dev/null
@@ -1,198 +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.
- */
-// Prefer importing entire lodash library, e.g. import { get } from "lodash"
-// eslint-disable-next-line no-restricted-imports
-import cloneDeep from 'lodash/cloneDeep';
-import { deserializePolicy, legacySerializePolicy } from './policy_serialization';
-import { defaultNewDeletePhase } from '../../constants';
-
-describe('Policy serialization', () => {
- test('serialize a policy using "default" data allocation', () => {
- expect(
- legacySerializePolicy(
- {
- name: 'test',
- phases: {
- delete: { ...defaultNewDeletePhase },
- },
- },
- {
- name: 'test',
- phases: {
- hot: { actions: {} },
- },
- }
- )
- ).toEqual({
- name: 'test',
- phases: {},
- });
- });
-
- test('serialize a policy using "custom" data allocation', () => {
- expect(
- legacySerializePolicy(
- {
- name: 'test',
- phases: {
- delete: { ...defaultNewDeletePhase },
- },
- },
- {
- name: 'test',
- phases: {
- hot: { actions: {} },
- },
- }
- )
- ).toEqual({
- name: 'test',
- phases: {},
- });
- });
-
- test('serialize a policy using "custom" data allocation with no node attributes', () => {
- expect(
- legacySerializePolicy(
- {
- name: 'test',
- phases: {
- delete: { ...defaultNewDeletePhase },
- },
- },
- {
- name: 'test',
- phases: {
- hot: { actions: {} },
- },
- }
- )
- ).toEqual({
- // There should be no allocation action in any phases...
- name: 'test',
- phases: {},
- });
- });
-
- test('serialize a policy using "none" data allocation with no node attributes', () => {
- expect(
- legacySerializePolicy(
- {
- name: 'test',
- phases: {
- delete: { ...defaultNewDeletePhase },
- },
- },
- {
- name: 'test',
- phases: {
- hot: { actions: {} },
- },
- }
- )
- ).toEqual({
- // There should be no allocation action in any phases...
- name: 'test',
- phases: {},
- });
- });
-
- test('serialization does not alter the original policy', () => {
- const originalPolicy = {
- name: 'test',
- phases: {},
- };
-
- const originalClone = cloneDeep(originalPolicy);
-
- const deserializedPolicy = {
- name: 'test',
- phases: {
- delete: { ...defaultNewDeletePhase },
- },
- };
-
- legacySerializePolicy(deserializedPolicy, originalPolicy);
- expect(originalPolicy).toEqual(originalClone);
- });
-
- test('serialize a policy using "best_compression" codec for forcemerge', () => {
- expect(
- legacySerializePolicy(
- {
- name: 'test',
- phases: {
- delete: { ...defaultNewDeletePhase },
- },
- },
- {
- name: 'test',
- phases: {
- hot: { actions: {} },
- },
- }
- )
- ).toEqual({
- name: 'test',
- phases: {},
- });
- });
-
- test('de-serialize a policy using "best_compression" codec for forcemerge', () => {
- expect(
- deserializePolicy({
- modified_date: Date.now().toString(),
- name: 'test',
- version: 1,
- policy: {
- name: 'test',
- phases: {
- hot: {
- actions: {
- rollover: {
- max_age: '30d',
- max_size: '50gb',
- },
- forcemerge: {
- max_num_segments: 1,
- index_codec: 'best_compression',
- },
- set_priority: {
- priority: 100,
- },
- },
- },
- },
- },
- })
- ).toEqual({
- name: 'test',
- phases: {
- delete: { ...defaultNewDeletePhase },
- },
- });
- });
-
- test('delete "best_compression" codec for forcemerge if disabled in UI', () => {
- expect(
- legacySerializePolicy(
- {
- name: 'test',
- phases: {
- delete: { ...defaultNewDeletePhase },
- },
- },
- {
- name: 'test',
- phases: {},
- }
- )
- ).toEqual({
- name: 'test',
- phases: {},
- });
- });
-});
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts
deleted file mode 100644
index 55e9d88dcd383..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts
+++ /dev/null
@@ -1,82 +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 { LegacyPolicy, PolicyFromES, SerializedPolicy } from '../../../../common/types';
-
-import { defaultNewDeletePhase, serializedPhaseInitialization } from '../../constants';
-
-import { deletePhaseFromES, deletePhaseToES } from './delete_phase';
-
-export const splitSizeAndUnits = (field: string): { size: string; units: string } => {
- let size = '';
- let units = '';
-
- const result = /(\d+)(\w+)/.exec(field);
- if (result) {
- size = result[1];
- units = result[2];
- }
-
- return {
- size,
- units,
- };
-};
-
-export const isNumber = (value: any): boolean => value !== '' && value !== null && isFinite(value);
-
-export const getPolicyByName = (
- policies: PolicyFromES[] | null | undefined,
- policyName: string = ''
-): PolicyFromES | undefined => {
- if (policies && policies.length > 0) {
- return policies.find((policy: PolicyFromES) => policy.name === policyName);
- }
-};
-
-export const initializeNewPolicy = (newPolicyName: string = ''): LegacyPolicy => {
- return {
- name: newPolicyName,
- phases: {
- delete: { ...defaultNewDeletePhase },
- },
- };
-};
-
-export const deserializePolicy = (policy: PolicyFromES): LegacyPolicy => {
- const {
- name,
- policy: { phases },
- } = policy;
-
- return {
- name,
- phases: {
- delete: deletePhaseFromES(phases.delete),
- },
- };
-};
-
-export const legacySerializePolicy = (
- policy: LegacyPolicy,
- originalEsPolicy: SerializedPolicy = {
- name: policy.name,
- phases: { hot: { ...serializedPhaseInitialization } },
- }
-): SerializedPolicy => {
- const serializedPolicy = {
- name: policy.name,
- phases: {},
- } as SerializedPolicy;
-
- if (policy.phases.delete.phaseEnabled) {
- serializedPolicy.phases.delete = deletePhaseToES(
- policy.phases.delete,
- originalEsPolicy.phases.delete
- );
- }
- return serializedPolicy;
-};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts
deleted file mode 100644
index 79c909c433f33..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts
+++ /dev/null
@@ -1,144 +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 { i18n } from '@kbn/i18n';
-import { DeletePhase, LegacyPolicy, PolicyFromES } from '../../../../common/types';
-import { validateDeletePhase } from './delete_phase';
-
-export const propertyof = (propertyName: keyof T & string) => propertyName;
-
-export const numberRequiredMessage = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.numberRequiredError',
- {
- defaultMessage: 'A number is required.',
- }
-);
-
-// TODO validation includes 0 -> should be non-negative number?
-export const positiveNumberRequiredMessage = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.positiveNumberRequiredError',
- {
- defaultMessage: 'Only positive numbers are allowed.',
- }
-);
-
-export const positiveNumbersAboveZeroErrorMessage = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.positiveNumberAboveZeroRequiredError',
- {
- defaultMessage: 'Only numbers above 0 are allowed.',
- }
-);
-
-export const policyNameRequiredMessage = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.policyNameRequiredError',
- {
- defaultMessage: 'A policy name is required.',
- }
-);
-
-export const policyNameStartsWithUnderscoreErrorMessage = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.policyNameStartsWithUnderscoreError',
- {
- defaultMessage: 'A policy name cannot start with an underscore.',
- }
-);
-export const policyNameContainsCommaErrorMessage = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.policyNameContainsCommaError',
- {
- defaultMessage: 'A policy name cannot include a comma.',
- }
-);
-export const policyNameContainsSpaceErrorMessage = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.policyNameContainsSpaceError',
- {
- defaultMessage: 'A policy name cannot include a space.',
- }
-);
-
-export const policyNameTooLongErrorMessage = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.policyNameTooLongError',
- {
- defaultMessage: 'A policy name cannot be longer than 255 bytes.',
- }
-);
-export const policyNameMustBeDifferentErrorMessage = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.differentPolicyNameRequiredError',
- {
- defaultMessage: 'The policy name must be different.',
- }
-);
-export const policyNameAlreadyUsedErrorMessage = i18n.translate(
- 'xpack.indexLifecycleMgmt.editPolicy.policyNameAlreadyUsedError',
- {
- defaultMessage: 'That policy name is already used.',
- }
-);
-export type PhaseValidationErrors = {
- [P in keyof Partial]: string[];
-};
-
-export interface ValidationErrors {
- delete: PhaseValidationErrors;
- policyName: string[];
-}
-
-export const validatePolicy = (
- saveAsNew: boolean,
- policy: LegacyPolicy,
- policies: PolicyFromES[],
- originalPolicyName: string
-): [boolean, ValidationErrors] => {
- const policyNameErrors: string[] = [];
- if (!policy.name) {
- policyNameErrors.push(policyNameRequiredMessage);
- } else {
- if (policy.name.startsWith('_')) {
- policyNameErrors.push(policyNameStartsWithUnderscoreErrorMessage);
- }
- if (policy.name.includes(',')) {
- policyNameErrors.push(policyNameContainsCommaErrorMessage);
- }
- if (policy.name.includes(' ')) {
- policyNameErrors.push(policyNameContainsSpaceErrorMessage);
- }
- if (window.TextEncoder && new window.TextEncoder().encode(policy.name).length > 255) {
- policyNameErrors.push(policyNameTooLongErrorMessage);
- }
-
- if (saveAsNew && policy.name === originalPolicyName) {
- policyNameErrors.push(policyNameMustBeDifferentErrorMessage);
- } else if (policy.name !== originalPolicyName) {
- const policyNames = policies.map((existingPolicy) => existingPolicy.name);
- if (policyNames.includes(policy.name)) {
- policyNameErrors.push(policyNameAlreadyUsedErrorMessage);
- }
- }
- }
-
- const deletePhaseErrors = validateDeletePhase(policy.phases.delete);
- const isValid = policyNameErrors.length === 0 && Object.keys(deletePhaseErrors).length === 0;
- return [
- isValid,
- {
- policyName: [...policyNameErrors],
- delete: deletePhaseErrors,
- },
- ];
-};
-
-export const findFirstError = (errors?: ValidationErrors): string | undefined => {
- if (!errors) {
- return;
- }
-
- if (errors.policyName.length > 0) {
- return propertyof('policyName');
- }
-
- if (Object.keys(errors.delete).length > 0) {
- return `${propertyof('delete')}.${Object.keys(errors.delete)[0]}`;
- }
-};
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 023aeba57aa7a..a127574d5bad0 100644
--- a/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts
@@ -18,6 +18,7 @@ export {
getFieldValidityAndErrorMessage,
useFormContext,
FormSchema,
+ ValidationConfig,
} from '../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib';
export { fieldValidators } from '../../../../src/plugins/es_ui_shared/static/forms/helpers';
@@ -27,6 +28,8 @@ export {
NumericField,
SelectField,
SuperSelectField,
+ ComboBoxField,
+ TextField,
} from '../../../../src/plugins/es_ui_shared/static/forms/components';
export { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public';
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index e7784846598e4..baa4f37791007 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -9119,24 +9119,18 @@
"xpack.indexLifecycleMgmt.editPolicy.nodeAttributesReloadButton": "再試行",
"xpack.indexLifecycleMgmt.editPolicy.nodeDetailsLoadingFailedTitle": "ノード属性詳細を読み込めません",
"xpack.indexLifecycleMgmt.editPolicy.nodeDetailsReloadButton": "再試行",
- "xpack.indexLifecycleMgmt.editPolicy.numberRequiredError": "数字が必要です。",
"xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeLabel": "コールドフェーズのタイミング",
"xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeUnitsAriaLabel": "コールドフェーズのタイミングの単位",
"xpack.indexLifecycleMgmt.editPolicy.phaseDelete.minimumAgeLabel": "削除フェーズのタイミング",
"xpack.indexLifecycleMgmt.editPolicy.phaseDelete.minimumAgeUnitsAriaLabel": "削除フェーズのタイミングの単位",
- "xpack.indexLifecycleMgmt.editPolicy.phaseErrorMessage": "エラーを修正してください",
"xpack.indexLifecycleMgmt.editPolicy.phaseWarm.minimumAgeLabel": "ウォームフェーズのタイミング",
"xpack.indexLifecycleMgmt.editPolicy.phaseWarm.minimumAgeUnitsAriaLabel": "ウォームフェーズのタイミングの単位",
"xpack.indexLifecycleMgmt.editPolicy.policiesLoading": "ポリシーを読み込み中…",
"xpack.indexLifecycleMgmt.editPolicy.policyNameAlreadyUsedError": "このポリシー名は既に使用されています。",
- "xpack.indexLifecycleMgmt.editPolicy.policyNameContainsCommaError": "ポリシー名にはコンマを使用できません。",
- "xpack.indexLifecycleMgmt.editPolicy.policyNameContainsSpaceError": "ポリシー名にはスペースを使用できません。",
"xpack.indexLifecycleMgmt.editPolicy.policyNameLabel": "ポリシー名",
"xpack.indexLifecycleMgmt.editPolicy.policyNameRequiredError": "ポリシー名が必要です。",
"xpack.indexLifecycleMgmt.editPolicy.policyNameStartsWithUnderscoreError": "ポリシー名の頭にアンダーラインを使用することはできません。",
"xpack.indexLifecycleMgmt.editPolicy.policyNameTooLongError": "ポリシー名は 255 バイト未満である必要があります。",
- "xpack.indexLifecycleMgmt.editPolicy.positiveNumberAboveZeroRequiredError": "0 よりも大きい数字のみ使用できます。",
- "xpack.indexLifecycleMgmt.editPolicy.positiveNumberRequiredError": "プラスの数字のみ使用できます。",
"xpack.indexLifecycleMgmt.editPolicy.rolloverDaysOptionLabel": "ロールオーバーからの経過日数",
"xpack.indexLifecycleMgmt.editPolicy.rolloverHoursOptionLabel": "ロールオーバーからの経過時間数",
"xpack.indexLifecycleMgmt.editPolicy.rolloverMicroSecondsOptionLabel": "ロールオーバーからの経過時間(マイクロ秒)",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index f3cd662bacba7..c4274524928fd 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -9128,24 +9128,18 @@
"xpack.indexLifecycleMgmt.editPolicy.nodeAttributesReloadButton": "重试",
"xpack.indexLifecycleMgmt.editPolicy.nodeDetailsLoadingFailedTitle": "无法加载节点属性详情",
"xpack.indexLifecycleMgmt.editPolicy.nodeDetailsReloadButton": "重试",
- "xpack.indexLifecycleMgmt.editPolicy.numberRequiredError": "数字必填。",
"xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeLabel": "冷阶段计时",
"xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeUnitsAriaLabel": "冷阶段计时单位",
"xpack.indexLifecycleMgmt.editPolicy.phaseDelete.minimumAgeLabel": "删除阶段计时",
"xpack.indexLifecycleMgmt.editPolicy.phaseDelete.minimumAgeUnitsAriaLabel": "删除阶段计时单位",
- "xpack.indexLifecycleMgmt.editPolicy.phaseErrorMessage": "修复错误",
"xpack.indexLifecycleMgmt.editPolicy.phaseWarm.minimumAgeLabel": "温阶段计时",
"xpack.indexLifecycleMgmt.editPolicy.phaseWarm.minimumAgeUnitsAriaLabel": "温阶段计时单位",
"xpack.indexLifecycleMgmt.editPolicy.policiesLoading": "正在加载策略……",
"xpack.indexLifecycleMgmt.editPolicy.policyNameAlreadyUsedError": "该策略名称已被使用。",
- "xpack.indexLifecycleMgmt.editPolicy.policyNameContainsCommaError": "策略名称不能包含逗号。",
- "xpack.indexLifecycleMgmt.editPolicy.policyNameContainsSpaceError": "策略名称不能包含空格。",
"xpack.indexLifecycleMgmt.editPolicy.policyNameLabel": "策略名称",
"xpack.indexLifecycleMgmt.editPolicy.policyNameRequiredError": "策略名称必填。",
"xpack.indexLifecycleMgmt.editPolicy.policyNameStartsWithUnderscoreError": "策略名称不能以下划线开头。",
"xpack.indexLifecycleMgmt.editPolicy.policyNameTooLongError": "策略名称的长度不能大于 255 字节。",
- "xpack.indexLifecycleMgmt.editPolicy.positiveNumberAboveZeroRequiredError": "仅允许使用 0 以上的数字。",
- "xpack.indexLifecycleMgmt.editPolicy.positiveNumberRequiredError": "仅允许使用正数。",
"xpack.indexLifecycleMgmt.editPolicy.rolloverDaysOptionLabel": "天(自滚动更新)",
"xpack.indexLifecycleMgmt.editPolicy.rolloverHoursOptionLabel": "小时(自滚动更新)",
"xpack.indexLifecycleMgmt.editPolicy.rolloverMicroSecondsOptionLabel": "微秒(自滚动更新)",