import React from 'react'; import { SvgIcon, Button, Menu, Divider, ListItemIcon, MenuItem } from '@mui/material'; import { DataColumnFix, DataSortType } from '../types/column.type'; import { DataTableHeadCell } from './head.cell'; import { DataColumnExtra, TableContext, TableMessages } from '../types/table.type'; import { DataTableFilters } from './filters'; import { ExternalFilter, FiltersStore } from '../types/filter.type'; import { FilterPopover, TableHeader, TableHeaderFixedCell, TableHeadFixedContent, TableHeadRow } from './style'; import { NoData, QueryRequest } from '../../services'; import { Data } from './filter.data'; import { IconColor } from '../types/style.types'; const cache = { timer: NoData as NodeJS.Timeout } interface DataColumn extends DataColumnExtra { sticky?: number, } export interface DataTableHeadProps { tableRef: any, context: TableContext, messages: TableMessages, onRestore: () => void, onFiltersChange: (query: QueryRequest) => void children?: React.ReactNode | React.ReactNode[] | any } export const DataTableHead: React.FC = ({ tableRef, context, messages, onRestore, onFiltersChange }) => { const headRef = React.useRef(); const [updated, setUpdated] = React.useState(false); const [filtersOpen, setFiltersOpen] = React.useState(false); const [forceUpdate, setForceUpdate] = React.useState(false); const [menuAnchor, setMenuAnchor] = React.useState(null); context.forceUpdateHead = () => { setForceUpdate(!forceUpdate); } const handleHeadersResize = React.useCallback(() => { clearTimeout(cache.timer); cache.timer = setTimeout(() => { context.forceUpdateHead(); }, 200) }, []); React.useEffect(() => { window.addEventListener("resize", handleHeadersResize); return () => { window.removeEventListener("resize", handleHeadersResize, true); }; }) React.useEffect(() => { sortColumns(context.columns); setUpdated(false); }, [context.columns]) const sortColumns = (columns: DataColumn[]) => { const contextColumns = [...columns]; columns.splice(0, columns.length); if (contextColumns) { let left = 0; let right = 0; for (let c = 0; c < contextColumns.length; c++) { const column = contextColumns[c]; switch (column.fix) { case 'left': { columns.splice(left, 0, column); left++ } break; case 'right': { columns.push(column); right++ } break; default: { columns.splice(columns.length - right, 0, column); } break; } } if (headRef && headRef.current) { const children = headRef.current['children'] as any[]; if (children) { if ((columns.length + 2) !== children.length) { if (!updated) { setTimeout(() => setUpdated(true)) } } else { let left = 0; for (let c = 1; c < children.length - 1 && columns[c - 1].fix === 'left'; c++) { const child = children[c]; const column = columns[c - 1]; if (!column.hidden) { column.sticky = left; left += child.clientWidth; } } let right = 0; for (let c = children.length - 2; c >= 1 && columns[c - 1].fix === 'right'; c--) { const child = children[c]; const column = columns[c - 1]; if (!column.hidden) { column.sticky = right; right += child.clientWidth; } } } } } } context.forceUpdateHead(); context.forceUpdateBody(); } const handleFixChange = (column: DataColumn) => (fix: DataColumnFix) => { column.fix = fix; sortColumns(context.columns); } const handleSortChange = (column: DataColumn) => (sort: DataSortType) => { if (context.paginator) { context.paginator.currentPage = 1; } context.columns.forEach(c => { if (c !== column) { delete c.sort; } }) column.sort = sort; context.forceUpdateHead(); onFiltersChange(Data.createQueryRequest(context)); } const handleHiddenChange = (column: DataColumn) => (hidden: boolean) => { column.hidden = hidden; sortColumns(context.columns); } const handleOpenMenu = (event: React.MouseEvent) => { setMenuAnchor(event.currentTarget); } const handleCloseMenu = () => { setMenuAnchor(null); } const handleShow = (column: DataColumn) => { handleHiddenChange(column)(false); sortColumns(context.columns); setMenuAnchor(null); } const handleRestore = () => { if (onRestore) { onRestore(); sortColumns(context.columns); } setMenuAnchor(null); } const handleFiltersChange = (filters: FiltersStore) => { context.filters = filters; context.forceUpdateHead(); } const handleExternalFilterChange = (filter: ExternalFilter) => { context.externalFilter = filter; context.forceUpdateHead(); } const handleApplyFilters = () => { if (context.paginator) { context.paginator.currentPage = 1; } onFiltersChange(Data.createQueryRequest(context)); setFiltersOpen(false); } const handleFiltersClose = () => { setFiltersOpen(false); } const hiddenColumns = context.columns.filter(c => !!c.hidden) return ( { context.columns.map(column => ( !column.hidden && 0} onFixChange={handleFixChange(column)} onSortChange={handleSortChange(column)} onHiddenChange={handleHiddenChange(column)}> )) } { (context.externalFilter || (context.filters && Object.keys(context.filters).length > 0)) && } placement="left" onClose={handleFiltersClose}> } { hiddenColumns && hiddenColumns.map(column => ( handleShow(column)} key={column.name}> { column.label } )) } { hiddenColumns && hiddenColumns.length > 0 && } {messages.headers.restore} ) } const MenuIcon = () => ( ) const ShowIcon = () => ( ) const RestoreIcon = () => ( ) const SearchIcon = ({ color }: { color: IconColor }) => ( )