1
0
mirror of https://gitlab.nic.cz/turris/reforis/foris-js.git synced 2025-05-05 09:40:54 +02:00

Compare commits

..

No commits in common. "0a839bf3690343b3d7045349c538d938a548db91" and "377b4279fd451a2b45434567882aeac0d9357a1d" have entirely different histories.

8 changed files with 44 additions and 226 deletions

36
package-lock.json generated
View File

@ -13,7 +13,6 @@
"@fortawesome/free-regular-svg-icons": "^6.7.2", "@fortawesome/free-regular-svg-icons": "^6.7.2",
"@fortawesome/free-solid-svg-icons": "^6.7.2", "@fortawesome/free-solid-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "^0.2.2", "@fortawesome/react-fontawesome": "^0.2.2",
"@tanstack/match-sorter-utils": "^8.19.4",
"@tanstack/react-table": "^8.21.2", "@tanstack/react-table": "^8.21.2",
"axios": "^1.7.9", "axios": "^1.7.9",
"immutability-helper": "^3.1.1", "immutability-helper": "^3.1.1",
@ -3385,22 +3384,6 @@
"@sinonjs/commons": "^3.0.0" "@sinonjs/commons": "^3.0.0"
} }
}, },
"node_modules/@tanstack/match-sorter-utils": {
"version": "8.19.4",
"resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.19.4.tgz",
"integrity": "sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==",
"license": "MIT",
"dependencies": {
"remove-accents": "0.5.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/react-table": { "node_modules/@tanstack/react-table": {
"version": "8.21.2", "version": "8.21.2",
"resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.2.tgz", "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.2.tgz",
@ -15882,12 +15865,6 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/remove-accents": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz",
"integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==",
"license": "MIT"
},
"node_modules/repeat-string": { "node_modules/repeat-string": {
"version": "1.6.1", "version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
@ -20916,14 +20893,6 @@
"@sinonjs/commons": "^3.0.0" "@sinonjs/commons": "^3.0.0"
} }
}, },
"@tanstack/match-sorter-utils": {
"version": "8.19.4",
"resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.19.4.tgz",
"integrity": "sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==",
"requires": {
"remove-accents": "0.5.0"
}
},
"@tanstack/react-table": { "@tanstack/react-table": {
"version": "8.21.2", "version": "8.21.2",
"resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.2.tgz", "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.2.tgz",
@ -30224,11 +30193,6 @@
"mdast-util-to-markdown": "^0.6.0" "mdast-util-to-markdown": "^0.6.0"
} }
}, },
"remove-accents": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz",
"integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A=="
},
"repeat-string": { "repeat-string": {
"version": "1.6.1", "version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",

View File

@ -18,7 +18,6 @@
"@fortawesome/free-regular-svg-icons": "^6.7.2", "@fortawesome/free-regular-svg-icons": "^6.7.2",
"@fortawesome/free-solid-svg-icons": "^6.7.2", "@fortawesome/free-solid-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "^0.2.2", "@fortawesome/react-fontawesome": "^0.2.2",
"@tanstack/match-sorter-utils": "^8.19.4",
"@tanstack/react-table": "^8.21.2", "@tanstack/react-table": "^8.21.2",
"axios": "^1.7.9", "axios": "^1.7.9",
"immutability-helper": "^3.1.1", "immutability-helper": "^3.1.1",
@ -71,4 +70,4 @@
"docs": "npx styleguidist build ", "docs": "npx styleguidist build ",
"docs:watch": "styleguidist server" "docs:watch": "styleguidist server"
} }
} }

View File

