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:
parent
b8346a0afa
commit
70bb897a85
3 changed files with 62 additions and 14 deletions
|
|
@ -65,10 +65,12 @@ export default function TableNodeComponent({
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
const [selectedNodes, setSelectedNodes] = useState<Array<any>>([]);
|
const [selectedNodes, setSelectedNodes] = useState<Array<any>>([]);
|
||||||
|
const [tempValue, setTempValue] = useState<any[]>(cloneDeep(value));
|
||||||
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
const agGrid = useRef<AgGridReact>(null);
|
const agGrid = useRef<AgGridReact>(null);
|
||||||
const componentColumns = columns
|
const componentColumns = columns
|
||||||
? columns
|
? columns
|
||||||
: generateBackendColumnsFromValue(value ?? [], table_options);
|
: generateBackendColumnsFromValue(tempValue ?? [], table_options);
|
||||||
let AgColumns = FormatColumns(componentColumns);
|
let AgColumns = FormatColumns(componentColumns);
|
||||||
// add info to each column
|
// add info to each column
|
||||||
AgColumns = AgColumns.map((col) => {
|
AgColumns = AgColumns.map((col) => {
|
||||||
|
|
@ -93,7 +95,7 @@ export default function TableNodeComponent({
|
||||||
if (agGrid.current && !agGrid.current.api.isDestroyed()) {
|
if (agGrid.current && !agGrid.current.api.isDestroyed()) {
|
||||||
const rows: any = [];
|
const rows: any = [];
|
||||||
agGrid.current.api.forEachNode((node) => rows.push(node.data));
|
agGrid.current.api.forEachNode((node) => rows.push(node.data));
|
||||||
handleOnNewValue({ value: rows });
|
setTempValue(rows);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function deleteRow() {
|
function deleteRow() {
|
||||||
|
|
@ -109,8 +111,7 @@ export default function TableNodeComponent({
|
||||||
if (agGrid.current && selectedNodes.length > 0) {
|
if (agGrid.current && selectedNodes.length > 0) {
|
||||||
const toDuplicate = selectedNodes.map((node) => cloneDeep(node.data));
|
const toDuplicate = selectedNodes.map((node) => cloneDeep(node.data));
|
||||||
setSelectedNodes([]);
|
setSelectedNodes([]);
|
||||||
const rows: any = [];
|
setTempValue([...tempValue, ...toDuplicate]);
|
||||||
handleOnNewValue({ value: [...value, ...toDuplicate] });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function addRow() {
|
function addRow() {
|
||||||
|
|
@ -118,12 +119,23 @@ export default function TableNodeComponent({
|
||||||
componentColumns.forEach((column) => {
|
componentColumns.forEach((column) => {
|
||||||
newRow[column.name] = column.default ?? null; // Use the default value if available
|
newRow[column.name] = column.default ?? null; // Use the default value if available
|
||||||
});
|
});
|
||||||
handleOnNewValue({ value: [...value, newRow] });
|
setTempValue([...tempValue, newRow]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateComponent() {
|
function updateComponent() {
|
||||||
setAllRows();
|
setAllRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleSave() {
|
||||||
|
handleOnNewValue({ value: tempValue });
|
||||||
|
setIsModalOpen(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCancel() {
|
||||||
|
setTempValue(cloneDeep(value));
|
||||||
|
setIsModalOpen(false);
|
||||||
|
}
|
||||||
|
|
||||||
const editable = componentColumns
|
const editable = componentColumns
|
||||||
.map((column) => {
|
.map((column) => {
|
||||||
const isCustomEdit =
|
const isCustomEdit =
|
||||||
|
|
@ -149,6 +161,8 @@ export default function TableNodeComponent({
|
||||||
>
|
>
|
||||||
<div className="flex w-full items-center gap-3" data-testid={"div-" + id}>
|
<div className="flex w-full items-center gap-3" data-testid={"div-" + id}>
|
||||||
<TableModal
|
<TableModal
|
||||||
|
open={isModalOpen}
|
||||||
|
setOpen={setIsModalOpen}
|
||||||
stopEditingWhenCellsLoseFocus={true}
|
stopEditingWhenCellsLoseFocus={true}
|
||||||
tableIcon={table_icon}
|
tableIcon={table_icon}
|
||||||
tableOptions={table_options}
|
tableOptions={table_options}
|
||||||
|
|
@ -169,8 +183,10 @@ export default function TableNodeComponent({
|
||||||
displayEmptyAlert={false}
|
displayEmptyAlert={false}
|
||||||
className="h-full w-full"
|
className="h-full w-full"
|
||||||
columnDefs={AgColumns}
|
columnDefs={AgColumns}
|
||||||
rowData={value}
|
rowData={tempValue}
|
||||||
context={{ field_parsers: table_options?.field_parsers }}
|
context={{ field_parsers: table_options?.field_parsers }}
|
||||||
|
onSave={handleSave}
|
||||||
|
onCancel={handleCancel}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,10 @@ interface TableModalProps extends TableComponentProps {
|
||||||
tableOptions?: TableOptionsTypeAPI;
|
tableOptions?: TableOptionsTypeAPI;
|
||||||
hideColumns?: boolean | string[];
|
hideColumns?: boolean | string[];
|
||||||
tableIcon?: string;
|
tableIcon?: string;
|
||||||
|
open?: boolean;
|
||||||
|
setOpen?: (open: boolean) => void;
|
||||||
|
onSave?: () => void;
|
||||||
|
onCancel?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TableModal = forwardRef<AgGridReact, TableModalProps>(
|
const TableModal = forwardRef<AgGridReact, TableModalProps>(
|
||||||
|
|
@ -25,22 +29,43 @@ const TableModal = forwardRef<AgGridReact, TableModalProps>(
|
||||||
children,
|
children,
|
||||||
disabled,
|
disabled,
|
||||||
tableIcon,
|
tableIcon,
|
||||||
|
open,
|
||||||
|
setOpen,
|
||||||
|
onSave,
|
||||||
|
onCancel,
|
||||||
...props
|
...props
|
||||||
}: TableModalProps,
|
}: TableModalProps,
|
||||||
ref: ForwardedRef<AgGridReact>,
|
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 (
|
return (
|
||||||
<BaseModal
|
<BaseModal
|
||||||
onEscapeKeyDown={(e) => {
|
onEscapeKeyDown={(e) => {
|
||||||
if (
|
handleOnEscapeKeyDown(e);
|
||||||
(
|
|
||||||
ref as React.RefObject<AgGridReact>
|
|
||||||
)?.current?.api.getEditingCells().length
|
|
||||||
) {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
disable={disabled}
|
disable={disabled}
|
||||||
|
open={open}
|
||||||
|
setOpen={(newOpen) => {
|
||||||
|
handleSetOpen(newOpen);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<BaseModal.Trigger asChild>{children}</BaseModal.Trigger>
|
<BaseModal.Trigger asChild>{children}</BaseModal.Trigger>
|
||||||
<BaseModal.Header
|
<BaseModal.Header
|
||||||
|
|
@ -59,6 +84,9 @@ const TableModal = forwardRef<AgGridReact, TableModalProps>(
|
||||||
{...props}
|
{...props}
|
||||||
></TableComponent>
|
></TableComponent>
|
||||||
</BaseModal.Content>
|
</BaseModal.Content>
|
||||||
|
<BaseModal.Footer
|
||||||
|
submit={onSave ? { label: "Save", onClick: onSave } : undefined}
|
||||||
|
></BaseModal.Footer>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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("sidebar-custom-component-button").click();
|
||||||
|
|
||||||
await page.getByTestId("zoom_out").click();
|
await page.getByTestId("zoom_out").click();
|
||||||
|
|
@ -164,7 +168,7 @@ class CustomComponent(Component):
|
||||||
numberOfCopiedRows = await page.getByText(thirdRandomText).count();
|
numberOfCopiedRows = await page.getByText(thirdRandomText).count();
|
||||||
expect(numberOfCopiedRows).toBe(0);
|
expect(numberOfCopiedRows).toBe(0);
|
||||||
|
|
||||||
await page.getByText("Close").last().click();
|
await page.getByText("Save").last().click();
|
||||||
|
|
||||||
await page.waitForSelector("text=Open table", {
|
await page.waitForSelector("text=Open table", {
|
||||||
timeout: 3000,
|
timeout: 3000,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue