From 8880315349eb5771d4df7a8f0a6c5ce6e0e59124 Mon Sep 17 00:00:00 2001 From: Priscila Moneo Date: Wed, 18 Mar 2026 17:34:05 -0300 Subject: [PATCH 1/3] feat: show admin figma-ux correlation fixes --- package.json | 2 +- src/actions/sponsor-forms-actions.js | 2 +- .../mui/__tests__/mui-table-editable.test.js | 367 ----------------- .../mui/editable-table/mui-table-editable.js | 378 ------------------ .../mui/editable-table/styles.module.less | 14 - .../mui/sortable-table/mui-table-sortable.js | 302 -------------- .../mui/sortable-table/styles.module.less | 14 - .../mui/table/extra-rows/NotesRow.jsx | 16 - .../mui/table/extra-rows/TotalRow.jsx | 32 -- src/components/mui/table/extra-rows/index.js | 2 - src/components/mui/table/mui-table.js | 295 -------------- .../mui/table/mui-table.module.less | 14 - src/i18n/en.json | 9 +- .../components/sponsor-form-item-form.js | 33 +- .../sponsors/sponsor-forms-list-page/index.js | 41 +- .../tabs/sponsor-forms-tab/index.js | 47 ++- .../sponsors/sponsor-forms-list-reducer.js | 2 + yarn.lock | 308 +++++++------- 18 files changed, 267 insertions(+), 1611 deletions(-) delete mode 100644 src/components/mui/__tests__/mui-table-editable.test.js delete mode 100644 src/components/mui/editable-table/mui-table-editable.js delete mode 100644 src/components/mui/editable-table/styles.module.less delete mode 100644 src/components/mui/sortable-table/mui-table-sortable.js delete mode 100644 src/components/mui/sortable-table/styles.module.less delete mode 100644 src/components/mui/table/extra-rows/NotesRow.jsx delete mode 100644 src/components/mui/table/extra-rows/TotalRow.jsx delete mode 100644 src/components/mui/table/extra-rows/index.js delete mode 100644 src/components/mui/table/mui-table.js delete mode 100644 src/components/mui/table/mui-table.module.less diff --git a/package.json b/package.json index 25c0c9721..d30b4546b 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "moment": "^2.29.1", "moment-duration-format": "^2.3.2", "moment-timezone": "^0.5.33", - "openstack-uicore-foundation": "5.0.8", + "openstack-uicore-foundation": "5.0.9", "p-limit": "^6.1.0", "path-browserify": "^1.0.1", "postcss-loader": "^6.2.1", diff --git a/src/actions/sponsor-forms-actions.js b/src/actions/sponsor-forms-actions.js index b148c21bf..4c6ad8d4d 100644 --- a/src/actions/sponsor-forms-actions.js +++ b/src/actions/sponsor-forms-actions.js @@ -132,7 +132,7 @@ export const getSponsorForms = const params = { page: currentPage, fields: - "id,code,name,level,expire_date,is_archived,sponsorship_types,apply_to_all_types", + "id,code,name,level,expire_date,is_archived,sponsorship_types,apply_to_all_types,opens_at,expires_at", relations: "items,sponsorship_types", per_page: perPage, access_token: accessToken, diff --git a/src/components/mui/__tests__/mui-table-editable.test.js b/src/components/mui/__tests__/mui-table-editable.test.js deleted file mode 100644 index 497585ba9..000000000 --- a/src/components/mui/__tests__/mui-table-editable.test.js +++ /dev/null @@ -1,367 +0,0 @@ -// ---- Mocks must come first ---- - -// i18n translate: echo the key -jest.mock("i18n-react/dist/i18n-react", () => ({ - __esModule: true, - default: { translate: (key) => key } -})); - -// Confirm dialog (exported mock we can control) -jest.mock("../showConfirmDialog", () => { - const mockShowConfirmDialog = jest.fn(); - return { __esModule: true, default: mockShowConfirmDialog }; -}); - -// Avoid MUI ripple noise -jest.mock("@mui/material/IconButton", () => { - const React = require("react"); - return { - __esModule: true, - default: ({ children, onClick, ...rest }) => ( - - ) - }; -}); -jest.mock("@mui/material/ButtonBase/TouchRipple", () => ({ - __esModule: true, - default: () => null -})); - -// TableCell shim to inspect sx prop in tests -jest.mock("@mui/material/TableCell", () => { - const React = require("react"); - return { - __esModule: true, - default: ({ children, sx, ...rest }) => ( - - {children} - - ) - }; -}); - -// TablePagination shim -jest.mock("@mui/material/TablePagination", () => { - const React = require("react"); - return { - __esModule: true, - default: function TablePaginationMock(props) { - const { - count, - rowsPerPage, - page, - rowsPerPageOptions, - onPageChange, - onRowsPerPageChange, - labelRowsPerPage - } = props; - - return ( -
-
count:{count}
-
rowsPerPage:{rowsPerPage}
-
page:{page}
-
label:{labelRowsPerPage}
-
- options:{rowsPerPageOptions && rowsPerPageOptions.join(",")} -
- - -
- ); - } - }; -}); - -// TableSortLabel shim -> renders an actual - ); - } - }; -}); - -// ---- Now imports ---- -/* eslint-disable import/first */ -import React from "react"; -import "@testing-library/jest-dom"; -import { render, screen, within } from "@testing-library/react"; -import userEvent from "@testing-library/user-event"; - -import MuiTableEditable from "../editable-table/mui-table-editable"; -import showConfirmDialog from "../showConfirmDialog"; -/* eslint-enable import/first */ - -afterEach(() => { - jest.clearAllMocks(); -}); - -// ---- Helpers ---- -const columns = [ - { columnKey: "name", header: "Name", sortable: true, editable: true }, - { columnKey: "role", header: "Role", sortable: false, editable: false }, - { - columnKey: "age", - header: "Age", - sortable: true, - editable: true, - width: 100 - } -]; - -const data = [ - { id: 1, name: "Alice", role: "Dev", age: 35 }, - { id: 2, name: "Bob", role: "PM", age: 41 } -]; - -const setup = (overrides = {}) => { - const props = { - columns, - data, - totalRows: 2, - perPage: 10, - currentPage: 1, - onPageChange: jest.fn(), - onPerPageChange: jest.fn(), - onSort: jest.fn(), - options: { sortCol: "name", sortDir: -1 }, - getName: (item) => item.name, - onEdit: jest.fn(), - onDelete: jest.fn(), - onCellChange: jest.fn(), - ...overrides - }; - render(); - return props; -}; - -const getCellSx = (cell) => { - const rawSx = cell.getAttribute("data-sx"); - if (!rawSx) return {}; - - try { - return JSON.parse(rawSx); - } catch { - return {}; - } -}; - -// ---- Tests ---- -describe("MuiTableEditable", () => { - test("renders headers and rows", () => { - setup(); - expect(screen.getByText("Name")).toBeInTheDocument(); - expect(screen.getByText("Role")).toBeInTheDocument(); - expect(screen.getByText("Age")).toBeInTheDocument(); - expect(screen.getByText("Alice")).toBeInTheDocument(); - expect(screen.getByText("Bob")).toBeInTheDocument(); - }); - - test("click editable cell -> edit, blur -> onCellChange", async () => { - const user = userEvent.setup(); - const { onCellChange } = setup(); - - const aliceNameCell = screen.getByText("Alice").closest("td"); - await user.click(aliceNameCell); - - const input = screen.getByDisplayValue("Alice"); - await user.clear(input); - await user.type(input, "Alicia"); - input.blur(); - - expect(onCellChange).toHaveBeenCalledWith(1, "name", "Alicia"); - }); - - test("press Enter commits edit", async () => { - const user = userEvent.setup(); - const { onCellChange } = setup(); - - const bobAgeCell = screen.getByText("41").closest("td"); - await user.click(bobAgeCell); - const input = screen.getByDisplayValue("41"); - await user.clear(input); - await user.type(input, "42{enter}"); - - expect(onCellChange).toHaveBeenCalledWith(2, "age", "42"); - }); - - test("non-editable cell does not enter edit mode", async () => { - const user = userEvent.setup(); - setup(); - const roleCell = screen.getAllByText("Dev")[0].closest("td"); - await user.click(roleCell); - expect(screen.queryByRole("textbox")).not.toBeInTheDocument(); - }); - - test("edit button calls onEdit", async () => { - const user = userEvent.setup(); - const { onEdit } = setup(); - const [btn] = screen.getAllByLabelText("general.edit"); - await user.click(btn); - expect(onEdit).toHaveBeenCalledWith( - expect.objectContaining({ id: 1, name: "Alice" }) - ); - }); - - test("delete confirmed calls onDelete", async () => { - const user = userEvent.setup(); - const { onDelete } = setup(); - showConfirmDialog.mockResolvedValueOnce(true); // ✅ use the exported mock - const [btn] = screen.getAllByLabelText("general.delete"); - await user.click(btn); - expect(showConfirmDialog).toHaveBeenCalled(); - expect(onDelete).toHaveBeenCalledWith(1); - }); - - test("delete canceled does not call onDelete", async () => { - const user = userEvent.setup(); - const { onDelete } = setup(); - showConfirmDialog.mockResolvedValueOnce(false); - const [btn] = screen.getAllByLabelText("general.delete"); - await user.click(btn); - expect(showConfirmDialog).toHaveBeenCalled(); - expect(onDelete).not.toHaveBeenCalled(); - }); - - test("pagination next -> onPageChange(2) when starting at page 1", async () => { - const user = userEvent.setup(); - const { onPageChange } = setup({ currentPage: 1 }); - const next = within(screen.getByTestId("pagination")).getByRole("button", { - name: "next-page" - }); - await user.click(next); - expect(onPageChange).toHaveBeenCalledWith(2); - }); - - test("change rows per page triggers onPerPageChange", async () => { - const user = userEvent.setup(); - const { onPerPageChange } = setup({ perPage: 25 }); - const change = within(screen.getByTestId("pagination")).getByRole( - "button", - { name: "change-rows" } - ); - await user.click(change); - expect(onPerPageChange).toHaveBeenCalledWith(expect.any(Number)); - }); - - test("uses totalRows when provided", () => { - setup({ totalRows: 123 }); - expect( - within(screen.getByTestId("pagination")).getByText("count:123") - ).toBeInTheDocument(); - }); - - test("falls back to data.length when totalRows missing", () => { - setup({ totalRows: undefined, data: [{ id: 1 }, { id: 2 }, { id: 3 }] }); - expect( - within(screen.getByTestId("pagination")).getByText("count:3") - ).toBeInTheDocument(); - }); - - test("sort click triggers onSort with flipped dir", async () => { - const user = userEvent.setup(); - const { onSort } = setup({ options: { sortCol: "name", sortDir: -1 } }); - - // 1) Try our mock's testid first (desc + active when sortDir === "-1") - let sortBtn = screen.queryByTestId("sort-label-desc-active"); - - // 2) Fallback: any sort-label button whose text includes "Name" - if (!sortBtn) { - const candidates = screen.queryAllByTestId(/sort-label-/i); - sortBtn = - candidates.find( - (el) => el.textContent && el.textContent.trim().includes("Name") - ) || null; - } - - // 3) Last resort: just click the element that renders "Name" - // (in our mock, the button itself contains the text "Name") - if (!sortBtn) { - sortBtn = screen.getByText(/^Name$/); - } - - await user.click(sortBtn); - - expect(onSort).toHaveBeenCalled(); - const [colKey, newDir] = onSort.mock.calls[0]; - expect(colKey).toBe("name"); - expect(newDir).toBe(1); - }); - - test("applies archived styles to content, edit and delete cells when disableProp matches", () => { - setup({ - options: { sortCol: "name", sortDir: -1, disableProp: "is_archived" }, - data: [ - { id: 1, name: "Alice", role: "Dev", age: 35, is_archived: true }, - { id: 2, name: "Bob", role: "PM", age: 41, is_archived: false } - ], - onArchive: jest.fn() - }); - - const aliceRow = screen.getByText("Alice").closest("tr"); - const cells = within(aliceRow).getAllByTestId("mui-table-cell"); - - const archivedCellIndexes = [0, 1, 2, 3, 5]; - archivedCellIndexes.forEach((index) => { - const sx = getCellSx(cells[index]); - expect(sx.backgroundColor).toBe("background.light"); - expect(sx.color).toBe("text.disabled"); - }); - }); - - test("does not apply archived styles to archive/unarchive action cell", () => { - setup({ - options: { sortCol: "name", sortDir: -1, disableProp: "is_archived" }, - data: [{ id: 1, name: "Alice", role: "Dev", age: 35, is_archived: true }], - onArchive: jest.fn() - }); - - const unarchiveButton = screen.getByRole("button", { - name: "general.unarchive" - }); - const actionCell = unarchiveButton.closest("td"); - const sx = getCellSx(actionCell); - - expect(sx.width).toBe(80); - expect(sx.backgroundColor).toBeUndefined(); - expect(sx.color).toBeUndefined(); - }); -}); diff --git a/src/components/mui/editable-table/mui-table-editable.js b/src/components/mui/editable-table/mui-table-editable.js deleted file mode 100644 index 2e3e69237..000000000 --- a/src/components/mui/editable-table/mui-table-editable.js +++ /dev/null @@ -1,378 +0,0 @@ -import * as React from "react"; -import T from "i18n-react/dist/i18n-react"; -import Box from "@mui/material/Box"; -import Button from "@mui/material/Button"; -import Table from "@mui/material/Table"; -import TableBody from "@mui/material/TableBody"; -import TableCell from "@mui/material/TableCell"; -import TableContainer from "@mui/material/TableContainer"; -import TableHead from "@mui/material/TableHead"; -import TablePagination from "@mui/material/TablePagination"; -import TableSortLabel from "@mui/material/TableSortLabel"; -import TableRow from "@mui/material/TableRow"; -import Paper from "@mui/material/Paper"; -import { IconButton, TextField } from "@mui/material"; -import EditIcon from "@mui/icons-material/Edit"; -import DeleteIcon from "@mui/icons-material/Delete"; -import { visuallyHidden } from "@mui/utils"; - -import { - DEFAULT_PER_PAGE, - FIFTY_PER_PAGE, - TWENTY_PER_PAGE -} from "../../../utils/constants"; -import showConfirmDialog from "../showConfirmDialog"; - -const ARCHIVED_CELL_SX = { - backgroundColor: "background.light", - color: "text.disabled" -}; - -const validateValue = (value, validation) => { - if (!validation) return { isValid: true }; - - // validate with yup schema - if ( - validation.schema && - typeof validation.schema.validateSync === "function" - ) { - try { - validation.schema.validateSync(value); - return { isValid: true, message: null }; - } catch (err) { - return { isValid: false, message: err.message }; - } - } - - return { isValid: true }; -}; - -// Updated component to handle editable cells with hover edit icon -const EditableCell = ({ value, isEditing, onBlur, validation }) => { - const [inputValue, setInputValue] = React.useState(value); - const [isHovering, setIsHovering] = React.useState(false); - const [error, setError] = React.useState(null); - - React.useEffect(() => { - setInputValue(value); - setError(null); - }, [value]); - - const handleValidationAndSave = (newValue) => { - const { isValid, message } = validateValue(newValue, validation); - - if (isValid) { - setError(null); - onBlur(newValue, true); - } else { - setError(message); - } - }; - - const handleKeyDown = (e) => { - if (e.key === "Enter") { - e.preventDefault(); - handleValidationAndSave(inputValue); - } - }; - - if (isEditing) { - return ( - { - setInputValue(e.target.value); - if (error) setError(null); - }} - onBlur={() => { - handleValidationAndSave(inputValue); - }} - onKeyDown={handleKeyDown} - size="small" - fullWidth - variant="standard" - error={!!error} - helperText={error} - /> - ); - } - - return ( - setIsHovering(true)} - onMouseLeave={() => setIsHovering(false)} - > - {value} - {isHovering && ( - - )} - - ); -}; - -const MuiTableEditable = ({ - columns = [], - data = [], - totalRows, - perPage, - currentPage, - onPageChange, - onPerPageChange, - onSort, - options = { sortCol: "", sortDir: 1, disableProp: null }, - getName = (item) => item.name, - onEdit, - onArchive, - onDelete, - onCellChange, // New prop for handling cell value changes - deleteDialogBody -}) => { - // State to track which cell is currently being edited - const [editingCell, setEditingCell] = React.useState(null); - - const handleChangePage = (_, newPage) => { - onPageChange(newPage + 1); - }; - - const handleChangeRowsPerPage = (ev) => { - onPerPageChange(ev.target.value); - }; - - const basePerPageOptions = [ - DEFAULT_PER_PAGE, - TWENTY_PER_PAGE, - FIFTY_PER_PAGE - ]; - - const customPerPageOptions = basePerPageOptions.includes(perPage) - ? basePerPageOptions - : [...basePerPageOptions, perPage].sort((a, b) => a - b); - - const { sortCol, sortDir } = options; - - const getArchivedCellSx = (row) => - options.disableProp && row[options.disableProp] ? ARCHIVED_CELL_SX : null; - - const getCellSx = (row, baseSx = {}) => ({ - ...baseSx, - ...(getArchivedCellSx(row) || {}) - }); - - const handleDelete = async (item) => { - const isConfirmed = await showConfirmDialog({ - title: T.translate("general.are_you_sure"), - text: deleteDialogBody - ? deleteDialogBody(getName(item)) - : `${T.translate("general.row_remove_warning")} ${getName(item)}`, - type: "warning", - showCancelButton: true, - confirmButtonColor: "#DD6B55", - confirmButtonText: T.translate("general.yes_delete") - }); - - if (isConfirmed) { - onDelete(item.id); - } - }; - - const isEditable = (col, row) => - typeof col.editable === "function" ? col.editable(row) : !!col.editable; - - // Handler for starting edit mode on a cell - const handleCellClick = (row, columnKey) => { - // Check if the column is editable - const column = columns.find((col) => col.columnKey === columnKey); - if (column && isEditable(column, row)) { - setEditingCell({ rowId: row.id, columnKey }); - } - }; - - // Handler for saving changes when editing is complete - const handleCellBlur = (rowId, columnKey, newValue, isValid) => { - if (onCellChange && isValid) { - onCellChange(rowId, columnKey, newValue); - } - setEditingCell(null); - }; - - return ( - - - - - {/* TABLE HEADER */} - - - {columns.map((col) => ( - - {col.sortable ? ( - onSort(col.columnKey, sortDir * -1)} - > - {col.header} - {sortCol === col.columnKey ? ( - - {sortDir === -1 - ? T.translate("mui_table.sorted_desc") - : T.translate("mui_table.sorted_asc")} - - ) : null} - - ) : ( - col.header - )} - - ))} - {onEdit && } - {onArchive && } - {onDelete && } - - - {/* TABLE BODY */} - - {data.map((row) => ( - - {columns.map((col) => ( - handleCellClick(row, col.columnKey)} - sx={getCellSx(row, { - cursor: isEditable(col, row) ? "pointer" : "default", - padding: isEditable(col, row) ? "8px 16px" : undefined // Ensure enough space for the edit icon - })} - > - {isEditable(col, row) ? ( - - handleCellBlur( - row.id, - col.columnKey, - newValue, - isValid - ) - } - validation={col.validation} - /> - ) : col.render ? ( - col.render(row) - ) : ( - row[col.columnKey] - )} - - ))} - {onEdit && ( - - onEdit(row)} - size="small" - aria-label={T.translate("general.edit")} - > - - - - )} - {onArchive && ( - - - - )} - {onDelete && ( - - handleDelete(row)} - size="small" - aria-label={T.translate("general.delete")} - > - - - - )} - - ))} - -
-
- -
-
- ); -}; - -export default MuiTableEditable; diff --git a/src/components/mui/editable-table/styles.module.less b/src/components/mui/editable-table/styles.module.less deleted file mode 100644 index d056f4b5c..000000000 --- a/src/components/mui/editable-table/styles.module.less +++ /dev/null @@ -1,14 +0,0 @@ -.dottedBorderLeft { - position: relative; - border-left: none; - &::before { - content: ""; - position: absolute; - top: 0; - bottom: 0; - left: 0; - border-left: 1px dashed #e0e0e0; - height: auto; - margin: 20px 0; - } -} diff --git a/src/components/mui/sortable-table/mui-table-sortable.js b/src/components/mui/sortable-table/mui-table-sortable.js deleted file mode 100644 index e8fa1b290..000000000 --- a/src/components/mui/sortable-table/mui-table-sortable.js +++ /dev/null @@ -1,302 +0,0 @@ -import * as React from "react"; -import T from "i18n-react/dist/i18n-react"; -import Box from "@mui/material/Box"; -import Table from "@mui/material/Table"; -import TableBody from "@mui/material/TableBody"; -import TableCell from "@mui/material/TableCell"; -import TableContainer from "@mui/material/TableContainer"; -import TableHead from "@mui/material/TableHead"; -import TablePagination from "@mui/material/TablePagination"; -import TableSortLabel from "@mui/material/TableSortLabel"; -import TableRow from "@mui/material/TableRow"; -import Paper from "@mui/material/Paper"; -import UnfoldMoreIcon from "@mui/icons-material/UnfoldMore"; -import { IconButton } from "@mui/material"; -import EditIcon from "@mui/icons-material/Edit"; -import DeleteIcon from "@mui/icons-material/Delete"; -import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd"; -import { visuallyHidden } from "@mui/utils"; - -import styles from "./styles.module.less"; - -import { - DEFAULT_PER_PAGE, - FIFTY_PER_PAGE, - TWENTY_PER_PAGE -} from "../../../utils/constants"; -import showConfirmDialog from "../showConfirmDialog"; - -const MuiTableSortable = ({ - columns = [], - data = [], - totalRows, - perPage, - currentPage, - onPageChange, - onPerPageChange, - onSort, - options = { sortCol: "", sortDir: 1 }, - getName = (item) => item.name, - onEdit, - onDelete, - deleteDialogTitle = null, - deleteDialogBody = null, - onReorder, - idKey = "id", - updateOrderKey = "order" -}) => { - const handleChangePage = (_, newPage) => { - onPageChange(newPage + 1); - }; - - const handleChangeRowsPerPage = (ev) => { - onPerPageChange(ev.target.value); - }; - - const basePerPageOptions = [ - DEFAULT_PER_PAGE, - TWENTY_PER_PAGE, - FIFTY_PER_PAGE - ]; - - const customPerPageOptions = basePerPageOptions.includes(perPage) - ? basePerPageOptions - : [...basePerPageOptions, perPage].sort((a, b) => a - b); - - const { sortCol, sortDir } = options; - - const handleDragEnd = (result) => { - if (!result.destination || result.source.index === result.destination.index) - return; - - const reordered = [...data]; - const [movedItem] = reordered.splice(result.source.index, 1); - reordered.splice(result.destination.index, 0, movedItem); - - // change value based on updateOrderKey - if (updateOrderKey) { - reordered.forEach((item, idx) => { - item[updateOrderKey] = idx + 1; - }); - } - - const movedItemId = movedItem.id; - const newOrder = reordered.find( - (item) => item[idKey || "id"] === movedItemId - )?.[updateOrderKey]; - - onReorder?.(reordered, movedItemId, newOrder); - }; - - const handleDelete = async (item) => { - const isConfirmed = await showConfirmDialog({ - title: deleteDialogTitle || T.translate("general.are_you_sure"), - text: - typeof deleteDialogBody === "function" - ? deleteDialogBody(getName(item)) - : deleteDialogBody || - `${T.translate("general.row_remove_warning")} ${getName(item)}`, - type: "warning", - showCancelButton: true, - confirmButtonColor: "#DD6B55", - confirmButtonText: T.translate("general.yes_delete") - }); - - if (isConfirmed) { - onDelete(item.id); - } - }; - - return ( - - - - - {/* TABLE HEADER */} - - - {columns.map((col) => ( - - {col.sortable ? ( - onSort(col.columnKey, sortDir * -1)} - > - {col.header} - {sortCol === col.columnKey ? ( - - {sortDir === -1 - ? T.translate("mui_table.sorted_desc") - : T.translate("mui_table.sorted_asc")} - - ) : null} - - ) : ( - col.header - )} - - ))} - {onEdit && } - {onDelete && } - {onReorder && } - - - - {/* TABLE BODY */} - - - {(droppableProvided) => ( - - {data.map((row, rowIndex) => ( - - {(provided, snapshot) => ( - - {/* Main content columns */} - {columns.map((col) => ( - - {col.render?.(row) || row[col.columnKey]} - - ))} - {/* Edit column */} - {onEdit && ( - - onEdit(row)} - > - - - - )} - {/* Delete column */} - {onDelete && ( - - handleDelete(row)} - > - - - - )} - {/* Re order column */} - {onReorder && ( - - - - - - )} - - )} - - ))} - {droppableProvided.placeholder} - {data.length === 0 && ( - - - {T.translate("mui_table.no_items")} - - - )} - - )} - - -
-
- - {/* PAGINATION */} - {onPerPageChange && onPageChange && ( - - )} -
-
- ); -}; - -export default MuiTableSortable; diff --git a/src/components/mui/sortable-table/styles.module.less b/src/components/mui/sortable-table/styles.module.less deleted file mode 100644 index d056f4b5c..000000000 --- a/src/components/mui/sortable-table/styles.module.less +++ /dev/null @@ -1,14 +0,0 @@ -.dottedBorderLeft { - position: relative; - border-left: none; - &::before { - content: ""; - position: absolute; - top: 0; - bottom: 0; - left: 0; - border-left: 1px dashed #e0e0e0; - height: auto; - margin: 20px 0; - } -} diff --git a/src/components/mui/table/extra-rows/NotesRow.jsx b/src/components/mui/table/extra-rows/NotesRow.jsx deleted file mode 100644 index 6b4b61394..000000000 --- a/src/components/mui/table/extra-rows/NotesRow.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import TableCell from "@mui/material/TableCell"; -import TableRow from "@mui/material/TableRow"; -import * as React from "react"; -import { Typography } from "@mui/material"; - -const NotesRow = ({ colCount, note }) => ( - - - - {note} - - - - ); - -export default NotesRow; diff --git a/src/components/mui/table/extra-rows/TotalRow.jsx b/src/components/mui/table/extra-rows/TotalRow.jsx deleted file mode 100644 index 2c1fa7d64..000000000 --- a/src/components/mui/table/extra-rows/TotalRow.jsx +++ /dev/null @@ -1,32 +0,0 @@ -import TableCell from "@mui/material/TableCell"; -import TableRow from "@mui/material/TableRow"; -import * as React from "react"; -import T from "i18n-react/dist/i18n-react"; - -const TotalRow = ({ columns, targetCol, total, trailing = 0 }) => { - return ( - - {columns.map((col, i) => { - if (i === 0) - return ( - - {T.translate("mui_table.total")} - - ); - if (col.columnKey === targetCol) - return ( - - {total} - - ); - return ; - })} - {[...Array(trailing)].map((_, i) => ( - // eslint-disable-next-line react/no-array-index-key - - ))} - - ); -}; - -export default TotalRow; diff --git a/src/components/mui/table/extra-rows/index.js b/src/components/mui/table/extra-rows/index.js deleted file mode 100644 index 6e7961237..000000000 --- a/src/components/mui/table/extra-rows/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { default as TotalRow } from "./TotalRow"; -export { default as NotesRow } from "./NotesRow"; diff --git a/src/components/mui/table/mui-table.js b/src/components/mui/table/mui-table.js deleted file mode 100644 index 433c8bb90..000000000 --- a/src/components/mui/table/mui-table.js +++ /dev/null @@ -1,295 +0,0 @@ -import * as React from "react"; -import T from "i18n-react/dist/i18n-react"; -import { isBoolean } from "lodash"; -import { - Box, - Button, - IconButton, - Paper, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TablePagination, - TableRow, - TableSortLabel -} from "@mui/material"; -import EditIcon from "@mui/icons-material/Edit"; -import DeleteIcon from "@mui/icons-material/Delete"; -import CheckIcon from "@mui/icons-material/Check"; -import CloseIcon from "@mui/icons-material/Close"; -import { visuallyHidden } from "@mui/utils"; -import { - DEFAULT_PER_PAGE, - FIFTY_PER_PAGE, - TWENTY_PER_PAGE -} from "../../../utils/constants"; -import showConfirmDialog from "../showConfirmDialog"; -import styles from "./mui-table.module.less"; - -const ARCHIVED_CELL_SX = { - backgroundColor: "background.light", - color: "text.disabled" -}; - -const MuiTable = ({ - columns = [], - data = [], - children, - totalRows, - perPage, - currentPage, - onPageChange, - onPerPageChange, - onSort, - options = { sortCol: "", sortDir: 1, disableProp: null }, // disableProp is the prop that will disable the row - getName = (item) => item.name, - onEdit, - onArchive, - onDelete, - canDelete = () => true, - deleteDialogTitle = null, - deleteDialogBody = null, - deleteDialogConfirmText = null, - confirmButtonColor = null -}) => { - const handleChangePage = (_, newPage) => { - onPageChange(newPage + 1); - }; - - const handleChangeRowsPerPage = (ev) => { - onPerPageChange(ev.target.value); - }; - - const basePerPageOptions = [ - DEFAULT_PER_PAGE, - TWENTY_PER_PAGE, - FIFTY_PER_PAGE - ]; - - const initialPerPage = React.useRef(perPage); - - let customPerPageOptions = basePerPageOptions.includes(initialPerPage.current) - ? basePerPageOptions - : [...basePerPageOptions, initialPerPage.current].sort((a, b) => a - b); - - // remove per page selection if no action passed - if (!onPerPageChange) { - customPerPageOptions = [initialPerPage.current]; - } - - const { sortCol, sortDir } = options; - - const getArchivedCellSx = (row) => - options.disableProp && row[options.disableProp] ? ARCHIVED_CELL_SX : null; - - const getCellSx = (row, baseSx = {}) => ({ - ...baseSx, - ...(getArchivedCellSx(row) || {}) - }); - - const handleDelete = async (item) => { - const isConfirmed = await showConfirmDialog({ - title: deleteDialogTitle || T.translate("general.are_you_sure"), - text: - typeof deleteDialogBody === "function" - ? deleteDialogBody(getName(item)) - : deleteDialogBody || - `${T.translate("general.row_remove_warning")} ${getName(item)}`, - type: "warning", - showCancelButton: true, - confirmButtonColor: confirmButtonColor || "#DD6B55", - confirmButtonText: - deleteDialogConfirmText || T.translate("general.yes_delete") - }); - - if (isConfirmed) { - onDelete(item.id); - } - }; - - const renderCell = (row, col) => { - if (col.render) { - return col.render(row); - } - - if (isBoolean(row[col.columnKey])) { - return row[col.columnKey] ? ( - - ) : ( - - ); - } - - return row[col.columnKey]; - }; - - return ( - - - - - {/* TABLE HEADER */} - - - {columns.map((col) => ( - - {col.sortable ? ( - onSort(col.columnKey, sortDir * -1)} - > - {col.header} - {sortCol === col.columnKey ? ( - - {sortDir === -1 - ? T.translate("mui_table.sorted_desc") - : T.translate("mui_table.sorted_asc")} - - ) : null} - - ) : ( - col.header - )} - - ))} - {onEdit && } - {onArchive && } - {onDelete && } - - - - {/* TABLE BODY */} - - {data.map((row) => ( - - {/* Main content columns */} - {columns.map((col) => ( - - {renderCell(row, col)} - - ))} - {/* Edit column */} - {onEdit && ( - - onEdit(row)}> - - - - )} - {/* Archive column */} - {onArchive && ( - - - - )} - {/* Delete column */} - {onDelete && ( - - {canDelete(row) && ( - handleDelete(row)} - > - - - )} - - )} - - ))} - {/* Here we inject extra rows passed as children */} - {children} - {data.length === 0 && ( - - - {T.translate("mui_table.no_items")} - - - )} - -
-
- - {/* PAGINATION */} - {perPage && currentPage && ( - - )} -
-
- ); -}; - -export default MuiTable; diff --git a/src/components/mui/table/mui-table.module.less b/src/components/mui/table/mui-table.module.less deleted file mode 100644 index f77d0c5f9..000000000 --- a/src/components/mui/table/mui-table.module.less +++ /dev/null @@ -1,14 +0,0 @@ -.dottedBorderLeft { - position: relative; - border-left: none; - &::before { - content: ""; - position: absolute; - top: 0; - bottom: 0; - left: 0; - border-left: 1px dashed #e0e0e0; - height: 60%; - align-self: center; - } -} diff --git a/src/i18n/en.json b/src/i18n/en.json index 09acb8d4a..c8c218949 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -2429,9 +2429,11 @@ "add_ons": "Add-ons", "opens_at": "Opens at", "expires_at": "Expires at", + "item": "Item", "items": "Items", "managed_forms": "Managed Forms", "manage_items": "Manage Items", + "none": "None", "customize": "Customize", "archive": "Archive", "unarchive": "Unarchive", @@ -2637,6 +2639,7 @@ "tiers_column_label": "Tiers", "manage_items_button": "Manage Items", "form_delete_success": "Form successfully deleted.", + "manage_items": "Manage Items", "unarchive_button": "Unarchive", "archive_button": "Archive", "remove_form_warning": "Please verify you want to delete {name}", @@ -2721,7 +2724,7 @@ "quantity_limit_per_sponsor": "Limit total amount per sponsor (empty = disabled)", "default_quantity": "Default quantity", "additional_fields": "Additional Input Fields", - "images": "Images", + "images": "Image File", "save": "save changes", "created": "Item created successfully.", "updated": "Item {name} updated successfully." @@ -3838,7 +3841,7 @@ "meta_field_required": "Required Field", "meta_field_type": "Field Type", "meta_field_add_value": "Add a value", - "meta_field_is_default": "Is Default?", + "meta_field_is_default": "Default Value", "placeholders": { "meta_field_name": "Name", "meta_field_value": "Value", @@ -3853,7 +3856,7 @@ "delete_value_warning": "Please verify you want to delete the added value", "name": "Name", "value": "Value", - "is_default": "Is Default?", + "is_default": "Default Value", "commit_value": "Set Value", "placeholders": { "name": "Name", 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 067add164..6a13d8fa3 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 @@ -13,6 +13,7 @@ import { import T from "i18n-react"; import * as yup from "yup"; import { FormikProvider, useFormik } from "formik"; +import { UploadInputV3 } from "openstack-uicore-foundation/lib/components"; import { addIssAfterDateFieldValidator, nullableDecimalValidation, @@ -24,10 +25,14 @@ import { 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 MuiFormikUpload from "../../../../components/mui/formik-inputs/mui-formik-upload"; import ItemPriceTiers from "../../../../components/mui/formik-inputs/item-price-tiers"; import FormikTextEditor from "../../../../components/inputs/formik-text-editor"; import MuiFormikQuantityField from "../../../../components/mui/formik-inputs/mui-formik-quantity-field"; +import { + ALLOWED_INVENTORY_IMAGE_FORMATS, + MAX_INVENTORY_IMAGE_UPLOAD_SIZE, + MAX_INVENTORY_IMAGES_UPLOAD_QTY +} from "../../../../utils/constants"; const buildInitialValues = (data) => ({ ...data }); @@ -143,7 +148,31 @@ const SponsorFormItemForm = ({ initialValues, onSubmit }) => { {T.translate("sponsor_form_item_list.edit_item.images")} - + { + const newImages = (formik.values.images || []).filter( + (img) => img.filename !== file.name + ); + formik.setFieldValue("images", newImages); + }} + postUrl={`${window.FILE_UPLOAD_API_BASE_URL}/api/v1/files/upload`} + mediaType={{ + type: { allowed_extensions: ALLOWED_INVENTORY_IMAGE_FORMATS }, + max_size: MAX_INVENTORY_IMAGE_UPLOAD_SIZE + }} + onUploadComplete={(response) => { + if (response && response.file) { + const newImages = [ + ...(formik.values.images || []), + response.file + ]; + formik.setFieldValue("images", newImages); + } + }} + maxFiles={MAX_INVENTORY_IMAGES_UPLOAD_QTY} + /> diff --git a/src/pages/sponsors/sponsor-forms-list-page/index.js b/src/pages/sponsors/sponsor-forms-list-page/index.js index 292cd4c9c..5e867b0aa 100644 --- a/src/pages/sponsors/sponsor-forms-list-page/index.js +++ b/src/pages/sponsors/sponsor-forms-list-page/index.js @@ -12,7 +12,7 @@ * */ import React, { useEffect, useState, useRef } from "react"; - +import { epochToMoment } from "openstack-uicore-foundation/lib/utils/methods"; import { connect } from "react-redux"; import T from "i18n-react/dist/i18n-react"; import { @@ -196,6 +196,11 @@ const SponsorFormsListPage = ({ }) .catch(() => {}); }; + + const formatDate = (timestamp) => { + if (!timestamp) return ""; + return epochToMoment(Number(timestamp)).format("MM/DD/YYYY"); + }; const columns = [ { @@ -286,28 +291,48 @@ const SponsorFormsListPage = ({ ); } }, + { + columnKey: "opens_at", + header: T.translate("edit_sponsor.forms_tab.opens_at"), + sortable: true, + width: 115, + render: (row) => formatDate(row.opens_at) + }, + { + columnKey: "expires_at", + header: T.translate("edit_sponsor.forms_tab.expires_at"), + sortable: true, + width: 120, + render: (row) => formatDate(row.expires_at) + }, { columnKey: "items_qty", width: 100, header: T.translate("sponsor_forms.items_column_label"), - sortable: false + sortable: false, + width: 90 }, { columnKey: "manage_items", header: "", - width: 175, - align: "center", + width: 140, + align: "left", render: (row) => ( - ), - dottedBorder: true + ) } ]; @@ -319,7 +344,7 @@ const SponsorFormsListPage = ({ return (
-

{T.translate("sponsor_forms.forms")}

+

{T.translate("sponsor_forms.forms")}

row.allowed_add_ons?.length > 0 ? row.allowed_add_ons.map((a) => `${a.type} ${a.name}`).join(", ") - : "None" + : T.translate("edit_sponsor.forms_tab.none") }, { columnKey: "opens_at", header: T.translate("edit_sponsor.forms_tab.opens_at"), - sortable: true + sortable: true, + width: 115 }, { columnKey: "expires_at", header: T.translate("edit_sponsor.forms_tab.expires_at"), - sortable: true + sortable: true, + width: 120 }, { columnKey: "items_qty", header: T.translate("edit_sponsor.forms_tab.items"), sortable: true, + width: 90, render: (row) => - `${row.items_count} ${row.items_count === 1 ? "Item" : "Items"}` + `${row.items_count} ${ + row.items_count === 1 + ? T.translate("edit_sponsor.forms_tab.item") + : T.translate("edit_sponsor.forms_tab.items") + }` }, { columnKey: "manage_items", header: "", - width: 100, - align: "center", + align: "left", + width: 130, render: (row) => ( - ), - dottedBorder: true + ) } ]; @@ -251,23 +265,24 @@ const SponsorFormsTab = ({ { columnKey: "archive", header: "", - width: 150, + width: 60, render: () => null }, { columnKey: "customize", header: "", - width: 156, + width: 100, align: "center", render: (row) => ( ), dottedBorder: true diff --git a/src/reducers/sponsors/sponsor-forms-list-reducer.js b/src/reducers/sponsors/sponsor-forms-list-reducer.js index 6ff05be2a..056f36066 100644 --- a/src/reducers/sponsors/sponsor-forms-list-reducer.js +++ b/src/reducers/sponsors/sponsor-forms-list-reducer.js @@ -105,6 +105,8 @@ const sponsorFormsListReducer = (state = DEFAULT_STATE, action) => { id: a.id, code: a.code, name: a.name, + opens_at: a.opens_at || "", + expires_at: a.expires_at || "", items_qty: `${a.items.length} ${ a.items.length === 1 ? T.translate("sponsor_forms.item_label_singular") diff --git a/yarn.lock b/yarn.lock index b1a7a9cfa..56f2256ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1123,9 +1123,9 @@ "@lezer/highlight" "^1.0.0" "@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.27.0", "@codemirror/view@^6.35.0", "@codemirror/view@^6.37.0": - version "6.41.0" - resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.41.0.tgz#482cbcb5f8f90131908e5f9c0e2f4681e0684db0" - integrity sha512-6H/qadXsVuDY219Yljhohglve8xf4B8xJkVOEWfA5uiYKiTFppjqsvsfR5iPA0RbvRBoOyTZpbLIxe9+0UR8xA== + version "6.41.1" + resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.41.1.tgz#8ecb39af289e7d03df0f3fb6e3c9b1f8747839bf" + integrity sha512-ToDnWKbBnke+ZLrP6vgTTDScGi5H37YYuZGniQaBzxMVdtCxMrslsmtnOvbPZk4RX9bvkQqnWR/WS/35tJA0qg== dependencies: "@codemirror/state" "^6.6.0" crelt "^1.0.6" @@ -1641,74 +1641,74 @@ resolved "https://registry.yarnpkg.com/@jsonjoy.com/codegen/-/codegen-1.0.0.tgz#5c23f796c47675f166d23b948cdb889184b93207" integrity sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g== -"@jsonjoy.com/fs-core@4.57.1": - version "4.57.1" - resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-core/-/fs-core-4.57.1.tgz#03c0d7a7bf96030376f7194b9c5c815cb7bf71d7" - integrity sha512-YrEi/ZPmgc+GfdO0esBF04qv8boK9Dg9WpRQw/+vM8Qt3nnVIJWIa8HwZ/LXVZ0DB11XUROM8El/7yYTJX+WtA== +"@jsonjoy.com/fs-core@4.57.2": + version "4.57.2" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-core/-/fs-core-4.57.2.tgz#e28f357ba9983ce53577ba34fc72d344f19ec459" + integrity sha512-SVjwklkpIV5wrynpYtuYnfYH1QF4/nDuLBX7VXdb+3miglcAgBVZb/5y0cOsehRV/9Vb+3UqhkMq3/NR3ztdkQ== dependencies: - "@jsonjoy.com/fs-node-builtins" "4.57.1" - "@jsonjoy.com/fs-node-utils" "4.57.1" + "@jsonjoy.com/fs-node-builtins" "4.57.2" + "@jsonjoy.com/fs-node-utils" "4.57.2" thingies "^2.5.0" -"@jsonjoy.com/fs-fsa@4.57.1": - version "4.57.1" - resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-fsa/-/fs-fsa-4.57.1.tgz#87ffa6cd695b363b58b9ccddc87a66212a1b25fd" - integrity sha512-ooEPvSW/HQDivPDPZMibHGKZf/QS4WRir1czGZmXmp3MsQqLECZEpN0JobrD8iV9BzsuwdIv+PxtWX9WpPLsIA== +"@jsonjoy.com/fs-fsa@4.57.2": + version "4.57.2" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-fsa/-/fs-fsa-4.57.2.tgz#ec6dd492ff8c104a0c1eae74959a013960fe8969" + integrity sha512-fhO8+iR2I+OCw668ISDJdn1aArc9zx033sWejIyzQ8RBeXa9bDSaUeA3ix0poYOfrj1KdOzytmYNv2/uLDfV6g== dependencies: - "@jsonjoy.com/fs-core" "4.57.1" - "@jsonjoy.com/fs-node-builtins" "4.57.1" - "@jsonjoy.com/fs-node-utils" "4.57.1" + "@jsonjoy.com/fs-core" "4.57.2" + "@jsonjoy.com/fs-node-builtins" "4.57.2" + "@jsonjoy.com/fs-node-utils" "4.57.2" thingies "^2.5.0" -"@jsonjoy.com/fs-node-builtins@4.57.1": - version "4.57.1" - resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.57.1.tgz#a6793654d6ffaead81f040e3becc063a265deb7c" - integrity sha512-XHkFKQ5GSH3uxm8c3ZYXVrexGdscpWKIcMWKFQpMpMJc8gA3AwOMBJXJlgpdJqmrhPyQXxaY9nbkNeYpacC0Og== - -"@jsonjoy.com/fs-node-to-fsa@4.57.1": - version "4.57.1" - resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.57.1.tgz#9011872df67ac302f0b0f7fd13502993a026c306" - integrity sha512-pqGHyWWzNck4jRfaGV39hkqpY5QjRUQ/nRbNT7FYbBa0xf4bDG+TE1Gt2KWZrSkrkZZDE3qZUjYMbjwSliX6pg== - dependencies: - "@jsonjoy.com/fs-fsa" "4.57.1" - "@jsonjoy.com/fs-node-builtins" "4.57.1" - "@jsonjoy.com/fs-node-utils" "4.57.1" - -"@jsonjoy.com/fs-node-utils@4.57.1": - version "4.57.1" - resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.57.1.tgz#e9d030b676f7f4074eb90a42927bac708dc4312c" - integrity sha512-vp+7ZzIB8v43G+GLXTS4oDUSQmhAsRz532QmmWBbdYA20s465JvwhkSFvX9cVTqRRAQg+vZ7zWDaIEh0lFe2gw== - dependencies: - "@jsonjoy.com/fs-node-builtins" "4.57.1" - -"@jsonjoy.com/fs-node@4.57.1": - version "4.57.1" - resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-node/-/fs-node-4.57.1.tgz#3dae969fe02d9450f5dfc7c12bfe3b859cb1038e" - integrity sha512-3YaKhP8gXEKN+2O49GLNfNb5l2gbnCFHyAaybbA2JkkbQP3dpdef7WcUaHAulg/c5Dg4VncHsA3NWAUSZMR5KQ== - dependencies: - "@jsonjoy.com/fs-core" "4.57.1" - "@jsonjoy.com/fs-node-builtins" "4.57.1" - "@jsonjoy.com/fs-node-utils" "4.57.1" - "@jsonjoy.com/fs-print" "4.57.1" - "@jsonjoy.com/fs-snapshot" "4.57.1" +"@jsonjoy.com/fs-node-builtins@4.57.2": + version "4.57.2" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.57.2.tgz#9174b87e70213b38caf1ac8669b130c4dfd6a909" + integrity sha512-xhiegylRmhw43Ki2HO1ZBL7DQ5ja/qpRsL29VtQ2xuUHiuDGbgf2uD4p9Qd8hJI5P6RCtGYD50IXHXVq/Ocjcg== + +"@jsonjoy.com/fs-node-to-fsa@4.57.2": + version "4.57.2" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.57.2.tgz#8542449b72dfc48f3bfe311a7b0af5323f9bc926" + integrity sha512-18LmWTSONhoAPW+IWRuf8w/+zRolPFGPeGwMxlAhhfY11EKzX+5XHDBPAw67dBF5dxDErHJbl40U+3IXSDRXSQ== + dependencies: + "@jsonjoy.com/fs-fsa" "4.57.2" + "@jsonjoy.com/fs-node-builtins" "4.57.2" + "@jsonjoy.com/fs-node-utils" "4.57.2" + +"@jsonjoy.com/fs-node-utils@4.57.2": + version "4.57.2" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.57.2.tgz#c3234c03b1e59d609a0915572dd6f450be0463b1" + integrity sha512-rsPSJgekz43IlNbLyAM/Ab+ouYLWGp5DDBfYBNNEqDaSpsbXfthBn29Q4muFA9L0F+Z3mKo+CWlgSCXrf+mOyQ== + dependencies: + "@jsonjoy.com/fs-node-builtins" "4.57.2" + +"@jsonjoy.com/fs-node@4.57.2": + version "4.57.2" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-node/-/fs-node-4.57.2.tgz#8db2875df19683683e5852053e0099e233dc45d2" + integrity sha512-nX2AdL6cOFwLdju9G4/nbRnYevmCJbh7N7hvR3gGm97Cs60uEjyd0rpR+YBS7cTg175zzl22pGKXR5USaQMvKg== + dependencies: + "@jsonjoy.com/fs-core" "4.57.2" + "@jsonjoy.com/fs-node-builtins" "4.57.2" + "@jsonjoy.com/fs-node-utils" "4.57.2" + "@jsonjoy.com/fs-print" "4.57.2" + "@jsonjoy.com/fs-snapshot" "4.57.2" glob-to-regex.js "^1.0.0" thingies "^2.5.0" -"@jsonjoy.com/fs-print@4.57.1": - version "4.57.1" - resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-print/-/fs-print-4.57.1.tgz#59359be175145cd44e83f7cdfba06cb1fed23313" - integrity sha512-Ynct7ZJmfk6qoXDOKfpovNA36ITUx8rChLmRQtW08J73VOiuNsU8PB6d/Xs7fxJC2ohWR3a5AqyjmLojfrw5yw== +"@jsonjoy.com/fs-print@4.57.2": + version "4.57.2" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-print/-/fs-print-4.57.2.tgz#286c4ceda19225a5c54aaad657ad9f466d5bd0c1" + integrity sha512-wK9NSow48i4DbDl9F1CQE5TqnyZOJ04elU3WFG5aJ76p+YxO/ulyBBQvKsessPxdo381Bc2pcEoyPujMOhcRqQ== dependencies: - "@jsonjoy.com/fs-node-utils" "4.57.1" + "@jsonjoy.com/fs-node-utils" "4.57.2" tree-dump "^1.1.0" -"@jsonjoy.com/fs-snapshot@4.57.1": - version "4.57.1" - resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.57.1.tgz#54cd9073a97e290a1650070f2ee9529a0accdb93" - integrity sha512-/oG8xBNFMbDXTq9J7vepSA1kerS5vpgd3p5QZSPd+nX59uwodGJftI51gDYyHRpP57P3WCQf7LHtBYPqwUg2Bg== +"@jsonjoy.com/fs-snapshot@4.57.2": + version "4.57.2" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.57.2.tgz#800424a076638a605dad5ef1540915bc0167d7f8" + integrity sha512-GdduDZuoP5V/QCgJkx9+BZ6SC0EZ/smXAdTS7PfMqgMTGXLlt/bH/FqMYaqB9JmLf05sJPtO0XRbAwwkEEPbVw== dependencies: "@jsonjoy.com/buffers" "^17.65.0" - "@jsonjoy.com/fs-node-utils" "4.57.1" + "@jsonjoy.com/fs-node-utils" "4.57.2" "@jsonjoy.com/json-pack" "^17.65.0" "@jsonjoy.com/util" "^17.65.0" @@ -1830,9 +1830,9 @@ "@lezer/lr" "^1.0.0" "@lezer/lr@^1.0.0", "@lezer/lr@^1.3.0": - version "1.4.8" - resolved "https://registry.yarnpkg.com/@lezer/lr/-/lr-1.4.8.tgz#333de9bc9346057323ff09beb4cda47ccc38a498" - integrity sha512-bPWa0Pgx69ylNlMlPvBPryqeLYQjyJjqPx+Aupm5zydLIF3NE+6MMLT8Yi23Bd9cif9VS00aUebn+6fDIGBcDA== + version "1.4.10" + resolved "https://registry.yarnpkg.com/@lezer/lr/-/lr-1.4.10.tgz#b3acc36e5ad049b74ddb7719594e7e74d9161ff5" + integrity sha512-rnCpTIBafOx4mRp43xOxDJbFipJm/c0cia/V5TiGlhmMa+wsSdoGmUN3w5Bqrks/09Q/D4tNAmWaT8p6NRi77A== dependencies: "@lezer/common" "^1.0.0" @@ -2158,13 +2158,13 @@ fontkit "^2.0.2" is-url "^1.2.4" -"@react-pdf/font@^4.0.6": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@react-pdf/font/-/font-4.0.6.tgz#933641615adc1aa14055377e2441ec6544d7d372" - integrity sha512-1RxR/hTyZcbgjESUjrMms574xuS9PLB4ovqQx6jvgdrIHXUyeUtSH6i3Szw1qVfUnA9MfaEm1FBuydQeJD39BQ== +"@react-pdf/font@^4.0.8": + version "4.0.8" + resolved "https://registry.yarnpkg.com/@react-pdf/font/-/font-4.0.8.tgz#2279fb487f8a532e8b82e11732703a904ad05bb3" + integrity sha512-deNd+emtZAJho1IlzKL9bRoLAGv/6oXOIKO2oZfs4RuXUrK1onLHbJO7e2YoVLPFP/sQxisRTnzdJFtd35iKwA== dependencies: - "@react-pdf/pdfkit" "^5.0.0" - "@react-pdf/types" "^2.10.0" + "@react-pdf/pdfkit" "^5.1.1" + "@react-pdf/types" "^2.11.1" fontkit "^2.0.2" is-url "^1.2.4" @@ -2209,20 +2209,20 @@ jay-peg "^1.0.2" vite-compatible-readable-stream "^3.6.1" -"@react-pdf/pdfkit@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@react-pdf/pdfkit/-/pdfkit-5.0.0.tgz#48ac22a479995cfbe57f16818f47857519a3957d" - integrity sha512-FcQBWGtfhMGuOB0G3NcnF/cBq/JnFVs22i1tuafiT1XlmG6KjCxgTGng5bVh+b9RtTuwNpUGmCtB6CmG6B4ZVA== +"@react-pdf/pdfkit@^5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@react-pdf/pdfkit/-/pdfkit-5.1.1.tgz#b3af968f94555a3d7c4cc1d5b81493bdbfbd76e0" + integrity sha512-wNcdSsNlNYyGHGAgIdt453egBF7fiF9UxpRlklUfVvu8OWCrUppG9xiUrPLVoKiqWet5tMi0w6LmuFUJuYqjEg== dependencies: "@babel/runtime" "^7.20.13" "@noble/ciphers" "^1.0.0" "@noble/hashes" "^1.6.0" - "@react-pdf/png-js" "^3.0.0" browserify-zlib "^0.2.0" fontkit "^2.0.2" jay-peg "^1.1.1" js-md5 "^0.8.3" linebreak "^1.1.0" + png-js "^2.0.0" vite-compatible-readable-stream "^3.6.1" "@react-pdf/png-js@^2.3.1": @@ -2232,22 +2232,15 @@ dependencies: browserify-zlib "^0.2.0" -"@react-pdf/png-js@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@react-pdf/png-js/-/png-js-3.0.0.tgz#c0b7dc7c77e36f0830e9b7bccca7ddd64ada1c5e" - integrity sha512-eSJnEItZ37WPt6Qv5pncQDxLJRK15eaRwPT+gZoujP548CodenOVp49GST8XJvKMFt9YqIBzGBV/j9AgrOQzVA== - dependencies: - browserify-zlib "^0.2.0" - "@react-pdf/primitives@^3.1.1": version "3.1.1" resolved "https://registry.yarnpkg.com/@react-pdf/primitives/-/primitives-3.1.1.tgz#45a3253806fa61046f3821b8553bfee3cd848d14" integrity sha512-miwjxLwTnO3IjoqkTVeTI+9CdyDggwekmSLhVCw+a/7FoQc+gF3J2dSKwsHvAcVFM0gvU8mzCeTofgw0zPDq0w== -"@react-pdf/primitives@^4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@react-pdf/primitives/-/primitives-4.2.0.tgz#96b127325076779f0da03806c02b16f11ede950a" - integrity sha512-onlXLcA6SpsD7SX9HOyt55qdRRJCfauegPlo4ZNw0hA/IipaZTbT9MJliWKtEXm03ibGxAQyp/BgTuXm91fo0A== +"@react-pdf/primitives@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@react-pdf/primitives/-/primitives-4.3.0.tgz#3bb5f74294bea923392499dd46bc5196d47b918c" + integrity sha512-nYXoZ36pvwNzbc54+DbL8RCn15jU7woJ9D/svnh5tpUXekJ+CbI4mZLo6boSv24CvJgychOu6h7gxX03B4ps0A== "@react-pdf/render@^3.5.0": version "3.5.0" @@ -2296,14 +2289,14 @@ media-engine "^1.0.3" postcss-value-parser "^4.1.0" -"@react-pdf/stylesheet@^6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@react-pdf/stylesheet/-/stylesheet-6.1.4.tgz#a770319b0ca61b21721b19918d626957c0935977" - integrity sha512-jiwovO7lUwgccAh3JbVcXnh90AiSKZetdz2ETcWsKApPPLzLUzPkEs6wCVvZqh3lcGOAPFV3AfdMkFnLwv1ryg== +"@react-pdf/stylesheet@^6.2.1": + version "6.2.1" + resolved "https://registry.yarnpkg.com/@react-pdf/stylesheet/-/stylesheet-6.2.1.tgz#baa87869c0cc953fb334d20c63359672b872475c" + integrity sha512-2+UEk+7e+z8baaWi2l5kPLWmwtJeOI+T5wW9GGeN3iDH7vd3kbTqOpN1yt9mmfNVZFxQsnDHpznFb5v5UF983A== dependencies: "@react-pdf/fns" "3.1.3" - "@react-pdf/types" "^2.10.0" - color-string "^1.9.1" + "@react-pdf/types" "^2.11.1" + color-string "^2.1.4" hsl-to-hex "^1.0.0" media-engine "^1.0.3" postcss-value-parser "^4.1.0" @@ -2319,14 +2312,14 @@ hyphen "^1.6.4" unicode-properties "^1.4.1" -"@react-pdf/types@^2.10.0", "@react-pdf/types@^2.6.0": - version "2.10.0" - resolved "https://registry.yarnpkg.com/@react-pdf/types/-/types-2.10.0.tgz#153a22987496d9d755307c955db18f98a855ac55" - integrity sha512-iz0NusqQ/9ZHQirWhJqOaxY1UkpvuNkEDtH4/SPCnhZJKBO/IhlFLFHuzbHkmWByBoX6X3m8GCc2b/1QH6QNlA== +"@react-pdf/types@^2.11.1", "@react-pdf/types@^2.6.0": + version "2.11.1" + resolved "https://registry.yarnpkg.com/@react-pdf/types/-/types-2.11.1.tgz#ae37a12a883ae2d54a2b98b9b9ba32fbf4241478" + integrity sha512-i9xQgfaDU9QoeNnbp6rltXCWg1huEh195rpOuN8cE4BZ2FuLdQrsIcb2dhFF9aOxXf+XBA6LOSpIW051MDD/bw== dependencies: - "@react-pdf/font" "^4.0.6" - "@react-pdf/primitives" "^4.2.0" - "@react-pdf/stylesheet" "^6.1.4" + "@react-pdf/font" "^4.0.8" + "@react-pdf/primitives" "^4.3.0" + "@react-pdf/stylesheet" "^6.2.1" "@rtsao/scc@^1.1.0": version "1.1.0" @@ -3276,9 +3269,9 @@ integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== "@xmldom/xmldom@^0.8.3": - version "0.8.12" - resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.12.tgz#cf488a5435fa06c7374ad1449c69cea0f823624b" - integrity sha512-9k/gHF6n/pAi/9tqr3m3aqkuiNosYTurLLUtc7xQ9sxB/wm7WPygCv8GYa6mS0fLJEHhqMC1ATYhz++U/lRHqg== + version "0.8.13" + resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.13.tgz#00d1dd940b218dff2e49309d410d8bb212159225" + integrity sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw== "@xtuc/ieee754@^1.2.0": version "1.2.0" @@ -3646,12 +3639,12 @@ asn1.js@^4.10.1: minimalistic-assert "^1.0.0" asn1js@^3.0.6: - version "3.0.7" - resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.7.tgz#15f1f2f59e60f80d5b43ef14047a294a969f824f" - integrity sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ== + version "3.0.9" + resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.9.tgz#d48f454d263a0c9f5fe8c6c66057a4d69bccfece" + integrity sha512-g35Ef4IMkE3mDaMAYd3GOJ/c41LKcaiJuuLZ9BF0EXkZwYc0tkFpmZqxWsKlmXS3Um42dAkyx//kibIETBjfqg== dependencies: pvtsutils "^1.3.6" - pvutils "^1.1.3" + pvutils "^1.1.5" tslib "^2.8.1" ast-types-flow@^0.0.8: @@ -3878,9 +3871,9 @@ base64-js@^1.1.2, base64-js@^1.3.0, base64-js@^1.3.1, base64-js@^1.5.1: integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== baseline-browser-mapping@^2.10.12: - version "2.10.19" - resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.19.tgz#7697721c22f94f66195d0c34299b1a91e3299493" - integrity sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g== + version "2.10.20" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.20.tgz#7c99b86d43ae9be3810cac515f4675802e1f6b87" + integrity sha512-1AaXxEPfXT+GvTBJFuy4yXVHWJBXa4OdbIebGN/wX5DlsIkU0+wzGnd2lOzokSk51d5LUmqjgBLRLlypLUqInQ== batch@0.6.1: version "0.6.1" @@ -4408,6 +4401,11 @@ color-name@^1.0.0, color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-name@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-2.1.0.tgz#0b677385c1c4b4edfdeaf77e38fa338e3a40b693" + integrity sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg== + color-string@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" @@ -4416,6 +4414,13 @@ color-string@^1.9.1: color-name "^1.0.0" simple-swizzle "^0.2.2" +color-string@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-2.1.4.tgz#9dcf566ff976e23368c8bd673f5c35103ab41058" + integrity sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg== + dependencies: + color-name "^2.0.0" + colord@^2.9.1: version "2.9.3" resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" @@ -5356,9 +5361,9 @@ ee-first@1.1.1: integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== electron-to-chromium@^1.5.328: - version "1.5.336" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.336.tgz#d7c25c0827b8c5e2885b2c91ac6cdcf3e5a1386e" - integrity sha512-AbH9q9J455r/nLmdNZes0G0ZKcRX73FicwowalLs6ijwOmCJSRRrLX63lcAlzy9ux3dWK1w1+1nsBJEWN11hcQ== + version "1.5.340" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.340.tgz#fe3f76e8d9b9541c123fb7edbc3381688272f79a" + integrity sha512-908qahOGocRMinT2nM3ajCEM99H4iPdv84eagPP3FfZy/1ZGeOy2CZYzjhms81ckOPCXPlW7LkY4XpxD8r1DrA== elliptic@^6.5.3, elliptic@^6.6.1: version "6.6.1" @@ -6103,6 +6108,11 @@ fbjs@^2.0.0: setimmediate "^1.0.5" ua-parser-js "^0.7.18" +fflate@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" + integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -6618,9 +6628,9 @@ hash.js@^1.0.0, hash.js@^1.0.3: minimalistic-assert "^1.0.1" hasown@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + version "2.0.3" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.3.tgz#5e5c2b15b60370a4c7930c383dfb76bf17bc403c" + integrity sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg== dependencies: function-bind "^1.1.2" @@ -6710,9 +6720,9 @@ html-minifier-terser@^6.0.2: terser "^5.10.0" html-webpack-plugin@^5.5.0: - version "5.6.6" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.6.6.tgz#5321b9579f4a1949318550ced99c2a4a4e60cbaf" - integrity sha512-bLjW01UTrvoWTJQL5LsMRo1SypHW80FTm12OJRSnr3v6YHNhfe+1r0MYUZJMACxnCHURVnBWRwAsWs2yPU9Ezw== + version "5.6.7" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.6.7.tgz#429bab4e12abf3c07e1c608886608e2df2c06b11" + integrity sha512-md+vXtdCAe60s1k6AU3dUyMJnDxUyQAwfwPKoLisvgUF1IXjtlLsk2se54+qfL9Mdm26bbwvjJybpNx48NKRLw== dependencies: "@types/html-minifier-terser" "^6.0.0" html-minifier-terser "^6.0.2" @@ -7906,7 +7916,7 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: +json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== @@ -8308,18 +8318,18 @@ media-typer@0.3.0: integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== memfs@^4.43.1: - version "4.57.1" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-4.57.1.tgz#5ccee42e2aab1cf086c45baf9c4ef1ff4fffb123" - integrity sha512-WvzrWPwMQT+PtbX2Et64R4qXKK0fj/8pO85MrUCzymX3twwCiJCdvntW3HdhG1teLJcHDDLIKx5+c3HckWYZtQ== - dependencies: - "@jsonjoy.com/fs-core" "4.57.1" - "@jsonjoy.com/fs-fsa" "4.57.1" - "@jsonjoy.com/fs-node" "4.57.1" - "@jsonjoy.com/fs-node-builtins" "4.57.1" - "@jsonjoy.com/fs-node-to-fsa" "4.57.1" - "@jsonjoy.com/fs-node-utils" "4.57.1" - "@jsonjoy.com/fs-print" "4.57.1" - "@jsonjoy.com/fs-snapshot" "4.57.1" + version "4.57.2" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-4.57.2.tgz#5f74e977c9a14681ea10d427b3ce5d7db5f817e7" + integrity sha512-2nWzSsJzrukurSDna4Z0WywuScK4Id3tSKejgu74u8KCdW4uNrseKRSIDg75C6Yw5ZRqBe0F0EtMNlTbUq8bAQ== + dependencies: + "@jsonjoy.com/fs-core" "4.57.2" + "@jsonjoy.com/fs-fsa" "4.57.2" + "@jsonjoy.com/fs-node" "4.57.2" + "@jsonjoy.com/fs-node-builtins" "4.57.2" + "@jsonjoy.com/fs-node-to-fsa" "4.57.2" + "@jsonjoy.com/fs-node-utils" "4.57.2" + "@jsonjoy.com/fs-print" "4.57.2" + "@jsonjoy.com/fs-snapshot" "4.57.2" "@jsonjoy.com/json-pack" "^1.11.0" "@jsonjoy.com/util" "^1.9.0" glob-to-regex.js "^1.0.1" @@ -8822,10 +8832,10 @@ open@^10.0.3: is-inside-container "^1.0.0" wsl-utils "^0.1.0" -openstack-uicore-foundation@5.0.8: - version "5.0.8" - resolved "https://registry.yarnpkg.com/openstack-uicore-foundation/-/openstack-uicore-foundation-5.0.8.tgz#8ec5900651c1fedbfa4877985a2ffbb1b8cabc52" - integrity sha512-rAbVNayfKDqoUUCrPLiLaU5U10JRXpcUaQqeCebqlwZ/OFS8LTgfhuVChU5ud7NTlskqs5KJUiiq5+vdXgck1Q== +openstack-uicore-foundation@5.0.9: + version "5.0.9" + resolved "https://registry.yarnpkg.com/openstack-uicore-foundation/-/openstack-uicore-foundation-5.0.9.tgz#07adad71dae95383e3e707cb63f1b30837f48608" + integrity sha512-Gk6QkQaY76a/u5Pzx1cPetX/NJ73AAda5n0YEVRX78sb4y1GknAKZNY8IdlF6QERR6yKAs4GNuuEzAEs/DcZfw== optionator@^0.9.1: version "0.9.4" @@ -9128,6 +9138,13 @@ pkijs@^3.3.3: pvutils "^1.1.3" tslib "^2.8.1" +png-js@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/png-js/-/png-js-2.0.0.tgz#7bc521aea1d47f5e3bf42eeecdd77095cba98d5f" + integrity sha512-GdzJuUMc6ZSpxFJWVxtOH1bzYHym+TOnveqUjb+VJIbZWbZzyiRGFiKhbiielfpYbgMlhHVhsJ0FTazfuRFkMA== + dependencies: + fflate "^0.8.2" + possible-typed-array-names@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" @@ -9389,9 +9406,9 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== postcss@^8.4.17, postcss@^8.4.33: - version "8.5.9" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.9.tgz#f6ee9e0b94f0f19c97d2f172bfbd7fc71fe1cca4" - integrity sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw== + version "8.5.10" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.10.tgz#8992d8c30acf3f12169e7c09514a12fed7e48356" + integrity sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ== dependencies: nanoid "^3.3.11" picocolors "^1.1.1" @@ -9552,7 +9569,7 @@ pvtsutils@^1.3.6: dependencies: tslib "^2.8.1" -pvutils@^1.1.3: +pvutils@^1.1.3, pvutils@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.5.tgz#84b0dea4a5d670249aa9800511804ee0b7c2809c" integrity sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA== @@ -10285,13 +10302,13 @@ rust-result@^1.0.0: individual "^2.0.0" safe-array-concat@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" - integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q== + version "1.1.4" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.4.tgz#a54cc9b61a57f33b42abad3cbdda3a2b38cc5719" + integrity sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg== dependencies: - call-bind "^1.0.8" - call-bound "^1.0.2" - get-intrinsic "^1.2.6" + call-bind "^1.0.9" + call-bound "^1.0.4" + get-intrinsic "^1.3.0" has-symbols "^1.1.0" isarray "^2.0.5" @@ -11705,9 +11722,9 @@ webpack-virtual-modules@^0.5.0: integrity sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw== webpack@^5.70.0: - version "5.106.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.106.1.tgz#0a3eeb43a50e4f67fbecd206e1e6fc2c89fc2b6f" - integrity sha512-EW8af29ak8Oaf4T8k8YsajjrDBDYgnKZ5er6ljWFJsXABfTNowQfvHLftwcepVgdz+IoLSdEAbBiM9DFXoll9w== + version "5.106.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.106.2.tgz#ca8174b4fd80f055cc5a45fcc5577d6db76c8ac5" + integrity sha512-wGN3qcrBQIFmQ/c0AiOAQBvrZ5lmY8vbbMv4Mxfgzqd/B6+9pXtLo73WuS1dSGXM5QYY3hZnIbvx+K1xxe6FyA== dependencies: "@types/eslint-scope" "^3.7.7" "@types/estree" "^1.0.8" @@ -11725,9 +11742,8 @@ webpack@^5.70.0: events "^3.2.0" glob-to-regexp "^0.4.1" graceful-fs "^4.2.11" - json-parse-even-better-errors "^2.3.1" loader-runner "^4.3.1" - mime-types "^2.1.27" + mime-db "^1.54.0" neo-async "^2.6.2" schema-utils "^4.3.3" tapable "^2.3.0" From 470bc19eb43e75854029705db2743730333e0ec6 Mon Sep 17 00:00:00 2001 From: Priscila Moneo Date: Wed, 8 Apr 2026 23:55:24 -0300 Subject: [PATCH 2/3] fix: replace mui-table, mui-table-editable and mui-table-sortable with uicore --- .../add-form-template-item-popup.js | 2 +- .../form-template-from-duplicate-popup.js | 2 +- .../form-template-item-list-page.js | 2 +- .../form-templates/form-template-list-page.js | 2 +- .../inventory/inventory-list-page.js | 2 +- .../page-templates/page-template-list-page.js | 2 +- .../__tests__/show-pages-list-page.test.js | 64 ++++++++++++------- .../sponsors/show-pages-list-page/index.js | 2 +- ...nsor-form-add-item-from-inventory-popup.js | 2 +- .../sponsor-form-item-list-page/index.js | 2 +- .../sponsors/sponsor-forms-list-page/index.js | 13 ++-- src/pages/sponsors/sponsor-list-page.js | 2 +- .../tabs/sponsor-badge-scans/index.js | 2 +- .../sponsor-cart-tab/components/cart-view.js | 3 +- .../add-sponsor-form-template-popup/index.js | 2 +- .../sponsor-form-item-from-inventory.js | 3 +- .../sponsor-forms-manage-items.js | 2 +- .../tabs/sponsor-forms-tab/index.js | 2 +- .../sponsor-general-form/extra-questions.js | 2 +- .../tabs/sponsor-general-form/sponsorship.js | 2 +- .../tabs/sponsor-media-upload-tab/index.js | 2 +- .../add-sponsor-page-template-popup/index.js | 2 +- .../tabs/sponsor-pages-tab/index.js | 2 +- .../tabs/sponsor-purchases-tab/index.js | 2 +- .../components/__tests__/users-table.test.js | 2 +- .../components/request-table.js | 2 +- .../components/users-table.js | 2 +- .../sponsors/summit-sponsorship-list-page.js | 2 +- 28 files changed, 74 insertions(+), 57 deletions(-) diff --git a/src/pages/sponsors-global/form-templates/add-form-template-item-popup.js b/src/pages/sponsors-global/form-templates/add-form-template-item-popup.js index aac1d2c05..9bb4df590 100644 --- a/src/pages/sponsors-global/form-templates/add-form-template-item-popup.js +++ b/src/pages/sponsors-global/form-templates/add-form-template-item-popup.js @@ -21,7 +21,7 @@ import SwapVertIcon from "@mui/icons-material/SwapVert"; import SearchIcon from "@mui/icons-material/Search"; import CloseIcon from "@mui/icons-material/Close"; import ImageIcon from "@mui/icons-material/Image"; -import MuiTable from "../../../components/mui/table/mui-table"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import MenuButton from "../../../components/mui/menu-button"; import { clearAllSelectedInventoryItems, diff --git a/src/pages/sponsors-global/form-templates/form-template-from-duplicate-popup.js b/src/pages/sponsors-global/form-templates/form-template-from-duplicate-popup.js index 67dcf3f10..a0382ddfb 100644 --- a/src/pages/sponsors-global/form-templates/form-template-from-duplicate-popup.js +++ b/src/pages/sponsors-global/form-templates/form-template-from-duplicate-popup.js @@ -19,7 +19,7 @@ import { import SwapVertIcon from "@mui/icons-material/SwapVert"; import SearchIcon from "@mui/icons-material/Search"; import CloseIcon from "@mui/icons-material/Close"; -import MuiTable from "../../../components/mui/table/mui-table"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import MenuButton from "../../../components/mui/menu-button"; const FormTemplateFromDuplicateDialog = ({ diff --git a/src/pages/sponsors-global/form-templates/form-template-item-list-page.js b/src/pages/sponsors-global/form-templates/form-template-item-list-page.js index ee3287591..b4a070ead 100644 --- a/src/pages/sponsors-global/form-templates/form-template-item-list-page.js +++ b/src/pages/sponsors-global/form-templates/form-template-item-list-page.js @@ -27,7 +27,7 @@ import AddIcon from "@mui/icons-material/Add"; import IconButton from "@mui/material/IconButton"; import Tooltip from "@mui/material/Tooltip"; import ImageIcon from "@mui/icons-material/Image"; -import MuiTable from "../../../components/mui/table/mui-table"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import { cloneFromInventoryItem, deleteFormTemplateItem, diff --git a/src/pages/sponsors-global/form-templates/form-template-list-page.js b/src/pages/sponsors-global/form-templates/form-template-list-page.js index 515561cdc..46be7fb5a 100644 --- a/src/pages/sponsors-global/form-templates/form-template-list-page.js +++ b/src/pages/sponsors-global/form-templates/form-template-list-page.js @@ -26,6 +26,7 @@ import AddIcon from "@mui/icons-material/Add"; import SearchIcon from "@mui/icons-material/Search"; import { connect } from "react-redux"; import T from "i18n-react/dist/i18n-react"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import { archiveFormTemplate, deleteFormTemplate, @@ -38,7 +39,6 @@ import { saveFormTemplate, unarchiveFormTemplate } from "../../../actions/form-template-actions"; -import MuiTable from "../../../components/mui/table/mui-table"; import FormTemplateDialog from "./form-template-popup"; import history from "../../../history"; import FormTemplateFromDuplicateDialog from "./form-template-from-duplicate-popup"; diff --git a/src/pages/sponsors-global/inventory/inventory-list-page.js b/src/pages/sponsors-global/inventory/inventory-list-page.js index efb1068cc..5a0089870 100644 --- a/src/pages/sponsors-global/inventory/inventory-list-page.js +++ b/src/pages/sponsors-global/inventory/inventory-list-page.js @@ -30,6 +30,7 @@ import IconButton from "@mui/material/IconButton"; import ImageIcon from "@mui/icons-material/Image"; import { connect } from "react-redux"; import T from "i18n-react/dist/i18n-react"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import { archiveInventoryItem, deleteInventoryItem, @@ -42,7 +43,6 @@ import { saveInventoryItem, unarchiveInventoryItem } from "../../../actions/inventory-item-actions"; -import MuiTable from "../../../components/mui/table/mui-table"; import SponsorInventoryDialog from "../form-templates/sponsor-inventory-popup"; import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants"; diff --git a/src/pages/sponsors-global/page-templates/page-template-list-page.js b/src/pages/sponsors-global/page-templates/page-template-list-page.js index c21f73b49..690475078 100644 --- a/src/pages/sponsors-global/page-templates/page-template-list-page.js +++ b/src/pages/sponsors-global/page-templates/page-template-list-page.js @@ -24,6 +24,7 @@ import Box from "@mui/material/Box"; import AddIcon from "@mui/icons-material/Add"; import { connect } from "react-redux"; import T from "i18n-react/dist/i18n-react"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import { archivePageTemplate, deletePageTemplate, @@ -33,7 +34,6 @@ import { unarchivePageTemplate, resetPageTemplateForm } from "../../../actions/page-template-actions"; -import MuiTable from "../../../components/mui/table/mui-table"; import SearchInput from "../../../components/mui/search-input"; import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants"; import PageTemplatePopup from "./page-template-popup"; diff --git a/src/pages/sponsors/show-pages-list-page/__tests__/show-pages-list-page.test.js b/src/pages/sponsors/show-pages-list-page/__tests__/show-pages-list-page.test.js index e7ffeea14..b93111757 100644 --- a/src/pages/sponsors/show-pages-list-page/__tests__/show-pages-list-page.test.js +++ b/src/pages/sponsors/show-pages-list-page/__tests__/show-pages-list-page.test.js @@ -1,6 +1,7 @@ import React from "react"; import userEvent from "@testing-library/user-event"; import { act, screen, waitFor } from "@testing-library/react"; +import { GlobalConfirmDialog } from "openstack-uicore-foundation/lib/components/mui/show-confirm-dialog"; import ShowPagesListPage from "../index"; import { renderWithRedux } from "../../../../utils/test-utils"; import { DEFAULT_STATE as showPagesListDefaultState } from "../../../../reducers/sponsors/show-pages-list-reducer"; @@ -13,6 +14,7 @@ import { unarchiveShowPage } from "../../../../actions/show-pages-actions"; import { getSponsorships } from "../../../../actions/sponsor-forms-actions"; + import { DEFAULT_CURRENT_PAGE, MAX_PER_PAGE @@ -32,8 +34,6 @@ jest.mock( } ); -jest.mock("../../../../components/mui/showConfirmDialog", () => jest.fn()); - jest.mock( "../../../sponsors-global/page-templates/page-template-popup", () => @@ -75,6 +75,14 @@ const createShowPage = (id, overrides = {}) => ({ ...overrides }); +const renderWithConfirmDialog = (ui, options) => renderWithRedux( + <> + + {ui} + , + options + ); + describe("ShowPagesListPage", () => { beforeEach(() => { jest.clearAllMocks(); @@ -82,7 +90,7 @@ describe("ShowPagesListPage", () => { describe("Component", () => { it("should render empty state when no pages exist", () => { - renderWithRedux(, { + renderWithConfirmDialog(, { initialState: { showPagesListState: { ...showPagesListDefaultState, @@ -98,7 +106,7 @@ describe("ShowPagesListPage", () => { }); it("should render table when pages exist", () => { - renderWithRedux(, { + renderWithConfirmDialog(, { initialState: { showPagesListState: { ...showPagesListDefaultState, @@ -113,7 +121,7 @@ describe("ShowPagesListPage", () => { }); it("should call getShowPage and open popup when edit is clicked", async () => { - renderWithRedux(, { + renderWithConfirmDialog(, { initialState: { showPagesListState: { ...showPagesListDefaultState, @@ -137,7 +145,7 @@ describe("ShowPagesListPage", () => { }); it("should refresh list after save", async () => { - renderWithRedux(, { + renderWithConfirmDialog(, { initialState: { showPagesListState: { ...showPagesListDefaultState, @@ -170,9 +178,7 @@ describe("ShowPagesListPage", () => { }); it("should call deleteShowPage and refresh list when delete is confirmed", async () => { - const showConfirmDialog = require("../../../../components/mui/showConfirmDialog"); - showConfirmDialog.mockResolvedValue(true); - renderWithRedux(, { + renderWithConfirmDialog(, { initialState: { showPagesListState: { ...showPagesListDefaultState, @@ -190,23 +196,26 @@ describe("ShowPagesListPage", () => { await act(async () => { await userEvent.click(secondDeleteButton); }); - expect(showConfirmDialog).toHaveBeenCalledWith( - expect.objectContaining({ - title: "general.are_you_sure", - type: "warning", - showCancelButton: true - }) - ); - expect(deleteShowPage).toHaveBeenCalledWith(2); // check id 2 + expect( + await screen.findByText("general.are_you_sure") + ).toBeInTheDocument(); + await act(async () => { + await userEvent.click( + await screen.findByRole("button", { + name: /general\.yes_delete|confirm/i + }) + ); + }); + await waitFor(() => { + expect(deleteShowPage).toHaveBeenCalledWith(2); // check id 2 + }); await waitFor(() => { expect(getShowPages).toHaveBeenCalledTimes(2); }); }); it("should not call deleteShowPage when delete is cancelled", async () => { - const showConfirmDialog = require("../../../../components/mui/showConfirmDialog"); - showConfirmDialog.mockResolvedValue(false); - renderWithRedux(, { + renderWithConfirmDialog(, { initialState: { showPagesListState: { ...showPagesListDefaultState, @@ -219,13 +228,22 @@ describe("ShowPagesListPage", () => { await act(async () => { await userEvent.click(deleteButton); }); - expect(showConfirmDialog).toHaveBeenCalled(); + expect( + await screen.findByText("general.are_you_sure") + ).toBeInTheDocument(); + await act(async () => { + await userEvent.click( + await screen.findByRole("button", { + name: /cancel|general\.cancel/i + }) + ); + }); expect(deleteShowPage).not.toHaveBeenCalled(); expect(getShowPages).toHaveBeenCalledTimes(1); }); it("should call archiveShowPage for non-archived item", async () => { - renderWithRedux(, { + renderWithConfirmDialog(, { initialState: { showPagesListState: { ...showPagesListDefaultState, @@ -242,7 +260,7 @@ describe("ShowPagesListPage", () => { }); it("should call unarchiveShowPage for archived item", async () => { - renderWithRedux(, { + renderWithConfirmDialog(, { initialState: { showPagesListState: { ...showPagesListDefaultState, diff --git a/src/pages/sponsors/show-pages-list-page/index.js b/src/pages/sponsors/show-pages-list-page/index.js index 334f1675c..2613906e4 100644 --- a/src/pages/sponsors/show-pages-list-page/index.js +++ b/src/pages/sponsors/show-pages-list-page/index.js @@ -23,6 +23,7 @@ import { Grid2 } from "@mui/material"; import AddIcon from "@mui/icons-material/Add"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import { getShowPages, archiveShowPage, @@ -34,7 +35,6 @@ import { } from "../../../actions/show-pages-actions"; import { getSponsorships } from "../../../actions/sponsor-forms-actions"; import CustomAlert from "../../../components/mui/custom-alert"; -import MuiTable from "../../../components/mui/table/mui-table"; import GlobalPagePopup from "./components/global-page/global-page-popup"; import PageTemplatePopup from "../../sponsors-global/page-templates/page-template-popup"; import { DEFAULT_CURRENT_PAGE, MAX_PER_PAGE } from "../../../utils/constants"; diff --git a/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-add-item-from-inventory-popup.js b/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-add-item-from-inventory-popup.js index e06be44a7..cac8927fa 100644 --- a/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-add-item-from-inventory-popup.js +++ b/src/pages/sponsors/sponsor-form-item-list-page/components/sponsor-form-add-item-from-inventory-popup.js @@ -19,9 +19,9 @@ import CloseIcon from "@mui/icons-material/Close"; import Tooltip from "@mui/material/Tooltip"; import ImageIcon from "@mui/icons-material/Image"; import Box from "@mui/material/Box"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import { formatRateFromCents } from "../../../../utils/rate-helpers"; import SearchInput from "../../../../components/mui/search-input"; -import MuiTable from "../../../../components/mui/table/mui-table"; import { addInventoryItems } from "../../../../actions/sponsor-forms-actions"; import { getInventoryItems } from "../../../../actions/inventory-item-actions"; import { DEFAULT_CURRENT_PAGE } from "../../../../utils/constants"; diff --git a/src/pages/sponsors/sponsor-form-item-list-page/index.js b/src/pages/sponsors/sponsor-form-item-list-page/index.js index 321f88c5f..e0849ecb3 100644 --- a/src/pages/sponsors/sponsor-form-item-list-page/index.js +++ b/src/pages/sponsors/sponsor-form-item-list-page/index.js @@ -28,6 +28,7 @@ import AddIcon from "@mui/icons-material/Add"; import IconButton from "@mui/material/IconButton"; import Tooltip from "@mui/material/Tooltip"; import ImageIcon from "@mui/icons-material/Image"; +import MuiTableEditable from "openstack-uicore-foundation/lib/components/mui/editable-table"; import { deleteSponsorFormItem, getSponsorFormItem, @@ -38,7 +39,6 @@ import { } from "../../../actions/sponsor-forms-actions"; import SponsorFormItemPopup from "./components/sponsor-form-item-popup"; import SponsorFormAddItemFromInventoryPopup from "./components/sponsor-form-add-item-from-inventory-popup"; -import MuiTableEditable from "../../../components/mui/editable-table/mui-table-editable"; import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants"; import { rateCellValidation } from "../../../utils/yup"; import { rateToCents } from "../../../utils/rate-helpers"; diff --git a/src/pages/sponsors/sponsor-forms-list-page/index.js b/src/pages/sponsors/sponsor-forms-list-page/index.js index 5e867b0aa..9670af935 100644 --- a/src/pages/sponsors/sponsor-forms-list-page/index.js +++ b/src/pages/sponsors/sponsor-forms-list-page/index.js @@ -25,6 +25,7 @@ import { } from "@mui/material"; import AddIcon from "@mui/icons-material/Add"; import MuiDropdownCheckbox from "openstack-uicore-foundation/lib/components/mui/dropdown-checkbox"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import history from "../../../history"; import { archiveSponsorForm, @@ -39,7 +40,6 @@ import CustomAlert from "../../../components/mui/custom-alert"; import SearchInput from "../../../components/mui/search-input"; import GlobalTemplatePopup from "./components/global-template/global-template-popup"; import FormTemplatePopup from "./components/form-template/form-template-popup"; -import MuiTable from "../../../components/mui/table/mui-table"; import { DEFAULT_CURRENT_PAGE, MAX_PER_PAGE } from "../../../utils/constants"; import { normalizeTiers, sameTierSet } from "./utils"; @@ -196,10 +196,12 @@ const SponsorFormsListPage = ({ }) .catch(() => {}); }; - + const formatDate = (timestamp) => { if (!timestamp) return ""; - return epochToMoment(Number(timestamp)).format("MM/DD/YYYY"); + const num = Number(timestamp); + if (Number.isNaN(num)) return ""; + return epochToMoment(num).format("MM/DD/YYYY"); }; const columns = [ @@ -307,10 +309,9 @@ const SponsorFormsListPage = ({ }, { columnKey: "items_qty", - width: 100, + width: 90, header: T.translate("sponsor_forms.items_column_label"), - sortable: false, - width: 90 + sortable: false }, { columnKey: "manage_items", diff --git a/src/pages/sponsors/sponsor-list-page.js b/src/pages/sponsors/sponsor-list-page.js index 413641265..10bc028b7 100644 --- a/src/pages/sponsors/sponsor-list-page.js +++ b/src/pages/sponsors/sponsor-list-page.js @@ -26,6 +26,7 @@ import Box from "@mui/material/Box"; import AddIcon from "@mui/icons-material/Add"; import SearchIcon from "@mui/icons-material/Search"; import _ from "lodash"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import { getLeadReportSettingsMeta, getSummitById, @@ -38,7 +39,6 @@ import { updateSponsorOrder } from "../../actions/sponsor-actions"; import Member from "../../models/member"; -import MuiTable from "../../components/mui/table/mui-table"; import { DEBOUNCE_WAIT, DEFAULT_CURRENT_PAGE } from "../../utils/constants"; import AddSponsorDialog from "./popup/add-sponsor-popup"; diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-badge-scans/index.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-badge-scans/index.js index e998d27f1..e6221391d 100644 --- a/src/pages/sponsors/sponsor-page/tabs/sponsor-badge-scans/index.js +++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-badge-scans/index.js @@ -18,7 +18,7 @@ import { Box, Button, Grid2, TextField } from "@mui/material"; import SearchIcon from "@mui/icons-material/Search"; import AddIcon from "@mui/icons-material/Add"; import DownloadIcon from "@mui/icons-material/Download"; -import MuiTable from "../../../../../components/mui/table/mui-table"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import { getBadgeScans, exportBadgeScans, diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-cart-tab/components/cart-view.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-cart-tab/components/cart-view.js index 375ff1a5b..d7b1a8680 100644 --- a/src/pages/sponsors/sponsor-page/tabs/sponsor-cart-tab/components/cart-view.js +++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-cart-tab/components/cart-view.js @@ -25,8 +25,7 @@ import { import AddIcon from "@mui/icons-material/Add"; import LockOpenIcon from "@mui/icons-material/LockOpen"; import LockClosedIcon from "@mui/icons-material/Lock"; -import MuiTable from "../../../../../../components/mui/table/mui-table"; -import { TotalRow } from "../../../../../../components/mui/table/extra-rows"; +import MuiTable, { TotalRow } from "openstack-uicore-foundation/lib/components/mui/table"; import SearchInput from "../../../../../../components/mui/search-input"; import { deleteSponsorCartForm, diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/add-sponsor-form-template-popup/index.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/add-sponsor-form-template-popup/index.js index 6c28f6c9f..eaee4ad44 100644 --- a/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/add-sponsor-form-template-popup/index.js +++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/add-sponsor-form-template-popup/index.js @@ -21,7 +21,7 @@ import SwapVertIcon from "@mui/icons-material/SwapVert"; import SearchIcon from "@mui/icons-material/Search"; import CloseIcon from "@mui/icons-material/Close"; import { FormikProvider, useFormik } from "formik"; -import MuiTable from "../../../../../../../components/mui/table/mui-table"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import MenuButton from "../../../../../../../components/mui/menu-button"; import { querySponsorAddons } from "../../../../../../../actions/sponsor-actions"; import { getSponsorForms } from "../../../../../../../actions/sponsor-forms-actions"; diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/manage-items/sponsor-form-item-from-inventory.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/manage-items/sponsor-form-item-from-inventory.js index dd6795e2b..84bacf762 100644 --- a/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/manage-items/sponsor-form-item-from-inventory.js +++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/manage-items/sponsor-form-item-from-inventory.js @@ -20,15 +20,14 @@ import { import CloseIcon from "@mui/icons-material/Close"; import ImageIcon from "@mui/icons-material/Image"; import SwapVertIcon from "@mui/icons-material/SwapVert"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import { formatRateFromCents } from "../../../../../../../utils/rate-helpers"; import SearchInput from "../../../../../../../components/mui/search-input"; import { DEFAULT_CURRENT_PAGE, DEFAULT_PER_PAGE } from "../../../../../../../utils/constants"; - import { getInventoryItems } from "../../../../../../../actions/inventory-item-actions"; -import MuiTable from "../../../../../../../components/mui/table/mui-table"; import MenuButton from "../../../../../../../components/mui/menu-button"; const SponsorFormItemFromInventoryPopup = ({ diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/manage-items/sponsor-forms-manage-items.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/manage-items/sponsor-forms-manage-items.js index 4b57b69d6..8c7866cfa 100644 --- a/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/manage-items/sponsor-forms-manage-items.js +++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/components/manage-items/sponsor-forms-manage-items.js @@ -26,6 +26,7 @@ import { } from "@mui/material"; import AddIcon from "@mui/icons-material/Add"; import ImageIcon from "@mui/icons-material/Image"; +import MuiTableEditable from "openstack-uicore-foundation/lib/components/mui/editable-table"; import { addSponsorManagedFormItems, archiveSponsorCustomizedFormItem, @@ -38,7 +39,6 @@ import { } from "../../../../../../../actions/sponsor-forms-actions"; import CustomAlert from "../../../../../../../components/mui/custom-alert"; import SearchInput from "../../../../../../../components/mui/search-input"; -import MuiTableEditable from "../../../../../../../components/mui/editable-table/mui-table-editable"; import SponsorInventoryDialog from "../../../../../../sponsors-global/form-templates/sponsor-inventory-popup"; import SponsorFormItemFromInventoryPopup from "./sponsor-form-item-from-inventory"; import { diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/index.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/index.js index 6395d3b21..35471fbc2 100644 --- a/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/index.js +++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-forms-tab/index.js @@ -24,6 +24,7 @@ import { } from "@mui/material"; import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; import AddIcon from "@mui/icons-material/Add"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import { archiveSponsorCustomizedForm, deleteSponsorCustomizedForm, @@ -34,7 +35,6 @@ import { } from "../../../../../actions/sponsor-forms-actions"; import CustomAlert from "../../../../../components/mui/custom-alert"; import SearchInput from "../../../../../components/mui/search-input"; -import MuiTable from "../../../../../components/mui/table/mui-table"; import AddSponsorFormTemplatePopup from "./components/add-sponsor-form-template-popup"; import CustomizedFormPopup from "./components/customized-form/customized-form-popup"; import { DEFAULT_CURRENT_PAGE } from "../../../../../utils/constants"; diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-general-form/extra-questions.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-general-form/extra-questions.js index b788e9a88..6fa3703f6 100644 --- a/src/pages/sponsors/sponsor-page/tabs/sponsor-general-form/extra-questions.js +++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-general-form/extra-questions.js @@ -15,7 +15,7 @@ import React, { useState, useEffect } from "react"; import T from "i18n-react/dist/i18n-react"; import { Box, Button, Divider, Grid2, Typography } from "@mui/material"; import AddIcon from "@mui/icons-material/Add"; -import MuiTableSortable from "../../../../../components/mui/sortable-table/mui-table-sortable"; +import MuiTableSortable from "openstack-uicore-foundation/lib/components/mui/sortable-table"; import { DEFAULT_CURRENT_PAGE, MAX_PER_PAGE diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-general-form/sponsorship.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-general-form/sponsorship.js index de2981ca3..c8eca25f8 100644 --- a/src/pages/sponsors/sponsor-page/tabs/sponsor-general-form/sponsorship.js +++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-general-form/sponsorship.js @@ -15,7 +15,7 @@ import React, { useState } from "react"; import T from "i18n-react/dist/i18n-react"; import { Box, Button, Grid2, Typography } from "@mui/material"; import AddIcon from "@mui/icons-material/Add"; -import MuiTable from "../../../../../components/mui/table/mui-table"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import AddTierPopup from "./add-tier-popup"; import ManageTierAddonsPopup from "./manage-tier-addons-popup"; import { DEFAULT_CURRENT_PAGE } from "../../../../../utils/constants"; diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-media-upload-tab/index.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-media-upload-tab/index.js index bc1e590df..66f822837 100644 --- a/src/pages/sponsors/sponsor-page/tabs/sponsor-media-upload-tab/index.js +++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-media-upload-tab/index.js @@ -19,6 +19,7 @@ import ArrowUpwardIcon from "@mui/icons-material/ArrowUpward"; import DownloadIcon from "@mui/icons-material/Download"; import DeleteIcon from "@mui/icons-material/Delete"; import VisibilityIcon from "@mui/icons-material/Visibility"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import { getGeneralMURequests, getSponsorMURequests, @@ -26,7 +27,6 @@ import { uploadFileForSponsorMU } from "../../../../../actions/sponsor-mu-actions"; import CustomAlert from "../../../../../components/mui/custom-alert"; -import MuiTable from "../../../../../components/mui/table/mui-table"; import { SPONSOR_MEDIA_UPLOAD_STATUS } from "../../../../../utils/constants"; import UploadDialog from "../../../../../components/upload-dialog"; import showConfirmDialog from "../../../../../components/mui/showConfirmDialog"; diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/components/add-sponsor-page-template-popup/index.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/components/add-sponsor-page-template-popup/index.js index 60a4d6da3..3333f7cb6 100644 --- a/src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/components/add-sponsor-page-template-popup/index.js +++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/components/add-sponsor-page-template-popup/index.js @@ -35,7 +35,7 @@ import SearchIcon from "@mui/icons-material/Search"; import CloseIcon from "@mui/icons-material/Close"; import * as yup from "yup"; import { FormikProvider, useFormik } from "formik"; -import MuiTable from "../../../../../../../components/mui/table/mui-table"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import MenuButton from "../../../../../../../components/mui/menu-button"; import { querySponsorAddons } from "../../../../../../../actions/sponsor-actions"; import { getShowPages } from "../../../../../../../actions/show-pages-actions"; diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/index.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/index.js index b31032fd8..0b6473cb0 100644 --- a/src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/index.js +++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-pages-tab/index.js @@ -24,6 +24,7 @@ import { } from "@mui/material"; import AddIcon from "@mui/icons-material/Add"; import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import { getSponsorManagedPages, getSponsorManagedPage, @@ -38,7 +39,6 @@ import { } from "../../../../../actions/sponsor-pages-actions"; import CustomAlert from "../../../../../components/mui/custom-alert"; import SearchInput from "../../../../../components/mui/search-input"; -import MuiTable from "../../../../../components/mui/table/mui-table"; import { DEFAULT_CURRENT_PAGE, SPONSOR_MANAGED_PAGE_ASSIGNMENT diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-purchases-tab/index.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-purchases-tab/index.js index ed66787a7..52abc4d4a 100644 --- a/src/pages/sponsors/sponsor-page/tabs/sponsor-purchases-tab/index.js +++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-purchases-tab/index.js @@ -23,8 +23,8 @@ import { Select } from "@mui/material"; import MenuIcon from "@mui/icons-material/Menu"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import SearchInput from "../../../../../components/mui/search-input"; -import MuiTable from "../../../../../components/mui/table/mui-table"; import { approveSponsorPurchase, getSponsorPurchases, diff --git a/src/pages/sponsors/sponsor-users-list-page/components/__tests__/users-table.test.js b/src/pages/sponsors/sponsor-users-list-page/components/__tests__/users-table.test.js index 916baa488..a98292767 100644 --- a/src/pages/sponsors/sponsor-users-list-page/components/__tests__/users-table.test.js +++ b/src/pages/sponsors/sponsor-users-list-page/components/__tests__/users-table.test.js @@ -3,7 +3,7 @@ import { render, screen } from "@testing-library/react"; import UsersTable from "../users-table"; // Capture the data passed to MuiTable so we can assert on processed userData -jest.mock("../../../../../components/mui/table/mui-table", () => { +jest.mock("openstack-uicore-foundation/lib/components/mui/table", () => { const MockMuiTable = ({ data }) => (
{data.map((row) => ( diff --git a/src/pages/sponsors/sponsor-users-list-page/components/request-table.js b/src/pages/sponsors/sponsor-users-list-page/components/request-table.js index b6d9c5c76..c42a22131 100644 --- a/src/pages/sponsors/sponsor-users-list-page/components/request-table.js +++ b/src/pages/sponsors/sponsor-users-list-page/components/request-table.js @@ -2,7 +2,7 @@ import React, { useState } from "react"; import T from "i18n-react"; import { IconButton } from "@mui/material"; import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; -import MuiTable from "../../../../components/mui/table/mui-table"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import ProcessRequestPopup from "./process-request-popup"; import { DEFAULT_CURRENT_PAGE } from "../../../../utils/constants"; diff --git a/src/pages/sponsors/sponsor-users-list-page/components/users-table.js b/src/pages/sponsors/sponsor-users-list-page/components/users-table.js index e0163d65d..fc85ead9f 100644 --- a/src/pages/sponsors/sponsor-users-list-page/components/users-table.js +++ b/src/pages/sponsors/sponsor-users-list-page/components/users-table.js @@ -2,7 +2,7 @@ import React from "react"; import T from "i18n-react"; import { IconButton } from "@mui/material"; import MailOutlineIcon from "@mui/icons-material/MailOutline"; -import MuiTable from "../../../../components/mui/table/mui-table"; +import MuiTable from "openstack-uicore-foundation/lib/components/mui/table"; import ChipList from "../../../../components/mui/chip-list"; import { titleCase } from "../../../../utils/methods"; diff --git a/src/pages/sponsors/summit-sponsorship-list-page.js b/src/pages/sponsors/summit-sponsorship-list-page.js index fcd0c363a..684870fa7 100644 --- a/src/pages/sponsors/summit-sponsorship-list-page.js +++ b/src/pages/sponsors/summit-sponsorship-list-page.js @@ -16,6 +16,7 @@ import { connect } from "react-redux"; import T from "i18n-react/dist/i18n-react"; import { Alert, Box, Button, Grid2 } from "@mui/material"; import AddIcon from "@mui/icons-material/Add"; +import MuiTableSortable from "openstack-uicore-foundation/lib/components/mui/sortable-table"; import { getSummitById } from "../../actions/summit-actions"; import { deleteSummitSponsorship, @@ -27,7 +28,6 @@ import { updateSummitSponsorhipOrder, uploadSponsorshipBadgeImage } from "../../actions/sponsor-actions"; -import MuiTableSortable from "../../components/mui/sortable-table/mui-table-sortable"; import EditTierPopup from "./popup/edit-tier-popup"; import { DEFAULT_CURRENT_PAGE } from "../../utils/constants"; From 396320b175b375933a3204ab9c83489d5124ff09 Mon Sep 17 00:00:00 2001 From: Priscila Moneo Date: Tue, 21 Apr 2026 15:59:20 -0300 Subject: [PATCH 3/3] fix: feedback from PR --- .../components/sponsor-form-item-form.js | 32 +++---------------- 1 file changed, 4 insertions(+), 28 deletions(-) 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 6a13d8fa3..809b18ae9 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 @@ -13,7 +13,7 @@ import { import T from "i18n-react"; import * as yup from "yup"; import { FormikProvider, useFormik } from "formik"; -import { UploadInputV3 } from "openstack-uicore-foundation/lib/components"; +import { MuiFormikUpload } from "openstack-uicore-foundation/lib/components"; import { addIssAfterDateFieldValidator, nullableDecimalValidation, @@ -28,11 +28,7 @@ import useScrollToError from "../../../../hooks/useScrollToError"; import ItemPriceTiers from "../../../../components/mui/formik-inputs/item-price-tiers"; import FormikTextEditor from "../../../../components/inputs/formik-text-editor"; import MuiFormikQuantityField from "../../../../components/mui/formik-inputs/mui-formik-quantity-field"; -import { - ALLOWED_INVENTORY_IMAGE_FORMATS, - MAX_INVENTORY_IMAGE_UPLOAD_SIZE, - MAX_INVENTORY_IMAGES_UPLOAD_QTY -} from "../../../../utils/constants"; +import { MAX_INVENTORY_IMAGES_UPLOAD_QTY } from "../../../../utils/constants"; const buildInitialValues = (data) => ({ ...data }); @@ -148,29 +144,9 @@ const SponsorFormItemForm = ({ initialValues, onSubmit }) => { {T.translate("sponsor_form_item_list.edit_item.images")} - { - const newImages = (formik.values.images || []).filter( - (img) => img.filename !== file.name - ); - formik.setFieldValue("images", newImages); - }} - postUrl={`${window.FILE_UPLOAD_API_BASE_URL}/api/v1/files/upload`} - mediaType={{ - type: { allowed_extensions: ALLOWED_INVENTORY_IMAGE_FORMATS }, - max_size: MAX_INVENTORY_IMAGE_UPLOAD_SIZE - }} - onUploadComplete={(response) => { - if (response && response.file) { - const newImages = [ - ...(formik.values.images || []), - response.file - ]; - formik.setFieldValue("images", newImages); - } - }} + name="images" maxFiles={MAX_INVENTORY_IMAGES_UPLOAD_QTY} />