2021-09-09 15:10:22 +00:00
|
|
|
import React, { useEffect, useMemo } from "react";
|
|
|
|
|
import Table from "./Table";
|
2020-07-20 06:04:05 +00:00
|
|
|
import {
|
2020-08-10 11:16:13 +00:00
|
|
|
ColumnTypes,
|
|
|
|
|
CompactMode,
|
|
|
|
|
ReactTableColumnProps,
|
|
|
|
|
ReactTableFilter,
|
2021-09-09 15:10:22 +00:00
|
|
|
} from "./Constants";
|
2021-07-07 05:52:10 +00:00
|
|
|
import { Row } from "react-table";
|
2021-09-09 15:10:22 +00:00
|
|
|
|
2021-03-30 05:29:03 +00:00
|
|
|
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
2021-05-11 06:55:42 +00:00
|
|
|
import { isEqual } from "lodash";
|
2020-06-03 10:50:10 +00:00
|
|
|
|
|
|
|
|
export interface ColumnMenuOptionProps {
|
|
|
|
|
content: string | JSX.Element;
|
|
|
|
|
closeOnClick?: boolean;
|
|
|
|
|
isSelected?: boolean;
|
2020-07-14 07:55:46 +00:00
|
|
|
editColumnName?: boolean;
|
2020-06-03 10:50:10 +00:00
|
|
|
columnAccessor?: string;
|
|
|
|
|
id?: string;
|
|
|
|
|
category?: boolean;
|
|
|
|
|
options?: ColumnMenuSubOptionProps[];
|
2020-06-22 08:25:03 +00:00
|
|
|
onClick?: (columnIndex: number, isSelected: boolean) => void;
|
2020-06-03 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ColumnMenuSubOptionProps {
|
2020-09-11 10:40:15 +00:00
|
|
|
content: string | JSX.Element;
|
|
|
|
|
isSelected?: boolean;
|
|
|
|
|
closeOnClick?: boolean;
|
|
|
|
|
onClick?: (columnIndex: number) => void;
|
|
|
|
|
id?: string;
|
|
|
|
|
category?: boolean;
|
2020-12-15 11:24:15 +00:00
|
|
|
isHeader?: boolean;
|
2020-06-03 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface ReactTableComponentProps {
|
|
|
|
|
widgetId: string;
|
2020-07-20 06:04:05 +00:00
|
|
|
widgetName: string;
|
2020-07-03 08:26:04 +00:00
|
|
|
searchKey: string;
|
2020-06-03 10:50:10 +00:00
|
|
|
isDisabled?: boolean;
|
|
|
|
|
isVisible?: boolean;
|
2020-07-02 06:26:01 +00:00
|
|
|
isLoading: boolean;
|
2020-08-20 09:30:19 +00:00
|
|
|
editMode: boolean;
|
2020-06-03 10:50:10 +00:00
|
|
|
width: number;
|
|
|
|
|
height: number;
|
|
|
|
|
pageSize: number;
|
2021-08-30 09:24:59 +00:00
|
|
|
totalRecordsCount?: number;
|
2020-10-28 15:40:33 +00:00
|
|
|
tableData: Array<Record<string, unknown>>;
|
2020-06-03 10:50:10 +00:00
|
|
|
disableDrag: (disable: boolean) => void;
|
2020-10-28 15:40:33 +00:00
|
|
|
onRowClick: (rowData: Record<string, unknown>, rowIndex: number) => void;
|
2020-07-14 07:55:46 +00:00
|
|
|
onCommandClick: (dynamicTrigger: string, onComplete: () => void) => void;
|
2021-07-07 05:52:10 +00:00
|
|
|
selectAllRow: (pageData: Row<Record<string, unknown>>[]) => void;
|
|
|
|
|
unSelectAllRow: (pageData: Row<Record<string, unknown>>[]) => void;
|
2020-11-06 11:15:47 +00:00
|
|
|
updatePageNo: (pageNo: number, event?: EventType) => void;
|
2020-08-10 06:45:31 +00:00
|
|
|
sortTableColumn: (column: string, asc: boolean) => void;
|
2020-10-28 15:40:33 +00:00
|
|
|
nextPageClick: () => void;
|
|
|
|
|
prevPageClick: () => void;
|
2020-06-03 10:50:10 +00:00
|
|
|
pageNo: number;
|
|
|
|
|
serverSidePaginationEnabled: boolean;
|
|
|
|
|
selectedRowIndex: number;
|
2020-09-09 07:12:15 +00:00
|
|
|
selectedRowIndices: number[];
|
2020-09-08 13:04:51 +00:00
|
|
|
multiRowSelection?: boolean;
|
2020-06-03 10:50:10 +00:00
|
|
|
hiddenColumns?: string[];
|
2021-01-22 10:12:34 +00:00
|
|
|
triggerRowSelection: boolean;
|
2020-06-03 10:50:10 +00:00
|
|
|
columnSizeMap?: { [key: string]: number };
|
2020-10-28 15:40:33 +00:00
|
|
|
handleResizeColumn: (columnSizeMap: { [key: string]: number }) => void;
|
|
|
|
|
handleReorderColumn: (columnOrder: string[]) => void;
|
2020-07-03 08:26:04 +00:00
|
|
|
searchTableData: (searchKey: any) => void;
|
2020-08-10 11:16:13 +00:00
|
|
|
filters?: ReactTableFilter[];
|
|
|
|
|
applyFilter: (filters: ReactTableFilter[]) => void;
|
2020-07-20 06:04:05 +00:00
|
|
|
columns: ReactTableColumnProps[];
|
2020-08-10 10:01:36 +00:00
|
|
|
compactMode?: CompactMode;
|
2021-05-11 07:32:58 +00:00
|
|
|
isVisibleSearch?: boolean;
|
|
|
|
|
isVisibleFilters?: boolean;
|
|
|
|
|
isVisibleDownload?: boolean;
|
|
|
|
|
isVisiblePagination?: boolean;
|
2021-08-18 10:33:26 +00:00
|
|
|
delimiter: string;
|
2020-06-03 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-28 10:28:39 +00:00
|
|
|
function ReactTableComponent(props: ReactTableComponentProps) {
|
2021-05-03 18:42:21 +00:00
|
|
|
const {
|
|
|
|
|
applyFilter,
|
|
|
|
|
columns,
|
|
|
|
|
columnSizeMap,
|
|
|
|
|
compactMode,
|
2021-08-18 10:33:26 +00:00
|
|
|
delimiter,
|
2021-05-03 18:42:21 +00:00
|
|
|
disableDrag,
|
|
|
|
|
editMode,
|
|
|
|
|
filters,
|
|
|
|
|
handleReorderColumn,
|
|
|
|
|
handleResizeColumn,
|
|
|
|
|
height,
|
|
|
|
|
isLoading,
|
2021-05-11 07:32:58 +00:00
|
|
|
isVisibleDownload,
|
|
|
|
|
isVisibleFilters,
|
|
|
|
|
isVisiblePagination,
|
|
|
|
|
isVisibleSearch,
|
2021-07-07 05:52:10 +00:00
|
|
|
multiRowSelection,
|
2021-05-03 18:42:21 +00:00
|
|
|
nextPageClick,
|
|
|
|
|
onRowClick,
|
|
|
|
|
pageNo,
|
|
|
|
|
pageSize,
|
|
|
|
|
prevPageClick,
|
|
|
|
|
searchKey,
|
|
|
|
|
searchTableData,
|
2021-07-07 05:52:10 +00:00
|
|
|
selectAllRow,
|
2021-05-03 18:42:21 +00:00
|
|
|
selectedRowIndex,
|
|
|
|
|
selectedRowIndices,
|
|
|
|
|
serverSidePaginationEnabled,
|
|
|
|
|
sortTableColumn: _sortTableColumn,
|
|
|
|
|
tableData,
|
2021-08-30 09:24:59 +00:00
|
|
|
totalRecordsCount,
|
2021-05-03 18:42:21 +00:00
|
|
|
triggerRowSelection,
|
2021-07-07 05:52:10 +00:00
|
|
|
unSelectAllRow,
|
2021-05-03 18:42:21 +00:00
|
|
|
updatePageNo,
|
|
|
|
|
widgetId,
|
|
|
|
|
widgetName,
|
|
|
|
|
width,
|
|
|
|
|
} = props;
|
|
|
|
|
|
2021-04-07 01:03:30 +00:00
|
|
|
const { columnOrder, hiddenColumns } = useMemo(() => {
|
|
|
|
|
const order: string[] = [];
|
|
|
|
|
const hidden: string[] = [];
|
2021-05-03 18:42:21 +00:00
|
|
|
columns.forEach((item) => {
|
2021-04-07 01:03:30 +00:00
|
|
|
if (item.isHidden) {
|
|
|
|
|
hidden.push(item.accessor);
|
|
|
|
|
} else {
|
|
|
|
|
order.push(item.accessor);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return { columnOrder: order, hiddenColumns: hidden };
|
2021-05-03 18:42:21 +00:00
|
|
|
}, [columns]);
|
2021-04-07 01:03:30 +00:00
|
|
|
|
2020-07-14 07:55:46 +00:00
|
|
|
useEffect(() => {
|
2020-08-10 11:16:13 +00:00
|
|
|
let dragged = -1;
|
2020-07-14 07:55:46 +00:00
|
|
|
const headers = Array.prototype.slice.call(
|
2021-05-03 18:42:21 +00:00
|
|
|
document.querySelectorAll(`#table${widgetId} .draggable-header`),
|
2020-07-14 07:55:46 +00:00
|
|
|
);
|
|
|
|
|
headers.forEach((header, i) => {
|
|
|
|
|
header.setAttribute("draggable", true);
|
|
|
|
|
|
|
|
|
|
header.ondragstart = (e: React.DragEvent<HTMLDivElement>) => {
|
|
|
|
|
header.style =
|
|
|
|
|
"background: #efefef; border-radius: 4px; z-index: 100; width: 100%; text-overflow: none; overflow: none;";
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
dragged = i;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
header.ondrag = (e: React.DragEvent<HTMLDivElement>) => {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
header.ondragend = (e: React.DragEvent<HTMLDivElement>) => {
|
|
|
|
|
header.style = "";
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
setTimeout(() => (dragged = -1), 1000);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// the dropped header
|
|
|
|
|
header.ondragover = (e: React.DragEvent<HTMLDivElement>) => {
|
|
|
|
|
if (i !== dragged && dragged !== -1) {
|
|
|
|
|
if (dragged > i) {
|
|
|
|
|
header.parentElement.className = "th header-reorder highlight-left";
|
|
|
|
|
} else if (dragged < i) {
|
|
|
|
|
header.parentElement.className =
|
|
|
|
|
"th header-reorder highlight-right";
|
|
|
|
|
}
|
2020-06-03 10:50:10 +00:00
|
|
|
}
|
2020-07-14 07:55:46 +00:00
|
|
|
e.preventDefault();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
header.ondragenter = (e: React.DragEvent<HTMLDivElement>) => {
|
|
|
|
|
if (i !== dragged && dragged !== -1) {
|
|
|
|
|
if (dragged > i) {
|
|
|
|
|
header.parentElement.className = "th header-reorder highlight-left";
|
|
|
|
|
} else if (dragged < i) {
|
|
|
|
|
header.parentElement.className =
|
|
|
|
|
"th header-reorder highlight-right";
|
|
|
|
|
}
|
2020-06-03 10:50:10 +00:00
|
|
|
}
|
2020-07-14 07:55:46 +00:00
|
|
|
e.preventDefault();
|
|
|
|
|
};
|
2020-06-03 10:50:10 +00:00
|
|
|
|
2020-07-14 07:55:46 +00:00
|
|
|
header.ondragleave = (e: React.DragEvent<HTMLDivElement>) => {
|
|
|
|
|
header.parentElement.className = "th header-reorder";
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
header.ondrop = (e: React.DragEvent<HTMLDivElement>) => {
|
|
|
|
|
header.style = "";
|
|
|
|
|
header.parentElement.className = "th header-reorder";
|
|
|
|
|
if (i !== dragged && dragged !== -1) {
|
|
|
|
|
e.preventDefault();
|
2021-04-07 01:03:30 +00:00
|
|
|
const newColumnOrder = [...columnOrder];
|
|
|
|
|
// The dragged column
|
|
|
|
|
const movedColumnName = newColumnOrder.splice(dragged, 1);
|
|
|
|
|
|
|
|
|
|
// If the dragged column exists
|
|
|
|
|
if (movedColumnName && movedColumnName.length === 1) {
|
|
|
|
|
newColumnOrder.splice(i, 0, movedColumnName[0]);
|
|
|
|
|
}
|
2021-05-03 18:42:21 +00:00
|
|
|
handleReorderColumn([...newColumnOrder, ...hiddenColumns]);
|
2020-07-14 07:55:46 +00:00
|
|
|
} else {
|
|
|
|
|
dragged = -1;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2020-08-10 06:45:31 +00:00
|
|
|
const sortTableColumn = (columnIndex: number, asc: boolean) => {
|
2020-08-20 06:38:16 +00:00
|
|
|
if (columnIndex === -1) {
|
2021-05-03 18:42:21 +00:00
|
|
|
_sortTableColumn("", asc);
|
2020-08-20 06:38:16 +00:00
|
|
|
} else {
|
2021-05-03 18:42:21 +00:00
|
|
|
const column = columns[columnIndex];
|
2020-08-20 06:38:16 +00:00
|
|
|
const columnType = column.metaProperties?.type || ColumnTypes.TEXT;
|
|
|
|
|
if (
|
|
|
|
|
columnType !== ColumnTypes.IMAGE &&
|
|
|
|
|
columnType !== ColumnTypes.VIDEO
|
|
|
|
|
) {
|
2021-05-03 18:42:21 +00:00
|
|
|
_sortTableColumn(column.accessor, asc);
|
2020-08-20 06:38:16 +00:00
|
|
|
}
|
2020-08-10 06:45:31 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2021-02-24 10:29:19 +00:00
|
|
|
const selectTableRow = (row: {
|
|
|
|
|
original: Record<string, unknown>;
|
|
|
|
|
index: number;
|
|
|
|
|
}) => {
|
2021-05-03 18:42:21 +00:00
|
|
|
onRowClick(row.original, row.index);
|
2020-06-03 10:50:10 +00:00
|
|
|
};
|
|
|
|
|
|
2021-07-07 05:52:10 +00:00
|
|
|
const toggleAllRowSelect = (
|
|
|
|
|
isSelect: boolean,
|
|
|
|
|
pageData: Row<Record<string, unknown>>[],
|
|
|
|
|
) => {
|
|
|
|
|
if (isSelect) {
|
|
|
|
|
selectAllRow(pageData);
|
|
|
|
|
} else {
|
|
|
|
|
unSelectAllRow(pageData);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2020-07-14 07:55:46 +00:00
|
|
|
return (
|
|
|
|
|
<Table
|
2021-05-03 18:42:21 +00:00
|
|
|
applyFilter={applyFilter}
|
|
|
|
|
columnSizeMap={columnSizeMap}
|
|
|
|
|
columns={columns}
|
|
|
|
|
compactMode={compactMode}
|
|
|
|
|
data={tableData}
|
2021-08-18 10:33:26 +00:00
|
|
|
delimiter={delimiter}
|
2021-04-28 10:28:39 +00:00
|
|
|
disableDrag={() => {
|
2021-05-03 18:42:21 +00:00
|
|
|
disableDrag(true);
|
2021-04-28 10:28:39 +00:00
|
|
|
}}
|
2021-05-03 18:42:21 +00:00
|
|
|
editMode={editMode}
|
2021-04-28 10:28:39 +00:00
|
|
|
enableDrag={() => {
|
2021-05-03 18:42:21 +00:00
|
|
|
disableDrag(false);
|
2021-04-28 10:28:39 +00:00
|
|
|
}}
|
2021-05-03 18:42:21 +00:00
|
|
|
filters={filters}
|
|
|
|
|
handleResizeColumn={handleResizeColumn}
|
|
|
|
|
height={height}
|
|
|
|
|
isLoading={isLoading}
|
2021-05-11 07:32:58 +00:00
|
|
|
isVisibleDownload={isVisibleDownload}
|
|
|
|
|
isVisibleFilters={isVisibleFilters}
|
|
|
|
|
isVisiblePagination={isVisiblePagination}
|
|
|
|
|
isVisibleSearch={isVisibleSearch}
|
2021-07-07 05:52:10 +00:00
|
|
|
multiRowSelection={multiRowSelection}
|
2021-05-11 06:55:42 +00:00
|
|
|
nextPageClick={nextPageClick}
|
2021-05-03 18:42:21 +00:00
|
|
|
pageNo={pageNo - 1}
|
|
|
|
|
pageSize={pageSize || 1}
|
2021-05-11 06:55:42 +00:00
|
|
|
prevPageClick={prevPageClick}
|
2021-05-03 18:42:21 +00:00
|
|
|
searchKey={searchKey}
|
|
|
|
|
searchTableData={searchTableData}
|
2021-04-28 10:28:39 +00:00
|
|
|
selectTableRow={selectTableRow}
|
2021-05-03 18:42:21 +00:00
|
|
|
selectedRowIndex={selectedRowIndex}
|
|
|
|
|
selectedRowIndices={selectedRowIndices}
|
|
|
|
|
serverSidePaginationEnabled={serverSidePaginationEnabled}
|
2021-04-28 10:28:39 +00:00
|
|
|
sortTableColumn={sortTableColumn}
|
2021-07-07 05:52:10 +00:00
|
|
|
toggleAllRowSelect={toggleAllRowSelect}
|
2021-08-30 09:24:59 +00:00
|
|
|
totalRecordsCount={totalRecordsCount}
|
2021-05-03 18:42:21 +00:00
|
|
|
triggerRowSelection={triggerRowSelection}
|
|
|
|
|
updatePageNo={updatePageNo}
|
|
|
|
|
widgetId={widgetId}
|
|
|
|
|
widgetName={widgetName}
|
|
|
|
|
width={width}
|
2020-07-14 07:55:46 +00:00
|
|
|
/>
|
|
|
|
|
);
|
2021-04-28 10:28:39 +00:00
|
|
|
}
|
2020-06-03 10:50:10 +00:00
|
|
|
|
2021-05-04 06:51:08 +00:00
|
|
|
export default React.memo(ReactTableComponent, (prev, next) => {
|
|
|
|
|
return (
|
|
|
|
|
prev.applyFilter === next.applyFilter &&
|
|
|
|
|
prev.compactMode === next.compactMode &&
|
2021-08-18 10:33:26 +00:00
|
|
|
prev.delimiter === next.delimiter &&
|
2021-05-04 06:51:08 +00:00
|
|
|
prev.disableDrag === next.disableDrag &&
|
|
|
|
|
prev.editMode === next.editMode &&
|
|
|
|
|
prev.filters === next.filters &&
|
|
|
|
|
prev.handleReorderColumn === next.handleReorderColumn &&
|
|
|
|
|
prev.handleResizeColumn === next.handleResizeColumn &&
|
|
|
|
|
prev.height === next.height &&
|
|
|
|
|
prev.isLoading === next.isLoading &&
|
2021-05-11 07:32:58 +00:00
|
|
|
prev.isVisibleDownload === next.isVisibleDownload &&
|
|
|
|
|
prev.isVisibleFilters === next.isVisibleFilters &&
|
|
|
|
|
prev.isVisiblePagination === next.isVisiblePagination &&
|
|
|
|
|
prev.isVisibleSearch === next.isVisibleSearch &&
|
2021-05-04 06:51:08 +00:00
|
|
|
prev.nextPageClick === next.nextPageClick &&
|
|
|
|
|
prev.onRowClick === next.onRowClick &&
|
|
|
|
|
prev.pageNo === next.pageNo &&
|
|
|
|
|
prev.pageSize === next.pageSize &&
|
|
|
|
|
prev.prevPageClick === next.prevPageClick &&
|
|
|
|
|
prev.searchKey === next.searchKey &&
|
|
|
|
|
prev.searchTableData === next.searchTableData &&
|
|
|
|
|
prev.selectedRowIndex === next.selectedRowIndex &&
|
|
|
|
|
prev.selectedRowIndices === next.selectedRowIndices &&
|
|
|
|
|
prev.serverSidePaginationEnabled === next.serverSidePaginationEnabled &&
|
|
|
|
|
prev.sortTableColumn === next.sortTableColumn &&
|
2021-08-30 09:24:59 +00:00
|
|
|
prev.totalRecordsCount === next.totalRecordsCount &&
|
2021-05-04 06:51:08 +00:00
|
|
|
prev.triggerRowSelection === next.triggerRowSelection &&
|
|
|
|
|
prev.updatePageNo === next.updatePageNo &&
|
|
|
|
|
prev.widgetId === next.widgetId &&
|
|
|
|
|
prev.widgetName === next.widgetName &&
|
|
|
|
|
prev.width === next.width &&
|
2021-05-13 12:08:15 +00:00
|
|
|
isEqual(prev.columnSizeMap, next.columnSizeMap) &&
|
2021-05-11 06:55:42 +00:00
|
|
|
isEqual(prev.tableData, next.tableData) &&
|
2021-05-13 12:08:15 +00:00
|
|
|
// Using JSON stringify becuase isEqual doesnt work with functions,
|
|
|
|
|
// and we are not changing the columns manually.
|
|
|
|
|
JSON.stringify(prev.columns) === JSON.stringify(next.columns)
|
2021-05-04 06:51:08 +00:00
|
|
|
);
|
|
|
|
|
});
|