import React from 'react'; import { groupBy } from 'lodash'; import { Table, TableHeader, TableBody, TableFooter, TableRow, TableHeaderCell, TableCell } from '../elements'; import { FlexTable } from '../..'; // // Supporting functions // ---------------------------------------------------------------------- // - Check headers const columnHasHeader = (child: FlexTable.ColumnType): boolean => child.props.headerClass || child.props.headerText ? true : false; const hasAnyColumnHeaders = (children: FlexTable.ColumnType[]): boolean => children && children.some((child: FlexTable.ColumnType) => columnHasHeader(child)); // - Get headers const getColumnHeader = (child: FlexTable.ColumnType, index: number) => { const { hideHeader, ...props } = child.props; return !hideHeader && }; const getColumnHeaders = (children: FlexTable.ColumnType[]) => ( { React.Children.map(children, (child, index: number) => { const element = child as FlexTable.ColumnType; return getColumnHeader(element, index); }) } ); // - Rendering const renderBody = (items: T[], children: React.ReactElement[], itemRenderer: FlexTable.RowRenderer = renderRow, grouping: FlexTable.Groupable, row: FlexTable.RowProps, ) => { if (grouping.groupOn) { const groupedItems = groupBy(items, grouping.groupOn); return Object.keys(groupedItems).map((group) => { const dataRows = renderGroup(groupedItems[group], children, row, itemRenderer, "group_" + group + "_"); const groupHeader = grouping.groupHeader ? grouping.groupHeader(groupedItems[group]) : group return [ {groupHeader} , dataRows ]; }); } else { return renderGroup(items, children, row, itemRenderer, ""); } } // Render rows that are grouped together. const renderGroup = (items: object[], children: React.ReactElement[], row: FlexTable.RowProps, itemRenderer: FlexTable.RowRenderer, key: any) => { return items.map((item, index) => React.cloneElement(itemRenderer(item, children, row, () => renderRow(item, children, row)), { key: key + index }) ); } /** * Default row render * @param item * @param columns * @param rowClassName */ const renderRow = (item: object, columns: React.ReactElement[], row: FlexTable.RowProps) => { const rowOnClick = row.onClick != undefined ? () => { row.onClick && row.onClick(item) } : undefined; return ( { React.Children.map(columns, (child, index: number) => { const column = child as React.ReactElement; return React.cloneElement(column, { key: index, item }); }) } ); } // // Components // ---------------------------------------------------------------------- /** * DataTable component pass in a collection of data * via the items property, and then define columns * for that data using some of our other provided components * such as BoundColumn! * * @param items any[] the tables data set. * @param header Feader render function. * @param footer Footer render function. */ export const DataTable = (props: FlexTable.DataTableProps) => { const { items, children, className, header, footer, footerClassName, itemRenderer, groupOn, groupHeader, row, ...attrs } = props; if (items) { const columns = Array.isArray(children) ? children as FlexTable.ColumnType[] : [children] as FlexTable.ColumnType[]; const renderColumnHeaders = hasAnyColumnHeaders(columns); const renderHeader = header !== false && (header || renderColumnHeaders); const renderFooter = !!footer; const grouping = { groupOn, groupHeader }; const rowProps = row || {}; return ( <> {renderHeader && {header && header(items)} {renderColumnHeaders && getColumnHeaders(columns)} } {renderBody(items, columns, itemRenderer, grouping, rowProps)} {renderFooter && {footer && footer(items)} }
); } else { return null; } };