diff --git a/ui/v2.5/src/components/List/Pagination.tsx b/ui/v2.5/src/components/List/Pagination.tsx
index 47d59e6cbe0..acca41f28a2 100644
--- a/ui/v2.5/src/components/List/Pagination.tsx
+++ b/ui/v2.5/src/components/List/Pagination.tsx
@@ -1,6 +1,132 @@
-import React from "react";
-import { Button, ButtonGroup } from "react-bootstrap";
-import { FormattedMessage, FormattedNumber, useIntl } from "react-intl";
+import React, { useEffect, useMemo, useRef, useState } from "react";
+import {
+ Button,
+ ButtonGroup,
+ Dropdown,
+ Form,
+ InputGroup,
+ Overlay,
+ Popover,
+} from "react-bootstrap";
+import { FormattedMessage, useIntl } from "react-intl";
+import useFocus from "src/utils/focus";
+import { Icon } from "../Shared/Icon";
+import { faCheck, faChevronDown } from "@fortawesome/free-solid-svg-icons";
+
+const PageCount: React.FC<{
+ totalPages: number;
+ currentPage: number;
+ onChangePage: (page: number) => void;
+}> = ({ totalPages, currentPage, onChangePage }) => {
+ const intl = useIntl();
+
+ const currentPageCtrl = useRef(null);
+
+ const [pageInput, pageFocus] = useFocus();
+
+ const [showSelectPage, setShowSelectPage] = useState(false);
+
+ useEffect(() => {
+ if (showSelectPage) {
+ pageFocus();
+ }
+ }, [showSelectPage, pageFocus]);
+
+ const pageOptions = useMemo(() => {
+ const maxPagesToShow = 10;
+ const min = Math.max(1, currentPage - maxPagesToShow / 2);
+ const max = Math.min(min + maxPagesToShow, totalPages);
+ const pages = [];
+ for (let i = min; i <= max; i++) {
+ pages.push(i);
+ }
+ return pages;
+ }, [totalPages, currentPage]);
+
+ function onCustomChangePage() {
+ const newPage = Number.parseInt(pageInput.current?.value ?? "0");
+ if (newPage) {
+ onChangePage(newPage);
+ }
+ setShowSelectPage(false);
+ }
+
+ return (
+
+
+
+
+
+
+
+
+ {pageOptions.map((s) => (
+ onChangePage(s)}
+ >
+ {s}
+
+ ))}
+
+
+
+
setShowSelectPage(false)}
+ >
+
+
+
+
+
+ );
+};
interface IPaginationProps {
itemsPerPage: number;
@@ -23,91 +149,55 @@ export const Pagination: React.FC = ({
totalItems,
onChangePage,
}) => {
- const totalPages = Math.ceil(totalItems / itemsPerPage);
-
- let startPage: number;
- let endPage: number;
- if (totalPages <= 10) {
- // less than 10 total pages so show all
- startPage = 1;
- endPage = totalPages;
- } else if (currentPage <= 6) {
- startPage = 1;
- endPage = 10;
- } else if (currentPage + 4 >= totalPages) {
- startPage = totalPages - 9;
- endPage = totalPages;
- } else {
- startPage = currentPage - 5;
- endPage = currentPage + 4;
- }
+ const intl = useIntl();
- const pages = [...Array(endPage + 1 - startPage).keys()].map(
- (i) => startPage + i
+ const totalPages = useMemo(
+ () => Math.ceil(totalItems / itemsPerPage),
+ [totalItems, itemsPerPage]
);
- const calculatePageClass = (buttonPage: number) => {
- if (pages.length <= 4) return "";
-
- if (currentPage === 1 && buttonPage <= 4) return "";
- const maxPage = pages[pages.length - 1];
- if (currentPage === maxPage && buttonPage > maxPage - 3) return "";
- if (Math.abs(buttonPage - currentPage) <= 1) return "";
- return "d-none d-sm-block";
- };
-
- const pageButtons = pages.map((page: number) => (
-
- ));
-
- if (pages.length <= 1) return ;
+ if (totalPages <= 1) return ;
return (
-
+
- {pageButtons}
+
+
+
);
diff --git a/ui/v2.5/src/components/List/styles.scss b/ui/v2.5/src/components/List/styles.scss
index f67b5b8b33d..1c8d993a309 100644
--- a/ui/v2.5/src/components/List/styles.scss
+++ b/ui/v2.5/src/components/List/styles.scss
@@ -7,14 +7,27 @@
padding-right: 15px;
transition: none;
+ &.page-count {
+ padding-right: 5px;
+ }
+
+ &.page-count-dropdown {
+ padding-left: 5px;
+ }
+
&:first-child {
border-left: none;
+ border-right: none;
}
&:last-child {
border-right: none;
}
}
+
+ .page-count-container .btn {
+ border-radius: 0;
+ }
}
.center-text {
diff --git a/ui/v2.5/src/index.scss b/ui/v2.5/src/index.scss
index 73cc4da01e9..2e9587f9632 100755
--- a/ui/v2.5/src/index.scss
+++ b/ui/v2.5/src/index.scss
@@ -713,7 +713,8 @@ div.dropdown-menu {
}
.filter-container,
-.operation-container {
+.operation-container,
+.pagination {
align-items: center;
display: flex;
justify-content: center;
@@ -1330,6 +1331,11 @@ $detailTabWidth: calc(100% / 3);
border-top-right-radius: 0;
}
+.btn-group > .dropdown:not(:first-child) > .btn {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+}
+
dl.details-list {
display: grid;
grid-column-gap: 10px;
diff --git a/ui/v2.5/src/locales/en-GB.json b/ui/v2.5/src/locales/en-GB.json
index 55d834b3c0e..76d573fefd0 100644
--- a/ui/v2.5/src/locales/en-GB.json
+++ b/ui/v2.5/src/locales/en-GB.json
@@ -1160,6 +1160,7 @@
"version": "Version"
},
"pagination": {
+ "current_total": "{current} of {total}",
"first": "First",
"last": "Last",
"next": "Next",