From 43d41617f2c5655b86e66d67ee3a4f5c92c31435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Castillo?= Date: Wed, 8 Apr 2026 15:46:53 -0300 Subject: [PATCH 1/2] fix: update additional input list from uicore, update uicore version, clean unused components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Castillo --- .../forms/form-template-meta-field-form.js | 349 ------------------ .../forms/inventory-item-meta-field-form.js | 318 ---------------- .../__tests__/additional-input-list.test.js | 349 ------------------ .../mui/__tests__/additional-input.test.js | 253 ------------- .../mui/__tests__/meta-field-values.test.js | 319 ---------------- .../additional-input/additional-input-list.js | 109 ------ .../additional-input/additional-input.js | 185 ---------- .../additional-input/meta-field-values.js | 180 --------- src/i18n/en.json | 65 +--- .../form-templates/form-template-popup.js | 2 +- .../form-templates/sponsor-inventory-popup.js | 2 +- .../components/sponsor-form-item-form.js | 2 +- .../form-template/form-template-form.js | 2 +- .../customized-form/customized-form.js | 2 +- 14 files changed, 24 insertions(+), 2113 deletions(-) delete mode 100644 src/components/forms/form-template-meta-field-form.js delete mode 100644 src/components/forms/inventory-item-meta-field-form.js delete mode 100644 src/components/mui/__tests__/additional-input-list.test.js delete mode 100644 src/components/mui/__tests__/additional-input.test.js delete mode 100644 src/components/mui/__tests__/meta-field-values.test.js delete mode 100644 src/components/mui/formik-inputs/additional-input/additional-input-list.js delete mode 100644 src/components/mui/formik-inputs/additional-input/additional-input.js delete mode 100644 src/components/mui/formik-inputs/additional-input/meta-field-values.js diff --git a/src/components/forms/form-template-meta-field-form.js b/src/components/forms/form-template-meta-field-form.js deleted file mode 100644 index 068ead2cc..000000000 --- a/src/components/forms/form-template-meta-field-form.js +++ /dev/null @@ -1,349 +0,0 @@ -/** - * Copyright 2024 OpenStack Foundation - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * */ - -import React, { useEffect, useState } from "react"; -import T from "i18n-react/dist/i18n-react"; -import "awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css"; -import { - Dropdown, - Input, - SortableTable -} from "openstack-uicore-foundation/lib/components"; -import Swal from "sweetalert2"; -import { hasErrors, scrollToError, shallowEqual } from "../../utils/methods"; -import { metafieldHasValues } from "../../actions/inventory-shared-actions"; - -const FormTemplateMetaFieldForm = ({ - entity: initialEntity, - errors: initialErrors, - index, - onMetaFieldTypeValueDeleted, - onChange -}) => { - const [entity, setEntity] = useState({ ...initialEntity }); - const [errors, setErrors] = useState(initialErrors); - const [currentValue, setCurrentValue] = useState(null); - const [showValues, setShowValues] = useState( - metafieldHasValues(initialEntity.type) - ); - - useEffect(() => { - if (onChange && !shallowEqual(initialEntity, entity)) { - onChange(entity); - } - }, [entity]); - - useEffect(() => { - scrollToError(initialErrors); - if (!shallowEqual(initialEntity, entity)) { - setEntity({ ...initialEntity }); - setErrors({}); - } - - if (!shallowEqual(initialErrors, errors)) { - setErrors({ ...initialErrors }); - } - }, [initialEntity, initialErrors]); - - const meta_field_value_types_ddl = [ - { label: "CheckBox", value: "CheckBox" }, - { label: "CheckBoxList", value: "CheckBoxList" }, - { label: "ComboBox", value: "ComboBox" }, - { label: "RadioButtonList", value: "RadioButtonList" }, - { label: "Text", value: "Text" }, - { label: "TextArea", value: "TextArea" } - ]; - - const handleMetaFieldChange = (id, ev) => { - const { value, checked, type } = ev.target; - setEntity((prevEntity) => ({ - ...prevEntity, - [id]: type === "checkbox" ? checked : value - })); - setShowValues(type === "dropdown" && metafieldHasValues(value)); - }; - - const handleMetaFieldValueChange = (id, ev) => { - const { value, checked, type } = ev.target; - setCurrentValue((prevValue) => ({ - ...prevValue, - [id]: type === "checkbox" ? checked : value - })); - }; - - const handleEditValueRequest = (valueId) => { - const selectedValue = entity.values.find((value) => value.id === valueId); - setCurrentValue(selectedValue); - }; - - const handleCommitValue = () => { - if (!currentValue || !currentValue.name || !currentValue.value) return; - - const formerValue = entity.values?.find( - (v) => v.name === currentValue.name - ); - const rest = - entity.values?.filter((v) => v.name !== currentValue.name) ?? []; - - let value = null; - if (formerValue) { - value = { ...currentValue, id: formerValue.id, order: formerValue.order }; - if (formerValue.isNew) { - value.isNew = formerValue.isNew; - } - } else { - value = { - ...currentValue, - id: Date.now(), - order: rest.length + 1, - isNew: true - }; - } - - setEntity((prevEntity) => ({ - ...prevEntity, - values: [...rest, value] - })); - - setCurrentValue(null); - }; - - const removeValueLocally = (value) => { - const values = entity.values - .filter((v) => v.id !== value.id) - .map((v, ix) => ({ ...v, order: ix + 1 })); - - setEntity((prevEntity) => ({ - ...prevEntity, - values: [...values] - })); - - setCurrentValue(null); - }; - - const handleDeleteValue = (valueId) => { - if (!onMetaFieldTypeValueDeleted) return; - const value = entity.values.find((v) => v.id === valueId); - if (value && value.isNew) { - removeValueLocally(value); - return; - } - - Swal.fire({ - title: T.translate("general.are_you_sure"), - text: `${T.translate("meta_field_values_list.delete_value_warning")} ${ - value.name - }`, - type: "warning", - showCancelButton: true, - confirmButtonColor: "#DD6B55", - confirmButtonText: T.translate("general.yes_delete") - }).then((result) => { - if (result.value) { - onMetaFieldTypeValueDeleted(entity.id, valueId); - } - }); - }; - - const columns = [ - { columnKey: "name", value: T.translate("meta_field_values_list.name") }, - { columnKey: "value", value: T.translate("meta_field_values_list.value") }, - { - columnKey: "is_default", - value: T.translate("meta_field_values_list.is_default"), - render: (filter) => (filter.is_default ? "YES" : "NO") - } - ]; - - const table_options = { - actions: { - edit: { onClick: handleEditValueRequest }, - delete: { onClick: handleDeleteValue } - } - }; - - const sortedValues = entity.values - ? entity.values.sort((a, b) => a.order - b.order) - : []; - - return ( -
-
-
-
- - { - handleMetaFieldChange("name", ev); - }} - /> -
-
- - { - handleMetaFieldChange("type", ev); - }} - options={meta_field_value_types_ddl} - /> -
-
-
-
-
-
- - { - handleMetaFieldChange("minimum_quantity", ev); - }} - /> -
-
- - { - handleMetaFieldChange("maximum_quantity", ev); - }} - /> -
-
- {showValues && ( -
-
- - {sortedValues.length > 0 && ( -
- {}} - orderField="order" - /> -
- )} -
-
- { - handleMetaFieldValueChange("name", ev); - }} - placeholder={T.translate( - "meta_field_values_list.placeholders.name" - )} - /> -
-
- { - handleMetaFieldValueChange("value", ev); - }} - placeholder={T.translate( - "meta_field_values_list.placeholders.value" - )} - /> -
-
-
- { - handleMetaFieldValueChange("is_default", ev); - }} - className="form-check-input" - /> - -
-
-
- -
-
-
-
- )} -
-
- ); -}; - -export default FormTemplateMetaFieldForm; diff --git a/src/components/forms/inventory-item-meta-field-form.js b/src/components/forms/inventory-item-meta-field-form.js deleted file mode 100644 index 220db2e6b..000000000 --- a/src/components/forms/inventory-item-meta-field-form.js +++ /dev/null @@ -1,318 +0,0 @@ -/** - * Copyright 2024 OpenStack Foundation - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * */ - -import React, { useEffect, useState } from "react"; -import T from "i18n-react/dist/i18n-react"; -import "awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css"; -import { - Dropdown, - Input, - SortableTable -} from "openstack-uicore-foundation/lib/components"; -import Swal from "sweetalert2"; -import { hasErrors, scrollToError, shallowEqual } from "../../utils/methods"; -import { metafieldHasValues } from "../../actions/inventory-shared-actions"; - -const InventoryItemMetaFieldForm = ({ - entity: initialEntity, - errors: initialErrors, - index, - onMetaFieldTypeValueDeleted, - onChange -}) => { - const [entity, setEntity] = useState({ ...initialEntity }); - const [errors, setErrors] = useState(initialErrors); - const [currentValue, setCurrentValue] = useState(null); - const [showValues, setShowValues] = useState( - metafieldHasValues(initialEntity.type) - ); - - useEffect(() => { - if (onChange && !shallowEqual(initialEntity, entity)) { - onChange(entity); - } - }, [entity]); - - useEffect(() => { - scrollToError(initialErrors); - if (!shallowEqual(initialEntity, entity)) { - setEntity({ ...initialEntity }); - setErrors({}); - } - - if (!shallowEqual(initialErrors, errors)) { - setErrors({ ...initialErrors }); - } - }, [initialEntity, initialErrors]); - - const meta_field_value_types_ddl = [ - { label: "CheckBox", value: "CheckBox" }, - { label: "CheckBoxList", value: "CheckBoxList" }, - { label: "ComboBox", value: "ComboBox" }, - { label: "RadioButtonList", value: "RadioButtonList" }, - { label: "Text", value: "Text" }, - { label: "TextArea", value: "TextArea" } - ]; - - const handleMetaFieldChange = (id, ev) => { - const { value, checked, type } = ev.target; - setEntity((prevEntity) => ({ - ...prevEntity, - [id]: type === "checkbox" ? checked : value - })); - setShowValues(type === "dropdown" && metafieldHasValues(value)); - }; - - const handleMetaFieldValueChange = (id, ev) => { - const { value, checked, type } = ev.target; - setCurrentValue((prevValue) => ({ - ...prevValue, - [id]: type === "checkbox" ? checked : value - })); - }; - - const handleEditValueRequest = (valueId) => { - const selectedValue = entity.values.find((value) => value.id === valueId); - setCurrentValue(selectedValue); - }; - - const handleCommitValue = () => { - if (!currentValue || !currentValue.name || !currentValue.value) return; - - const formerValue = entity.values?.find( - (v) => v.name === currentValue.name - ); - const rest = - entity.values - ?.filter((v) => v.name !== currentValue.name) - .map((v) => ({ - ...v, - is_default: currentValue.is_default ? false : v.is_default - })) ?? []; - - let value = null; - if (formerValue) { - value = { ...currentValue, id: formerValue.id, order: formerValue.order }; - if (formerValue.isNew) { - value.isNew = formerValue.isNew; - } - } else { - value = { - ...currentValue, - id: Date.now(), - order: rest.length + 1, - isNew: true - }; - } - - setEntity((prevEntity) => ({ - ...prevEntity, - values: [...rest, value] - })); - - setCurrentValue(null); - }; - - const removeValueLocally = (value) => { - const values = entity.values - .filter((v) => v.id !== value.id) - .map((v, ix) => ({ ...v, order: ix + 1 })); - - setEntity((prevEntity) => ({ - ...prevEntity, - values: [...values] - })); - - setCurrentValue(null); - }; - - const handleDeleteValue = (valueId) => { - if (!onMetaFieldTypeValueDeleted) return; - const value = entity.values.find((v) => v.id === valueId); - if (value && value.isNew) { - removeValueLocally(value); - return; - } - - Swal.fire({ - title: T.translate("general.are_you_sure"), - text: `${T.translate("meta_field_values_list.delete_value_warning")} ${ - value.name - }`, - type: "warning", - showCancelButton: true, - confirmButtonColor: "#DD6B55", - confirmButtonText: T.translate("general.yes_delete") - }).then((result) => { - if (result.value) { - onMetaFieldTypeValueDeleted(entity.id, valueId); - } - }); - }; - - const columns = [ - { columnKey: "name", value: T.translate("meta_field_values_list.name") }, - { columnKey: "value", value: T.translate("meta_field_values_list.value") }, - { - columnKey: "is_default", - value: T.translate("meta_field_values_list.is_default"), - render: (filter) => (filter.is_default ? "YES" : "NO") - } - ]; - - const table_options = { - actions: { - edit: { onClick: handleEditValueRequest }, - delete: { onClick: handleDeleteValue } - } - }; - - const sortedValues = entity.values - ? entity.values.sort((a, b) => a.order - b.order) - : []; - - return ( -
-
-
-
- - { - handleMetaFieldChange("name", ev); - }} - /> -
-
- - { - handleMetaFieldChange("type", ev); - }} - options={meta_field_value_types_ddl} - /> -
-
-
-
- {showValues && ( -
-
- - {sortedValues.length > 0 && ( -
- {}} - orderField="order" - /> -
- )} -
-
- { - handleMetaFieldValueChange("name", ev); - }} - placeholder={T.translate( - "meta_field_values_list.placeholders.name" - )} - /> -
-
- { - handleMetaFieldValueChange("value", ev); - }} - placeholder={T.translate( - "meta_field_values_list.placeholders.value" - )} - /> -
-
-
- { - handleMetaFieldValueChange("is_default", ev); - }} - className="form-check-input" - /> - -
-
-
- -
-
-
-
- )} -
-
- ); -}; - -export default InventoryItemMetaFieldForm; diff --git a/src/components/mui/__tests__/additional-input-list.test.js b/src/components/mui/__tests__/additional-input-list.test.js deleted file mode 100644 index 46b922d73..000000000 --- a/src/components/mui/__tests__/additional-input-list.test.js +++ /dev/null @@ -1,349 +0,0 @@ -import React from "react"; -import { render, screen, waitFor } from "@testing-library/react"; -import userEvent from "@testing-library/user-event"; -import { Formik, Form, useFormikContext } from "formik"; -import "@testing-library/jest-dom"; -import AdditionalInputList from "../formik-inputs/additional-input/additional-input-list"; -import showConfirmDialog from "../showConfirmDialog"; - -// Mocks -jest.mock("../showConfirmDialog", () => jest.fn()); - -jest.mock( - "../formik-inputs/additional-input/additional-input", - () => - function MockAdditionalInput({ - item, - itemIdx, - onAdd, - onDelete, - isAddDisabled - }) { - return ( -
- {item.name} - {item.type} - - -
- ); - } -); - -// Helper function to render the component with Formik -const renderWithFormik = (props, initialValues = { meta_fields: [] }) => - render( - -
- - -
- ); - -describe("AdditionalInputList", () => { - const defaultMetaField = { - id: 1, - name: "Field 1", - type: "Text", - is_required: false, - minimum_quantity: 0, - maximum_quantity: 0, - values: [] - }; - - const defaultProps = { - name: "meta_fields", - onDelete: jest.fn(), - onDeleteValue: jest.fn(), - entityId: 1 - }; - - const defaultInitialValues = { - meta_fields: [defaultMetaField] - }; - - beforeEach(() => { - jest.clearAllMocks(); - }); - - describe("Rendering", () => { - test("renders an AdditionalInput for each meta field", () => { - const multipleFields = { - meta_fields: [ - { ...defaultMetaField, id: 1, name: "Field 1" }, - { ...defaultMetaField, id: 2, name: "Field 2" }, - { ...defaultMetaField, id: 3, name: "Field 3" } - ] - }; - - renderWithFormik(defaultProps, multipleFields); - - expect(screen.getByTestId("additional-input-0")).toBeInTheDocument(); - expect(screen.getByTestId("additional-input-1")).toBeInTheDocument(); - expect(screen.getByTestId("additional-input-2")).toBeInTheDocument(); - expect(screen.getByTestId("item-name-0")).toHaveTextContent("Field 1"); - expect(screen.getByTestId("item-name-1")).toHaveTextContent("Field 2"); - expect(screen.getByTestId("item-name-2")).toHaveTextContent("Field 3"); - }); - - test("renders a default metafield when meta_fields is empty", () => { - renderWithFormik(defaultProps, { meta_fields: [] }); - - // Should render one default empty field - expect(screen.getByTestId("additional-input-0")).toBeInTheDocument(); - expect(screen.getByTestId("item-name-0")).toHaveTextContent(""); - expect(screen.getByTestId("item-type-0")).toHaveTextContent(""); - }); - }); - - describe("handleAddItem", () => { - test("adds a new empty meta field when onAdd is called", async () => { - const TestWrapper = () => { - const { values } = useFormikContext(); - return ( - <> - -
{values.meta_fields.length}
- - ); - }; - - render( - -
- - -
- ); - - expect(screen.getByTestId("field-count")).toHaveTextContent("1"); - - const addButton = screen.getByTestId("add-btn-0"); - await userEvent.click(addButton); - - await waitFor(() => { - expect(screen.getByTestId("field-count")).toHaveTextContent("2"); - }); - }); - }); - - describe("handleRemove", () => { - test("shows confirmation dialog when delete is clicked", async () => { - showConfirmDialog.mockResolvedValue(false); - - renderWithFormik(defaultProps, defaultInitialValues); - - const deleteButton = screen.getByTestId("delete-btn-0"); - await userEvent.click(deleteButton); - - expect(showConfirmDialog).toHaveBeenCalledWith( - expect.objectContaining({ - title: expect.any(String), - type: "warning" - }) - ); - }); - - test("calls API and removes from UI when item has id", async () => { - const mockOnDelete = jest.fn().mockResolvedValue(); - showConfirmDialog.mockResolvedValue(true); - - const TestWrapper = ({ onDelete }) => { - const { values } = useFormikContext(); - return ( - <> - -
{values.meta_fields.length}
- - ); - }; - - render( - -
- - -
- ); - - expect(screen.getByTestId("field-count")).toHaveTextContent("1"); - - const deleteButton = screen.getByTestId("delete-btn-0"); - await userEvent.click(deleteButton); - - await waitFor(() => { - expect(mockOnDelete).toHaveBeenCalledWith(1, 1); // entityId, item.id - }); - }); - - test("removes from UI without API call when item has no id", async () => { - const mockOnDelete = jest.fn(); - showConfirmDialog.mockResolvedValue(true); - - const fieldWithoutId = { - name: "New Field", - type: "Text", - is_required: false, - values: [] - }; - - const TestWrapper = ({ onDelete }) => { - const { values } = useFormikContext(); - return ( - <> - -
{values.meta_fields.length}
- - ); - }; - - render( - -
- - -
- ); - - expect(screen.getByTestId("field-count")).toHaveTextContent("2"); - - // remove the second field (without id) - const deleteButton = screen.getByTestId("delete-btn-1"); - await userEvent.click(deleteButton); - - await waitFor(() => { - expect(mockOnDelete).not.toHaveBeenCalled(); - expect(screen.getByTestId("field-count")).toHaveTextContent("1"); - }); - }); - - test("resets to default meta field when last item is deleted", async () => { - const mockOnDelete = jest.fn().mockResolvedValue(); - showConfirmDialog.mockResolvedValue(true); - - const TestWrapper = ({ onDelete }) => { - const { values } = useFormikContext(); - return ( - <> - -
{values.meta_fields.length}
-
- {values.meta_fields[0]?.name || "empty"} -
- - ); - }; - - render( - -
- - -
- ); - - const deleteButton = screen.getByTestId("delete-btn-0"); - await userEvent.click(deleteButton); - - await waitFor(() => { - // should still have 1 field (the default empty one) - expect(screen.getByTestId("field-count")).toHaveTextContent("1"); - // field should be reset to empty - expect(screen.getByTestId("first-field-name")).toHaveTextContent( - "empty" - ); - }); - }); - }); - - describe("areMetafieldsIncomplete", () => { - test("disables add button when name is empty", () => { - const fieldWithEmptyName = { ...defaultMetaField, name: "" }; - - renderWithFormik(defaultProps, { meta_fields: [fieldWithEmptyName] }); - - expect(screen.getByTestId("add-btn-0")).toBeDisabled(); - }); - - test("disables add button when type is empty", () => { - const fieldWithEmptyType = { - ...defaultMetaField, - name: "Field", - type: "" - }; - - renderWithFormik(defaultProps, { meta_fields: [fieldWithEmptyType] }); - - expect(screen.getByTestId("add-btn-0")).toBeDisabled(); - }); - - test("disables add button when type with options has no values", () => { - const fieldWithNoValues = { - ...defaultMetaField, - name: "Field", - type: "CheckBoxList", - values: [] - }; - - renderWithFormik(defaultProps, { meta_fields: [fieldWithNoValues] }); - - expect(screen.getByTestId("add-btn-0")).toBeDisabled(); - }); - - test("disables add button when values are incomplete", () => { - const fieldWithIncompleteValues = { - ...defaultMetaField, - name: "Field", - type: "ComboBox", - values: [{ name: "Option", value: "" }] // value is empty - }; - - renderWithFormik(defaultProps, { - meta_fields: [fieldWithIncompleteValues] - }); - - expect(screen.getByTestId("add-btn-0")).toBeDisabled(); - }); - - test("enables add button when all fields are complete", () => { - const completeField = { - ...defaultMetaField, - name: "Field", - type: "Text" - }; - - renderWithFormik(defaultProps, { meta_fields: [completeField] }); - - expect(screen.getByTestId("add-btn-0")).not.toBeDisabled(); - }); - - test("enables add button when type with options has complete values", () => { - const completeFieldWithValues = { - ...defaultMetaField, - name: "Field", - type: "CheckBoxList", - values: [{ name: "Option 1", value: "opt1" }] - }; - - renderWithFormik(defaultProps, { - meta_fields: [completeFieldWithValues] - }); - - expect(screen.getByTestId("add-btn-0")).not.toBeDisabled(); - }); - }); -}); diff --git a/src/components/mui/__tests__/additional-input.test.js b/src/components/mui/__tests__/additional-input.test.js deleted file mode 100644 index de283043d..000000000 --- a/src/components/mui/__tests__/additional-input.test.js +++ /dev/null @@ -1,253 +0,0 @@ -import React from "react"; -import { render, screen } from "@testing-library/react"; -import userEvent from "@testing-library/user-event"; -import { Formik, Form } from "formik"; -import "@testing-library/jest-dom"; -import AdditionalInput from "../formik-inputs/additional-input/additional-input"; - -// Mocks -jest.mock( - "../formik-inputs/additional-input/meta-field-values", - () => - function MockMetaFieldValues() { - return
MetaFieldValues
; - } -); - -// Helper function to render the component with Formik -const renderWithFormik = (props, initialValues = { meta_fields: [] }) => - render( - -
- - -
- ); - -describe("AdditionalInput", () => { - const defaultItem = { - id: 1, - name: "Test Field", - type: "", - is_required: false, - minimum_quantity: 0, - maximum_quantity: 0, - values: [] - }; - - const defaultProps = { - item: defaultItem, - itemIdx: 0, - baseName: "meta_fields", - onAdd: jest.fn(), - onDelete: jest.fn(), - onDeleteValue: jest.fn(), - entityId: 1, - isAddDisabled: false - }; - - const defaultInitialMetaFields = { - meta_fields: [defaultItem] - }; - - beforeEach(() => { - jest.clearAllMocks(); - }); - - describe("Rendering", () => { - test("renders name, type and is_required fields", () => { - renderWithFormik(defaultProps, defaultInitialMetaFields); - - expect( - screen.getByPlaceholderText( - "additional_inputs.placeholders.meta_field_title" - ) - ).toBeInTheDocument(); - expect(screen.getByRole("combobox")).toBeInTheDocument(); - expect(screen.getByRole("checkbox")).toBeInTheDocument(); - }); - - test("renders add and delete buttons", () => { - renderWithFormik(defaultProps, defaultInitialMetaFields); - - expect( - screen.getByRole("button", { name: /delete/i }) - ).toBeInTheDocument(); - expect(screen.getByRole("button", { name: /add/i })).toBeInTheDocument(); - }); - }); - - describe("Conditional rendering based on type", () => { - test("shows MetaFieldValues when type is CheckBoxList", () => { - const itemWithOptions = { ...defaultItem, type: "CheckBoxList" }; - - renderWithFormik( - { ...defaultProps, item: itemWithOptions }, - { meta_fields: [itemWithOptions] } - ); - - expect(screen.getByTestId("meta-field-values")).toBeInTheDocument(); - }); - - test("shows MetaFieldValues when type is ComboBox", () => { - const itemWithOptions = { ...defaultItem, type: "ComboBox" }; - - renderWithFormik( - { ...defaultProps, item: itemWithOptions }, - { meta_fields: [itemWithOptions] } - ); - - expect(screen.getByTestId("meta-field-values")).toBeInTheDocument(); - }); - - test("shows MetaFieldValues when type is RadioButtonList", () => { - const itemWithOptions = { ...defaultItem, type: "RadioButtonList" }; - - renderWithFormik( - { ...defaultProps, item: itemWithOptions }, - { meta_fields: [itemWithOptions] } - ); - - expect(screen.getByTestId("meta-field-values")).toBeInTheDocument(); - }); - - test("does not show MetaFieldValues when type is Text", () => { - renderWithFormik(defaultProps, defaultInitialMetaFields); - - expect(screen.queryByTestId("meta-field-values")).not.toBeInTheDocument(); - }); - - test("shows quantity fields when type is Quantity", () => { - const itemQuantity = { ...defaultItem, type: "Quantity" }; - - renderWithFormik( - { ...defaultProps, item: itemQuantity }, - { meta_fields: [itemQuantity] } - ); - - expect( - screen.getByPlaceholderText( - "additional_inputs.placeholders.meta_field_minimum_quantity" - ) - ).toBeInTheDocument(); - expect( - screen.getByPlaceholderText( - "additional_inputs.placeholders.meta_field_maximum_quantity" - ) - ).toBeInTheDocument(); - }); - - test("does not show quantity fields when type is not Quantity", () => { - renderWithFormik(defaultProps, defaultInitialMetaFields); - - expect( - screen.queryByPlaceholderText( - "additional_inputs.placeholders.meta_field_minimum_quantity" - ) - ).not.toBeInTheDocument(); - expect( - screen.queryByPlaceholderText( - "additional_inputs.placeholders.meta_field_maximum_quantity" - ) - ).not.toBeInTheDocument(); - }); - }); - - describe("Button interactions", () => { - test("calls onDelete with item and index when delete button is clicked", async () => { - const mockOnDelete = jest.fn(); - - renderWithFormik( - { ...defaultProps, onDelete: mockOnDelete }, - defaultInitialMetaFields - ); - - const deleteButton = screen.getByRole("button", { name: /delete/i }); - await userEvent.click(deleteButton); - - expect(mockOnDelete).toHaveBeenCalledWith(defaultItem, 0); - }); - - test("calls onAdd when add button is clicked", async () => { - const mockOnAdd = jest.fn(); - - renderWithFormik( - { ...defaultProps, onAdd: mockOnAdd }, - defaultInitialMetaFields - ); - - const addButton = screen.getByRole("button", { name: /add/i }); - await userEvent.click(addButton); - - expect(mockOnAdd).toHaveBeenCalled(); - }); - - test("disables add button when isAddDisabled is true", () => { - renderWithFormik( - { ...defaultProps, isAddDisabled: true }, - defaultInitialMetaFields - ); - - const addButton = screen.getByRole("button", { name: /add/i }); - expect(addButton).toBeDisabled(); - }); - - test("enables add button when isAddDisabled is false", () => { - renderWithFormik( - { ...defaultProps, isAddDisabled: false }, - defaultInitialMetaFields - ); - - const addButton = screen.getByRole("button", { name: /add/i }); - expect(addButton).not.toBeDisabled(); - }); - }); - - describe("Error display", () => { - test("shows values error when touched and has error", () => { - const itemWithOptions = { ...defaultItem, type: "CheckBoxList" }; - - render( - -
- - -
- ); - - expect( - screen.getByText("At least one option required") - ).toBeInTheDocument(); - }); - - test("does not show values error when not touched", () => { - const itemWithOptions = { ...defaultItem, type: "CheckBoxList" }; - - render( - -
- - -
- ); - - expect( - screen.queryByText("At least one option required") - ).not.toBeInTheDocument(); - }); - }); -}); diff --git a/src/components/mui/__tests__/meta-field-values.test.js b/src/components/mui/__tests__/meta-field-values.test.js deleted file mode 100644 index 36b8950ed..000000000 --- a/src/components/mui/__tests__/meta-field-values.test.js +++ /dev/null @@ -1,319 +0,0 @@ -import React from "react"; -import { render, screen, waitFor } from "@testing-library/react"; -import userEvent from "@testing-library/user-event"; -import { Formik, Form, useFormikContext } from "formik"; -import "@testing-library/jest-dom"; -import MetaFieldValues from "../formik-inputs/additional-input/meta-field-values"; -import showConfirmDialog from "../showConfirmDialog"; - -// Mocks -jest.mock("../showConfirmDialog", () => jest.fn()); - -jest.mock( - "../dnd-list", - () => - function MockDragAndDropList({ items, renderItem }) { - return ( -
- {items.map((item, index) => ( -
- {renderItem(item, index, {}, { isDragging: false })} -
- ))} -
- ); - } -); - -// Helper function to render the component with Formik -const renderWithFormik = (props, initialValues = { meta_fields: [] }) => - render( - -
- - -
- ); - -describe("MetaFieldValues", () => { - const defaultField = { - id: 1, - name: "Test Field", - type: "CheckBoxList", - values: [ - { id: 101, name: "Option 1", value: "opt1", is_default: false, order: 1 }, - { id: 102, name: "Option 2", value: "opt2", is_default: true, order: 2 } - ] - }; - - const defaultProps = { - field: defaultField, - fieldIndex: 0, - baseName: "meta_fields", - onMetaFieldTypeValueDeleted: jest.fn(), - entityId: 1 - }; - - const defaultInitialValues = { - meta_fields: [defaultField] - }; - - beforeEach(() => { - jest.clearAllMocks(); - }); - - describe("Rendering", () => { - test("renders all field values sorted by order prop", () => { - const fieldWithUnorderedValues = { - ...defaultField, - values: [ - { id: 103, name: "Option 3", value: "opt3", order: 3 }, - { id: 101, name: "Option 1", value: "opt1", order: 1 }, - { id: 102, name: "Option 2", value: "opt2", order: 2 } - ] - }; - - renderWithFormik( - { ...defaultProps, field: fieldWithUnorderedValues }, - { meta_fields: [fieldWithUnorderedValues] } - ); - - // verify all values are rendered - const items = screen.getAllByPlaceholderText( - "edit_inventory_item.placeholders.meta_field_name" - ); - expect(items).toHaveLength(3); - - // verify the values are rendered using the order prop - expect(items[0]).toHaveValue("Option 1"); - expect(items[1]).toHaveValue("Option 2"); - expect(items[2]).toHaveValue("Option 3"); - }); - }); - - describe("handleAddValue", () => { - test("adds a new empty value when add button is clicked", async () => { - // Componente wrapper que sincroniza field con Formik - const TestWrapper = () => { - const { values } = useFormikContext(); - const field = values.meta_fields[0]; - return ( - - ); - }; - - render( - -
- - -
- ); - - // Verificar cantidad inicial - const initialInputs = screen.getAllByPlaceholderText( - "edit_inventory_item.placeholders.meta_field_name" - ); - expect(initialInputs).toHaveLength(2); - - // Click en agregar - const addButton = screen.getByRole("button", { name: /add/i }); - await userEvent.click(addButton); - - // Esperar actualización - await waitFor(() => { - const updatedInputs = screen.getAllByPlaceholderText( - "edit_inventory_item.placeholders.meta_field_name" - ); - expect(updatedInputs).toHaveLength(3); - }); - }); - }); - - describe("isMetafieldValueIncomplete", () => { - test("disables add button when a value name is empty", () => { - const fieldWithIncomplete = { - ...defaultField, - values: [ - { id: 101, name: "", value: "opt1", is_default: false, order: 1 } - ] - }; - - renderWithFormik( - { ...defaultProps, field: fieldWithIncomplete }, - { meta_fields: [fieldWithIncomplete] } - ); - - const addButton = screen.getByRole("button", { name: /add/i }); - expect(addButton).toBeDisabled(); - }); - - test("disables add button when a value is empty", () => { - const fieldWithIncomplete = { - ...defaultField, - values: [ - { id: 101, name: "Option", value: "", is_default: false, order: 1 } - ] - }; - - renderWithFormik( - { ...defaultProps, field: fieldWithIncomplete }, - { meta_fields: [fieldWithIncomplete] } - ); - - const addButton = screen.getByRole("button", { name: /add/i }); - expect(addButton).toBeDisabled(); - }); - - test("enables add button when all values are complete", () => { - renderWithFormik(defaultProps, defaultInitialValues); - - const addButton = screen.getByRole("button", { name: /add/i }); - expect(addButton).not.toBeDisabled(); - }); - - test("enables add button when there are no values", () => { - const fieldWithNoValues = { ...defaultField, values: [] }; - - renderWithFormik( - { ...defaultProps, field: fieldWithNoValues }, - { meta_fields: [fieldWithNoValues] } - ); - - const addButton = screen.getByRole("button", { name: /add/i }); - expect(addButton).not.toBeDisabled(); - }); - }); - - describe("handleDefaultChange", () => { - test("only one value can be default at a time", async () => { - renderWithFormik(defaultProps, defaultInitialValues); - - const checkboxes = screen.getAllByRole("checkbox"); - - // Option 2 is default - expect(checkboxes[1]).toBeChecked(); - expect(checkboxes[0]).not.toBeChecked(); - - // click on Option 1 - await userEvent.click(checkboxes[0]); - - // Option 1 should be checked and Option 2 unchecked - expect(checkboxes[0]).toBeChecked(); - expect(checkboxes[1]).not.toBeChecked(); - }); - }); - - describe("handleRemoveValue", () => { - test("shows confirmation dialog when remove is clicked", async () => { - showConfirmDialog.mockResolvedValue(false); - renderWithFormik(defaultProps, defaultInitialValues); - - const closeIcons = screen.getAllByTestId("CloseIcon"); - const closeButton = closeIcons[0].closest("button"); - await userEvent.click(closeButton); - - expect(showConfirmDialog).toHaveBeenCalledWith( - expect.objectContaining({ - title: expect.any(String), - type: "warning" - }) - ); - }); - - test("calls API and removes from UI when value has id", async () => { - const mockOnDelete = jest.fn().mockResolvedValue(); - showConfirmDialog.mockResolvedValue(true); - - const TestWrapper = ({ onDelete }) => { - const { values } = useFormikContext(); - const field = values.meta_fields[0]; - return ( - - ); - }; - - render( - -
- - -
- ); - - expect(screen.getAllByTestId("CloseIcon")).toHaveLength(2); - - const closeButton = screen - .getAllByTestId("CloseIcon")[0] - .closest("button"); - await userEvent.click(closeButton); - - await waitFor(() => { - expect(mockOnDelete).toHaveBeenCalledWith(1, 1, 101); - expect(screen.getAllByTestId("CloseIcon")).toHaveLength(1); - }); - }); - - test("removes from UI without API call when value has no id", async () => { - const mockOnDelete = jest.fn(); - showConfirmDialog.mockResolvedValue(true); - - const fieldWithoutIds = { - ...defaultField, - values: [ - { name: "Option 1", value: "opt1", is_default: false, order: 1 }, - { name: "Option 2", value: "opt2", is_default: false, order: 2 } - ] - }; - - const TestWrapper = ({ onDelete }) => { - const { values } = useFormikContext(); - const field = values.meta_fields[0]; - return ( - - ); - }; - - render( - -
- - -
- ); - - expect(screen.getAllByTestId("CloseIcon")).toHaveLength(2); - - const closeButton = screen - .getAllByTestId("CloseIcon")[0] - .closest("button"); - await userEvent.click(closeButton); - - await waitFor(() => { - expect(mockOnDelete).not.toHaveBeenCalled(); - expect(screen.getAllByTestId("CloseIcon")).toHaveLength(1); - }); - }); - }); -}); diff --git a/src/components/mui/formik-inputs/additional-input/additional-input-list.js b/src/components/mui/formik-inputs/additional-input/additional-input-list.js deleted file mode 100644 index 2fbe1bbbf..000000000 --- a/src/components/mui/formik-inputs/additional-input/additional-input-list.js +++ /dev/null @@ -1,109 +0,0 @@ -import React, { useEffect } from "react"; -import { useFormikContext, getIn } from "formik"; -import T from "i18n-react"; -import AdditionalInput from "./additional-input"; -import showConfirmDialog from "../../showConfirmDialog"; -import { METAFIELD_TYPES_WITH_OPTIONS } from "../../../../utils/constants"; - -const DEFAULT_META_FIELD = { - name: "", - type: "", - is_required: false, - minimum_quantity: 0, - maximum_quantity: 0, - values: [] -}; - -const AdditionalInputList = ({ name, onDelete, onDeleteValue, entityId }) => { - const { values, setFieldValue, errors } = useFormikContext(); - - const metaFields = values[name] || []; - - useEffect(() => { - if (metaFields.length === 0) { - setFieldValue(name, [ - { ...DEFAULT_META_FIELD, _key: `draft_${Date.now()}` } - ]); - } - }, [metaFields.length]); - - const handleAddItem = () => { - setFieldValue(name, [ - ...metaFields, - { ...DEFAULT_META_FIELD, _key: `draft_${Date.now()}` } - ]); - }; - - const handleRemove = async (item, index) => { - const isConfirmed = await showConfirmDialog({ - title: T.translate("general.are_you_sure"), - text: `${T.translate("additional_inputs.delete_meta_field_warning")} ${ - item.name - }`, - type: "warning", - confirmButtonColor: "#DD6B55", - confirmButtonText: T.translate("general.yes_delete") - }); - - if (!isConfirmed) return; - - const removeFromUI = () => { - const newValues = metaFields.filter((_, idx) => idx !== index); - if (newValues.length === 0) { - newValues.push({ ...DEFAULT_META_FIELD, _key: `draft_${Date.now()}` }); - } - setFieldValue(name, newValues); - }; - - if (item.id && onDelete) { - onDelete(entityId, item.id) - .then(() => removeFromUI()) - .catch((err) => console.error("Error deleting field from API", err)); - } else { - removeFromUI(); - } - }; - - const areMetafieldsIncomplete = () => { - const fieldErrors = getIn(errors, name); - if (fieldErrors && Array.isArray(fieldErrors)) { - const hasRealErrors = fieldErrors.some( - (err) => err && Object.keys(err).length > 0 - ); - if (hasRealErrors) return true; - } - - return metaFields.some((field) => { - if (!field.name?.trim() || !field.type) return true; - if (METAFIELD_TYPES_WITH_OPTIONS.includes(field.type)) { - if (!field.values || field.values.length === 0) return true; - const hasIncompleteValues = field.values.some( - (v) => !v.name?.trim() || !v.value?.trim() - ); - if (hasIncompleteValues) return true; - } - - return false; - }); - }; - - return ( - <> - {metaFields.map((item, itemIdx) => ( - - ))} - - ); -}; - -export default AdditionalInputList; diff --git a/src/components/mui/formik-inputs/additional-input/additional-input.js b/src/components/mui/formik-inputs/additional-input/additional-input.js deleted file mode 100644 index c1f66fbcc..000000000 --- a/src/components/mui/formik-inputs/additional-input/additional-input.js +++ /dev/null @@ -1,185 +0,0 @@ -import React from "react"; -import { - Box, - Button, - Divider, - FormHelperText, - Grid2, - InputLabel, - MenuItem -} from "@mui/material"; -import { useFormikContext, getIn } from "formik"; -import T from "i18n-react/dist/i18n-react"; -import DeleteIcon from "@mui/icons-material/Delete"; -import AddIcon from "@mui/icons-material/Add"; -import MetaFieldValues from "./meta-field-values"; -import MuiFormikTextField from "../mui-formik-textfield"; -import MuiFormikSelect from "../mui-formik-select"; -import MuiFormikCheckbox from "../mui-formik-checkbox"; -import { - METAFIELD_TYPES, - METAFIELD_TYPES_WITH_OPTIONS -} from "../../../../utils/constants"; - -const AdditionalInput = ({ - item, - itemIdx, - baseName, - onAdd, - onDelete, - onDeleteValue, - entityId, - isAddDisabled -}) => { - const { errors, touched, values } = useFormikContext(); - - const buildFieldName = (fieldName) => `${baseName}[${itemIdx}].${fieldName}`; - const currentType = getIn(values, buildFieldName("type")); - - const fieldErrors = getIn(errors, `${baseName}[${itemIdx}]`); - const fieldTouched = getIn(touched, `${baseName}[${itemIdx}]`); - - const showValuesError = - fieldTouched?.values && - fieldErrors?.values && - typeof fieldErrors.values === "string"; - - return ( - - - - - - - {T.translate("additional_inputs.meta_field_title")} - - - - - - {T.translate("additional_inputs.meta_field_type")} - - - {METAFIELD_TYPES.map((fieldType) => ( - - {fieldType} - - ))} - - - - - - - {METAFIELD_TYPES_WITH_OPTIONS.includes(currentType) && ( - <> - - - {showValuesError && ( - - {fieldErrors.values} - - )} - - )} - {currentType === "Quantity" && ( - - - - - - - - - )} - - - - - - - - - - ); -}; - -export default AdditionalInput; diff --git a/src/components/mui/formik-inputs/additional-input/meta-field-values.js b/src/components/mui/formik-inputs/additional-input/meta-field-values.js deleted file mode 100644 index 98a4a232b..000000000 --- a/src/components/mui/formik-inputs/additional-input/meta-field-values.js +++ /dev/null @@ -1,180 +0,0 @@ -import React from "react"; -import T from "i18n-react/dist/i18n-react"; -import { useFormikContext } from "formik"; -import { Box, Button, Grid2, Divider, IconButton } from "@mui/material"; -import CloseIcon from "@mui/icons-material/Close"; -import AddIcon from "@mui/icons-material/Add"; -import DragAndDropList from "../../dnd-list"; -import showConfirmDialog from "../../showConfirmDialog"; -import MuiFormikTextField from "../mui-formik-textfield"; -import MuiFormikCheckbox from "../mui-formik-checkbox"; - -const MetaFieldValues = ({ - field, - fieldIndex, - baseName = "meta_fields", - onMetaFieldTypeValueDeleted, - entityId -}) => { - const { values, setFieldValue } = useFormikContext(); - - const metaFields = values[baseName] || []; - const sortedValues = [...field.values].sort((a, b) => a.order - b.order); - - const buildValueFieldName = (valueIndex, fieldName) => - `${baseName}[${fieldIndex}].values[${valueIndex}].${fieldName}`; - - const onReorder = (newValues) => { - const newMetaFields = [...metaFields]; - newMetaFields[fieldIndex].values = newValues; - setFieldValue(baseName, newMetaFields); - }; - - const handleAddValue = () => { - const newFields = [...metaFields]; - newFields[fieldIndex].values.push({ - value: "", - name: "", - is_default: false - }); - setFieldValue(baseName, newFields); - }; - - const handleDefaultChange = (valueIndex, checked) => { - const newFields = [...metaFields]; - if (checked) { - newFields[fieldIndex].values.forEach((v) => { - v.is_default = false; - }); - } - newFields[fieldIndex].values[valueIndex].is_default = checked; - setFieldValue(baseName, newFields); - }; - - const isMetafieldValueIncomplete = () => { - if (field.values.length > 0) { - return field.values.some((v) => !v.name?.trim() || !v.value?.trim()); - } - return false; - }; - - const handleRemoveValue = async (metaFieldValue, valueIndex) => { - const isConfirmed = await showConfirmDialog({ - title: T.translate("general.are_you_sure"), - text: T.translate("meta_field_values_list.delete_value_warning"), - type: "warning", - confirmButtonColor: "#DD6B55", - confirmButtonText: T.translate("general.yes_delete") - }); - - if (!isConfirmed) return; - - const removeValueFromFields = () => { - const newFields = [...metaFields]; - newFields[fieldIndex].values = newFields[fieldIndex].values.filter( - (_, index) => index !== valueIndex - ); - setFieldValue(baseName, newFields); - }; - - if (field.id && metaFieldValue.id && onMetaFieldTypeValueDeleted) { - onMetaFieldTypeValueDeleted(entityId, field.id, metaFieldValue.id).then( - () => removeValueFromFields() - ); - } else { - removeValueFromFields(); - } - }; - - const renderMetaFieldValue = (val, sortedIndex, provided, snapshot) => { - const originalIndex = field.values.findIndex( - (v) => (v.id && v.id === val.id) || v === val - ); - const valueIndex = originalIndex !== -1 ? originalIndex : sortedIndex; - - return ( - - - - - - - handleRemoveValue(val, valueIndex)} - aria-label="remove value" - > - - - ) - }} - /> - - - - handleDefaultChange(valueIndex, e.target.checked) - } - /> - - - - - ); - }; - - return ( - - - - - - - ); -}; - -export default MetaFieldValues; diff --git a/src/i18n/en.json b/src/i18n/en.json index ef12e0877..3fb5ca6c3 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -2455,11 +2455,6 @@ "expires_at": "Expires at", "instructions": "Instructions", "additional_fields": "Additional Input Fields", - "meta_field_title": "Field Title", - "meta_field_type": "Field Type", - "meta_field_required": "Required", - "delete_meta_field_warning": "Are you sure you want to delete meta field ", - "delete_value_warning": "Are you sure you want to delete meta field value ", "save": "Save Form", "created": "Form created successfully.", "updated": "Form {formName} updated successfully.", @@ -2643,16 +2638,25 @@ } }, "additional_inputs": { - "meta_field_title": "Field Title", - "meta_field_type": "Field Type", - "meta_field_required": "Required", - "delete_meta_field_warning": "Are you sure you want to delete meta field ", + "title": "Field Title", + "type": "Field Type", + "required": "Required", + "delete_warning": "Are you sure you want to delete meta field ", "delete_value_warning": "Are you sure you want to delete meta field value ", "placeholders": { - "meta_field_title": "Field Title", - "meta_field_type": "Select...", - "meta_field_maximum_quantity": "Maximum", - "meta_field_minimum_quantity": "Minimum" + "title": "Field Title", + "type": "Select...", + "maximum_quantity": "Maximum", + "minimum_quantity": "Minimum" + } + }, + "meta_fields": { + "delete_value_warning": "Please verify you want to delete the added value", + "is_default": "Is Default?", + "add_value": "Add a value", + "placeholders": { + "name": "Name", + "value": "Value" } }, "sponsor_forms": { @@ -2708,11 +2712,6 @@ "expires_at": "Expires at", "instructions": "Instructions", "additional_fields": "Additional Input Fields", - "meta_field_title": "Field Title", - "meta_field_type": "Field Type", - "meta_field_required": "Required", - "delete_meta_field_warning": "Are you sure you want to delete meta field ", - "delete_value_warning": "Are you sure you want to delete meta field value ", "save": "Save Form", "created": "Form created successfully.", "updated": "Form {formName} updated successfully.", @@ -3918,22 +3917,10 @@ "instructions": "Instructions", "delete_meta_field_warning": "Are you sure you want to delete meta field ", "meta_fields": "Additional Input Fields", - "meta_field_values": "Field Values", "materials": "Materials", "save_changes": "Save Changes", "add_form": "Add Form", - "required_error": "This field is required.", - "meta_field_title": "Field Title", - "meta_field_required": "Required Field", - "meta_field_type": "Field Type", - "placeholders": { - "meta_field_title": "Field Title", - "meta_field_required": "Required Field", - "meta_field_type": "Field Type", - "meta_field_values": "Field Values", - "meta_field_minimum_quantity": "Minimum Quantity", - "meta_field_maximum_quantity": "Maximum Quantity" - } + "required_error": "This field is required." }, "form_template_from_duplicate_dialog": { "duplicate_form": "Duplicate Form", @@ -3979,22 +3966,8 @@ } }, "edit_form_template_item": { - "form_template_item": "Item", "form_template_item_created": "Form Template Item created successfully.", - "form_template_item_saved": "Form Template Item saved successfully.", - "code": "Code", - "name": "Name", - "description": "Description", - "delete_meta_field_warning": "Are you sure you want to delete meta field ", - "meta_fields": "Additional Input Fields", - "meta_field_values": "Field Values", - "placeholders": { - "meta_field_title": "Field Title", - "meta_field_required": "Required Field", - "meta_field_type": "Field Type", - "meta_field_values": "Field Values" - }, - "images": "Images" + "form_template_item_saved": "Form Template Item saved successfully." }, "mui_table": { "no_items": "No items found.", diff --git a/src/pages/sponsors-global/form-templates/form-template-popup.js b/src/pages/sponsors-global/form-templates/form-template-popup.js index 3046eb5cd..3a3a3f648 100644 --- a/src/pages/sponsors-global/form-templates/form-template-popup.js +++ b/src/pages/sponsors-global/form-templates/form-template-popup.js @@ -16,9 +16,9 @@ import { import CloseIcon from "@mui/icons-material/Close"; import { useFormik, FormikProvider } from "formik"; import * as yup from "yup"; +import AdditionalInputList from "openstack-uicore-foundation/lib/components/mui/formik-inputs/additional-input-list"; import MuiFormikTextField from "../../../components/mui/formik-inputs/mui-formik-textfield"; import FormikTextEditor from "../../../components/inputs/formik-text-editor"; -import AdditionalInputList from "../../../components/mui/formik-inputs/additional-input/additional-input-list"; import useScrollToError from "../../../hooks/useScrollToError"; import { formMetafieldsValidation, diff --git a/src/pages/sponsors-global/form-templates/sponsor-inventory-popup.js b/src/pages/sponsors-global/form-templates/sponsor-inventory-popup.js index ffe9c6489..207c84b8b 100644 --- a/src/pages/sponsors-global/form-templates/sponsor-inventory-popup.js +++ b/src/pages/sponsors-global/form-templates/sponsor-inventory-popup.js @@ -19,6 +19,7 @@ import { } from "@mui/material"; import CloseIcon from "@mui/icons-material/Close"; import { UploadInputV2 } from "openstack-uicore-foundation/lib/components"; +import AdditionalInputList from "openstack-uicore-foundation/lib/components/mui/formik-inputs/additional-input-list"; import { ALLOWED_INVENTORY_IMAGE_FORMATS, MAX_INVENTORY_IMAGE_UPLOAD_SIZE, @@ -34,7 +35,6 @@ import { formMetafieldsValidation, requiredHTMLValidation } from "../../../utils/yup"; -import AdditionalInputList from "../../../components/mui/formik-inputs/additional-input/additional-input-list"; import ItemPriceTiers from "../../../components/mui/formik-inputs/item-price-tiers"; import MuiFormikQuantityField from "../../../components/mui/formik-inputs/mui-formik-quantity-field"; import { getMediaInputValue } from "../../../utils/methods"; diff --git a/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-item-form.js b/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-item-form.js index 809b18ae9..3c650908b 100644 --- a/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-item-form.js +++ b/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-item-form.js @@ -14,6 +14,7 @@ import T from "i18n-react"; import * as yup from "yup"; import { FormikProvider, useFormik } from "formik"; import { MuiFormikUpload } from "openstack-uicore-foundation/lib/components"; +import AdditionalInputList from "openstack-uicore-foundation/lib/components/mui/formik-inputs/additional-input-list"; import { addIssAfterDateFieldValidator, nullableDecimalValidation, @@ -23,7 +24,6 @@ import { requiredStringValidation } from "../../../../utils/yup"; import MuiFormikTextField from "../../../../components/mui/formik-inputs/mui-formik-textfield"; -import AdditionalInputList from "../../../../components/mui/formik-inputs/additional-input/additional-input-list"; import useScrollToError from "../../../../hooks/useScrollToError"; import ItemPriceTiers from "../../../../components/mui/formik-inputs/item-price-tiers"; import FormikTextEditor from "../../../../components/inputs/formik-text-editor"; diff --git a/src/pages/sponsors/sponsor-forms-list-page/components/form-template/form-template-form.js b/src/pages/sponsors/sponsor-forms-list-page/components/form-template/form-template-form.js index d9bdbfbd7..60025fa92 100644 --- a/src/pages/sponsors/sponsor-forms-list-page/components/form-template/form-template-form.js +++ b/src/pages/sponsors/sponsor-forms-list-page/components/form-template/form-template-form.js @@ -10,6 +10,7 @@ import { Typography } from "@mui/material"; import { epochToMomentTimeZone } from "openstack-uicore-foundation/lib/utils/methods"; +import AdditionalInputList from "openstack-uicore-foundation/lib/components/mui/formik-inputs/additional-input-list"; import T from "i18n-react"; import * as yup from "yup"; import { FormikProvider, useFormik } from "formik"; @@ -23,7 +24,6 @@ import { } from "../../../../../utils/yup"; import MuiFormikTextField from "../../../../../components/mui/formik-inputs/mui-formik-textfield"; import MuiFormikDatepicker from "../../../../../components/mui/formik-inputs/mui-formik-datepicker"; -import AdditionalInputList from "../../../../../components/mui/formik-inputs/additional-input/additional-input-list"; import useScrollToError from "../../../../../hooks/useScrollToError"; import FormikTextEditor from "../../../../../components/inputs/formik-text-editor"; diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/customized-form/customized-form.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/customized-form/customized-form.js index 8c5c1072a..d20420364 100644 --- a/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/customized-form/customized-form.js +++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/customized-form/customized-form.js @@ -13,6 +13,7 @@ import { epochToMomentTimeZone } from "openstack-uicore-foundation/lib/utils/met import T from "i18n-react"; import * as yup from "yup"; import { FormikProvider, useFormik } from "formik"; +import AdditionalInputList from "openstack-uicore-foundation/lib/components/mui/formik-inputs/additional-input-list"; import { addIssAfterDateFieldValidator, formMetafieldsValidation, @@ -21,7 +22,6 @@ import { } from "../../../../../../../utils/yup"; import MuiFormikTextField from "../../../../../../../components/mui/formik-inputs/mui-formik-textfield"; import MuiFormikDatepicker from "../../../../../../../components/mui/formik-inputs/mui-formik-datepicker"; -import AdditionalInputList from "../../../../../../../components/mui/formik-inputs/additional-input/additional-input-list"; import useScrollToError from "../../../../../../../hooks/useScrollToError"; import FormikTextEditor from "../../../../../../../components/inputs/formik-text-editor"; import { querySponsorAddons } from "../../../../../../../actions/sponsor-actions"; From f96ea3e93f134bb4107a88b48b6734ea808f95cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Castillo?= Date: Fri, 24 Apr 2026 15:35:51 -0300 Subject: [PATCH 2/2] fix: adjust test and rename hideArchived param MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Castillo --- src/pages/sponsors/show-pages-list-page/index.js | 2 +- .../sponsors/__tests__/show-pages-list-reducer.test.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/sponsors/show-pages-list-page/index.js b/src/pages/sponsors/show-pages-list-page/index.js index 85f968d07..54c90f9d5 100644 --- a/src/pages/sponsors/show-pages-list-page/index.js +++ b/src/pages/sponsors/show-pages-list-page/index.js @@ -112,7 +112,7 @@ const ShowPagesListPage = ({ perPage, order, orderDir, - hideArchived + showArchived ); }; diff --git a/src/reducers/sponsors/__tests__/show-pages-list-reducer.test.js b/src/reducers/sponsors/__tests__/show-pages-list-reducer.test.js index 66845db60..32c0875f3 100644 --- a/src/reducers/sponsors/__tests__/show-pages-list-reducer.test.js +++ b/src/reducers/sponsors/__tests__/show-pages-list-reducer.test.js @@ -71,7 +71,7 @@ describe("showPagesListReducer", () => { orderDir: -1, page: 2, perPage: 25, - hideArchived: true, + showArchived: false, summitTZ: "America/New_York" } }); @@ -82,7 +82,7 @@ describe("showPagesListReducer", () => { expect(result.orderDir).toBe(-1); expect(result.currentPage).toBe(2); expect(result.perPage).toBe(25); - expect(result.hideArchived).toBe(true); + expect(result.showArchived).toBe(false); expect(result.summitTZ).toBe("America/New_York"); }); });