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 = (
el && (el.indeterminate = this.props.isIndeterminate) } onChange={this.props.onSelectionClick} />
); if (config.hasLevels) { thColumnClassNameArray.push('mmui-pl-3'); } } else if (config.hasLevels) { thColumnClassNameArray.push('mmui-pl-3'); } if (config.isNumeric || config.isMetric) { thClassNameArray.push('text-right'); nameClassNameArray.push('mmui-th-metric'); } if (config.hasTooltip) { toolTipElement = } if (config.hasFilter) { thClassNameArray.push('mmui-refiner'); const filterIconStyleArray = ['fa', 'fa-filter']; if (this.state.isFiltered) { filterIconStyleArray.push('background-core-brand-blue-90'); filterIconStyleArray.push('color-neutral-white'); } refinerBtnElmt = ( ); } const hasTranformOrder = transforms.order && transforms.order.column === config.columnName; if (this.props.preSort || hasTranformOrder) { let orderMethod = this.props.preSort; if (transforms.order && transforms.order.method) { orderMethod = transforms.order.method; } classNameArray.push('active'); if (orderMethod == 'ASC') { sortSymbol = ; } else { sortSymbol = ; } orderUrl = orderUrl + `&order_method=${orderMethod}`; } /** * Set the filterPanelComponent based on the config.dataType. */ if (config.hasFilter && config.dataType) { let isExtentEmpty = false; if (data && data.extent) { isExtentEmpty = (data.extent != undefined && data.extent?.length == 0) || (data.extent?.length == 1 && data.extent[0] == ''); } switch (config.dataType) { case 'datetime': filterPanelComponent = ( ); break; case 'categorical': if (isExtentEmpty) { refinerBtnElmt = null; } filterPanelComponent = ( ); break; case 'choice': if (isExtentEmpty) { refinerBtnElmt = null; } filterPanelComponent = ( ); break; case 'numerical': filterPanelComponent = ( ); break; default: if (isExtentEmpty) { refinerBtnElmt = null; } filterPanelComponent = ( ); break; } } if (config.isSortable) { nameElmt = ( ); } else { nameElmt =
{config.name}
; } filterPanelComponentStyle.display = this.state.filterPanelMode === 'open' ? 'block' : 'none'; if (this.state.filterPanelLayout.align == 'right') { filterPanelComponentStyle.right = 0; } else { filterPanelComponentStyle.left = 0; } return (
{selectionElmt} {refinerBtnElmt} {nameElmt} {toolTipElement} {sortSymbol}
{filterPanelComponent}
); } }