fix: added save button to table component to improve consistency (#6663)

* Added onSave and onCancel to tableModal, in order for it to preserve state

* Changed TableNodeComponent to handle temp values and only change value when saved

* 🔧 (tableModal/index.tsx): refactor handleSetOpen and handleOnEscapeKeyDown functions to improve code readability and maintainability

* Fix test that use tableInput

---------

Co-authored-by: cristhianzl <cristhian.lousa@gmail.com>
This commit is contained in:
Lucas Oliveira 2025-02-18 17:50:27 -03:00 committed by GitHub
commit 70bb897a85
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 62 additions and 14 deletions

View file

@ -65,10 +65,12 @@ export default function TableNodeComponent({
};
}, []);
const [selectedNodes, setSelectedNodes] = useState<Array<any>>([]);
const [tempValue, setTempValue] = useState<any[]>(cloneDeep(value));
const [isModalOpen, setIsModalOpen] = useState(false);
const agGrid = useRef<AgGridReact>(null);
const componentColumns = columns
? columns
: generateBackendColumnsFromValue(value ?? [], table_options);
: generateBackendColumnsFromValue(tempValue ?? [], table_options);
let AgColumns = FormatColumns(componentColumns);
// add info to each column
AgColumns = AgColumns.map((col) => {
@ -93,7 +95,7 @@ export default function TableNodeComponent({
if (agGrid.current && !agGrid.current.api.isDestroyed()) {
const rows: any = [];
agGrid.current.api.forEachNode((node) => rows.push(node.data));
handleOnNewValue({ value: rows });
setTempValue(rows);
}
}
function deleteRow() {
@ -109,8 +111,7 @@ export default function TableNodeComponent({
if (agGrid.current && selectedNodes.length > 0) {
const toDuplicate = selectedNodes.map((node) => cloneDeep(node.data));
setSelectedNodes([]);
const rows: any = [];
handleOnNewValue({ value: [...value, ...toDuplicate] });
setTempValue([...tempValue, ...toDuplicate]);
}
}
function addRow() {
@ -118,12 +119,23 @@ export default function TableNodeComponent({
componentColumns.forEach((column) => {
newRow[column.name] = column.default ?? null; // Use the default value if available
});
handleOnNewValue({ value: [...value, newRow] });
setTempValue([...tempValue, newRow]);
}
function updateComponent() {
setAllRows();
}
function handleSave() {
handleOnNewValue({ value: tempValue });
setIsModalOpen(false);
}
function handleCancel() {
setTempValue(cloneDeep(value));
setIsModalOpen(false);
}
const editable = componentColumns
.map((column) => {
const isCustomEdit =
@ -149,6 +161,8 @@ export default function TableNodeComponent({
>
<div className="flex w-full items-center gap-3" data-testid={"div-" + id}>
<TableModal
open={isModalOpen}
setOpen={setIsModalOpen}
stopEditingWhenCellsLoseFocus={true}
tableIcon={table_icon}
tableOptions={table_options}
@ -169,8 +183,10 @@ export default function TableNodeComponent({
displayEmptyAlert={false}
className="h-full w-full"
columnDefs={AgColumns}
rowData={value}
rowData={tempValue}
context={{ field_parsers: table_options?.field_parsers }}
onSave={handleSave}
onCancel={handleCancel}
>
<Button
disabled={disabled}

View file

@ -15,6 +15,10 @@ interface TableModalProps extends TableComponentProps {
tableOptions?: TableOptionsTypeAPI;
hideColumns?: boolean | string[];
tableIcon?: string;
open?: boolean;
setOpen?: (open: boolean) => void;
onSave?: () => void;
onCancel?: () => void;
}
const TableModal = forwardRef<AgGridReact, TableModalProps>(
@ -25,22 +29,43 @@ const TableModal = forwardRef<AgGridReact, TableModalProps>(
children,
disabled,
tableIcon,
open,
setOpen,
onSave,
onCancel,
...props
}: TableModalProps,
ref: ForwardedRef<AgGridReact>,
) => {
const handleSetOpen = (newOpen: boolean) => {
if (!newOpen && onCancel) {
onCancel();
}
if (setOpen) {
setOpen(newOpen);
}
};
const handleOnEscapeKeyDown = (e: KeyboardEvent) => {
const editingCells = (
ref as React.RefObject<AgGridReact>
)?.current?.api?.getEditingCells();
if (editingCells && editingCells.length > 0) {
e.preventDefault();
}
};
return (
<BaseModal
onEscapeKeyDown={(e) => {
if (
(
ref as React.RefObject<AgGridReact>
)?.current?.api.getEditingCells().length
) {
e.preventDefault();
}
handleOnEscapeKeyDown(e);
}}
disable={disabled}
open={open}
setOpen={(newOpen) => {
handleSetOpen(newOpen);
}}
>
<BaseModal.Trigger asChild>{children}</BaseModal.Trigger>
<BaseModal.Header
@ -59,6 +84,9 @@ const TableModal = forwardRef<AgGridReact, TableModalProps>(
{...props}
></TableComponent>
</BaseModal.Content>
<BaseModal.Footer
submit={onSave ? { label: "Save", onClick: onSave } : undefined}
></BaseModal.Footer>
</BaseModal>
);
},

View file

@ -25,6 +25,10 @@ test(
},
);
await page.waitForSelector('[data-testid="zoom_out"]', {
timeout: 3000,
});
await page.getByTestId("sidebar-custom-component-button").click();
await page.getByTestId("zoom_out").click();
@ -164,7 +168,7 @@ class CustomComponent(Component):
numberOfCopiedRows = await page.getByText(thirdRandomText).count();
expect(numberOfCopiedRows).toBe(0);
await page.getByText("Close").last().click();
await page.getByText("Save").last().click();
await page.waitForSelector("text=Open table", {
timeout: 3000,