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`] = ` +
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+`; 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;