feat: Support row virtualization using react-window in Table widget (#16872)
This commit is contained in:
parent
4bae04ea64
commit
81458035d5
|
|
@ -0,0 +1,73 @@
|
|||
import { ObjectsRegistry } from "../../../../../support/Objects/Registry";
|
||||
|
||||
const PropertyPane = ObjectsRegistry.PropertyPane;
|
||||
const totalRows = 100;
|
||||
|
||||
describe("Table Widget Virtualized Row", function() {
|
||||
before(() => {
|
||||
cy.dragAndDropToCanvas("tablewidgetv2", { x: 300, y: 600 });
|
||||
const row = {
|
||||
step: "#3",
|
||||
task: "Bind the query using => fetch_users.data",
|
||||
status: "--",
|
||||
action: "",
|
||||
};
|
||||
|
||||
const rows = new Array(totalRows).fill("").map((d, i) => ({
|
||||
...row,
|
||||
step: i,
|
||||
}));
|
||||
|
||||
PropertyPane.UpdatePropertyFieldValue("Table Data", JSON.stringify(rows));
|
||||
PropertyPane.ToggleOnOrOff("Server Side Pagination", "On");
|
||||
PropertyPane.ToggleOnOrOff("Show Pagination", "Off");
|
||||
});
|
||||
|
||||
it("1. should check that row is getting rendered", () => {
|
||||
cy.get(".tr[data-rowindex]").should("exist");
|
||||
cy.get(".td[data-rowindex]").should("exist");
|
||||
});
|
||||
|
||||
it("2. should check that virtual rows are getting rendered when scrolling through the table", () => {
|
||||
cy.get(".tr[data-rowindex]").should("not.have.length", totalRows);
|
||||
cy.get(".tr[data-rowindex='0']").should("exist");
|
||||
cy.get(".tbody > div").scrollTo("bottom");
|
||||
cy.wait(500);
|
||||
cy.get(".tr[data-rowindex='0']").should("not.exist");
|
||||
cy.get(".tr[data-rowindex='98']").should("exist");
|
||||
cy.get(".tbody > div").scrollTo("top");
|
||||
cy.wait(500);
|
||||
cy.get(".tr[data-rowindex='0']").should("exist");
|
||||
cy.get(".tr[data-rowindex='98']").should("not.exist");
|
||||
cy.get(".t--virtual-row").should("exist");
|
||||
});
|
||||
|
||||
it("3. should check that virtual rows feature is turned off when cell wrapping is enabled", () => {
|
||||
cy.editColumn("step");
|
||||
cy.wait(500);
|
||||
PropertyPane.ToggleOnOrOff("Cell Wrapping", "On");
|
||||
cy.get(".tr[data-rowindex]").should("have.length", totalRows);
|
||||
cy.get(".tr[data-rowindex='0']").should("exist");
|
||||
cy.get(".tr[data-rowindex='98']").should("exist");
|
||||
cy.get(".tbody").scrollTo("bottom");
|
||||
cy.wait(500);
|
||||
cy.get(".tr[data-rowindex='0']").should("exist");
|
||||
cy.get(".tr[data-rowindex='98']").should("exist");
|
||||
cy.get(".tbody").scrollTo("top");
|
||||
cy.wait(500);
|
||||
cy.get(".tr[data-rowindex='0']").should("exist");
|
||||
cy.get(".tr[data-rowindex='98']").should("exist");
|
||||
cy.get(".t--virtual-row").should("not.exist");
|
||||
});
|
||||
|
||||
it("4. should check that virtual rows feature is turned off when server side pagination is disabled", () => {
|
||||
PropertyPane.ToggleOnOrOff("Cell Wrapping", "Off");
|
||||
PropertyPane.NavigateBackToPropertyPane();
|
||||
cy.wait(500);
|
||||
PropertyPane.ToggleOnOrOff("Show Pagination", "On");
|
||||
cy.wait(500);
|
||||
PropertyPane.ToggleOnOrOff("Server Side Pagination", "Off");
|
||||
cy.get(".tr[data-rowindex]").should("have.length", 5);
|
||||
cy.get(".t--virtual-row").should("not.exist");
|
||||
});
|
||||
});
|
||||
|
|
@ -53,6 +53,7 @@
|
|||
"exceljs-lightweight": "^1.14.0",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-xml-parser": "^3.17.5",
|
||||
"fastdom": "^1.0.11",
|
||||
"flow-bin": "^0.148.0",
|
||||
"focus-trap-react": "^8.9.2",
|
||||
"fuse.js": "^3.4.5",
|
||||
|
|
|
|||
|
|
@ -464,3 +464,5 @@ export const scrollbarOnHoverCSS = `
|
|||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const MULTISELECT_CHECKBOX_WIDTH = 40;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import {
|
|||
useBlockLayout,
|
||||
useResizeColumns,
|
||||
useRowSelect,
|
||||
Row,
|
||||
Row as ReactTableRowType,
|
||||
} from "react-table";
|
||||
import {
|
||||
TableWrapper,
|
||||
|
|
@ -28,12 +28,10 @@ import { ScrollIndicator } from "design-system";
|
|||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import { Scrollbars } from "react-custom-scrollbars";
|
||||
import { renderEmptyRows } from "./cellComponents/EmptyCell";
|
||||
import {
|
||||
renderBodyCheckBoxCell,
|
||||
renderHeaderCheckBoxCell,
|
||||
} from "./cellComponents/SelectionCheckboxCell";
|
||||
import { renderHeaderCheckBoxCell } from "./cellComponents/SelectionCheckboxCell";
|
||||
import { HeaderCell } from "./cellComponents/HeaderCell";
|
||||
import { EditableCell } from "../constants";
|
||||
import { TableBody } from "./TableBody";
|
||||
|
||||
interface TableProps {
|
||||
width: number;
|
||||
|
|
@ -68,7 +66,7 @@ interface TableProps {
|
|||
enableDrag: () => void;
|
||||
toggleAllRowSelect: (
|
||||
isSelect: boolean,
|
||||
pageData: Row<Record<string, unknown>>[],
|
||||
pageData: ReactTableRowType<Record<string, unknown>>[],
|
||||
) => void;
|
||||
triggerRowSelection: boolean;
|
||||
searchTableData: (searchKey: any) => void;
|
||||
|
|
@ -85,6 +83,7 @@ interface TableProps {
|
|||
boxShadow?: string;
|
||||
onBulkEditDiscard: () => void;
|
||||
onBulkEditSave: () => void;
|
||||
primaryColumnId?: string;
|
||||
}
|
||||
|
||||
const defaultColumn = {
|
||||
|
|
@ -185,7 +184,6 @@ export function Table(props: TableProps) {
|
|||
endIndex = props.data.length;
|
||||
}
|
||||
const subPage = page.slice(startIndex, endIndex);
|
||||
const selectedRowIndex = props.selectedRowIndex;
|
||||
const selectedRowIndices = props.selectedRowIndices || [];
|
||||
const tableSizes = TABLE_SIZES[props.compactMode || CompactModeTypes.DEFAULT];
|
||||
const tableWrapperRef = useRef<HTMLDivElement | null>(null);
|
||||
|
|
@ -228,6 +226,12 @@ export function Table(props: TableProps) {
|
|||
[props.width],
|
||||
);
|
||||
|
||||
const shouldUseVirtual =
|
||||
props.serverSidePaginationEnabled &&
|
||||
!props.columns.some(
|
||||
(column) => !!column.columnProperties.allowCellWrapping,
|
||||
);
|
||||
|
||||
return (
|
||||
<TableWrapper
|
||||
accentColor={props.accentColor}
|
||||
|
|
@ -354,73 +358,32 @@ export function Table(props: TableProps) {
|
|||
props.columns,
|
||||
props.width,
|
||||
subPage,
|
||||
prepareRow,
|
||||
props.multiRowSelection,
|
||||
props.accentColor,
|
||||
props.borderRadius,
|
||||
{},
|
||||
prepareRow,
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
{...getTableBodyProps()}
|
||||
className={`tbody ${
|
||||
props.pageSize > subPage.length ? "no-scroll" : ""
|
||||
}`}
|
||||
<TableBody
|
||||
accentColor={props.accentColor}
|
||||
borderRadius={props.borderRadius}
|
||||
columns={props.columns}
|
||||
getTableBodyProps={getTableBodyProps}
|
||||
height={props.height}
|
||||
multiRowSelection={!!props.multiRowSelection}
|
||||
pageSize={props.pageSize}
|
||||
prepareRow={prepareRow}
|
||||
primaryColumnId={props.primaryColumnId}
|
||||
ref={tableBodyRef}
|
||||
>
|
||||
{subPage.map((row, rowIndex) => {
|
||||
prepareRow(row);
|
||||
const rowProps = {
|
||||
...row.getRowProps(),
|
||||
style: { display: "flex" },
|
||||
};
|
||||
const isRowSelected = props.multiRowSelection
|
||||
? selectedRowIndices.includes(row.index)
|
||||
: row.index === selectedRowIndex;
|
||||
return (
|
||||
<div
|
||||
{...rowProps}
|
||||
className={"tr" + `${isRowSelected ? " selected-row" : ""}`}
|
||||
key={rowIndex}
|
||||
onClick={(e) => {
|
||||
row.toggleRowSelected();
|
||||
props.selectTableRow(row);
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
{props.multiRowSelection &&
|
||||
renderBodyCheckBoxCell(
|
||||
isRowSelected,
|
||||
props.accentColor,
|
||||
props.borderRadius,
|
||||
)}
|
||||
{row.cells.map((cell, cellIndex) => {
|
||||
return (
|
||||
<div
|
||||
{...cell.getCellProps()}
|
||||
className="td"
|
||||
data-colindex={cellIndex}
|
||||
data-rowindex={rowIndex}
|
||||
key={cellIndex}
|
||||
>
|
||||
{cell.render("Cell")}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{props.pageSize > subPage.length &&
|
||||
renderEmptyRows(
|
||||
props.pageSize - subPage.length,
|
||||
props.columns,
|
||||
props.width,
|
||||
subPage,
|
||||
prepareRow,
|
||||
props.multiRowSelection,
|
||||
props.accentColor,
|
||||
props.borderRadius,
|
||||
)}
|
||||
</div>
|
||||
rows={subPage}
|
||||
selectTableRow={props.selectTableRow}
|
||||
selectedRowIndex={props.selectedRowIndex}
|
||||
selectedRowIndices={props.selectedRowIndices}
|
||||
tableSizes={tableSizes}
|
||||
useVirtual={shouldUseVirtual}
|
||||
width={props.width}
|
||||
/>
|
||||
</div>
|
||||
</Scrollbars>
|
||||
</div>
|
||||
|
|
|
|||
129
app/client/src/widgets/TableWidgetV2/component/TableBody/Row.tsx
Normal file
129
app/client/src/widgets/TableWidgetV2/component/TableBody/Row.tsx
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
import React, { CSSProperties, Key, useContext } from "react";
|
||||
import { Row as ReactTableRowType } from "react-table";
|
||||
import { ListChildComponentProps } from "react-window";
|
||||
import { BodyContext } from ".";
|
||||
import { renderEmptyRows } from "../cellComponents/EmptyCell";
|
||||
import { renderBodyCheckBoxCell } from "../cellComponents/SelectionCheckboxCell";
|
||||
|
||||
type RowType = {
|
||||
className?: string;
|
||||
index: number;
|
||||
row: ReactTableRowType<Record<string, unknown>>;
|
||||
style?: ListChildComponentProps["style"];
|
||||
};
|
||||
|
||||
export function Row(props: RowType) {
|
||||
const {
|
||||
accentColor,
|
||||
borderRadius,
|
||||
multiRowSelection,
|
||||
prepareRow,
|
||||
primaryColumnId,
|
||||
selectedRowIndex,
|
||||
selectedRowIndices,
|
||||
selectTableRow,
|
||||
} = useContext(BodyContext);
|
||||
|
||||
prepareRow?.(props.row);
|
||||
const rowProps = {
|
||||
...props.row.getRowProps(),
|
||||
style: {
|
||||
display: "flex",
|
||||
...(props.style || {}),
|
||||
},
|
||||
};
|
||||
const isRowSelected = multiRowSelection
|
||||
? selectedRowIndices.includes(props.row.index)
|
||||
: props.row.index === selectedRowIndex;
|
||||
|
||||
const key =
|
||||
(primaryColumnId && (props.row.original[primaryColumnId] as Key)) ||
|
||||
props.index;
|
||||
|
||||
return (
|
||||
<div
|
||||
{...rowProps}
|
||||
className={`tr ${isRowSelected ? "selected-row" : ""} ${props.className ||
|
||||
""}`}
|
||||
data-rowindex={props.index}
|
||||
key={key}
|
||||
onClick={(e) => {
|
||||
props.row.toggleRowSelected();
|
||||
selectTableRow?.(props.row);
|
||||
e.stopPropagation();
|
||||
}}
|
||||
role="button"
|
||||
>
|
||||
{multiRowSelection &&
|
||||
renderBodyCheckBoxCell(isRowSelected, accentColor, borderRadius)}
|
||||
{props.row.cells.map((cell, cellIndex) => {
|
||||
return (
|
||||
<div
|
||||
{...cell.getCellProps()}
|
||||
className="td"
|
||||
data-colindex={cellIndex}
|
||||
data-rowindex={props.index}
|
||||
key={cellIndex}
|
||||
>
|
||||
{cell.render("Cell")}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const EmptyRows = (props: {
|
||||
style?: CSSProperties;
|
||||
rowCount: number;
|
||||
}) => {
|
||||
const {
|
||||
accentColor,
|
||||
borderRadius,
|
||||
columns,
|
||||
multiRowSelection,
|
||||
prepareRow,
|
||||
rows,
|
||||
width,
|
||||
} = useContext(BodyContext);
|
||||
|
||||
return (
|
||||
<>
|
||||
{renderEmptyRows(
|
||||
props.rowCount,
|
||||
columns,
|
||||
width,
|
||||
rows,
|
||||
multiRowSelection,
|
||||
accentColor,
|
||||
borderRadius,
|
||||
props.style,
|
||||
prepareRow,
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const EmptyRow = (props: { style?: CSSProperties }) => {
|
||||
const {
|
||||
accentColor,
|
||||
borderRadius,
|
||||
columns,
|
||||
multiRowSelection,
|
||||
prepareRow,
|
||||
rows,
|
||||
width,
|
||||
} = useContext(BodyContext);
|
||||
|
||||
return renderEmptyRows(
|
||||
1,
|
||||
columns,
|
||||
width,
|
||||
rows,
|
||||
multiRowSelection,
|
||||
accentColor,
|
||||
borderRadius,
|
||||
props.style,
|
||||
prepareRow,
|
||||
)?.[0];
|
||||
};
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
import React, { Ref } from "react";
|
||||
import {
|
||||
Row as ReactTableRowType,
|
||||
TableBodyPropGetter,
|
||||
TableBodyProps,
|
||||
} from "react-table";
|
||||
import { FixedSizeList, ListChildComponentProps, areEqual } from "react-window";
|
||||
import { WIDGET_PADDING } from "constants/WidgetConstants";
|
||||
import { EmptyRows, EmptyRow, Row } from "./Row";
|
||||
import { ReactTableColumnProps, TableSizes } from "../Constants";
|
||||
|
||||
type BodyContextType = {
|
||||
accentColor: string;
|
||||
borderRadius: string;
|
||||
multiRowSelection: boolean;
|
||||
prepareRow?(row: ReactTableRowType<Record<string, unknown>>): void;
|
||||
selectTableRow?: (row: {
|
||||
original: Record<string, unknown>;
|
||||
index: number;
|
||||
}) => void;
|
||||
selectedRowIndex: number;
|
||||
selectedRowIndices: number[];
|
||||
columns: ReactTableColumnProps[];
|
||||
width: number;
|
||||
rows: ReactTableRowType<Record<string, unknown>>[];
|
||||
primaryColumnId?: string;
|
||||
};
|
||||
|
||||
export const BodyContext = React.createContext<BodyContextType>({
|
||||
accentColor: "",
|
||||
borderRadius: "",
|
||||
multiRowSelection: false,
|
||||
selectedRowIndex: -1,
|
||||
selectedRowIndices: [],
|
||||
columns: [],
|
||||
width: 0,
|
||||
rows: [],
|
||||
primaryColumnId: "",
|
||||
});
|
||||
|
||||
const rowRenderer = React.memo((rowProps: ListChildComponentProps) => {
|
||||
const { data, index, style } = rowProps;
|
||||
|
||||
if (index < data.length) {
|
||||
const row = data[index];
|
||||
|
||||
return (
|
||||
<Row
|
||||
className="t--virtual-row"
|
||||
index={index}
|
||||
key={index}
|
||||
row={row}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return <EmptyRow style={style} />;
|
||||
}
|
||||
}, areEqual);
|
||||
|
||||
type BodyPropsType = {
|
||||
getTableBodyProps(
|
||||
propGetter?: TableBodyPropGetter<Record<string, unknown>> | undefined,
|
||||
): TableBodyProps;
|
||||
pageSize: number;
|
||||
rows: ReactTableRowType<Record<string, unknown>>[];
|
||||
height: number;
|
||||
tableSizes: TableSizes;
|
||||
};
|
||||
|
||||
const TableVirtualBodyComponent = React.forwardRef(
|
||||
(props: BodyPropsType, ref: Ref<HTMLDivElement>) => {
|
||||
return (
|
||||
<div {...props.getTableBodyProps()} className="tbody no-scroll">
|
||||
<FixedSizeList
|
||||
height={
|
||||
props.height -
|
||||
props.tableSizes.TABLE_HEADER_HEIGHT -
|
||||
props.tableSizes.COLUMN_HEADER_HEIGHT -
|
||||
2 * WIDGET_PADDING // Top and bottom padding
|
||||
}
|
||||
itemCount={Math.max(props.rows.length, props.pageSize)}
|
||||
itemData={props.rows}
|
||||
itemSize={props.tableSizes.ROW_HEIGHT}
|
||||
outerRef={ref}
|
||||
width={`calc(100% + ${2 * WIDGET_PADDING}px`}
|
||||
>
|
||||
{rowRenderer}
|
||||
</FixedSizeList>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
const TableBodyComponent = React.forwardRef(
|
||||
(props: BodyPropsType, ref: Ref<HTMLDivElement>) => {
|
||||
return (
|
||||
<div {...props.getTableBodyProps()} className="tbody" ref={ref}>
|
||||
{props.rows.map((row, index) => {
|
||||
return <Row index={index} key={index} row={row} />;
|
||||
})}
|
||||
{props.pageSize > props.rows.length && (
|
||||
<EmptyRows rowCount={props.pageSize - props.rows.length} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
export const TableBody = React.forwardRef(
|
||||
(
|
||||
props: BodyPropsType & BodyContextType & { useVirtual: boolean },
|
||||
ref: Ref<HTMLDivElement>,
|
||||
) => {
|
||||
const {
|
||||
accentColor,
|
||||
borderRadius,
|
||||
columns,
|
||||
multiRowSelection,
|
||||
prepareRow,
|
||||
primaryColumnId,
|
||||
rows,
|
||||
selectedRowIndex,
|
||||
selectedRowIndices,
|
||||
selectTableRow,
|
||||
useVirtual,
|
||||
width,
|
||||
...restOfProps
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<BodyContext.Provider
|
||||
value={{
|
||||
accentColor,
|
||||
borderRadius,
|
||||
multiRowSelection,
|
||||
prepareRow,
|
||||
primaryColumnId,
|
||||
selectTableRow,
|
||||
selectedRowIndex,
|
||||
selectedRowIndices,
|
||||
columns,
|
||||
width,
|
||||
rows,
|
||||
}}
|
||||
>
|
||||
{useVirtual ? (
|
||||
<TableVirtualBodyComponent ref={ref} rows={rows} {...restOfProps} />
|
||||
) : (
|
||||
<TableBodyComponent ref={ref} rows={rows} {...restOfProps} />
|
||||
)}
|
||||
</BodyContext.Provider>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
@ -11,6 +11,7 @@ import {
|
|||
CellAlignment,
|
||||
VerticalAlignment,
|
||||
scrollbarOnHoverCSS,
|
||||
MULTISELECT_CHECKBOX_WIDTH,
|
||||
} from "./Constants";
|
||||
import { Colors, Color } from "constants/Colors";
|
||||
import { hideScrollbar, invisible } from "constants/DefaultTheme";
|
||||
|
|
@ -81,6 +82,9 @@ export const TableWrapper = styled.div<{
|
|||
overflow-y: auto;
|
||||
${hideScrollbar};
|
||||
}
|
||||
.tbody.no-scroll {
|
||||
overflow: hidden;
|
||||
}
|
||||
.tr {
|
||||
overflow: hidden;
|
||||
cursor: ${(props) => props.triggerRowSelection && "pointer"};
|
||||
|
|
@ -429,11 +433,11 @@ export const CellWrapper = styled.div<{
|
|||
|
||||
export const CellCheckboxWrapper = styled(CellWrapper)<{
|
||||
isChecked?: boolean;
|
||||
accentColor: string;
|
||||
borderRadius: string;
|
||||
accentColor?: string;
|
||||
borderRadius?: string;
|
||||
}>`
|
||||
justify-content: center;
|
||||
width: 40px;
|
||||
width: ${MULTISELECT_CHECKBOX_WIDTH}px;
|
||||
height: auto;
|
||||
& > div {
|
||||
border-radius: ${({ borderRadius }) => borderRadius};
|
||||
|
|
|
|||
|
|
@ -39,15 +39,14 @@ function useToolTip(
|
|||
const [showTooltip, updateToolTip] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
requestAnimationFrame(() => {
|
||||
const element = ref.current?.querySelector("div") as HTMLDivElement;
|
||||
|
||||
if (element && element.offsetWidth < element.scrollWidth) {
|
||||
updateToolTip(true);
|
||||
} else {
|
||||
updateToolTip(false);
|
||||
}
|
||||
});
|
||||
}, [children, ref.current]);
|
||||
}, [children]);
|
||||
|
||||
return showTooltip && children ? (
|
||||
<Tooltip
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React from "react";
|
||||
import React, { CSSProperties } from "react";
|
||||
import { Cell, Row } from "react-table";
|
||||
import { ReactTableColumnProps } from "../Constants";
|
||||
import { EmptyCell, EmptyRow } from "../TableStyledWrappers";
|
||||
|
|
@ -9,10 +9,11 @@ export const renderEmptyRows = (
|
|||
columns: ReactTableColumnProps[],
|
||||
tableWidth: number,
|
||||
page: Row<Record<string, unknown>>[],
|
||||
prepareRow: (row: Row<Record<string, unknown>>) => void,
|
||||
multiRowSelection = false,
|
||||
accentColor: string,
|
||||
borderRadius: string,
|
||||
style?: CSSProperties,
|
||||
prepareRow?: (row: Row<Record<string, unknown>>) => void,
|
||||
) => {
|
||||
const rows: string[] = new Array(rowCount).fill("");
|
||||
|
||||
|
|
@ -20,10 +21,13 @@ export const renderEmptyRows = (
|
|||
const row = page[0];
|
||||
|
||||
return rows.map((item: string, index: number) => {
|
||||
prepareRow(row);
|
||||
prepareRow?.(row);
|
||||
const rowProps = {
|
||||
...row.getRowProps(),
|
||||
style: { display: "flex" },
|
||||
style: {
|
||||
display: "flex",
|
||||
...style,
|
||||
},
|
||||
};
|
||||
return (
|
||||
<div {...rowProps} className="tr" key={index}>
|
||||
|
|
@ -41,26 +45,18 @@ export const renderEmptyRows = (
|
|||
? columns
|
||||
: new Array(3).fill({ width: tableWidth / 3, isHidden: false });
|
||||
|
||||
return rows.map((row: string, index: number) => {
|
||||
return (
|
||||
<>
|
||||
{rows.map((row: string, index: number) => {
|
||||
return (
|
||||
<EmptyRow className="tr" key={index}>
|
||||
<EmptyRow className="tr" key={index} style={style}>
|
||||
{multiRowSelection &&
|
||||
renderBodyCheckBoxCell(false, accentColor, borderRadius)}
|
||||
{tableColumns.map((column: any, colIndex: number) => {
|
||||
return (
|
||||
<EmptyCell
|
||||
className="td"
|
||||
key={colIndex}
|
||||
width={column.width}
|
||||
/>
|
||||
<EmptyCell className="td" key={colIndex} width={column.width} />
|
||||
);
|
||||
})}
|
||||
</EmptyRow>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import { CheckboxState } from "../Constants";
|
|||
|
||||
export const renderBodyCheckBoxCell = (
|
||||
isChecked: boolean,
|
||||
accentColor: string,
|
||||
borderRadius: string,
|
||||
accentColor?: string,
|
||||
borderRadius?: string,
|
||||
) => (
|
||||
<CellCheckboxWrapper
|
||||
accentColor={accentColor}
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ interface ReactTableComponentProps {
|
|||
borderRadius: string;
|
||||
boxShadow?: string;
|
||||
isEditableCellValid?: boolean;
|
||||
primaryColumnId?: string;
|
||||
}
|
||||
|
||||
function ReactTableComponent(props: ReactTableComponentProps) {
|
||||
|
|
@ -113,6 +114,7 @@ function ReactTableComponent(props: ReactTableComponentProps) {
|
|||
pageNo,
|
||||
pageSize,
|
||||
prevPageClick,
|
||||
primaryColumnId,
|
||||
searchKey,
|
||||
searchTableData,
|
||||
selectAllRow,
|
||||
|
|
@ -293,6 +295,7 @@ function ReactTableComponent(props: ReactTableComponentProps) {
|
|||
pageNo={pageNo - 1}
|
||||
pageSize={pageSize || 1}
|
||||
prevPageClick={prevPageClick}
|
||||
primaryColumnId={primaryColumnId}
|
||||
searchKey={searchKey}
|
||||
searchTableData={searchTableData}
|
||||
selectTableRow={selectTableRow}
|
||||
|
|
@ -354,6 +357,7 @@ export default React.memo(ReactTableComponent, (prev, next) => {
|
|||
// and we are not changing the columns manually.
|
||||
JSON.stringify(prev.columns) === JSON.stringify(next.columns) &&
|
||||
equal(prev.editableCell, next.editableCell) &&
|
||||
prev.isEditableCellValid === next.isEditableCellValid
|
||||
prev.isEditableCellValid === next.isEditableCellValid &&
|
||||
prev.primaryColumnId === next.primaryColumnId
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -858,6 +858,7 @@ class TableWidgetV2 extends BaseWidget<TableWidgetProps, WidgetState> {
|
|||
isVisibleHeaderOptions ? Math.max(1, pageSize) : pageSize + 1
|
||||
}
|
||||
prevPageClick={this.handlePrevPageClick}
|
||||
primaryColumnId={this.props.primaryColumnId}
|
||||
searchKey={this.props.searchText}
|
||||
searchTableData={this.handleSearchTable}
|
||||
selectAllRow={this.handleAllRowSelect}
|
||||
|
|
|
|||
|
|
@ -7376,6 +7376,13 @@ fast-xml-parser@^3.17.5:
|
|||
version "3.17.5"
|
||||
resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.17.5.tgz"
|
||||
|
||||
fastdom@^1.0.11:
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/fastdom/-/fastdom-1.0.11.tgz#f22984f9df6b9a6081e5ce2e49cfb5525daf198a"
|
||||
integrity sha512-jl9MwXDFxhg354W4E3s1UMsLh3HWFuVMQiRUlXpHckcHRXQvUe76yzBf1Z7b+x5Ci4TUJ1KmynI9alGUXG95IQ==
|
||||
dependencies:
|
||||
strictdom "^1.0.1"
|
||||
|
||||
fastq@^1.6.0:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz"
|
||||
|
|
@ -14262,6 +14269,11 @@ strict-event-emitter@^0.2.0:
|
|||
dependencies:
|
||||
events "^3.3.0"
|
||||
|
||||
strictdom@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strictdom/-/strictdom-1.0.1.tgz#189de91649f73d44d59b8432efa68ef9d2659460"
|
||||
integrity sha512-cEmp9QeXXRmjj/rVp9oyiqcvyocWab/HaoN4+bwFeZ7QzykJD6L3yD4v12K1x0tHpqRqVpJevN3gW7kyM39Bqg==
|
||||
|
||||
string-argv@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user