-
+
+
You can think of policies as state machines. "Actions" are the operations ISM performs when an index is in a certain state.
"Transitions" define when to move from one state to another.{" "}
-
+
Learn more
diff --git a/public/pages/VisualCreatePolicy/components/States/__snapshots__/State.test.tsx.snap b/public/pages/VisualCreatePolicy/components/States/__snapshots__/State.test.tsx.snap
index 67f99b7ac..30fa05919 100644
--- a/public/pages/VisualCreatePolicy/components/States/__snapshots__/State.test.tsx.snap
+++ b/public/pages/VisualCreatePolicy/components/States/__snapshots__/State.test.tsx.snap
@@ -11,7 +11,7 @@ exports[` spec renders the component 1`] = `
@@ -113,25 +113,33 @@ exports[` spec renders the component 1`] = `
-
- EuiIconMock
-
+
+ EuiIconMock
+
+
-
- EuiIconMock
-
+
+ EuiIconMock
+
+
@@ -163,7 +171,7 @@ exports[` spec renders the component 1`] = `
class="euiFlexItem"
>
spec renders the component 1`] = `
class="euiFlexItem"
>
spec renders the component 1`] = `
class="euiText euiText--small"
style="padding: 5px 0px;"
>
-
- You can think of policies as state machines. "Actions" are the operations ISM performs when an index is in a certain state.
-
- "Transitions" define when to move from one state to another.
-
-
- Learn more
- EuiIconMock
-
-
+ You can think of policies as state machines. "Actions" are the operations ISM performs when an index is in a certain state.
+
+ "Transitions" define when to move from one state to another.
+
+
+ Learn more
+ EuiIconMock
+
+
+
@@ -120,7 +124,7 @@ exports[` spec renders the component 1`] = `
@@ -222,25 +226,33 @@ exports[` spec renders the component 1`] = `
-
- EuiIconMock
-
+
+ EuiIconMock
+
+
-
- EuiIconMock
-
+
+ EuiIconMock
+
+
@@ -272,7 +284,7 @@ exports[` spec renders the component 1`] = `
class="euiFlexItem"
>
spec renders the component 1`] = `
class="euiFlexItem"
>
spec renders the component 1`] = `
@@ -415,25 +427,33 @@ exports[` spec renders the component 1`] = `
-
- EuiIconMock
-
+
+ EuiIconMock
+
+
-
- EuiIconMock
-
+
+ EuiIconMock
+
+
@@ -465,7 +485,7 @@ exports[` spec renders the component 1`] = `
class="euiFlexItem"
>
) => {
const timeout = e.target.value;
onChangeAction(action.clone({ ...action.action, timeout }));
@@ -59,18 +59,23 @@ const TimeoutRetrySettings = ({ action, editAction, onChangeAction }: TimeoutRet
-
+
) => {
const count = e.target.valueAsNumber;
- onChangeAction(action.clone({ ...action.action, retry: { ...action.action.retry, count } }));
+ const retry = { ...action.action.retry, count };
+ if (isNaN(count)) delete retry.count;
+ onChangeAction(action.clone({ ...action.action, retry }));
}}
/>
@@ -81,10 +86,10 @@ const TimeoutRetrySettings = ({ action, editAction, onChangeAction }: TimeoutRet
) => {
const backoff = e.target.value;
onChangeAction(action.clone({ ...action.action, retry: { ...action.action.retry, backoff } }));
@@ -98,9 +103,9 @@ const TimeoutRetrySettings = ({ action, editAction, onChangeAction }: TimeoutRet
) => {
const delay = e.target.value;
onChangeAction(action.clone({ ...action.action, retry: { ...action.action.retry, delay } }));
diff --git a/public/pages/VisualCreatePolicy/components/TimeoutRetrySettings/__snapshots__/TimeoutRetrySettings.test.tsx.snap b/public/pages/VisualCreatePolicy/components/TimeoutRetrySettings/__snapshots__/TimeoutRetrySettings.test.tsx.snap
index f2a3319ad..96f4576f6 100644
--- a/public/pages/VisualCreatePolicy/components/TimeoutRetrySettings/__snapshots__/TimeoutRetrySettings.test.tsx.snap
+++ b/public/pages/VisualCreatePolicy/components/TimeoutRetrySettings/__snapshots__/TimeoutRetrySettings.test.tsx.snap
@@ -61,6 +61,7 @@ exports[` spec renders the component 1`] = `
style="margin-bottom: 5px;"
>
The timeout period for the action. Accepts time units, e.g. "5h" or "1d".
+
@@ -114,6 +116,7 @@ exports[`
spec renders the component 1`] = `
style="margin-bottom: 5px;"
>
- The number of times the action should be retried if it fails.
+ The number of times the action should be retried if it fails. Must be greater than 0.
+
@@ -168,6 +172,7 @@ exports[` spec renders the component 1`] = `
style="margin-bottom: 5px;"
>
The backoff policy type to use when retrying.
+
@@ -236,6 +242,7 @@ exports[` spec renders the component 1`] = `
style="margin-bottom: 5px;"
>
The time to wait between retries. Accepts time units, e.g. "2h" or "1d"
+
diff --git a/public/pages/VisualCreatePolicy/components/Transition/Transition.tsx b/public/pages/VisualCreatePolicy/components/Transition/Transition.tsx
index 8ac282502..24bbb6743 100644
--- a/public/pages/VisualCreatePolicy/components/Transition/Transition.tsx
+++ b/public/pages/VisualCreatePolicy/components/Transition/Transition.tsx
@@ -10,14 +10,16 @@
*/
import React, { ChangeEvent } from "react";
-import { EuiFormRow, EuiSelect, EuiSpacer, EuiFieldText, EuiFieldNumber } from "@elastic/eui";
+import { EuiLink, EuiIcon, EuiFormRow, EuiSelect, EuiSpacer, EuiFieldText, EuiFieldNumber } from "@elastic/eui";
import moment from "moment-timezone";
import EuiFormCustomLabel from "../EuiFormCustomLabel";
import { UITransition } from "../../../../../models/interfaces";
+import { TRANSITION_DOCUMENTATION_URL } from "../../../../utils/constants";
const timezones = moment.tz.names().map((tz) => ({ label: tz, text: tz }));
const conditionTypeOptions = [
+ { value: "none", text: "No condition" },
{ value: "min_index_age", text: "Minimum index age" },
{ value: "min_doc_count", text: "Minimum doc count" },
{ value: "min_size", text: "Minimum size" },
@@ -31,30 +33,30 @@ interface TransitionProps {
const Transition = ({ uiTransition, onChangeTransition }: TransitionProps) => {
// We currently only support one transition condition
- const conditionType = Object.keys(uiTransition.transition?.conditions || []).pop() || "min_index_age";
+ const conditionType = Object.keys(uiTransition.transition.conditions || []).pop() || "none";
+ const conditions = uiTransition.transition.conditions;
return (
<>
-
+
{
const selectedConditionType = e.target.value;
- let condition = {};
- if (selectedConditionType === "min_index_age") condition = { min_index_age: "30d" };
- if (selectedConditionType === "min_doc_count") condition = { min_doc_count: 1000000 };
- if (selectedConditionType === "min_size") condition = { min_size: "50gb" };
+ const transition = { ...uiTransition.transition };
+ if (selectedConditionType === "none") delete transition.conditions;
+ if (selectedConditionType === "min_index_age") transition.conditions = { min_index_age: "30d" };
+ if (selectedConditionType === "min_doc_count") transition.conditions = { min_doc_count: 1000000 };
+ if (selectedConditionType === "min_size") transition.conditions = { min_size: "50gb" };
if (selectedConditionType === "cron")
- condition = { cron: { cron: { expression: "* 17 * * SAT", timezone: "America/Los_Angeles" } } };
+ transition.conditions = { cron: { cron: { expression: "* 17 * * SAT", timezone: "America/Los_Angeles" } } };
onChangeTransition({
...uiTransition,
- transition: {
- ...uiTransition.transition,
- conditions: condition,
- },
+ transition,
});
}}
data-test-subj="create-state-action-type"
@@ -66,10 +68,10 @@ const Transition = ({ uiTransition, onChangeTransition }: TransitionProps) => {
{conditionType === "min_index_age" && (
<>
-
+
) => {
const minIndexAge = e.target.value;
onChangeTransition({
@@ -94,19 +96,21 @@ const Transition = ({ uiTransition, onChangeTransition }: TransitionProps) => {
title="Minimum doc count"
helpText="The minimum number of documents required to transition to the next state."
/>
-
+
) => {
const minDocCount = e.target.valueAsNumber;
+ const conditions = { min_doc_count: minDocCount };
+ // TODO: clean this up..
+ // set it to undefined instead of deleting... as we use the presence of the key itself for the type of transition
+ if (isNaN(minDocCount)) conditions.min_doc_count = undefined;
onChangeTransition({
...uiTransition,
transition: {
...uiTransition.transition,
- conditions: {
- min_doc_count: minDocCount,
- },
+ conditions,
},
});
}}
@@ -122,10 +126,10 @@ const Transition = ({ uiTransition, onChangeTransition }: TransitionProps) => {
title="Minimum index size"
helpText="The minimum size of the total primary shard storage required to transition to the next state."
/>
-
+
) => {
const minSize = e.target.value;
onChangeTransition({
@@ -146,11 +150,19 @@ const Transition = ({ uiTransition, onChangeTransition }: TransitionProps) => {
{conditionType === "cron" && (
<>
-
-
+
+ Learn more
+
+ }
+ />
+
) => {
const expression = e.target.value;
onChangeTransition({
@@ -175,11 +187,12 @@ const Transition = ({ uiTransition, onChangeTransition }: TransitionProps) => {
-
+
) => {
const timezone = e.target.value;
onChangeTransition({
diff --git a/public/pages/VisualCreatePolicy/components/Transition/__snapshots__/Transition.test.tsx.snap b/public/pages/VisualCreatePolicy/components/Transition/__snapshots__/Transition.test.tsx.snap
index 66cc43b8d..a623686d1 100644
--- a/public/pages/VisualCreatePolicy/components/Transition/__snapshots__/Transition.test.tsx.snap
+++ b/public/pages/VisualCreatePolicy/components/Transition/__snapshots__/Transition.test.tsx.snap
@@ -6,6 +6,7 @@ exports[` spec renders the component 1`] = `
style="margin-bottom: 5px;"
>
Specify the condition needed to be met to transition to the destination state.
+
diff --git a/public/pages/VisualCreatePolicy/components/UIActions/AllocationUIAction.tsx b/public/pages/VisualCreatePolicy/components/UIActions/AllocationUIAction.tsx
index d6822093e..eb6f9cae9 100644
--- a/public/pages/VisualCreatePolicy/components/UIActions/AllocationUIAction.tsx
+++ b/public/pages/VisualCreatePolicy/components/UIActions/AllocationUIAction.tsx
@@ -10,9 +10,11 @@
*/
import React from "react";
+import { EuiFormRow, EuiCodeEditor } from "@elastic/eui";
import { AllocationAction, UIAction } from "../../../../../models/interfaces";
import { makeId } from "../../../../utils/helpers";
import { ActionType } from "../../utils/constants";
+import { DarkModeConsumer } from "../../../../components/DarkMode";
export default class AllocationUIAction implements UIAction {
id: string;
@@ -28,9 +30,54 @@ export default class AllocationUIAction implements UIAction {
clone = (action: AllocationAction = this.action) => new AllocationUIAction(action, this.id);
+ isValid = () => {
+ try {
+ JSON.parse(this.getActionJsonString(this.action));
+ return true;
+ } catch (err) {
+ return false;
+ }
+ };
+
+ getActionJsonString = (action: AllocationAction) => {
+ const allocation = action.allocation;
+ return allocation.hasOwnProperty("jsonString") ? allocation.jsonString : JSON.stringify(allocation, null, 4);
+ };
+
+ getActionJson = (action: AllocationAction) => {
+ const allocation = action.allocation;
+ return allocation.hasOwnProperty("jsonString") ? JSON.parse(allocation.jsonString) : allocation;
+ };
+
render = (action: UIAction, onChangeAction: (action: UIAction) => void) => {
- return
;
+ return (
+
+
+ {(isDarkMode) => (
+ {
+ onChangeAction(
+ this.clone({
+ ...action.action,
+ allocation: { jsonString: str },
+ })
+ );
+ }}
+ setOptions={{ fontSize: "14px" }}
+ aria-label="Code Editor"
+ />
+ )}
+
+
+ );
};
- toAction = () => this.action;
+ toAction = () => ({
+ ...this.action,
+ allocation: this.getActionJson(this.action),
+ });
}
diff --git a/public/pages/VisualCreatePolicy/components/UIActions/CloseUIAction.tsx b/public/pages/VisualCreatePolicy/components/UIActions/CloseUIAction.tsx
index 3f3a286fe..a474bea4e 100644
--- a/public/pages/VisualCreatePolicy/components/UIActions/CloseUIAction.tsx
+++ b/public/pages/VisualCreatePolicy/components/UIActions/CloseUIAction.tsx
@@ -28,6 +28,8 @@ export default class CloseUIAction implements UIAction {
clone = (action: CloseAction) => new CloseUIAction(action, this.id);
+ isValid = () => true;
+
render = (action: UIAction, onChangeAction: (action: UIAction) => void) => {
return
;
};
diff --git a/public/pages/VisualCreatePolicy/components/UIActions/DeleteUIAction.tsx b/public/pages/VisualCreatePolicy/components/UIActions/DeleteUIAction.tsx
index ece534f7a..35f1afeb7 100644
--- a/public/pages/VisualCreatePolicy/components/UIActions/DeleteUIAction.tsx
+++ b/public/pages/VisualCreatePolicy/components/UIActions/DeleteUIAction.tsx
@@ -28,6 +28,8 @@ export default class DeleteUIAction implements UIAction {
clone = (action: DeleteAction) => new DeleteUIAction(action, this.id);
+ isValid = () => true;
+
render = (action: UIAction, onChangeAction: (action: UIAction) => void) => {
return
;
};
diff --git a/public/pages/VisualCreatePolicy/components/UIActions/ForceMergeUIAction.tsx b/public/pages/VisualCreatePolicy/components/UIActions/ForceMergeUIAction.tsx
index c768940a8..a3bc01e12 100644
--- a/public/pages/VisualCreatePolicy/components/UIActions/ForceMergeUIAction.tsx
+++ b/public/pages/VisualCreatePolicy/components/UIActions/ForceMergeUIAction.tsx
@@ -30,23 +30,25 @@ export default class ForceMergeUIAction implements UIAction {
clone = (action: ForceMergeAction) => new ForceMergeUIAction(action, this.id);
+ isValid = () => {
+ const segments = this.action.force_merge.max_num_segments;
+ return !!segments && segments > 0;
+ };
+
render = (action: UIAction, onChangeAction: (action: UIAction) => void) => {
+ const segments = action.action.force_merge.max_num_segments;
return (
<>
-
-
+
+
) => {
const maxNumSegments = e.target.valueAsNumber;
- onChangeAction(
- this.clone({
- force_merge: {
- max_num_segments: maxNumSegments,
- },
- })
- );
+ const forceMerge = { max_num_segments: maxNumSegments };
+ if (isNaN(maxNumSegments)) delete forceMerge.max_num_segments;
+ onChangeAction(this.clone({ force_merge: forceMerge }));
}}
data-test-subj="action-render-force-merge"
/>
diff --git a/public/pages/VisualCreatePolicy/components/UIActions/IndexPriorityUIAction.tsx b/public/pages/VisualCreatePolicy/components/UIActions/IndexPriorityUIAction.tsx
index 0b466f03e..fb47f8ed7 100644
--- a/public/pages/VisualCreatePolicy/components/UIActions/IndexPriorityUIAction.tsx
+++ b/public/pages/VisualCreatePolicy/components/UIActions/IndexPriorityUIAction.tsx
@@ -30,21 +30,29 @@ export default class IndexPriorityUIAction implements UIAction new IndexPriorityUIAction(action, this.id);
+ isValid = () => {
+ const priority = this.action.index_priority.priority;
+ return typeof priority !== "undefined" && priority >= 0;
+ };
+
render = (action: UIAction, onChangeAction: (action: UIAction) => void) => {
+ const priority = action.action.index_priority.priority;
return (
<>
-
-
+
+
) => {
const priority = e.target.valueAsNumber;
- onChangeAction(
- this.clone({
- index_priority: { priority },
- })
- );
+ const indexPriority = { priority };
+ if (isNaN(priority)) delete indexPriority.priority;
+ onChangeAction(this.clone({ index_priority: indexPriority }));
}}
data-test-subj="action-render-index-priority"
/>
diff --git a/public/pages/VisualCreatePolicy/components/UIActions/NotificationUIAction.tsx b/public/pages/VisualCreatePolicy/components/UIActions/NotificationUIAction.tsx
index 627f595a6..2641609d3 100644
--- a/public/pages/VisualCreatePolicy/components/UIActions/NotificationUIAction.tsx
+++ b/public/pages/VisualCreatePolicy/components/UIActions/NotificationUIAction.tsx
@@ -22,6 +22,7 @@ interface NotifUIProps {
action: NotificationAction;
clone: (action: NotificationAction) => NotificationUIAction;
onChangeAction: (action: UIAction) => void;
+ isInvalid: boolean;
}
class NotifUI extends React.Component {
onChangeNotificationJsonString = (str: string) => {
@@ -35,12 +36,13 @@ class NotifUI extends React.Component {
};
render() {
- const { action } = this.props;
+ const { action, isInvalid } = this.props;
return (
);
}
@@ -61,11 +63,21 @@ export default class NotificationUIAction implements UIAction new NotificationUIAction(action, this.id);
+ isValid = () => {
+ try {
+ JSON.parse(this.action.notificationJsonString);
+ return true;
+ } catch (err) {
+ console.error(err);
+ return false;
+ }
+ };
+
render = (action: UIAction, onChangeAction: (action: UIAction) => void) => {
return (
{(services: BrowserServices | null) =>
- services &&
+ services &&
}
);
diff --git a/public/pages/VisualCreatePolicy/components/UIActions/OpenUIAction.tsx b/public/pages/VisualCreatePolicy/components/UIActions/OpenUIAction.tsx
index 0f0443200..42e335122 100644
--- a/public/pages/VisualCreatePolicy/components/UIActions/OpenUIAction.tsx
+++ b/public/pages/VisualCreatePolicy/components/UIActions/OpenUIAction.tsx
@@ -28,6 +28,8 @@ export default class OpenUIAction implements UIAction {
clone = (action: OpenAction) => new OpenUIAction(action, this.id);
+ isValid = () => true;
+
render = (action: UIAction, onChangeAction: (action: UIAction) => void) => {
return
;
};
diff --git a/public/pages/VisualCreatePolicy/components/UIActions/ReadOnlyUIAction.tsx b/public/pages/VisualCreatePolicy/components/UIActions/ReadOnlyUIAction.tsx
index b50be8a51..ffe876050 100644
--- a/public/pages/VisualCreatePolicy/components/UIActions/ReadOnlyUIAction.tsx
+++ b/public/pages/VisualCreatePolicy/components/UIActions/ReadOnlyUIAction.tsx
@@ -28,6 +28,8 @@ export default class ReadOnlyUIAction implements UIAction {
clone = (action: ReadOnlyAction) => new ReadOnlyUIAction(action, this.id);
+ isValid = () => true;
+
render = (action: UIAction, onChangeAction: (action: UIAction) => void) => {
return
;
};
diff --git a/public/pages/VisualCreatePolicy/components/UIActions/ReadWriteUIAction.tsx b/public/pages/VisualCreatePolicy/components/UIActions/ReadWriteUIAction.tsx
index 5cf13b408..ea67fdb52 100644
--- a/public/pages/VisualCreatePolicy/components/UIActions/ReadWriteUIAction.tsx
+++ b/public/pages/VisualCreatePolicy/components/UIActions/ReadWriteUIAction.tsx
@@ -28,6 +28,8 @@ export default class ReadWriteUIAction implements UIAction {
clone = (action: ReadWriteAction) => new ReadWriteUIAction(action, this.id);
+ isValid = () => true;
+
render = (action: UIAction, onChangeAction: (action: UIAction) => void) => {
return
;
};
diff --git a/public/pages/VisualCreatePolicy/components/UIActions/ReplicaCountUIAction.tsx b/public/pages/VisualCreatePolicy/components/UIActions/ReplicaCountUIAction.tsx
index 45c1be5be..9ecde903a 100644
--- a/public/pages/VisualCreatePolicy/components/UIActions/ReplicaCountUIAction.tsx
+++ b/public/pages/VisualCreatePolicy/components/UIActions/ReplicaCountUIAction.tsx
@@ -14,6 +14,7 @@ import { EuiFormRow, EuiFieldNumber } from "@elastic/eui";
import { ReplicaCountAction, UIAction } from "../../../../../models/interfaces";
import { makeId } from "../../../../utils/helpers";
import { ActionType } from "../../utils/constants";
+import EuiFormCustomLabel from "../EuiFormCustomLabel";
export default class ReplicaCountUIAction implements UIAction {
id: string;
@@ -29,25 +30,34 @@ export default class ReplicaCountUIAction implements UIAction new ReplicaCountUIAction(action, this.id);
+ isValid = () => {
+ const numberOfReplicas = this.action.replica_count.number_of_replicas;
+ return typeof numberOfReplicas !== "undefined" && numberOfReplicas >= 0;
+ };
+
render = (action: UIAction, onChangeAction: (action: UIAction) => void) => {
+ const replicas = action.action.replica_count.number_of_replicas;
return (
-
- ) => {
- const numberOfReplicas = e.target.valueAsNumber;
- onChangeAction(
- this.clone({
- replica_count: {
- number_of_replicas: numberOfReplicas,
- },
- })
- );
- }}
- data-test-subj="action-render-replica-count"
+ <>
+
-
+
+ ) => {
+ const numberOfReplicas = e.target.valueAsNumber;
+ const replicaCount = { number_of_replicas: numberOfReplicas };
+ if (isNaN(numberOfReplicas)) delete replicaCount.number_of_replicas;
+ onChangeAction(this.clone({ replica_count: replicaCount }));
+ }}
+ data-test-subj="action-render-replica-count"
+ />
+
+ >
);
};
diff --git a/public/pages/VisualCreatePolicy/components/UIActions/RolloverUIAction.tsx b/public/pages/VisualCreatePolicy/components/UIActions/RolloverUIAction.tsx
index cde80fdff..94ac38c1b 100644
--- a/public/pages/VisualCreatePolicy/components/UIActions/RolloverUIAction.tsx
+++ b/public/pages/VisualCreatePolicy/components/UIActions/RolloverUIAction.tsx
@@ -10,10 +10,11 @@
*/
import React, { ChangeEvent } from "react";
-import { EuiFormRow, EuiFieldNumber, EuiFieldText } from "@elastic/eui";
+import { EuiFormRow, EuiFieldNumber, EuiFieldText, EuiSpacer } from "@elastic/eui";
import { RolloverAction, UIAction } from "../../../../../models/interfaces";
import { makeId } from "../../../../utils/helpers";
import { ActionType } from "../../utils/constants";
+import EuiFormCustomLabel from "../EuiFormCustomLabel";
export default class RolloverUIAction implements UIAction {
id: string;
@@ -29,69 +30,78 @@ export default class RolloverUIAction implements UIAction {
clone = (action: RolloverAction) => new RolloverUIAction(action, this.id);
+ isValid = () => {
+ const minIndexAge = this.action.rollover.min_index_age;
+ const minDocCount = this.action.rollover.min_doc_count;
+ const minSize = this.action.rollover.min_size;
+ if (typeof minDocCount !== "undefined") {
+ if (minDocCount <= 0) return false;
+ }
+
+ // for minIndexAge and minSize just let them through and backend will fail the validation
+ // TODO -> add validation for index age and size.. but involves replicating checks for byte strings and time strings
+ return !!minIndexAge || minDocCount === 0 || !!minDocCount || !!minSize;
+ };
+
render = (action: UIAction, onChangeAction: (action: UIAction) => void) => {
+ const rollover = action.action.rollover;
return (
<>
-
+
+
) => {
const minIndexAge = e.target.value;
- onChangeAction(
- this.clone({
- rollover: {
- ...action.action.rollover,
- min_index_age: minIndexAge,
- },
- })
- );
+ const rollover = { ...action.action.rollover };
+ if (minIndexAge) rollover.min_index_age = minIndexAge;
+ else delete rollover.min_index_age;
+ onChangeAction(this.clone({ rollover }));
}}
data-test-subj="action-render-rollover-min-index-age"
/>
-
+
+ isInvalid={!this.isValid()}
+ />
+
) => {
const minDocCount = e.target.valueAsNumber;
- onChangeAction(
- this.clone({
- rollover: {
- ...action.action.rollover,
- min_doc_count: minDocCount,
- },
- })
- );
+ const rollover = { ...action.action.rollover };
+ if (!isNaN(minDocCount)) rollover.min_doc_count = minDocCount;
+ else delete rollover.min_doc_count;
+ onChangeAction(this.clone({ rollover }));
}}
data-test-subj="action-render-rollover-min-doc-count"
/>
-
+
+
+
) => {
const minSize = e.target.value;
- onChangeAction(
- this.clone({
- rollover: {
- ...action.action.rollover,
- min_size: minSize,
- },
- })
- );
+ const rollover = { ...action.action.rollover };
+ if (minSize) rollover.min_size = minSize;
+ else delete rollover.min_size;
+ onChangeAction(this.clone({ rollover }));
}}
data-test-subj="action-render-rollover-min-size"
/>
diff --git a/public/pages/VisualCreatePolicy/components/UIActions/RollupUIAction.tsx b/public/pages/VisualCreatePolicy/components/UIActions/RollupUIAction.tsx
index a8cb03e6f..7c873eddb 100644
--- a/public/pages/VisualCreatePolicy/components/UIActions/RollupUIAction.tsx
+++ b/public/pages/VisualCreatePolicy/components/UIActions/RollupUIAction.tsx
@@ -30,20 +30,40 @@ export default class RollupUIAction implements UIAction {
clone = (action: RollupAction) => new RollupUIAction(action, this.id);
+ isValid = () => {
+ try {
+ JSON.parse(this.getActionJsonString(this.action));
+ return true;
+ } catch (err) {
+ return false;
+ }
+ };
+
+ getActionJsonString = (action: RollupAction) => {
+ const rollup = action.rollup;
+ return rollup.hasOwnProperty("jsonString") ? rollup.jsonString : JSON.stringify(rollup, null, 4);
+ };
+
+ getActionJson = (action: RollupAction) => {
+ const rollup = action.rollup;
+ return rollup.hasOwnProperty("jsonString") ? JSON.parse(rollup.jsonString) : rollup;
+ };
+
render = (action: UIAction, onChangeAction: (action: UIAction) => void) => {
+ // If we don't have a JSON string yet it just means we haven't converted the rollup to it yet
return (
-
+
{(isDarkMode) => (
{
onChangeAction(
this.clone({
- ...action,
+ ...action.action,
rollup: { jsonString: str },
})
);
@@ -59,7 +79,6 @@ export default class RollupUIAction implements UIAction {
toAction = () => ({
...this.action,
- // TODO: validate this in UI before parsing here in case it failsZ
- rollup: { ism_rollup: JSON.parse(this.action.rollup.jsonString) },
+ rollup: this.getActionJson(this.action),
});
}
diff --git a/public/pages/VisualCreatePolicy/components/UIActions/SnapshotUIAction.tsx b/public/pages/VisualCreatePolicy/components/UIActions/SnapshotUIAction.tsx
index 1916502e6..136c7b2b3 100644
--- a/public/pages/VisualCreatePolicy/components/UIActions/SnapshotUIAction.tsx
+++ b/public/pages/VisualCreatePolicy/components/UIActions/SnapshotUIAction.tsx
@@ -10,10 +10,11 @@
*/
import React, { ChangeEvent } from "react";
-import { EuiFormRow, EuiFieldText } from "@elastic/eui";
+import { EuiFormRow, EuiFieldText, EuiSpacer } from "@elastic/eui";
import { SnapshotAction, UIAction } from "../../../../../models/interfaces";
import { makeId } from "../../../../utils/helpers";
import { ActionType } from "../../utils/constants";
+import EuiFormCustomLabel from "../EuiFormCustomLabel";
export default class SnapshotUIAction implements UIAction {
id: string;
@@ -29,18 +30,22 @@ export default class SnapshotUIAction implements UIAction {
clone = (action: SnapshotAction) => new SnapshotUIAction(action, this.id);
+ isValid = () => {
+ return !!this.action.snapshot.snapshot && !!this.action.snapshot.repository;
+ };
+
render = (action: UIAction, onChangeAction: (action: UIAction) => void) => {
return (
<>
-
+ isInvalid={!this.isValid()}
+ />
+
) => {
const repository = e.target.value;
onChangeAction(
@@ -55,10 +60,12 @@ export default class SnapshotUIAction implements UIAction {
data-test-subj="action-render-snapshot-repository"
/>
-
+
+
+
) => {
const snapshot = e.target.value;
onChangeAction(
diff --git a/public/pages/VisualCreatePolicy/containers/CreateAction/CreateAction.tsx b/public/pages/VisualCreatePolicy/containers/CreateAction/CreateAction.tsx
index 9c927724e..0b2c27d8a 100644
--- a/public/pages/VisualCreatePolicy/containers/CreateAction/CreateAction.tsx
+++ b/public/pages/VisualCreatePolicy/containers/CreateAction/CreateAction.tsx
@@ -10,13 +10,13 @@
*/
import React, { Component, ChangeEvent } from "react";
-import { EuiFlyoutBody, EuiFlyoutFooter, EuiTitle, EuiFormRow, EuiSelect, EuiSpacer } from "@elastic/eui";
+import { EuiText, EuiLink, EuiIcon, EuiFlyoutBody, EuiFlyoutFooter, EuiTitle, EuiFormRow, EuiSelect, EuiSpacer } from "@elastic/eui";
import { UIAction, Action } from "../../../../../models/interfaces";
-import { actions } from "../../utils/constants";
import TimeoutRetrySettings from "../../components/TimeoutRetrySettings";
import { actionRepoSingleton, capitalizeFirstLetter } from "../../utils/helpers";
import FlyoutFooter from "../../components/FlyoutFooter";
import EuiFormCustomLabel from "../../components/EuiFormCustomLabel";
+import { ACTIONS_DOCUMENTATION_URL } from "../../../../utils/constants";
interface CreateActionProps {
stateName: string;
@@ -71,7 +71,7 @@ export default class CreateAction extends Component{bodyTitle}
+
+ Actions are the operations ISM performs when an index is in a certain state.{" "}
+
+ Learn more
+
+
+
-
+
diff --git a/public/pages/VisualCreatePolicy/containers/CreateAction/__snapshots__/CreateAction.test.tsx.snap b/public/pages/VisualCreatePolicy/containers/CreateAction/__snapshots__/CreateAction.test.tsx.snap
index 41cbe3618..af9693558 100644
--- a/public/pages/VisualCreatePolicy/containers/CreateAction/__snapshots__/CreateAction.test.tsx.snap
+++ b/public/pages/VisualCreatePolicy/containers/CreateAction/__snapshots__/CreateAction.test.tsx.snap
@@ -15,6 +15,22 @@ exports[` spec renders the component 1`] = `
>
Edit action
+
@@ -23,6 +39,7 @@ exports[` spec renders the component 1`] = `
style="margin-bottom: 5px;"
>
Select the action you want to add to this state.
+
diff --git a/public/pages/VisualCreatePolicy/containers/CreateState/Actions.tsx b/public/pages/VisualCreatePolicy/containers/CreateState/Actions.tsx
index e62592e6a..25dd13952 100644
--- a/public/pages/VisualCreatePolicy/containers/CreateState/Actions.tsx
+++ b/public/pages/VisualCreatePolicy/containers/CreateState/Actions.tsx
@@ -41,6 +41,7 @@ const Actions = ({ actions, onClickDeleteAction, onClickEditAction, onDragEndAct
isLast={actions.length - 1 === idx}
onClickDelete={() => onClickDeleteAction(idx)}
onClickEdit={() => onClickEditAction(action)}
+ draggableType="action"
/>
))}
diff --git a/public/pages/VisualCreatePolicy/containers/CreateState/CreateState.tsx b/public/pages/VisualCreatePolicy/containers/CreateState/CreateState.tsx
index 0846101c6..326f5ec34 100644
--- a/public/pages/VisualCreatePolicy/containers/CreateState/CreateState.tsx
+++ b/public/pages/VisualCreatePolicy/containers/CreateState/CreateState.tsx
@@ -47,6 +47,7 @@ interface CreateStateProps {
interface CreateStateState {
name: string;
+ nameError: string;
createAction: boolean;
editAction: UIAction | null;
createTransition: boolean;
@@ -65,6 +66,7 @@ export default class CreateState extends Component) => {
+ const { state, policy } = this.props;
const name = event.target.value;
- this.setState((state) => ({ name }));
+ const isEditing = !!this.props.state;
+ let nameError = "";
+ // If we are not editing a state or if we are editing and have changed the name
+ if (!isEditing || (isEditing && name !== state?.name)) {
+ // then check to make sure a state doesn't already exist in the policy with that name
+ if (!!policy.states.find((state) => state.name === name)) {
+ nameError = "A state with this name already exists.";
+ }
+ }
+
+ this.setState({ name, nameError });
};
onDragEndActions = ({ source, destination }: DropResult) => {
@@ -145,7 +158,9 @@ export default class CreateState extends Component action.id === id);
+ // Use edit action id instead of action id.. as current logic of editing an action can end
+ // up with a new id if you switch action types, i.e. rollover -> delete will create a new class w/ a new id
+ const foundActionIdx = actions.findIndex(({ id }) => editAction.id === id);
if (foundActionIdx >= 0) {
newActions = actions
.slice(0, foundActionIdx)
@@ -183,7 +198,7 @@ export default class CreateState extends Component {
const { policy, state } = this.props;
- const { actions, name, afterBeforeState, order, disableOrderSelections } = this.state;
+ const { actions, name, nameError, afterBeforeState, order, disableOrderSelections } = this.state;
// If we are editing a state filter it out from the selectable options
const stateOptions = policy.states.map((state) => ({ value: state.name, text: state.name })).filter((s) => s.value !== state?.name);
return (
@@ -193,10 +208,10 @@ export default class CreateState extends Component {/* Dummy span to get rid of last child styling on h5 */}
-
+
{
const { onCloseFlyout, state } = this.props;
- const { name } = this.state;
+ const { name, nameError } = this.state;
const isEditing = !!state;
return (
- Close
+ Cancel
-
+
{isEditing ? "Update state" : "Save state"}
@@ -288,8 +303,9 @@ export default class CreateState extends Component s.name);
@@ -323,7 +339,7 @@ export default class CreateState extends Component
-
+
{title}
diff --git a/public/pages/VisualCreatePolicy/containers/CreateState/Transitions.tsx b/public/pages/VisualCreatePolicy/containers/CreateState/Transitions.tsx
index 7268cb861..6d97adbe9 100644
--- a/public/pages/VisualCreatePolicy/containers/CreateState/Transitions.tsx
+++ b/public/pages/VisualCreatePolicy/containers/CreateState/Transitions.tsx
@@ -50,6 +50,7 @@ const Transitions = ({
isLast={transitions.length - 1 === idx}
onClickDelete={() => onClickDeleteTransition(idx)}
onClickEdit={() => onClickEditTransition(transition)}
+ draggableType="transition"
/>
))}
diff --git a/public/pages/VisualCreatePolicy/containers/CreateState/__snapshots__/Actions.test.tsx.snap b/public/pages/VisualCreatePolicy/containers/CreateState/__snapshots__/Actions.test.tsx.snap
index 976076fb1..65a7eb7f8 100644
--- a/public/pages/VisualCreatePolicy/containers/CreateState/__snapshots__/Actions.test.tsx.snap
+++ b/public/pages/VisualCreatePolicy/containers/CreateState/__snapshots__/Actions.test.tsx.snap
@@ -6,6 +6,7 @@ exports[` spec renders the component 1`] = `
style="margin-bottom: 5px;"
>
Actions are the operations ISM performs when an index is in a certain state.
+
diff --git a/public/pages/VisualCreatePolicy/containers/CreateState/__snapshots__/CreateState.test.tsx.snap b/public/pages/VisualCreatePolicy/containers/CreateState/__snapshots__/CreateState.test.tsx.snap
index 909a1d5a8..e26b63b15 100644
--- a/public/pages/VisualCreatePolicy/containers/CreateState/__snapshots__/CreateState.test.tsx.snap
+++ b/public/pages/VisualCreatePolicy/containers/CreateState/__snapshots__/CreateState.test.tsx.snap
@@ -27,14 +27,6 @@ exports[` spec renders the component 1`] = `
style="max-width: 600px;"
tabindex="0"
>
-
- EuiIconMock
-
spec renders the component 1`] = `
style="margin-bottom: 5px;"
>
Actions are the operations ISM performs when an index is in a certain state.
+
@@ -258,6 +252,7 @@ exports[` spec renders the component 1`] = `
style="margin-bottom: 5px;"
>
Transitions define the conditions that need to be met for a state to change. After all actions in the current state are completed, the policy starts checking the conditions for transitions.
+
@@ -327,7 +323,7 @@ exports[` spec renders the component 1`] = `
- Close
+ Cancel
diff --git a/public/pages/VisualCreatePolicy/containers/CreateState/__snapshots__/Transitions.test.tsx.snap b/public/pages/VisualCreatePolicy/containers/CreateState/__snapshots__/Transitions.test.tsx.snap
index b8de9da93..e0b566034 100644
--- a/public/pages/VisualCreatePolicy/containers/CreateState/__snapshots__/Transitions.test.tsx.snap
+++ b/public/pages/VisualCreatePolicy/containers/CreateState/__snapshots__/Transitions.test.tsx.snap
@@ -6,6 +6,7 @@ exports[` spec renders the component 1`] = `
style="margin-bottom: 5px;"
>
Transitions define the conditions that need to be met for a state to change. After all actions in the current state are completed, the policy starts checking the conditions for transitions.
+
diff --git a/public/pages/VisualCreatePolicy/containers/CreateTransition/CreateTransition.tsx b/public/pages/VisualCreatePolicy/containers/CreateTransition/CreateTransition.tsx
index 4ba38e9f6..8543b5059 100644
--- a/public/pages/VisualCreatePolicy/containers/CreateTransition/CreateTransition.tsx
+++ b/public/pages/VisualCreatePolicy/containers/CreateTransition/CreateTransition.tsx
@@ -10,12 +10,13 @@
*/
import React, { Component } from "react";
-import { EuiFlyoutBody, EuiFlyoutFooter, EuiTitle, EuiFormRow, EuiSpacer, EuiComboBox } from "@elastic/eui";
+import { EuiText, EuiLink, EuiIcon, EuiFlyoutBody, EuiFlyoutFooter, EuiTitle, EuiFormRow, EuiSpacer, EuiComboBox } from "@elastic/eui";
import { Transition as ITransition, UITransition } from "../../../../../models/interfaces";
import FlyoutFooter from "../../components/FlyoutFooter";
import EuiFormCustomLabel from "../../components/EuiFormCustomLabel";
import { makeId } from "../../../../utils/helpers";
import Transition from "../../components/Transition";
+import { TRANSITION_DOCUMENTATION_URL } from "../../../../utils/constants";
interface CreateTransitionProps {
editTransition: UITransition | null;
@@ -38,7 +39,6 @@ export default class CreateTransition extends Component
@@ -93,6 +93,14 @@ export default class CreateTransition extends Component{title}
+
+ Transitions define the conditions that need to be met for a state to change. After all actions in the current state are
+ completed, the policy starts checking the conditions for transitions.{" "}
+
+ Learn more
+
+
+
-
+
({ label: state }))}
diff --git a/public/pages/VisualCreatePolicy/containers/CreateTransition/__snapshots__/CreateTransition.test.tsx.snap b/public/pages/VisualCreatePolicy/containers/CreateTransition/__snapshots__/CreateTransition.test.tsx.snap
index f68ee8847..990e1888d 100644
--- a/public/pages/VisualCreatePolicy/containers/CreateTransition/__snapshots__/CreateTransition.test.tsx.snap
+++ b/public/pages/VisualCreatePolicy/containers/CreateTransition/__snapshots__/CreateTransition.test.tsx.snap
@@ -15,6 +15,22 @@ exports[` spec renders the component 1`] = `
>
Edit transition
+
@@ -23,6 +39,7 @@ exports[` spec renders the component 1`] = `
style="margin-bottom: 5px;"
>
If entering a state that does not exist yet then you must create it before creating the policy.
+