Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix user pagination and page setting #3056

Merged
merged 1 commit into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 111 additions & 20 deletions web/components/templates/users/usersPageV2.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { UIFilterRowTree } from "@/services/lib/filters/types";
import { UserGroupIcon } from "@heroicons/react/24/outline";
import Link from "next/link";
import { useSearchParams } from "next/navigation";
import { useRouter } from "next/router";
import { useState, useCallback } from "react";
import { useCallback, useEffect, useState } from "react";
import { useDebounce } from "../../../services/hooks/debounce";
import { useUsers } from "../../../services/hooks/users";
import { userTableFilters } from "../../../services/lib/filters/frontendFilterDefs";
import { SortLeafRequest } from "../../../services/lib/sorts/requests/sorts";
import { SortDirection } from "../../../services/lib/sorts/users/sorts";
import AuthHeader from "../../shared/authHeader";
import ThemedTable from "../../shared/themed/table/themedTable";
import {
filterUITreeToFilterNode,
getRootFilterNode,
} from "../../../services/lib/filters/uiFilterRowTree";
import { UIFilterRowTree } from "@/services/lib/filters/types";
import { SortLeafRequest } from "../../../services/lib/sorts/requests/sorts";
import { SortDirection } from "../../../services/lib/sorts/users/sorts";
import AuthHeader from "../../shared/authHeader";
import ThemedTable from "../../shared/themed/table/themedTable";
import TableFooter from "../requestsV2/tableFooter";
import { INITIAL_COLUMNS } from "./initialColumns";

Expand All @@ -27,8 +28,50 @@ interface UsersPageV2Props {
};
}

function useQueryParam(
paramName: string,
defaultValue: string
): [queryParam: string, setQueryParam: (value: string) => void] {
const router = useRouter();
const searchParams = useSearchParams();

const setQueryParam = useCallback(
(value: string) => {
const currentQuery = { ...router.query };
currentQuery[paramName] = value;
router.push(
{
pathname: router.pathname,
query: currentQuery,
},
undefined,
{ shallow: true }
);
},
[router, paramName]
);

// Get the current value from the URL
const queryParam = searchParams?.get(paramName) || defaultValue;

useEffect(() => {
// If the parameter is not in the URL, set it to the default value
if (!searchParams?.has(paramName)) {
setQueryParam(defaultValue);
}
}, [paramName, defaultValue, searchParams, setQueryParam]);

return [queryParam, setQueryParam];
}

