import React from 'react'; import { Checkbox, TableBody } from '@mui/material'; import { DataColumnExtra, TableContext, TableMessages } from '../types/table.type'; import { TableBodyFixedCell, TableBodyFixedContent, TableBodyRow, TableBodyRowHeight, TableBodySummaryFixedCell, TableBodySummaryFixedContent, TableBodySummaryRow } from './style'; import { DataTableBodyCell } from './body.cell'; import { guid } from 'sync-ql'; import { DataRow } from '../types/body.type'; import { DataTableBodySummary } from './body.summary'; interface DataColumn extends DataColumnExtra { sticky?: number, } export interface DataTableBodyProps { tableRef: any, context: TableContext, messages: TableMessages, selectable: boolean, virtualization?: { from: number, to: number }, onDataChange: (column: DataColumn, row: DataRow, value: any) => void } export const DataTableBody: React.FC = ({ tableRef, context, messages, selectable, virtualization, onDataChange }) => { const bodyRef = React.useRef(); const [forceUpdate, setForceUpdate] = React.useState(false); const [selectedRow, setSelectedRow] = React.useState(''); context.forceUpdateBody = () => { setForceUpdate(!forceUpdate); } const getStyle = (column: DataColumn) => { const result: React.CSSProperties = {}; if (column) { if (column.width) { result.width = column.width; } if (column.minWidth) { result.minWidth = column.minWidth; } if (column.maxWidth) { result.maxWidth = column.maxWidth; } if (column.fix === 'left') { result.left = column.sticky ? column.sticky + 40 : 40; result.zIndex = 1000; result.position = 'sticky'; result.backgroundImage = 'linear-gradient(rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.05))'; } if (column.fix === 'right') { result.right = column.sticky ? column.sticky + 40 : 40; result.zIndex = 1000; result.position = 'sticky'; result.backgroundImage = 'linear-gradient(rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.05))'; } } return result; } const getCellStyle = (column: DataColumn) => { if (column) { const result = getStyle(column); if (column.cell && column.cell.style) { Object.keys(column.cell.style).forEach((k: any) => { (result as any)[k] = (column as any).cell.style[k] }) } return result; } return {} as React.CSSProperties; } const getSummaryStyle = (column: DataColumn) => { if (column) { const result = getCellStyle(column); if (column.summary && column.summary.style) { Object.keys(column.summary.style).forEach(k => { (result as any)[k] = (column as any).summary.style[k] }) } return result; } return {} as React.CSSProperties; } const getCellAlign = (column: DataColumn) => { return column.cell && column.cell.align ? column.cell.align : column.align; } const getSummaryAlign = (column: DataColumn) => { return column.summary && column.summary.align ? column.summary.align : getCellAlign(column); } const handleChange = (column: DataColumn, row: DataRow) => (value: any) => { onDataChange(column, row, value) } const handleEditting = (column: DataColumn, row: DataRow) => (value: boolean) => { if (row) { (context as any).editting.row = value ? row[''] : ''; (context as any).editting.column = value ? column.name : ''; context.forceUpdateBody(); } } const handleSelectionChange = (row: DataRow) => (event: React.ChangeEvent) => { const value = event.target.checked; if (value) { context.selection = { [(row as any)['']]: row } context.forceUpdateToolbar(); setSelectedRow((row as any)['']); } else { context.selection = {} context.forceUpdateToolbar(); setSelectedRow('') } } const getVirtualization = () => { const pageSize = !!virtualization ? 1000 : context.paginator.pageSize; const currentPage = context.paginator.currentPage; if (context.data && context.data.rows && pageSize > 0) { const startLimit = Math.min( context.data.rows.length, (currentPage - 1) * pageSize ); const endLimit = Math.min( context.data.rows.length, (currentPage) * pageSize ); const start = Math.min( context.data.rows.length, virtualization ? virtualization.from + startLimit : startLimit ); const end = Math.min( context.data.rows.length, virtualization ? Math.min(virtualization.to + startLimit, endLimit) : endLimit ); const top = !!virtualization && start > startLimit ? Math.max(0, TableBodyRowHeight * (start - startLimit)) : 0; const bottom = !!virtualization && end < endLimit ? TableBodyRowHeight * (endLimit - end) : 0; const height = tableRef && tableRef.current ? tableRef.current.clientHeight - TableBodyRowHeight - (context.hasSummary ? TableBodyRowHeight : 0) : 0 return { top, start, end, bottom: Math.max(bottom, height - (top + (end - start) * TableBodyRowHeight + bottom)), spacer: tableRef && tableRef.current } } return null; } const getCell = (row: DataRow, column: DataColumnExtra, index: number) => { const value = row[column.name]; const modification = context.modifications[(row as any)['']]; const modified = modification && modification.original && modification.changed && modification.original[column.name] !== modification.changed[column.name]; const editting = row[''] === context.editting.row && column.name === context.editting.column; return ( !column.hidden && ) } const getRows = () => { const result: React.ReactNode[] = []; const virtualization = getVirtualization(); if (!!virtualization) { result.push( { !!virtualization && virtualization.top > 0 &&
} ) for (let i = virtualization.start; i < virtualization.end; i++) { const index = i - virtualization.start + 1; const row = i < context.data.rows.length && context.data.rows[i] ? !context.data.rows[i][''] ? context.data.rows[i] = { ...context.data.rows[i], ['']: guid() } : context.data.rows[i] : null; result.push( '] : `row-${index}`} ref={bodyRef}> { !!selectable && ']} onChange={row ? handleSelectionChange(row) : () => { }} /> } { row && context.columns.map((column) => getCell(row, column, i)) } ) } result.push( { !!virtualization && virtualization.bottom > 0 &&
} ) } return result; } return ( {getRows()} { context.hasSummary && context.data && context.data.rows && context.data.rows.length > 0 && { context.columns.map((column) => ( !column.hidden && )) } } ) }