/* QQQ - Low-code Application Framework for Engineers. * Copyright (C) 2021-2022. Kingsrook, LLC * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States * contact@kingsrook.com * https://github.com/Kingsrook/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ import {tooltipClasses, TooltipProps} from "@mui/material"; import Autocomplete from "@mui/material/Autocomplete"; import Icon from "@mui/material/Icon"; import {styled} from "@mui/material/styles"; import Table from "@mui/material/Table"; import TableBody from "@mui/material/TableBody"; import TableContainer from "@mui/material/TableContainer"; import TableRow from "@mui/material/TableRow"; import Tooltip from "@mui/material/Tooltip"; import parse from "html-react-parser"; import {useEffect, useMemo, useState} from "react"; import {useAsyncDebounce, useGlobalFilter, usePagination, useSortBy, useTable} from "react-table"; import DataTableBodyCell from "qqq/components/Temporary/DataTable/DataTableBodyCell"; import DataTableHeadCell from "qqq/components/Temporary/DataTable/DataTableHeadCell"; import DefaultCell from "qqq/components/Temporary/DefaultCell"; import MDBox from "qqq/components/Temporary/MDBox"; import MDInput from "qqq/components/Temporary/MDInput"; import MDPagination from "qqq/components/Temporary/MDPagination"; import MDTypography from "qqq/components/Temporary/MDTypography"; import ImageCell from "qqq/pages/dashboards/Tables/ImageCell"; export interface TableDataInput { columns: { [key: string]: any }[]; rows: { [key: string]: any }[]; } interface Props { entriesPerPage?: | false | { defaultValue: number; entries: number[]; }; canSearch?: boolean; showTotalEntries?: boolean; table: TableDataInput; pagination?: { variant: "contained" | "gradient"; color: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "dark" | "light"; }; isSorted?: boolean; noEndBorder?: boolean; } const NoMaxWidthTooltip = styled(({className, ...props}: TooltipProps) => ( ))({ [`& .${tooltipClasses.tooltip}`]: { maxWidth: "none", textAlign: "left" }, }); function DataTable({ entriesPerPage, canSearch, showTotalEntries, table, pagination, isSorted, noEndBorder, }: Props): JSX.Element { let defaultValue: any; let entries: any[]; if (entriesPerPage) { defaultValue = entriesPerPage.defaultValue ? entriesPerPage.defaultValue : "10"; entries = entriesPerPage.entries ? entriesPerPage.entries : ["10", "25", "50", "100"]; } const columns = useMemo(() => table.columns, [table]); const data = useMemo(() => table.rows, [table]); if (!columns || !data) { return null; } const tableInstance = useTable( {columns, data, initialState: {pageIndex: 0}}, useGlobalFilter, useSortBy, usePagination ); const { getTableProps, getTableBodyProps, headerGroups, prepareRow, rows, page, pageOptions, canPreviousPage, canNextPage, gotoPage, nextPage, previousPage, setPageSize, setGlobalFilter, state: {pageIndex, pageSize, globalFilter}, }: any = tableInstance; // Set the default value for the entries per page when component mounts useEffect(() => setPageSize(defaultValue || 10), [defaultValue]); // Set the entries per page value based on the select value const setEntriesPerPage = (value: any) => setPageSize(value); // Render the paginations const renderPagination = pageOptions.map((option: any) => ( gotoPage(Number(option))} active={pageIndex === option} > {option + 1} )); // Handler for the input to set the pagination index const handleInputPagination = ({target: {value}}: any) => value > pageOptions.length || value < 0 ? gotoPage(0) : gotoPage(Number(value)); // Customized page options starting from 1 const customizedPageOptions = pageOptions.map((option: any) => option + 1); // Setting value for the pagination input const handleInputPaginationValue = ({target: value}: any) => gotoPage(Number(value.value - 1)); // Search input value state const [search, setSearch] = useState(globalFilter); // Search input state handle const onSearchChange = useAsyncDebounce((value) => { setGlobalFilter(value || undefined); }, 100); // A function that sets the sorted value for the table const setSortedValue = (column: any) => { let sortedValue; if (isSorted && column.isSorted) { sortedValue = column.isSortedDesc ? "desc" : "asce"; } else if (isSorted) { sortedValue = "none"; } else { sortedValue = false; } return sortedValue; }; // Setting the entries starting point const entriesStart = pageIndex === 0 ? pageIndex + 1 : pageIndex * pageSize + 1; // Setting the entries ending point let entriesEnd; if (pageIndex === 0) { entriesEnd = pageSize; } else if (pageIndex === pageOptions.length - 1) { entriesEnd = rows.length; } else { entriesEnd = pageSize * (pageIndex + 1); } return ( {entriesPerPage || canSearch ? ( {entriesPerPage && ( { setEntriesPerPage(parseInt(newValue, 10)); }} size="small" sx={{width: "5rem"}} renderInput={(params) => } />   entries per page )} {canSearch && ( { setSearch(search); onSearchChange(currentTarget.value); }} /> )} ) : null} {headerGroups.map((headerGroup: any, i: number) => ( {headerGroup.headers.map((column: any) => ( column.type !== "hidden" && ( {column.render("header")} ) ))} ))} {page.map((row: any, key: any) => { prepareRow(row); return ( {row.cells.map((cell: any) => ( cell.column.type !== "hidden" && ( { cell.column.type === "default" && ( cell.value && "number" === typeof cell.value ? ( {cell.value.toLocaleString()} ) : ({cell.render("Cell")}) ) } { cell.column.type === "htmlAndTooltip" && ( {parse(cell.value)} ) } { cell.column.type === "html" && ( {parse(cell.value)} ) } { cell.column.type === "image" && row.values["imageTotal"] && ( ) } { cell.column.type === "image" && !row.values["imageTotal"] && ( ) } ) ))} ); })}
{showTotalEntries && ( Showing {entriesStart} to {entriesEnd} of {rows.length} entries )} {pageOptions.length > 1 && ( {canPreviousPage && ( previousPage()}> chevron_left )} {renderPagination.length > 6 ? ( { handleInputPagination(event); handleInputPaginationValue(event); }} /> ) : ( renderPagination )} {canNextPage && ( nextPage()}> chevron_right )} )}
); } // Declaring default props for DataTable DataTable.defaultProps = { entriesPerPage: {defaultValue: 10, entries: ["5", "10", "15", "20", "25"]}, canSearch: false, showTotalEntries: true, pagination: {variant: "gradient", color: "info"}, isSorted: true, noEndBorder: false, }; export default DataTable;