- {intl.formatMessage(messages.showingresults, {
- from: pageIndex * 10,
- to:
- data.results.length < 10
- ? pageIndex * 10 + data.results.length
- : (pageIndex + 1) * 10,
- total: data.pageInfo.results,
- strong: function strong(msg) {
- return {msg};
- },
- })}
+ {data.results.length > 0 &&
+ intl.formatMessage(messages.showingresults, {
+ from: pageIndex * currentPageSize + 1,
+ to:
+ data.results.length < currentPageSize
+ ? pageIndex * currentPageSize + data.results.length
+ : (pageIndex + 1) * currentPageSize,
+ total: data.pageInfo.results,
+ strong: function strong(msg) {
+ return {msg};
+ },
+ })}
-
-
+
+
+ {intl.formatMessage(messages.resultsperpage, {
+ pageSize: (
+
+ ),
+ })}
+
+
+
{errors.port && touched.port && (
diff --git a/src/components/Settings/SonarrModal/index.tsx b/src/components/Settings/SonarrModal/index.tsx
index 7c03d4234..c95b2124c 100644
--- a/src/components/Settings/SonarrModal/index.tsx
+++ b/src/components/Settings/SonarrModal/index.tsx
@@ -431,7 +431,7 @@ const SonarrModal: React.FC = ({
name="port"
type="text"
placeholder="8989"
- className="port"
+ className="short"
onChange={(e: React.ChangeEvent) => {
setIsValidated(false);
setFieldValue('port', e.target.value);
diff --git a/src/components/UserList/index.tsx b/src/components/UserList/index.tsx
index cb1bc21cf..ebe88b3af 100644
--- a/src/components/UserList/index.tsx
+++ b/src/components/UserList/index.tsx
@@ -21,6 +21,7 @@ import Alert from '../Common/Alert';
import BulkEditModal from './BulkEditModal';
import PageTitle from '../Common/PageTitle';
import Link from 'next/link';
+import type { UserResultsResponse } from '../../../server/interfaces/api/userInterfaces';
const messages = defineMessages({
users: 'Users',
@@ -65,6 +66,11 @@ const messages = defineMessages({
sortUpdated: 'Last Updated',
sortDisplayName: 'Display Name',
sortRequests: 'Request Count',
+ next: 'Next',
+ previous: 'Previous',
+ showingresults:
+ 'Showing {from} to {to} of {total} results',
+ resultsperpage: 'Display {pageSize} results per page',
});
type Sort = 'created' | 'updated' | 'requests' | 'displayname';
@@ -73,10 +79,16 @@ const UserList: React.FC = () => {
const intl = useIntl();
const router = useRouter();
const { addToast } = useToasts();
+ const [pageIndex, setPageIndex] = useState(0);
const [currentSort, setCurrentSort] = useState('created');
- const { data, error, revalidate } = useSWR(
- `/api/v1/user?sort=${currentSort}`
+ const [currentPageSize, setCurrentPageSize] = useState(10);
+
+ const { data, error, revalidate } = useSWR(
+ `/api/v1/user?take=${currentPageSize}&skip=${
+ pageIndex * currentPageSize
+ }&sort=${currentSort}`
);
+
const [isDeleting, setDeleting] = useState(false);
const [isImporting, setImporting] = useState(false);
const [deleteModal, setDeleteModal] = useState<{
@@ -99,7 +111,7 @@ const UserList: React.FC = () => {
const isAllUsersSelected = () => {
return (
selectedUsers.length ===
- data?.filter((user) => user.id !== currentUser?.id).length
+ data?.results.filter((user) => user.id !== currentUser?.id).length
);
};
const isUserSelected = (userId: number) => selectedUsers.includes(userId);
@@ -107,10 +119,12 @@ const UserList: React.FC = () => {
if (
data &&
selectedUsers.length >= 0 &&
- selectedUsers.length < data?.length - 1
+ selectedUsers.length < data?.results.length - 1
) {
setSelectedUsers(
- data.filter((user) => isUserPermsEditable(user.id)).map((u) => u.id)
+ data.results
+ .filter((user) => isUserPermsEditable(user.id))
+ .map((u) => u.id)
);
} else {
setSelectedUsers([]);
@@ -191,6 +205,13 @@ const UserList: React.FC = () => {
),
});
+ if (!data) {
+ return ;
+ }
+
+ const hasNextPage = data.pageInfo.pages > pageIndex + 1;
+ const hasPrevPage = pageIndex > 0;
+
return (
<>
@@ -372,7 +393,7 @@ const UserList: React.FC = () => {
revalidate();
}}
selectedUserIds={selectedUsers}
- users={data}
+ users={data.results}
/>
@@ -411,6 +432,7 @@ const UserList: React.FC = () => {
id="sort"
name="sort"
onChange={(e) => {
+ setPageIndex(0);
setCurrentSort(e.target.value as Sort);
}}
value={currentSort}
@@ -436,7 +458,7 @@ const UserList: React.FC = () => {
- {(data ?? []).length > 1 && (
+ {(data.results ?? []).length > 1 && (
{
{intl.formatMessage(messages.created)}
{intl.formatMessage(messages.lastupdated)}
- {(data ?? []).length > 1 && (
+ {(data.results ?? []).length > 1 && (
- {data?.map((user) => (
+ {data?.results.map((user) => (
{isUserPermsEditable(user.id) && (
@@ -554,6 +576,69 @@ const UserList: React.FC = () => {
))}
+
+
+
+
+
>
diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json
index 2d8247af3..c805abf40 100644
--- a/src/i18n/locale/en.json
+++ b/src/i18n/locale/en.json
@@ -170,6 +170,7 @@
"components.RequestList.previous": "Previous",
"components.RequestList.requestedAt": "Requested At",
"components.RequestList.requests": "Requests",
+ "components.RequestList.resultsperpage": "Display {pageSize} results per page",
"components.RequestList.showallrequests": "Show All Requests",
"components.RequestList.showingresults": "Showing {from} to {to} of {total} results",
"components.RequestList.sortAdded": "Request Date",
@@ -635,14 +636,18 @@
"components.UserList.importfromplexerror": "Something went wrong while importing users from Plex.",
"components.UserList.lastupdated": "Last Updated",
"components.UserList.localuser": "Local User",
+ "components.UserList.next": "Next",
"components.UserList.password": "Password",
"components.UserList.passwordinfo": "Password Information",
"components.UserList.passwordinfodescription": "Email notifications need to be configured and enabled in order to automatically generate passwords.",
"components.UserList.permissions": "Permissions",
"components.UserList.plexuser": "Plex User",
+ "components.UserList.previous": "Previous",
+ "components.UserList.resultsperpage": "Display {pageSize} results per page",
"components.UserList.role": "Role",
"components.UserList.save": "Save Changes",
"components.UserList.saving": "Saving…",
+ "components.UserList.showingResults": "Showing {from} to {to} of {total} results",
"components.UserList.sortCreated": "Creation Date",
"components.UserList.sortDisplayName": "Display Name",
"components.UserList.sortRequests": "Request Count",
diff --git a/src/styles/globals.css b/src/styles/globals.css
index 2f1080169..35229d752 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -102,8 +102,9 @@ select.rounded-r-only {
@apply rounded-l-none;
}
-input.port {
- @apply w-24;
+input.short,
+select.short {
+ @apply w-20;
}
.protocol {