@ -34,14 +34,12 @@ const Input = forwardRef(
return ( return (
<div className="mb-3"> <div className="mb-3">
{label && ( <label
<label className={`form-label ${labelClassName || ""}`.trim()}
className={`form-label ${labelClassName || ""}`.trim()} htmlFor={uid}
htmlFor={uid} >
> {label}
{label} </label>
</label>
)}
<div className={`input-group ${groupClassName || ""}`.trim()}> <div className={`input-group ${groupClassName || ""}`.trim()}>
<input <input
className={`form-control ${inputClassName}`.trim()} className={`form-control ${inputClassName}`.trim()}
@ -67,7 +65,7 @@ Input.displayName = "Input";
Input.propTypes = { Input.propTypes = {
type: PropTypes.string.isRequired, type: PropTypes.string.isRequired,
label: PropTypes.string, label: PropTypes.string.isRequired,
helpText: PropTypes.string, helpText: PropTypes.string,
error: PropTypes.string, error: PropTypes.string,
className: PropTypes.string, className: PropTypes.string,

View File

@ -7,22 +7,18 @@
import React, { useMemo, useState } from "react"; import React, { useMemo, useState } from "react";
import { rankItem } from "@tanstack/match-sorter-utils";
import { import {
flexRender, flexRender,
getCoreRowModel, getCoreRowModel,
getSortedRowModel, getSortedRowModel,
getFilteredRowModel,
getPaginationRowModel, getPaginationRowModel,
useReactTable, useReactTable,
} from "@tanstack/react-table"; } from "@tanstack/react-table";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import RichTableBody from "./RichTableBody"; import RichTableBody from "./RichTableBody";
import RichTableColumnsDropdown from "./RichTableColumnsDropdown";
import RichTableHeader from "./RichTableHeader"; import RichTableHeader from "./RichTableHeader";
import RichTablePagination from "./RichTablePagination"; import RichTablePagination from "./RichTablePagination";
import Input from "../../bootstrap/Input";
RichTable.propTypes = { RichTable.propTypes = {
/** Columns to be displayed in the table */ /** Columns to be displayed in the table */
@ -50,69 +46,36 @@ export default function RichTable({
pageIndex, pageIndex,
pageSize, pageSize,
}); });
const [globalFilter, setGlobalFilter] = useState("");
const [columnVisibility, setColumnVisibility] = useState({});
const table = useReactTable({ const table = useReactTable({
data, data,
columns: tableColumns, columns: tableColumns,
filterFns: {
fuzzy: fuzzyFilter,
},
globalFilterFn: "fuzzy",
getCoreRowModel: getCoreRowModel(), getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(), getSortedRowModel: getSortedRowModel(),
getPaginationRowModel: getPaginationRowModel(), getPaginationRowModel: getPaginationRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onSortingChange: setSorting,
onPaginationChange: setPagination, onPaginationChange: setPagination,
onGlobalFilterChange: setGlobalFilter, onSortingChange: setSorting,
onColumnVisibilityChange: setColumnVisibility,
state: { state: {
sorting, sorting,
pagination, pagination,
globalFilter,
columnVisibility,
}, },
}); });
const paginationIsNeeded = data.length > pageSize && withPagination; const paginationIsNeeded = data.length > pageSize && withPagination;
return ( return (
<div> <div className="table-responsive">
<div className="d-flex justify-content-between align-items-center"> <table className="table table-hover text-nowrap">
<Input <RichTableHeader table={table} flexRender={flexRender} />
className="me-3" <RichTableBody table={table} flexRender={flexRender} />
type="text" </table>
placeholder={_("Search…")} {paginationIsNeeded && (
value={globalFilter ?? ""} <RichTablePagination
onChange={(e) => setGlobalFilter(String(e.target.value))} table={table}
tablePageSize={pageSize}
allRows={data.length}
/> />
<RichTableColumnsDropdown columns={table.getAllLeafColumns()} /> )}
</div>
<div className="table-responsive">
<table className="table table-hover text-nowrap">
<RichTableHeader table={table} flexRender={flexRender} />
<RichTableBody
table={table}
columns={tableColumns}
flexRender={flexRender}
/>
</table>
{paginationIsNeeded && (
<RichTablePagination
table={table}
tablePageSize={pageSize}
allRows={data.length}
/>
)}
</div>
</div> </div>
); );
} }
function fuzzyFilter(row, columnId, value, addMeta) {
const itemRank = rankItem(row.getValue(columnId), value);
addMeta({ itemRank });
return itemRank.passed;
}

View File

@ -13,44 +13,34 @@ RichTableBody.propTypes = {
table: propTypes.shape({ table: propTypes.shape({
getRowModel: propTypes.func.isRequired, getRowModel: propTypes.func.isRequired,
}).isRequired, }).isRequired,
columns: propTypes.array.isRequired,
flexRender: propTypes.func.isRequired, flexRender: propTypes.func.isRequired,
}; };
function RichTableBody({ table, columns, flexRender }) { function RichTableBody({ table, flexRender }) {
return ( return (
<tbody> <tbody>
{table.getRowModel().rows?.length ? ( {table.getRowModel().rows.map((row) => {
table.getRowModel().rows.map((row) => { return (
return ( <tr key={row.id} className="align-middle">
<tr key={row.id} className="align-middle"> {row.getVisibleCells().map((cell) => {
{row.getVisibleCells().map((cell) => { return (
return ( <td
<td key={cell.id}
key={cell.id} {...(cell.column.columnDef.className && {
{...(cell.column.columnDef className:
.className && { cell.column.columnDef.className,
className: })}
cell.column.columnDef.className, >
})} {flexRender(
> cell.column.columnDef.cell,
{flexRender( cell.getContext()
cell.column.columnDef.cell, )}
cell.getContext() </td>
)} );
</td> })}
); </tr>
})} );
</tr> })}
);
})
) : (
<tr>
<td colSpan={columns.length} className="text-center py-4">
<span>{_("No results.")}</span>
</td>
</tr>
)}
</tbody> </tbody>
); );
} }

View File

@ -1,90 +0,0 @@
/*
* Copyright (C) 2019-2025 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 { faCheck, faRotateLeft } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import PropTypes from "prop-types";
import Button from "../../bootstrap/Button";
RichTableColumnsDropdown.propTypes = {
columns: PropTypes.array.isRequired,
};
function RichTableColumnsDropdown({ columns }) {
return (
<div className="dropdown mb-3">
<Button
className="btn btn-outline-secondary dropdown-toggle"
data-bs-toggle="dropdown"
>
{_("Columns")}
</Button>
<ul className="dropdown-menu dropdown-menu-end">
{columns.map((column) => {
return (
<li key={column.id}>
<button
type="button"
className="dropdown-item d-flex align-items-center"
onClick={column.getToggleVisibilityHandler()}
style={{ paddingLeft: "2rem" }}
disabled={
column.columnDef?.enableHiding === false
}
>
{column.getIsVisible() && (
<FontAwesomeIcon
icon={faCheck}
className="position-absolute text-secondary me-2"
style={{ left: "0.6rem" }}
width="1rem"
/>
)}
<span>{column.columnDef.header}</span>
</button>
</li>
);
})}
{columns.some((column) => !column.getIsVisible()) && (
<>
<li>
<hr className="dropdown-divider" />
</li>
<li>
<button
type="button"
className="dropdown-item d-flex align-items-center"
style={{ paddingLeft: "2rem" }}
onClick={() => {
// toggleVisibility for columns that are hidden
columns.forEach((column) => {
if (!column.getIsVisible()) {
column.toggleVisibility();
}
});
}}
>
<FontAwesomeIcon
icon={faRotateLeft}
className="position-absolute text-secondary me-2"
width="1rem"
style={{ left: "0.6rem" }}
/>
{_("Reset")}
</button>
</li>
</>
)}
</ul>
</div>
);
}
export default RichTableColumnsDropdown;

View File

@ -55,12 +55,6 @@ function RichTableHeader({ table, flexRender }) {
) : ( ) : (
<button <button
type="button" type="button"
style={
header.column.columnDef
.headerClassName === "text-center"
? { justifySelf: "center" }
: {}
}
className={`btn btn-link text-decoration-none text-reset fw-bold p-0 d-flex align-items-center className={`btn btn-link text-decoration-none text-reset fw-bold p-0 d-flex align-items-center
${ ${
header.column.getCanSort() header.column.getCanSort()

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2019-2025 CZ.NIC z.s.p.o. (https://www.nic.cz/) * 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. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.