Skip to content
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
8 changes: 2 additions & 6 deletions govtool/backend/sql/list-dreps.sql
Original file line number Diff line number Diff line change
Expand Up @@ -317,10 +317,6 @@ WHERE
(
COALESCE(?, '') = '' OR
(CASE WHEN LENGTH(?) % 2 = 0 AND ? ~ '^[0-9a-fA-F]+$' THEN drep_hash = ? ELSE false END) OR
view ILIKE ? OR
given_name ILIKE ? OR
payment_address ILIKE ? OR
objectives ILIKE ? OR
motivations ILIKE ? OR
qualifications ILIKE ?
(CASE WHEN lower(?) ~ '^drep1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]+$' THEN view = lower(?) ELSE FALSE END) OR
given_name ILIKE ?
)
7 changes: 2 additions & 5 deletions govtool/backend/src/VVA/DRep.hs
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,9 @@ listDReps mSearchQuery = withPool $ \conn -> do
, searchParam -- LENGTH(?)
, searchParam -- AND ?
, searchParam -- decode(?, 'hex')
, "%" <> searchParam <> "%" -- dh.view
, searchParam -- lower(?)
, searchParam -- lower(?)
, "%" <> searchParam <> "%" -- given_name
, "%" <> searchParam <> "%" -- payment_address
, "%" <> searchParam <> "%" -- objectives
, "%" <> searchParam <> "%" -- motivations
, "%" <> searchParam <> "%" -- qualifications
) :: IO [DRepQueryResult])

timeZone <- liftIO getCurrentTimeZone
Expand Down
18 changes: 16 additions & 2 deletions govtool/frontend/src/components/molecules/DataActionsBar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dispatch, FC, SetStateAction } from "react";
import { Box, InputBase } from "@mui/material";
import { Box, InputBase, IconButton } from "@mui/material";
import Search from "@mui/icons-material/Search";
import CloseIcon from "@mui/icons-material/Close";

