import * as React from 'react'; import { getParentElmtByClassName, getRelativeBoundingClientRect, } from '../../../mmui-util'; import { RefinerProps, RefinerState } from './utils'; import { ColumnNumericalRefinerComponent } from './ColumnNumericalRefinerComponent'; import { ColumnCategoricalRefinerComponent } from './ColumnCategoricalRefinerComponent'; import { ColumnDateRefinerComponent } from './ColumnDateRefinerComponent'; import { ColumnChoiceRefinerComponent } from './ColumnChoiceRefinerComponent'; /** * Column Head Component to add sorting and filter functionality to table columns. * This Component */ export class ColumnHeadComponent extends React.Component< RefinerProps, RefinerState > { hasRowLevels; private static id_counter = 0; protected id; /** * Generate a unique id for this component instance */ protected getId(): number { if (this.id === undefined) { this.id = ColumnHeadComponent.id_counter; ColumnHeadComponent.id_counter++; } return this.id; } constructor(props) { super(props); this.hasRowLevels = false; if (props.hasRowLevels) { this.hasRowLevels = true; } this.state = { id: 'mmui_column_head_' + this.getId(), filterPanelMode: 'closed', isFiltered: false, filterPanelLayout: { align: 'right' }, }; } setIsFiltered = (isFiltered: boolean) => { this.setState({ isFiltered }); }; /** * Handles clicks to change the sort order of the column. * @param evt */ handleSortOrderChange(evt) { evt.preventDefault(); let config = this.props.config, transforms = this.props.transforms, orderColumn = config.columnName == 'pivot' ? config.rowKey : config.columnName, orderMethod = 'ASC'; if (transforms.order) { if (transforms.order.column === orderColumn) { orderMethod = transforms.order.method === 'ASC' ? 'DESC' : 'ASC'; } } else if (this.props.preSort === 'ASC') { orderMethod = 'DESC'; } transforms.order = { column: orderColumn, method: orderMethod, ignoreCase: config.orderIgnoreCase ? true : false, emptyLocation: config.orderEmptyLocation, }; this.props.setTransforms(transforms); } /** * Handles clicks to toggle the visibility of the filter panel. * @param evt */ handlePanelBtnClick(evt) { // let config = this.props.config, // transforms = this.props.transforms, // panels = transforms.panels, // filterPanel = panels[config.columnName], // value = evt.target.value // ; evt.preventDefault(); let parentElmt = getParentElmtByClassName( evt.currentTarget, 'table-responsive' ); if (parentElmt === undefined || parentElmt === null) { parentElmt = getParentElmtByClassName( evt.currentTarget, 'mmui-table' ); } const filterPanelLayout = { align: 'left' }; if (parentElmt) { const childRect = evt.currentTarget.getBoundingClientRect(); const parentRect = parentElmt.getBoundingClientRect(); const relativeRect = getRelativeBoundingClientRect( childRect, parentRect ); if (Math.abs(relativeRect.left) > Math.abs(relativeRect.right)) { filterPanelLayout.align = 'right'; } } let filterPanelMode = this.state.filterPanelMode; if (filterPanelMode === undefined || filterPanelMode === 'closed') { filterPanelMode = 'open'; } else { filterPanelMode = 'closed'; } this.setState({ filterPanelMode: filterPanelMode, filterPanelLayout: filterPanelLayout, }); // transforms.panels[config.columnName] = filterPanel; // this.props.setTransforms(transforms); } onBlur = () => { if (this.state.filterPanelMode === 'open') { let elmt = event.target as HTMLElement, isFilterPanelClick = false; while (elmt) { isFilterPanelClick = isFilterPanelClick || elmt.id === this.state.id; if (isFilterPanelClick) { break; } elmt = elmt.parentElement; } if (!isFilterPanelClick) { this.setState({ filterPanelMode: 'closed' }); } } }; componentDidMount(): void { document.addEventListener('click', this.onBlur); } componentWillUnmount(): void { document.removeEventListener('click', this.onBlur); } /** * Render Column Head Component */ render() { let classNameArray = [], thClassNameArray = [], thColumnClassNameArray = ['mmui-th-column'], nameClassNameArray = [], nameElmt = null, sortSymbol = null, selectionElmt, refinerBtnElmt, toolTipElement, filterPanelComponent = null, config = this.props.config, data = this.props.data, transforms = this.props.transforms, orderUrl = `?order_column=${config.columnName}`, filterBtnStyle: any = {}, filterPanelComponentStyle: any = { display: 'none' }; if (this.props.isSelectionColumn) { selectionElmt = (