import * as classNames from 'classnames'; import { Iterable } from 'ix'; import * as React from 'react'; import { Logging } from '../../../Utils'; import { ItemsPresenter } from '../Items/ItemsPresenter'; import { PanelFragment, PanelItemContext } from '../Panel/Panel'; import { BootstrapTableProps, TablePanel } from '../Panel/TablePanel'; import { GridViewColumn, GridViewColumns } from './GridViewColumn'; import { ListItemsViewTemplate, ListItemsViewTemplateProps, } from './ListItemsViewTemplate'; import { PanelView } from './PanelView'; export interface GridTemplateProps { headerTemplate?: ( header: PanelFragment, item: T | undefined, field: string | undefined, ) => PanelFragment; cellTemplate?: ( cell: PanelFragment, item: T | undefined, field: string | undefined, ) => PanelFragment; } export interface GridTableRenderProps extends BootstrapTableProps { fixedLayout?: boolean; } export interface GridViewProps< T = {}, TContext extends PanelItemContext = PanelItemContext > extends GridTemplateProps, ListItemsViewTemplateProps, GridTableRenderProps {} export interface GridViewComponentProps extends React.HTMLProps, GridViewProps {} export class GridView extends ListItemsViewTemplate { public static displayName = 'GridView'; public static readonly Columns = GridViewColumns; private readonly logger: Logging.Logger = Logging.getLogger( GridView.displayName, ); private columns: React.ReactChild[] | undefined; constructor(props: any) { super(props); this.renderTablePanel = this.renderTablePanel.bind(this); } render() { const { className, children, props, rest } = this.restProps(x => { const { headerTemplate, cellTemplate, bordered, condensed, hover, responsive, striped, bsClass, fixedLayout, listItems, itemsProps, } = x; return { headerTemplate, cellTemplate, bordered, condensed, hover, responsive, striped, bsClass, fixedLayout, listItems, itemsProps, }; }); this.columns = this.getColumnDefinitions(); if (this.columns == null) { return null; } const gridProps = this.getItemsProps(); gridProps.itemsPanelTemplate = gridProps.itemsPanelTemplate || this.renderTablePanel.bind(this); gridProps.itemTemplate = gridProps.itemTemplate || this.renderTableRow.bind(this); return ( {children} ); } protected renderTablePanel( itemTemplates: React.ReactNode[], itemsPresenter: ItemsPresenter, items: Array<{}> | undefined, ) { const { props } = this.restProps(x => { const { bordered, condensed, hover, responsive, striped, bsClass, fixedLayout, } = x; return { bordered, condensed, hover, responsive, striped, bsClass, fixedLayout, }; }); return ( {itemTemplates} ); } protected getColumnDefinitions(): React.ReactChild[] | undefined { const count = React.Children.count(this.props.children); if (count === 0) { // try and auto-gen columns const item = this.getListItems() .getItems() .first(); if (item == null) { this.logger.warn('Unable to Autogenerate Columns'); return undefined; } return Iterable.from(Object.keys(item)) .orderBy(x => x) .map(x => ) .toArray(); } if (count === 1) { const elem = React.Children.only(this.props.children); if (React.isType(elem, GridViewColumns)) { return React.Children.toArray(elem.props.children); } } return React.Children.toArray(this.props.children); } protected renderTableHeaderRow() { if (this.columns == null) { return undefined; } const renderHeaders = Iterable.from(this.columns).some(x => GridViewColumn.canRenderHeader(x), ); if (renderHeaders) { const props = this.trimProps({ itemTemplate: this.props.headerTemplate, }); return ( {this.columns.map(x => { if (React.isValidElement(x)) { return ; } return ''; })} ); } return undefined; } protected renderTableRow(item: {}, index: number) { const columns = this.getColumnDefinitions(); const props = this.trimProps({ item, itemTemplate: this.props.cellTemplate, }); return columns == null ? undefined : this.renderListItem( {columns.map(x => { if (React.isValidElement(x)) { return ; } return ''; })} , item, PanelView.getSelectedProps, ); } }