import React, { useCallback, useMemo } from "react"; import { flexRender, useReactTable, getCoreRowModel, getSortedRowModel, getFilteredRowModel, ColumnDef, createColumnHelper, ColumnFiltersState, Column, FilterFn, Table as TanstackTable, FilterFns, getFacetedRowModel, getFacetedUniqueValues, Row, } from "@tanstack/react-table"; import Col from "react-bootstrap/Col"; import Table from "react-bootstrap/Table"; import { useTranslation } from "react-i18next"; import { // aiFillOffline, // aiFillOnline, notApplicableIcons, OfflineText, OnlineText, } from "../../../utils/Legends/legends"; import { useSelector } from "react-redux"; import { IRootState } from "../../../store"; import { IServerStatusCount, ICompleteServerStatus, IStatusTable, IServer, } from "../HomeSlice"; import jsonp from "jsonpath"; import "./Tables.scss"; import { RankingInfo, rankItem } from "@tanstack/match-sorter-utils"; import { useVirtualizer, useWindowVirtualizer } from "@tanstack/react-virtual"; declare module "@tanstack/table-core" { interface FilterFns { fuzzy: FilterFn; } interface FilterMeta { itemRank: RankingInfo; } } const fuzzyFilter: FilterFn = (row, columnId, value, addMeta) => { const itemRank = rankItem(row.getValue(columnId), value); addMeta({ itemRank, }); return itemRank.passed; }; export const Tables: React.FC<{ region: string; dc: string }> = ({ region, dc, }) => { const { t } = useTranslation(); const { tables, columns: originalColumns, boldColumns, } = useSelector( (state) => state.home.completeServerStatus ); const { tables: serverStatusCountTables } = useSelector< IRootState, IServerStatusCount >((state) => state.home.serverStatusCount); const filteredColumns: string[] = useMemo(() => { if (region === "all") return originalColumns; return originalColumns.filter( (column) => !["Region", "DC"].includes(column) ); }, [originalColumns, region]); const components: { [key: string]: { online: number; offline: number } } = useMemo(() => { let retVal: { [key: string]: { online: number; offline: number } } = {}; if (region === "all") { for (let column of Object.keys(serverStatusCountTables[0].components)) { const totalOnlineCount: number = jsonp .query(serverStatusCountTables, `$..components['${column}'].online`) .reduce((acc: number, val: number) => acc + val); const totalOfflineCount: number = jsonp .query( serverStatusCountTables, `$..components['${column}'].offline` ) .reduce((acc: number, val: number) => acc + val); retVal[column] = { online: totalOnlineCount, offline: totalOfflineCount, }; } } else { retVal = serverStatusCountTables.find( ({ region: tableRegion, dc: tableDC }) => tableRegion === region && tableDC === dc )?.components!; } return retVal; }, [region, dc, serverStatusCountTables]); // let allServers: IServer[] = useMemo(() => { // if (region === "all") { // return jsonp.query(tables, "$..servers[*]"); // } else { // const theTable: IStatusTable = tables.find( // ({ region: tableRegion, dc: tableDC }) => // region === tableRegion && dc === tableDC // )!; // return theTable.products![0].servers; // } // }, [tables, region, dc]); let allServers: IServer[]; if (region?.toLowerCase() === "all") { allServers = jsonp.query(tables, "$..servers[*]"); } else { const theTable: IStatusTable = tables.find( ({ region: tableRegion, dc: tableDC }) => region === tableRegion && dc === tableDC )!; allServers = theTable.products![0].servers; } const data: IServer[] = allServers; const columnHelper = createColumnHelper(); const returnIcon = useCallback((status: any): React.ReactNode => { if (typeof status === "object" && status !== null) { return <>; } if (!status) { return notApplicableIcons; } switch (status?.toString().toLowerCase()) { case "online": return ; case "offline": return ; default: return {status}; } }, []); // const returnIcon = (status: any): React.ReactNode => { // if (status !== null && typeof status === typeof {}) { // return <>; // } // if (!status) { // return notApplicableIcons; // } // switch (status?.toString().toLowerCase()) { // case "online": // return ; // case "offline": // return ; // default: // return {status}; // } // }; const columnSwitch = useCallback( (column: string): boolean => { return boldColumns.indexOf(column) > -1; }, [boldColumns] ); // const columnSwitch = (column: string) => boldColumns.indexOf(column) > -1; const columns: ColumnDef[] = useMemo(() => { return filteredColumns.map((column) => columnHelper.accessor((row) => row[column], { id: column, header: () => column, cell: (info) => { const value = info.getValue(); let returnData = columnSwitch(column) ? (

{typeof value === "object" && value !== null ? "" : value}

) : (
{returnIcon(value)}
); return
{returnData}
; }, enableColumnFilter: "Customer Name" === column, // enableGlobalFilter: allowFilteringColumns.includes(column), }) ); }, [filteredColumns, columnHelper, returnIcon, columnSwitch]); const [columnFilters, setColumnFilters] = React.useState( [] ); const table: TanstackTable = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), getFilteredRowModel: getFilteredRowModel(), onColumnFiltersChange: setColumnFilters, getFacetedRowModel: getFacetedRowModel(), getFacetedUniqueValues: getFacetedUniqueValues(), enableColumnFilters: true, state: { columnFilters }, filterFns: { fuzzy: fuzzyFilter }, }); const { rows } = table.getRowModel(); const parentRef = React.useRef(null); const virtualizer = useWindowVirtualizer({ count: rows.length, estimateSize: () => 9, overscan: 5, scrollMargin: parentRef.current?.offsetTop ?? 0, }); return (
{columns.length === 0 ? ( {t("noTableDataAvailable")} ) : (
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( ))} ))} {virtualizer.getVirtualItems().map((virtualRow, index) => { const row = rows[virtualRow.index] as Row; return ( {row.getVisibleCells().map((cell) => { return ( ); })} ); })}
{flexRender( header.column.columnDef.header, header.getContext() )} {header.column.getCanFilter() ? (
) : null}
{flexRender( cell.column.columnDef.cell, cell.getContext() )}
)}
); }; function Filter({ column, table, }: { column: Column; table: TanstackTable; }) { // const firstValue = table // .getPreFilteredRowModel() // .flatRows[0]?.getValue(column.id); const columnFilterValue = column.getFilterValue(); const facetedUniqValues = column.getFacetedUniqueValues(); const sortedUniqueValues = useMemo( () => Array.from(facetedUniqValues.keys()).sort(), [facetedUniqValues] ); return ( <> {sortedUniqueValues.map((value: any) => ( {/* column.setFilterValue(value)} placeholder={`Search... (${column.getFacetedUniqueValues().size})`} className="w-36 border rounded" list={column.id + "list"} /> */}
); } // A debounced input react component function DebouncedInput({ value: initialValue, onChange, debounce = 500, ...props }: { value: string | number; onChange: (value: string | number) => void; debounce?: number; } & Omit, "onChange">) { const [value, setValue] = React.useState(initialValue); React.useEffect(() => { setValue(initialValue); }, [initialValue]); React.useEffect(() => { const timeout = setTimeout(() => { onChange(value); }, debounce); return () => clearTimeout(timeout); }, [value, debounce, onChange]); return ( setValue(e.target.value)} /> ); }