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

[#740] feat: add drep list pagination #830

Merged
merged 3 commits into from
Apr 23, 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ changes.
- Add frontend test workflow on github actions [Issue 500](https://github.com/IntersectMBO/govtool/issues/500)
- Add type check & lint to github actions [Issue 512](https://github.com/IntersectMBO/govtool/issues/512)
- Add eslint & prettier to frontend package [Issue 166](https://github.com/IntersectMBO/govtool/issues/166)
- Add DRep list pagination [Issue 740](https://github.com/IntersectMBO/govtool/issues/740)

### Fixed

Expand Down
2 changes: 1 addition & 1 deletion govtool/frontend/src/consts/queryKeys.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export const QUERY_KEYS = {
getAdaHolderCurrentDelegationKey: "getAdaHolderCurrentDelegationKey",
getAdaHolderVotingPowerKey: "getAdaHolderVotingPowerKey",
useGetDRepListKey: "useGetDRepListKey",
useGetDRepListInfiniteKey: "useGetDRepListInfiniteKey",
useGetDRepVotesKey: "useGetDRepVotesKey",
useGetDRepVotingPowerKey: "useGetDRepVotingPowerKey",
useGetProposalKey: "useGetProposalKey",
Expand Down
6 changes: 4 additions & 2 deletions govtool/frontend/src/hooks/forms/useDelegateTodRepForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useForm, useWatch } from "react-hook-form";

import { PATHS } from "@consts";
import { useCardano, useModal } from "@context";
import { useGetDRepListQuery, useTranslation } from "@hooks";
import { useGetDRepListInfiniteQuery, useTranslation } from "@hooks";
import { formHexToBech32 } from "@utils";

export interface DelegateTodrepFormValues {
Expand All @@ -13,7 +13,9 @@ export interface DelegateTodrepFormValues {

export const useDelegateTodRepForm = () => {
const { buildSignSubmitConwayCertTx, buildVoteDelegationCert } = useCardano();
const { data: drepList } = useGetDRepListQuery();
const { dRepData: drepList } = useGetDRepListInfiniteQuery({
page: 0,
});
const { openModal, closeModal, modal } = useModal();
const [isLoading, setIsLoading] = useState<boolean>(false);
const navigate = useNavigate();
Expand Down
82 changes: 60 additions & 22 deletions govtool/frontend/src/hooks/queries/useGetDRepListQuery.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,73 @@
import { UseQueryOptions, useQuery } from "react-query";
import { UseInfiniteQueryOptions, useInfiniteQuery } from "react-query";

import { QUERY_KEYS } from "@consts";
import { useCardano } from "@context";
import { GetDRepListParams, getDRepList } from "@services";
import { DRepData } from "@/models";
import { GetDRepListArguments, getDRepList } from "@services";
import { InfinityDRepData } from "@/models";

export const useGetDRepListQuery = (
params?: GetDRepListParams,
options?: UseQueryOptions<DRepData[]>
export const useGetDRepListInfiniteQuery = (
{
filters = [],
pageSize = 10,
searchPhrase,
sorting,
status,
}: GetDRepListArguments,
options?: UseInfiniteQueryOptions<InfinityDRepData>,
) => {
const { search, sort, status } = params || {};
const { pendingTransaction } = useCardano();

const { data, isLoading, isPreviousData } = useQuery<DRepData[]>({
queryKey: [
QUERY_KEYS.useGetDRepListKey,
(pendingTransaction.registerAsSoleVoter ||
const {
data,
isLoading,
fetchNextPage,
hasNextPage,
isFetching,
isFetchingNextPage,
isPreviousData,
} = useInfiniteQuery(
[
QUERY_KEYS.useGetDRepListInfiniteKey,
(
pendingTransaction.registerAsSoleVoter ||
pendingTransaction.registerAsDrep ||
pendingTransaction.retireAsSoleVoter ||
pendingTransaction.retireAsDrep)?.transactionHash,
search,
sort,
pendingTransaction.retireAsDrep
)?.transactionHash,
filters,
searchPhrase,
sorting,
status,
],
queryFn: () => getDRepList({
...(search && { search }),
...(sort && { sort }),
...(status && { status }),
}),
...options
});
async ({ pageParam = 0 }) =>
getDRepList({
page: pageParam,
pageSize,
filters,
searchPhrase,
sorting,
status,
}),
{
getNextPageParam: (lastPage) => {
if (lastPage.elements.length === 0) {
return undefined;
}

return { data, isLoading, isPreviousData };
return lastPage.page + 1;
},
enabled: options?.enabled,
keepPreviousData: options?.keepPreviousData,
},
);

return {
dRepListFetchNextPage: fetchNextPage,
dRepListHasNextPage: hasNextPage,
isDRepListFetching: isFetching,
isDRepListFetchingNextPage: isFetchingNextPage,
isDRepListLoading: isLoading,
dRepData: data?.pages.flatMap((page) => page.elements),
isPreviousData,
};
};
12 changes: 12 additions & 0 deletions govtool/frontend/src/models/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ export enum DRepStatus {
Retired = "Retired",
}

export enum DRepListSort {
VotingPower = "VotingPower",
RegistrationDate = "RegistrationDate",
Status = "Status",
}

export interface DRepData {
drepId: string;
view: string;
Expand All @@ -28,6 +34,12 @@ export interface DRepData {
status: DRepStatus;
type: "DRep" | "SoleVoter";
}
export type InfinityDRepData = {
elements: DRepData[];
page: number;
pageSize: number;
total: number;
};

export type Vote = "yes" | "no" | "abstain";

Expand Down
10 changes: 6 additions & 4 deletions govtool/frontend/src/pages/DRepDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ICONS, PATHS } from "@consts";
import { useCardano, useModal } from "@context";
import {
useDelegateTodRep,
useGetDRepListQuery,
useGetDRepListInfiniteQuery,
useScreenDimension,
useTranslation,
} from "@hooks";
Expand Down Expand Up @@ -36,10 +36,12 @@ export const DRepDetails = ({ isConnected }: DRepDetailsProps) => {

const { delegate, isDelegating } = useDelegateTodRep();

const { data, isLoading } = useGetDRepListQuery({ search: dRepParam });
const dRep = data?.[0];
const { dRepData, isDRepListLoading } = useGetDRepListInfiniteQuery({
searchPhrase: dRepParam,
});
const dRep = dRepData?.[0];

if (data === undefined || isLoading)
if (dRep === undefined || isDRepListLoading)
return (
<Box
sx={{
Expand Down
30 changes: 22 additions & 8 deletions govtool/frontend/src/pages/DRepDirectoryContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ import { FC } from "react";
import { Trans, useTranslation } from "react-i18next";
import { Box, CircularProgress } from "@mui/material";

import { Typography } from "@atoms";
import { Button, Typography } from "@atoms";
import { DREP_DIRECTORY_FILTERS, DREP_DIRECTORY_SORTING } from "@consts";
import { useCardano, useDataActionsBar } from "@context";
import {
useDelegateTodRep,
useGetAdaHolderCurrentDelegationQuery,
useGetAdaHolderVotingPowerQuery,
useGetDRepListQuery,
useGetDRepListInfiniteQuery,
} from "@hooks";
import { Card, DataActionsBar } from "@molecules";
import { AutomatedVotingOptions, DRepCard } from "@organisms";
import { correctAdaFormat, formHexToBech32, isSameDRep } from "@utils";
import { DRepListSort, DRepStatus } from "@models";

interface DRepDirectoryContentProps {
isConnected?: boolean;
Expand Down Expand Up @@ -47,20 +48,26 @@ export const DRepDirectoryContent: FC<DRepDirectoryContentProps> = ({
const { currentDelegation } = useGetAdaHolderCurrentDelegationQuery(stakeKey);
const inProgressDelegation = pendingTransaction.delegate?.resourceId;

const { data: myDRepList } = useGetDRepListQuery(
const { dRepData: myDRepList } = useGetDRepListInfiniteQuery(
{
search: currentDelegation?.dRepView?.startsWith("drep")
searchPhrase: currentDelegation?.dRepView?.startsWith("drep")
? currentDelegation.dRepView
: formHexToBech32(currentDelegation?.dRepHash ?? ""),
},
{ enabled: !!inProgressDelegation || !!currentDelegation },
);
const myDrep = myDRepList?.[0];
const { data: dRepList, isPreviousData } = useGetDRepListQuery(

const {
dRepData: dRepList,
isPreviousData,
dRepListHasNextPage,
dRepListFetchNextPage,
} = useGetDRepListInfiniteQuery(
{
search: debouncedSearchText,
sort: chosenSorting,
status: chosenFilters,
searchPhrase: debouncedSearchText,
sorting: chosenSorting as DRepListSort,
status: chosenFilters as DRepStatus[],
},
{
keepPreviousData: true,
Expand Down Expand Up @@ -186,6 +193,13 @@ export const DRepDirectoryContent: FC<DRepDirectoryContentProps> = ({
})}
</Box>
</>
{dRepListHasNextPage && (
<Box sx={{ justifyContent: "center", display: "flex" }}>
<Button variant="outlined" onClick={() => dRepListFetchNextPage()}>
{t("showMore")}
</Button>
</Box>
)}
</Box>
);
};
33 changes: 26 additions & 7 deletions govtool/frontend/src/services/requests/getDRepList.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,32 @@
import type { DRepData } from "@models";
import type { InfinityDRepData, DRepStatus, DRepListSort } from "@models";
import { API } from "../API";

export type GetDRepListParams = {
search?: string;
sort?: string;
status?: string[];
export type GetDRepListArguments = {
filters?: string[];
page?: number;
pageSize?: number;
sorting?: DRepListSort;
status?: DRepStatus[];
searchPhrase?: string;
};

export const getDRepList = async (params: GetDRepListParams) => {
const response = await API.get<DRepData[]>("/drep/list", { params });
export const getDRepList = async ({
sorting,
filters = [],
page = 0,
pageSize = 10,
searchPhrase = "",
status = [],
}: GetDRepListArguments): Promise<InfinityDRepData> => {
const response = await API.get("/drep/list", {
params: {
page,
pageSize,
...(searchPhrase && { search: searchPhrase }),
...(filters.length && { type: filters }),
...(sorting && { sort: sorting }),
...(status.length && { status }),
},
});
return response.data;
};
4 changes: 2 additions & 2 deletions govtool/frontend/src/services/requests/getProposals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const getProposals = async ({
pageSize = 7,
searchPhrase = "",
sorting = "",
}: GetProposalsArguments) => {
}: GetProposalsArguments): Promise<InfinityProposals> => {
const response = await API.get("/proposal/list", {
params: {
page,
Expand All @@ -29,5 +29,5 @@ export const getProposals = async ({
...(dRepID && { drepId: dRepID }),
},
});
return response.data as InfinityProposals;
return response.data;
};
36 changes: 28 additions & 8 deletions govtool/frontend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7415,11 +7415,6 @@ isobject@^3.0.1:
resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz"
integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==

istanbul-badges-readme@^1.8.5:
version "1.8.5"
resolved "https://registry.npmjs.org/istanbul-badges-readme/-/istanbul-badges-readme-1.8.5.tgz"
integrity sha512-VEh90ofuufPZIbLeDF2g14wpe0sebhirG0xHooYKpNPYOkGXm6y+HJFotQqIzCg0NmbCnlKnOPL1B2oxG7/piA==

istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0, istanbul-lib-coverage@^3.2.2:
version "3.2.2"
resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz"
Expand Down Expand Up @@ -10358,7 +10353,16 @@ string-length@^5.0.1:
char-regex "^2.0.0"
strip-ansi "^7.0.1"

"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"

string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
Expand Down Expand Up @@ -10436,7 +10440,14 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"

"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"

strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
Expand Down Expand Up @@ -11349,7 +11360,7 @@ wordwrap@^1.0.0:
resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz"
integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==

"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
Expand All @@ -11367,6 +11378,15 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz"
Expand Down
Loading