PromucFlow_constructor/app/client/src/components/designSystems/appsmith/ReactTableComponent.tsx

336 lines
10 KiB
TypeScript
Raw Normal View History

import React, { useEffect } from "react";
2020-06-03 10:50:10 +00:00
import { ColumnAction } from "components/propertyControls/ColumnActionSelectorControl";
import Table from "components/designSystems/appsmith/Table";
import { debounce } from "lodash";
import { getMenuOptions } from "components/designSystems/appsmith/TableUtilities";
import {
ColumnTypes,
CompactMode,
ReactTableColumnProps,
ReactTableFilter,
} from "widgets/TableWidget";
2020-06-03 10:50:10 +00:00
export interface ColumnMenuOptionProps {
content: string | JSX.Element;
closeOnClick?: boolean;
isSelected?: boolean;
editColumnName?: boolean;
2020-06-03 10:50:10 +00:00
columnAccessor?: string;
id?: string;
category?: boolean;
options?: ColumnMenuSubOptionProps[];
onClick?: (columnIndex: number, isSelected: boolean) => void;
2020-06-03 10:50:10 +00:00
}
export interface ColumnMenuSubOptionProps {
content: string | JSX.Element;
isSelected?: boolean;
closeOnClick?: boolean;
onClick?: (columnIndex: number) => void;
id?: string;
category?: boolean;
2020-06-03 10:50:10 +00:00
}
interface ReactTableComponentProps {
widgetId: string;
widgetName: string;
searchKey: string;
2020-06-03 10:50:10 +00:00
isDisabled?: boolean;
isVisible?: boolean;
isLoading: boolean;
editMode: boolean;
2020-06-03 10:50:10 +00:00
width: number;
height: number;
pageSize: number;
tableData: object[];
columnOrder?: string[];
disableDrag: (disable: boolean) => void;
onRowClick: (rowData: object, rowIndex: number) => void;
onCommandClick: (dynamicTrigger: string, onComplete: () => void) => void;
2020-06-03 10:50:10 +00:00
updatePageNo: Function;
updateHiddenColumns: (hiddenColumns?: string[]) => void;
sortTableColumn: (column: string, asc: boolean) => void;
2020-06-03 10:50:10 +00:00
nextPageClick: Function;
prevPageClick: Function;
pageNo: number;
serverSidePaginationEnabled: boolean;
columnActions?: ColumnAction[];
selectedRowIndex: number;
selectedRowIndices: number[];
multiRowSelection?: boolean;
2020-06-03 10:50:10 +00:00
hiddenColumns?: string[];
columnNameMap?: { [key: string]: string };
columnTypeMap?: {
[key: string]: {
type: string;
format: string;
inputFormat?: string;
2020-06-03 10:50:10 +00:00
};
};
columnSizeMap?: { [key: string]: number };
updateColumnType: Function;
updateColumnName: Function;
handleResizeColumn: Function;
handleReorderColumn: Function;
searchTableData: (searchKey: any) => void;
filters?: ReactTableFilter[];
applyFilter: (filters: ReactTableFilter[]) => void;
columns: ReactTableColumnProps[];
compactMode?: CompactMode;
updateCompactMode: (compactMode: CompactMode) => void;
2020-06-03 10:50:10 +00:00
}
const ReactTableComponent = (props: ReactTableComponentProps) => {
useEffect(() => {
let dragged = -1;
const headers = Array.prototype.slice.call(
document.querySelectorAll(`#table${props.widgetId} .draggable-header`),
);
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
}
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
}
e.preventDefault();
};
2020-06-03 10:50:10 +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();
let columnOrder = props.columnOrder;
if (columnOrder === undefined) {
columnOrder = props.columns.map(item => item.accessor);
}
const draggedColumn = props.columns[dragged].accessor;
columnOrder.splice(dragged, 1);
columnOrder.splice(i, 0, draggedColumn);
props.handleReorderColumn(columnOrder);
} else {
dragged = -1;
}
};
});
});
const getColumnMenu = (columnIndex: number) => {
const column = props.columns[columnIndex];
const columnId = column.accessor;
const columnType =
props.columnTypeMap && props.columnTypeMap[columnId]
? props.columnTypeMap[columnId].type
: "";
const format =
props.columnTypeMap && props.columnTypeMap[columnId]
? props.columnTypeMap[columnId].format
: "";
const inputFormat =
props.columnTypeMap && props.columnTypeMap[columnId]
? props.columnTypeMap[columnId].inputFormat
: "";
2020-06-03 10:50:10 +00:00
const isColumnHidden = !!(
props.hiddenColumns && props.hiddenColumns.includes(columnId)
2020-06-03 10:50:10 +00:00
);
const columnMenuOptions: ColumnMenuOptionProps[] = getMenuOptions({
columnAccessor: columnId,
isColumnHidden,
columnType,
format,
inputFormat,
hideColumn: hideColumn,
updateColumnType: updateColumnType,
handleUpdateCurrencySymbol: handleUpdateCurrencySymbol,
handleDateFormatUpdate: handleDateFormatUpdate,
2020-06-03 10:50:10 +00:00
});
return columnMenuOptions;
};
const hideColumn = (columnIndex: number, isColumnHidden: boolean) => {
const column = props.columns[columnIndex];
let hiddenColumns = props.hiddenColumns || [];
2020-06-03 10:50:10 +00:00
if (!isColumnHidden) {
hiddenColumns.push(column.accessor);
const columnOrder = props.columnOrder || [];
2020-06-03 10:50:10 +00:00
if (columnOrder.includes(column.accessor)) {
columnOrder.splice(columnOrder.indexOf(column.accessor), 1);
props.handleReorderColumn(columnOrder);
2020-06-03 10:50:10 +00:00
}
} else {
hiddenColumns = hiddenColumns.filter(item => {
return item !== column.accessor;
});
}
props.updateHiddenColumns(hiddenColumns);
2020-06-03 10:50:10 +00:00
};
const updateColumnType = (columnIndex: number, columnType: string) => {
const column = props.columns[columnIndex];
const columnTypeMap = props.columnTypeMap || {};
2020-06-03 10:50:10 +00:00
columnTypeMap[column.accessor] = {
type: columnType,
format: "",
};
props.updateColumnType(columnTypeMap);
2020-06-03 10:50:10 +00:00
};
const handleColumnNameUpdate = (columnIndex: number, columnName: string) => {
const column = props.columns[columnIndex];
const columnNameMap = props.columnNameMap || {};
2020-06-03 10:50:10 +00:00
columnNameMap[column.accessor] = columnName;
props.updateColumnName(columnNameMap);
2020-06-03 10:50:10 +00:00
};
const handleUpdateCurrencySymbol = (
columnIndex: number,
currencySymbol: string,
) => {
const column = props.columns[columnIndex];
const columnTypeMap = props.columnTypeMap || {};
2020-06-03 10:50:10 +00:00
columnTypeMap[column.accessor] = {
type: "currency",
format: currencySymbol,
};
props.updateColumnType(columnTypeMap);
2020-06-03 10:50:10 +00:00
};
const handleDateFormatUpdate = (
columnIndex: number,
dateFormat: string,
dateInputFormat?: string,
) => {
const column = props.columns[columnIndex];
const columnTypeMap = props.columnTypeMap || {};
2020-06-03 10:50:10 +00:00
columnTypeMap[column.accessor] = {
type: "date",
format: dateFormat,
};
if (dateInputFormat) {
columnTypeMap[column.accessor].inputFormat = dateInputFormat;
}
props.updateColumnType(columnTypeMap);
2020-06-03 10:50:10 +00:00
};
const sortTableColumn = (columnIndex: number, asc: boolean) => {
if (columnIndex === -1) {
props.sortTableColumn("", asc);
} else {
const column = props.columns[columnIndex];
const columnType = column.metaProperties?.type || ColumnTypes.TEXT;
if (
columnType !== ColumnTypes.IMAGE &&
columnType !== ColumnTypes.VIDEO
) {
props.sortTableColumn(column.accessor, asc);
}
}
};
const handleResizeColumn = (columnIndex: number, columnWidth: string) => {
const column = props.columns[columnIndex];
const columnSizeMap = props.columnSizeMap || {};
2020-06-03 10:50:10 +00:00
const width = Number(columnWidth.split("px")[0]);
columnSizeMap[column.accessor] = width;
props.handleResizeColumn(columnSizeMap);
2020-06-03 10:50:10 +00:00
};
const selectTableRow = (
2020-06-03 10:50:10 +00:00
row: { original: object; index: number },
isSelected: boolean,
) => {
if (!isSelected || !!props.multiRowSelection) {
props.onRowClick(row.original, row.index);
2020-06-03 10:50:10 +00:00
}
};
return (
<Table
isLoading={props.isLoading}
width={props.width}
height={props.height}
pageSize={props.pageSize || 1}
widgetId={props.widgetId}
widgetName={props.widgetName}
searchKey={props.searchKey}
columns={props.columns}
hiddenColumns={props.hiddenColumns}
updateHiddenColumns={props.updateHiddenColumns}
data={props.tableData}
editMode={props.editMode}
columnNameMap={props.columnNameMap}
getColumnMenu={getColumnMenu}
handleColumnNameUpdate={handleColumnNameUpdate}
handleResizeColumn={debounce(handleResizeColumn, 300)}
sortTableColumn={sortTableColumn}
selectTableRow={selectTableRow}
pageNo={props.pageNo - 1}
updatePageNo={props.updatePageNo}
columnActions={props.columnActions}
nextPageClick={() => {
props.nextPageClick();
}}
prevPageClick={() => {
props.prevPageClick();
}}
serverSidePaginationEnabled={props.serverSidePaginationEnabled}
selectedRowIndex={props.selectedRowIndex}
selectedRowIndices={props.selectedRowIndices}
disableDrag={() => {
props.disableDrag(true);
}}
enableDrag={() => {
props.disableDrag(false);
}}
searchTableData={props.searchTableData}
filters={props.filters}
applyFilter={props.applyFilter}
compactMode={props.compactMode}
updateCompactMode={props.updateCompactMode}
/>
);
};
2020-06-03 10:50:10 +00:00
export default ReactTableComponent;