import { DataActionsFilters, DataActionsSorting } from "@molecules";
import { OrderActionsChip } from "./OrderActionsChip";
Expand All @@ -20,6 +21,7 @@ type DataActionsBarProps = {
filtersTitle?: string;
isFiltering?: boolean;
searchText: string;
placeholder?: string;
setChosenFilters?: Dispatch<SetStateAction<string[]>>;
setChosenSorting: Dispatch<SetStateAction<string>>;
setFiltersOpen?: Dispatch<SetStateAction<boolean>>;
Expand Down Expand Up @@ -51,6 +53,7 @@ export const DataActionsBar: FC<DataActionsBarProps> = ({ ...props }) => {
setSortOpen,
sortOpen,
sortOptions = [],
placeholder = "Search...",
} = props;
const {
palette: { boxShadow2 },
Expand All @@ -61,7 +64,7 @@ export const DataActionsBar: FC<DataActionsBarProps> = ({ ...props }) => {
<InputBase
inputProps={{ "data-testid": "search-input" }}
onChange={(e) => setSearchText(e.target.value)}
placeholder="Search..."
placeholder={placeholder}
value={searchText}
startAdornment={
<Search
Expand All @@ -73,6 +76,17 @@ export const DataActionsBar: FC<DataActionsBarProps> = ({ ...props }) => {
}}
/>
}
endAdornment={
searchText && (
<IconButton
size="small"
onClick={() => setSearchText("")}
sx={{ ml: 1 }}
>
<CloseIcon fontSize="small" />
</IconButton>
)
}
sx={{
bgcolor: "white",
border: 1,
Expand Down
118 changes: 118 additions & 0 deletions govtool/frontend/src/hooks/queries/useGetDRepListInfiniteQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import {
UseInfiniteQueryOptions,
useInfiniteQuery,
useQuery,
} from "react-query";
import { useRef, useMemo } from "react";

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

const makeStatusKey = (status?: string[] | undefined) =>
(status && status.length ? [...status].sort().join("|") : "__EMPTY__");

export const useGetDRepListInfiniteQuery = (
{
filters = [],
pageSize = 10,
searchPhrase,
sorting,
status,
}: GetDRepListArguments,
options?: UseInfiniteQueryOptions<Infinite<DRepData>>,
) => {
const { pendingTransaction } = useCardano();
const totalsByStatusRef = useRef<Record<string, number>>({});
const statusKey = useMemo(() => makeStatusKey(status), [status]);

const {
data,
isLoading,
fetchNextPage,
hasNextPage,
isFetching,
isFetchingNextPage,
isPreviousData,
} = useInfiniteQuery(
[
QUERY_KEYS.useGetDRepListInfiniteKey,
(
pendingTransaction.registerAsDirectVoter ||
pendingTransaction.registerAsDrep ||
pendingTransaction.retireAsDirectVoter ||
pendingTransaction.retireAsDrep
)?.transactionHash ?? "noPendingTransaction",
filters.length ? filters : "",
searchPhrase ?? "",
sorting ?? "",
status?.length ? status : "",
],
async ({ pageParam = 0 }) =>
getDRepList({
page: pageParam,
pageSize,
filters,
searchPhrase,
sorting,
status,
}),
{
getNextPageParam: (lastPage) => {
if (lastPage.elements.length === 0) return undefined;
return lastPage.page + 1;
},
enabled: options?.enabled,
keepPreviousData: options?.keepPreviousData,
onSuccess: (pagesData) => {
if (!searchPhrase) {
const firstPage = pagesData.pages?.[0];
if (firstPage && typeof firstPage.total === "number") {
totalsByStatusRef.current[statusKey] = firstPage.total;
}
}
options?.onSuccess?.(pagesData);
},
},
);

useQuery(
[QUERY_KEYS.useGetDRepListInfiniteKey, "baseline", statusKey],
async () => {
const resp = await getDRepList({
page: 0,
pageSize: 1,
filters,
searchPhrase: "",
sorting,
status,
});
return resp;
},
{
enabled:
options?.enabled &&
searchPhrase !== "" &&
totalsByStatusRef.current[statusKey] === undefined,
onSuccess: (resp) => {
if (typeof resp.total === "number") {
totalsByStatusRef.current[statusKey] = resp.total;
}
},
},
);

return {
dRepListFetchNextPage: fetchNextPage,
dRepListHasNextPage: hasNextPage,
isDRepListFetching: isFetching,
isDRepListFetchingNextPage: isFetchingNextPage,
isDRepListLoading: isLoading,
dRepData: data?.pages.flatMap((page) => page.elements),
isPreviousData,
dRepListTotal: data?.pages[0].total,
dRepTotalsByStatus: totalsByStatusRef.current,
dRepBaselineTotalForStatus: totalsByStatusRef.current[statusKey],
};
};
131 changes: 83 additions & 48 deletions govtool/frontend/src/hooks/queries/useGetDRepListQuery.ts
Original file line number Diff line number Diff line change
@@ -1,73 +1,108 @@
import { UseInfiniteQueryOptions, useInfiniteQuery } from "react-query";
import { useMemo, useRef } from "react";
import { useQuery, UseQueryOptions } from "react-query";

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

export const useGetDRepListInfiniteQuery = (
{
filters = [],
pageSize = 10,
searchPhrase,
sorting,
status,
}: GetDRepListArguments,
options?: UseInfiniteQueryOptions<Infinite<DRepData>>,
) => {
const makeStatusKey = (status?: string[] | undefined) =>
(status && status.length ? [...status].sort().join("|") : "__EMPTY__");

type PaginatedResult = {
dRepData: DRepData[] | undefined;
isLoading: boolean;
isFetching: boolean;
isPreviousData: boolean;
total: number | undefined;
baselineTotalForStatus: number | undefined;
};

type Args = GetDRepListArguments & {
page: number;
pageSize?: number;
};

export function useGetDRepListPaginatedQuery(
{ page, pageSize = 10, filters = [], searchPhrase, sorting, status }: Args,
options?: UseQueryOptions<Infinite<DRepData>>,
): PaginatedResult {
const { pendingTransaction } = useCardano();
const totalsByStatusRef = useRef<Record<string, number>>({});
const statusKey = useMemo(() => makeStatusKey(status), [status]);

const {
data,
isLoading,
fetchNextPage,
hasNextPage,
isFetching,
isFetchingNextPage,
isPreviousData,
} = useInfiniteQuery(
[
QUERY_KEYS.useGetDRepListInfiniteKey,
(
pendingTransaction.registerAsDirectVoter ||
pendingTransaction.registerAsDrep ||
pendingTransaction.retireAsDirectVoter ||
pendingTransaction.retireAsDrep
)?.transactionHash ?? "noPendingTransaction",
filters.length ? filters : "",
searchPhrase ?? "",
sorting ?? "",
status?.length ? status : "",
],
async ({ pageParam = 0 }) =>
const queryKey = [
QUERY_KEYS.useGetDRepListInfiniteKey,
(
pendingTransaction.registerAsDirectVoter ||
pendingTransaction.registerAsDrep ||
pendingTransaction.retireAsDirectVoter ||
pendingTransaction.retireAsDrep
)?.transactionHash ?? "noPendingTransaction",
"paged",
page,
pageSize,
filters.length ? filters : "",
searchPhrase ?? "",
sorting ?? "",
status?.length ? status : "",
];

const { data, isLoading, isFetching, isPreviousData } = useQuery(
queryKey,
async () =>
getDRepList({
page: pageParam,
page,
pageSize,
filters,
searchPhrase,
sorting,
status,
}),
{
getNextPageParam: (lastPage) => {
if (lastPage.elements.length === 0) {
return undefined;
keepPreviousData: true,
enabled: options?.enabled,
onSuccess: (resp) => {
if (!searchPhrase && typeof resp?.total === "number") {
totalsByStatusRef.current[statusKey] = resp.total;
}
options?.onSuccess?.(resp);
},
},
);

return lastPage.page + 1;
useQuery(
[QUERY_KEYS.useGetDRepListInfiniteKey, "baseline", statusKey],
async () => {
const resp = await getDRepList({
page: 0,
pageSize: 1,
filters,
searchPhrase: "",
sorting,
status,
});
return resp;
},
{
enabled:
options?.enabled &&
searchPhrase !== "" &&
totalsByStatusRef.current[statusKey] === undefined,
onSuccess: (resp) => {
if (typeof resp.total === "number") {
totalsByStatusRef.current[statusKey] = resp.total;
}
},
enabled: options?.enabled,
keepPreviousData: options?.keepPreviousData,
},
);

return {
dRepListFetchNextPage: fetchNextPage,
dRepListHasNextPage: hasNextPage,
isDRepListFetching: isFetching,
isDRepListFetchingNextPage: isFetchingNextPage,
isDRepListLoading: isLoading,
dRepData: data?.pages.flatMap((page) => page.elements),
dRepData: data?.elements,
isLoading,
isFetching,
isPreviousData,
total: data?.total,
baselineTotalForStatus: totalsByStatusRef.current[statusKey],
};
};
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { UseInfiniteQueryOptions } from "react-query";

import { Infinite, DRepData } from "@/models";
import { useGetDRepListInfiniteQuery } from "./useGetDRepListQuery";
import { useGetDRepListInfiniteQuery } from "./useGetDRepListInfiniteQuery";

export const useGetDRepDetailsQuery = (
dRepId: string | null | undefined,
Expand Down
1 change: 1 addition & 0 deletions govtool/frontend/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@
"myDelegationToYourself": "You have delegated <strong>₳ {{ada}}</strong> to yourself",
"myDRep": "You have delegated <strong>₳ {{ada}}</strong> to this DRep",
"listTitle": "Find a DRep",
"searchBarPlaceholder": "Search for a DRep name or ID",
"noConfidenceDefaultDescription": "Select this to signal no confidence in the current constitutional committee by voting NO on every proposal and voting YES to no confidence proposals",
"noConfidenceDefaultTitle": "Signal No Confidence on Every Vote",
"noResultsForTheSearchTitle": "No DReps found",
Expand Down
Loading
Loading