diff --git a/models/interfaces.ts b/models/interfaces.ts
index 5180e1183..79f8c1dfd 100644
--- a/models/interfaces.ts
+++ b/models/interfaces.ts
@@ -124,6 +124,11 @@ export interface MessageTemplate {
lang?: string;
}
+export interface ISMTemplate {
+ index_patterns: string[];
+ priority: number;
+}
+
export interface State {
name: string;
actions: object[];
diff --git a/public/pages/VisualCreatePolicy/components/ISMTemplate/ISMTemplate.test.tsx b/public/pages/VisualCreatePolicy/components/ISMTemplate/ISMTemplate.test.tsx
new file mode 100644
index 000000000..4da406e70
--- /dev/null
+++ b/public/pages/VisualCreatePolicy/components/ISMTemplate/ISMTemplate.test.tsx
@@ -0,0 +1,58 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ *
+ * Modifications Copyright OpenSearch Contributors. See
+ * GitHub history for details.
+ */
+
+import React from "react";
+import "@testing-library/jest-dom/extend-expect";
+import { render } from "@testing-library/react";
+import ISMTemplate from "./ISMTemplate";
+import { fireEvent } from "@testing-library/dom";
+import userEvent from "@testing-library/user-event/dist";
+
+describe(" spec", () => {
+ it("renders the component", () => {
+ const { container } = render(
+ {}}
+ onRemoveTemplate={() => {}}
+ isFirst={true}
+ />
+ );
+ expect(container.firstChild).toMatchSnapshot();
+ });
+
+ it("calls on remove template when clicking remove button", () => {
+ const onRemoveTemplate = jest.fn();
+ const { getByTestId } = render(
+ {}}
+ onRemoveTemplate={onRemoveTemplate}
+ isFirst={true}
+ />
+ );
+ fireEvent.click(getByTestId("ism-template-remove-button"));
+ expect(onRemoveTemplate).toHaveBeenCalled();
+ });
+
+ it("calls on update template when typing in priority input", async () => {
+ const template = { index_patterns: ["*"], priority: 7 };
+ const onUpdateTemplate = jest.fn();
+ const { getByTestId } = render(
+ {}} isFirst={true} />
+ );
+ fireEvent.focus(getByTestId("ism-template-priority-input"));
+ userEvent.type(getByTestId("ism-template-priority-input"), "2");
+ fireEvent.blur(getByTestId("ism-template-priority-input"));
+ expect(onUpdateTemplate).toHaveBeenCalled();
+ expect(onUpdateTemplate).toHaveBeenCalledWith({ ...template, priority: 72 }); // already contains 7, just added 2
+ });
+});
diff --git a/public/pages/VisualCreatePolicy/components/ISMTemplate/ISMTemplate.tsx b/public/pages/VisualCreatePolicy/components/ISMTemplate/ISMTemplate.tsx
new file mode 100644
index 000000000..11c79331e
--- /dev/null
+++ b/public/pages/VisualCreatePolicy/components/ISMTemplate/ISMTemplate.tsx
@@ -0,0 +1,95 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ *
+ * Modifications Copyright OpenSearch Contributors. See
+ * GitHub history for details.
+ */
+
+import React, { ChangeEvent, useState } from "react";
+import { EuiButton, EuiFormRow, EuiComboBox, EuiFlexGroup, EuiFlexItem, EuiFieldNumber } from "@elastic/eui";
+import "brace/theme/github";
+import "brace/mode/json";
+import { ISMTemplate as ISMTemplateData } from "../../../../../models/interfaces";
+import { ISM_TEMPLATE_INPUT_MAX_WIDTH } from "../../utils/constants";
+
+interface ISMTemplateProps {
+ template: ISMTemplateData;
+ onUpdateTemplate: (template: ISMTemplateData) => void;
+ onRemoveTemplate: () => void;
+ isFirst: boolean;
+}
+
+const ISMTemplate = ({ template, onUpdateTemplate, onRemoveTemplate, isFirst }: ISMTemplateProps) => {
+ // TODO: Move this top top of form submition
+ const [isInvalid, setInvalid] = useState(false);
+ return (
+
+
+
+ ({ label: pattern }))}
+ onChange={(selectedOptions) => {
+ onUpdateTemplate({ ...template, index_patterns: selectedOptions.map(({ label }) => label) });
+ setInvalid(false);
+ }}
+ onCreateOption={(searchValue) => {
+ if (!searchValue.trim()) {
+ return false;
+ }
+
+ if (searchValue.includes(" ")) {
+ setInvalid(false);
+ return;
+ }
+
+ onUpdateTemplate({ ...template, index_patterns: [...template.index_patterns, searchValue] });
+ }}
+ onSearchChange={(searchValue) => {
+ if (!searchValue) {
+ setInvalid(false);
+
+ return;
+ }
+
+ if (searchValue.includes(" ")) {
+ setInvalid(true);
+ return;
+ }
+ //TODO
+ setInvalid(false);
+ }}
+ isClearable={true}
+ isInvalid={isInvalid}
+ data-test-subj="ism-template-index-pattern-input"
+ />
+
+
+
+
+ ) => {
+ const priority = e.target.valueAsNumber;
+ onUpdateTemplate({ ...template, priority });
+ }}
+ isInvalid={false}
+ data-test-subj="ism-template-priority-input"
+ />
+
+
+
+
+ Remove
+
+
+
+ );
+};
+
+export default ISMTemplate;
diff --git a/public/pages/VisualCreatePolicy/components/ISMTemplate/__snapshots__/ISMTemplate.test.tsx.snap b/public/pages/VisualCreatePolicy/components/ISMTemplate/__snapshots__/ISMTemplate.test.tsx.snap
new file mode 100644
index 000000000..35094f9a0
--- /dev/null
+++ b/public/pages/VisualCreatePolicy/components/ISMTemplate/__snapshots__/ISMTemplate.test.tsx.snap
@@ -0,0 +1,140 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` spec renders the component 1`] = `
+
+
+
+
+
+
+
+ Remove
+
+
+
+
+
+`;
diff --git a/public/pages/VisualCreatePolicy/components/ISMTemplate/index.ts b/public/pages/VisualCreatePolicy/components/ISMTemplate/index.ts
new file mode 100644
index 000000000..4e9297405
--- /dev/null
+++ b/public/pages/VisualCreatePolicy/components/ISMTemplate/index.ts
@@ -0,0 +1,14 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ *
+ * Modifications Copyright OpenSearch Contributors. See
+ * GitHub history for details.
+ */
+
+import ISMTemplate from "./ISMTemplate";
+
+export default ISMTemplate;