From a3417b58b4842645033ac1fed8c41cb7b4bc4b6e Mon Sep 17 00:00:00 2001 From: Aleksandr Gumroian Date: Mon, 4 Nov 2024 22:27:21 +0100 Subject: [PATCH] Add RichTable component with header, body, and pagination --- src/common/RichTable/RichTable.js | 70 +++++++++++++ src/common/RichTable/RichTableBody.js | 39 +++++++ src/common/RichTable/RichTableHeader.js | 86 +++++++++++++++ src/common/RichTable/RichTablePagination.js | 109 ++++++++++++++++++++ src/index.js | 1 + 5 files changed, 305 insertions(+) create mode 100644 src/common/RichTable/RichTable.js create mode 100644 src/common/RichTable/RichTableBody.js create mode 100644 src/common/RichTable/RichTableHeader.js create mode 100644 src/common/RichTable/RichTablePagination.js diff --git a/src/common/RichTable/RichTable.js b/src/common/RichTable/RichTable.js new file mode 100644 index 0000000..258ef87 --- /dev/null +++ b/src/common/RichTable/RichTable.js @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/) + * + * This is free software, licensed under the GNU General Public License v3. + * See /LICENSE for more information. + */ + +import React, { useMemo, useState } from "react"; + +import { + flexRender, + getCoreRowModel, + getSortedRowModel, + getPaginationRowModel, + useReactTable, +} from "@tanstack/react-table"; + +import RichTableBody from "./RichTableBody"; +import RichTableHeader from "./RichTableHeader"; +import RichTablePagination from "./RichTablePagination"; + +const fallbackData = []; + +const RichTable = ({ + columns, + data, + withPagination, + pageSize = 5, + pageIndex = 0, +}) => { + const tableColumns = useMemo(() => columns, []); + const [tableData, _] = useState(data ?? fallbackData); + const [sorting, setSorting] = useState([]); + const [pagination, setPagination] = useState({ + pageIndex, + pageSize, + }); + + const table = useReactTable({ + data: tableData, + columns: tableColumns, + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: getSortedRowModel(), + getPaginationRowModel: getPaginationRowModel(), + onPaginationChange: setPagination, + onSortingChange: setSorting, + state: { + sorting, + pagination, + }, + }); + + return ( +
+ + + +
+ {withPagination && ( + + )} +
+ ); +}; + +export default RichTable; diff --git a/src/common/RichTable/RichTableBody.js b/src/common/RichTable/RichTableBody.js new file mode 100644 index 0000000..97f6f48 --- /dev/null +++ b/src/common/RichTable/RichTableBody.js @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/) + * + * This is free software, licensed under the GNU General Public License v3. + * See /LICENSE for more information. + */ + +import React from "react"; + +const RichTableBody = ({ table, flexRender }) => { + return ( + + {table.getRowModel().rows.map((row) => { + return ( + + {row.getVisibleCells().map((cell) => { + return ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext() + )} + + ); + })} + + ); + })} + + ); +}; + +export default RichTableBody; diff --git a/src/common/RichTable/RichTableHeader.js b/src/common/RichTable/RichTableHeader.js new file mode 100644 index 0000000..feb204e --- /dev/null +++ b/src/common/RichTable/RichTableHeader.js @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/) + * + * This is free software, licensed under the GNU General Public License v3. + * See /LICENSE for more information. + */ + +import React from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + faSquareCaretUp, + faSquareCaretDown, +} from "@fortawesome/free-solid-svg-icons"; + +const RichTableHeader = ({ table, flexRender }) => { + const getThTitle = (header) => + header.column.getCanSort() + ? header.column.getNextSortingOrder() === "asc" + ? _("Sort ascending") + : header.column.getNextSortingOrder() === "desc" + ? _("Sort descending") + : _("Clear sort") + : undefined; + + return ( + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + + {header.isPlaceholder || + header.column.columnDef.headerIsHidden ? ( + + ) : ( + + )} + + ))} + + ))} + + ); +}; + +export default RichTableHeader; diff --git a/src/common/RichTable/RichTablePagination.js b/src/common/RichTable/RichTablePagination.js new file mode 100644 index 0000000..c0a5ace --- /dev/null +++ b/src/common/RichTable/RichTablePagination.js @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/) + * + * This is free software, licensed under the GNU General Public License v3. + * See /LICENSE for more information. + */ + +import React, { useMemo } from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + faAngleLeft, + faAnglesLeft, + faAngleRight, + faAnglesRight, +} from "@fortawesome/free-solid-svg-icons"; + +const RichTablePagination = ({ table, tablePageSize, allRows }) => { + const { pagination } = table.getState(); + const prevPagBtnDisabled = !table.getCanPreviousPage(); + const nextPagBtnDisabled = !table.getCanNextPage(); + + const pageSizes = useMemo(() => { + return [tablePageSize ?? 5, 10, 25].filter( + (value, index, self) => self.indexOf(value) === index + ); + }, [tablePageSize]); + + const renderPaginationButton = (icon, ariaLabel, onClick, disabled) => ( +
  • + +
  • + ); + + return ( + + ); +}; + +export default RichTablePagination; diff --git a/src/index.js b/src/index.js index 4e7839f..8052fb1 100644 --- a/src/index.js +++ b/src/index.js @@ -43,6 +43,7 @@ export { Modal, ModalBody, ModalFooter, ModalHeader } from "./bootstrap/Modal"; export { default as RebootButton } from "./common/RebootButton"; export { default as WiFiSettings } from "./common/WiFiSettings/WiFiSettings"; export { default as ResetWiFiSettings } from "./common/WiFiSettings/ResetWiFiSettings"; +export { default as RichTable } from "./common/RichTable/RichTable"; // Form export { default as ForisForm } from "./form/components/ForisForm"; export {