const UsersPageV2 = (props: UsersPageV2Props) => {
const { currentPage, pageSize, sort } = props;
const [currentPage, setCurrentPage] = useQueryParam("page", "1");
const [pageSize, setPageSize] = useQueryParam("pageSize", "100");
const [sortDirection, setSortDirection] = useQueryParam(
"sortDirection",
"asc"
);
Comment on lines +70 to +73
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Default sortDirection is 'asc' but fallback on line 89 uses 'desc'. This inconsistency could cause unexpected sorting behavior.

const [sortKey, setSortKey] = useQueryParam("sortKey", "last_active");

const [advancedFilters, setAdvancedFilters] = useState<UIFilterRowTree>(
getRootFilterNode()
Expand All @@ -38,22 +81,24 @@ const UsersPageV2 = (props: UsersPageV2Props) => {
const router = useRouter();

const sortLeaf: SortLeafRequest =
sort.sortKey && sort.sortDirection
sortKey && sortDirection
? {
[sort.sortKey]: sort.sortDirection,
[sortKey]: sortDirection,
}
: {
last_active: "desc",
};
// const [timeFilter, setTimeFilter] = useState<FilterNode>("all");

const { users, count, from, isLoading, to, refetch } = useUsers(
currentPage,
pageSize,
parseInt(currentPage, 10),
parseInt(pageSize, 10),
sortLeaf,
filterUITreeToFilterNode(
userTableFilters.sort((a, b) => a.label.localeCompare(b.label)),
debouncedAdvancedFilters
)
// timeFilter
);
Comment on lines 93 to 102
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: refetch is imported but never used after removing the refetch calls from page change handlers


const checkIsNotUniqueUser = useCallback(() => {
Expand All @@ -74,17 +119,63 @@ const UsersPageV2 = (props: UsersPageV2Props) => {
[]
);

// const onTimeSelectHandler = (key: TimeInterval, value: string) => {
// if (key === "custom") {
// const [start, end] = value.split("_");
// const filter: FilterNode = {
// left: {
// request_response_rmt: {
// request_created_at: {
// gte: new Date(start),
// },
// },
// },
// operator: "and",
// right: {
// request_response_rmt: {
// request_created_at: {
// lte: new Date(end),
// },
// },
// },
// };
// setTimeFilter(filter);
// } else {
// setTimeFilter({
// request_response_rmt: {
// request_created_at: {
// gte: new Date(getTimeIntervalAgo(key)),
// },
// },
// });
// }
// };
// const defaultTimeFilter: TimeFilter = useMemo(() => {
// return {
// start: new Date(getTimeIntervalAgo("1m")),
// end: new Date(),
// };
// }, []);
return (
<>
<AuthHeader title={"Users"} />
<div className="flex flex-col space-y-4">
<div className="flex flex-col space-y-4 pb-10">
<ThemedTable
id="user-table"
defaultData={users}
defaultColumns={INITIAL_COLUMNS}
skeletonLoading={isLoading}
dataLoading={false}
sortable={sort}
// timeFilter={{
// currentTimeFilter: defaultTimeFilter,
// defaultValue: "24h",
// onTimeSelectHandler: onTimeSelectHandler,
// }}
sortable={{
sortKey: sortKey,
sortDirection: sortDirection as SortDirection,
isCustomProperty: false,
}}
advancedFilters={{
filterMap: userTableFilters,
setAdvancedFilters: onSetAdvancedFiltersHandler,
Expand Down Expand Up @@ -123,17 +214,17 @@ const UsersPageV2 = (props: UsersPageV2Props) => {
)}

<TableFooter
currentPage={currentPage}
pageSize={pageSize}
currentPage={parseInt(currentPage, 10)}
pageSize={parseInt(pageSize, 10)}
isCountLoading={isLoading}
count={count || 0}
onPageChange={() => {
refetch();
onPageChange={(newPage) => {
setCurrentPage(newPage.toString());
}}
onPageSizeChange={() => {
refetch();
onPageSizeChange={(newPageSize) => {
setPageSize(newPageSize.toString());
}}
pageSizeOptions={[25, 50, 100]}
pageSizeOptions={[100, 250, 500]}
showCount={true}
/>
</div>
Expand Down
26 changes: 22 additions & 4 deletions web/services/hooks/users.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,23 +141,41 @@ const useUsers = (
currentPage: number,
currentPageSize: number,
sortLeaf: SortLeafUsers,
advancedFilter?: FilterNode
advancedFilter?: FilterNode,
timeFilter?: FilterNode
) => {
const { data, isLoading, refetch, isRefetching } = useQuery({
queryKey: ["users", currentPage, currentPageSize, advancedFilter, sortLeaf],
queryKey: [
"users",
currentPage,
currentPageSize,
advancedFilter,
sortLeaf,
timeFilter,
],
queryFn: async (query) => {
const currentPage = query.queryKey[1] as number;
const currentPageSize = query.queryKey[2] as number;
const advancedFilter = query.queryKey[3];
const advancedFilter = query.queryKey[3] as FilterNode | undefined;
const sortLeaf = query.queryKey[4];
const timeFilter = query.queryKey[5] as FilterNode | undefined;

let filter = advancedFilter ?? timeFilter;
if (timeFilter && advancedFilter) {
filter = {
left: advancedFilter,
operator: "and",
right: timeFilter,
};
}
const [response, count] = await Promise.all([
fetch("/api/request_users", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
filter: advancedFilter,
filter: filter,
offset: (currentPage - 1) * currentPageSize,
limit: currentPageSize,
sort: sortLeaf,
Expand Down
Loading