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.
0a839bf369
...
377b4279fd
36
package-lock.json
generated
36
package-lock.json
generated
@ -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",
|
||||||
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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,
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
@ -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()
|
||||||
|
@ -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.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user