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

[ECO-2363] Fix page number wrong on search #323

Merged
merged 7 commits into from
Nov 12, 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
6 changes: 3 additions & 3 deletions src/typescript/frontend/src/app/home/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { type MarketDataSortByHomePage } from "lib/queries/sorting/types";
export interface HomePageProps {
featured?: DatabaseModels["market_state"];
markets: Array<DatabaseModels["market_state"]>;
numRegisteredMarkets: number;
numMarkets: number;
page: number;
sortBy: MarketDataSortByHomePage;
searchBytes?: string;
Expand All @@ -20,7 +20,7 @@ export interface HomePageProps {
export default async function HomePageComponent({
featured,
markets,
numRegisteredMarkets,
numMarkets,
page,
sortBy,
searchBytes,
Expand All @@ -42,7 +42,7 @@ export default async function HomePageComponent({

<EmojiTable
markets={markets}
numRegisteredMarkets={numRegisteredMarkets}
numMarkets={numMarkets}
page={page}
sortBy={sortBy}
searchBytes={searchBytes}
Expand Down
36 changes: 27 additions & 9 deletions src/typescript/frontend/src/app/home/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { headers } from "next/headers";
import {
fetchFeaturedMarket,
fetchMarkets,
fetchMarketsWithCount,
fetchNumRegisteredMarkets,
fetchPriceFeed,
} from "@/queries/home";
Expand All @@ -17,15 +18,32 @@ export default async function Home({ searchParams }: HomePageParams) {
const { page, sortBy, orderBy, q } = toHomePageParamsWithDefault(searchParams);
const searchEmojis = q ? symbolBytesToEmojis(q).emojis.map((e) => e.emoji) : undefined;

const numRegisteredMarkets = await fetchNumRegisteredMarkets();
const featured = await fetchFeaturedMarket();
const markets = await fetchMarkets({
page,
sortBy,
orderBy,
searchEmojis,
pageSize: MARKETS_PER_PAGE,
});
let numMarkets: number;
let markets: Awaited<ReturnType<typeof fetchMarketsWithCount>>["rows"];

if (searchEmojis?.length) {
const res = await fetchMarketsWithCount({
page,
sortBy,
orderBy,
searchEmojis,
pageSize: MARKETS_PER_PAGE,
count: true,
});
numMarkets = res.count!;
markets = res.rows;
} else {
numMarkets = await fetchNumRegisteredMarkets();
markets = await fetchMarkets({
page,
sortBy,
orderBy,
searchEmojis,
pageSize: MARKETS_PER_PAGE,
});
}

const priceFeed = await fetchPriceFeed({});

// Call this last because `headers()` is a dynamic API and all fetches after this aren't cached.
Expand All @@ -34,7 +52,7 @@ export default async function Home({ searchParams }: HomePageParams) {
<HomePageComponent
featured={featured}
markets={markets}
numRegisteredMarkets={numRegisteredMarkets}
numMarkets={numMarkets}
page={page}
sortBy={sortBy}
searchBytes={q}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export type ButtonsBlockProps = {
className?: string;
};

const ButtonsBlock: React.FC<ButtonsBlockProps> = ({
export const ButtonsBlock: React.FC<ButtonsBlockProps> = ({
value,
numPages,
onChange,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import React, { useEffect, useMemo } from "react";

import { ButtonsBlock } from "./components";
import { ButtonsBlock } from "./components/buttons-block";
import {
InnerGridContainer,
SearchWrapper,
Expand Down Expand Up @@ -42,7 +42,7 @@ const EmojiTable = (props: EmojiTableProps) => {

const { markets, page, sort, pages, searchBytes } = useMemo(() => {
const { markets, page, sortBy: sort } = props;
const numMarkets = Math.max(props.numRegisteredMarkets, 1);
const numMarkets = Math.max(props.numMarkets, 1);
const pages = Math.ceil(numMarkets / MARKETS_PER_PAGE);
const searchBytes = props.searchBytes ?? "";
return { markets, page, sort, pages, searchBytes };
Expand Down Expand Up @@ -85,7 +85,7 @@ const EmojiTable = (props: EmojiTableProps) => {
};

useEffect(() => {
pushURL();
pushURL({ page: 0 });
/* eslint-disable-next-line react-hooks/exhaustive-deps */
}, [emojis]);

Expand Down
25 changes: 20 additions & 5 deletions src/typescript/sdk/src/indexer-v2/queries/app/home.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import { LIMIT, ORDER_BY } from "../../../queries/const";
import { SortMarketsBy, type MarketStateQueryArgs } from "../../types/common";
import { DatabaseRpc, TableName } from "../../types/json-types";
import { postgrest, toQueryArray } from "../client";
import { getLatestProcessedEmojicoinVersion, queryHelper } from "../utils";
import { getLatestProcessedEmojicoinVersion, queryHelper, queryHelperWithCount } from "../utils";
import { DatabaseTypeConverter } from "../../types";
import { RegistryView } from "../../../emojicoin_dot_fun/emojicoin-dot-fun";
import { getAptosClient } from "../../../utils/aptos-client";
import { toRegistryView } from "../../../types";
import { sortByWithFallback } from "../query-params";
import { type PostgrestFilterBuilder } from "@supabase/postgrest-js";

const selectMarketStates = ({
page = 1,
Expand All @@ -20,10 +21,19 @@ const selectMarketStates = ({
searchEmojis,
sortBy = SortMarketsBy.MarketCap,
inBondingCurve,
}: MarketStateQueryArgs) => {
let query = postgrest
.from(TableName.MarketState)
.select("*")
count,
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
}: MarketStateQueryArgs): PostgrestFilterBuilder<any, any, any[], TableName, unknown> => {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
let query: any = postgrest.from(TableName.MarketState);

if (count === true) {
query = query.select("*", { count: "exact" });
} else {
query = query.select("*");
}

query = query
.order(sortByWithFallback(sortBy), orderBy)
.range((page - 1) * pageSize, page * pageSize - 1);

Expand All @@ -43,6 +53,11 @@ export const fetchMarkets = queryHelper(
DatabaseTypeConverter[TableName.MarketState]
);

export const fetchMarketsWithCount = queryHelperWithCount(
selectMarketStates,
DatabaseTypeConverter[TableName.MarketState]
);

// The featured market is simply the current highest daily volume market.
export const fetchFeaturedMarket = async () =>
fetchMarkets({
Expand Down
70 changes: 45 additions & 25 deletions src/typescript/sdk/src/indexer-v2/queries/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,9 @@ export const waitForEmojicoinIndexer = async (
});

/**
* Return the curried version of queryHelperWithCount that extracts just the rows.
*
* @param queryFn Takes in a query function that's used to be called after waiting for the indexer
* to reach a certain version. Then it extracts the row data and returns it.
* @param convert A function that converts the raw row data into the desired output, usually
* by converting it into a camelCased representation of the database row.
* @returns A curried function that applies the logic to the new query function.
* @see queryHelperWithCount
*/
export function queryHelper<
Row extends Record<string, unknown>,
Expand All @@ -108,6 +105,16 @@ export function queryHelper<
queryFn: QueryFunction<Row, Result, RelationName, EnumLiteralType<Relationships>, QueryArgs>,
convert: (rows: Row) => OutputType
): (args: WithConfig<QueryArgs>) => Promise<OutputType[]> {
// Return the curried version of queryHelperWithCount that extracts just the rows.
return async (args) => (await queryHelperWithCount(queryFn, convert)(args)).rows;
}

export function queryHelperSingle<
T extends TableName,
Row extends DatabaseJsonType[T],
Model extends DatabaseModels[T],
QueryArgs extends Record<string, any> | undefined,
>(queryFn: (args: QueryArgs) => PostgrestBuilder<Row>, convert: (row: Row) => Model) {
const query = async (args: WithConfig<QueryArgs>) => {
const { minimumVersion, ...queryArgs } = args;
const innerQuery = queryFn(queryArgs as QueryArgs);
Expand All @@ -116,29 +123,33 @@ export function queryHelper<
await waitForEmojicoinIndexer(minimumVersion);
}

try {
const res = await innerQuery;
const rows = extractRows<Row>(res);
if (res.error) {
console.error("[Failed row conversion]:\n");
throw new Error(JSON.stringify(res));
}
return rows.map(convert);
} catch (e) {
console.error(e);
return [];
}
const res = await innerQuery;
const row = extractRow<Row>(res);
return row ? convert(row) : null;
};

return query;
}

export function queryHelperSingle<
T extends TableName,
Row extends DatabaseJsonType[T],
Model extends DatabaseModels[T],
/**
*
* @param queryFn Takes in a query function that's used to be called after waiting for the indexer
* to reach a certain version. Then it extracts the row data and returns it.
* @param convert A function that converts the raw row data into the desired output, usually
* by converting it into a camelCased representation of the database row.
* @returns A curried function that applies the logic to the new query function.
*/
export function queryHelperWithCount<
Row extends Record<string, unknown>,
Result extends Row[],
RelationName,
Relationships extends TableName,
QueryArgs extends Record<string, any> | undefined,
>(queryFn: (args: QueryArgs) => PostgrestBuilder<Row>, convert: (row: Row) => Model) {
OutputType,
>(
queryFn: QueryFunction<Row, Result, RelationName, EnumLiteralType<Relationships>, QueryArgs>,
convert: (rows: Row) => OutputType
): (args: WithConfig<QueryArgs>) => Promise<{ rows: OutputType[]; count: number | null }> {
const query = async (args: WithConfig<QueryArgs>) => {
const { minimumVersion, ...queryArgs } = args;
const innerQuery = queryFn(queryArgs as QueryArgs);
Expand All @@ -147,9 +158,18 @@ export function queryHelperSingle<
await waitForEmojicoinIndexer(minimumVersion);
}

const res = await innerQuery;
const row = extractRow<Row>(res);
return row ? convert(row) : null;
try {
const res = await innerQuery;
const rows = extractRows<Row>(res);
if (res.error) {
console.error("[Failed row conversion]:\n");
throw new Error(JSON.stringify(res));
}
return { rows: rows.map(convert), count: res.count };
} catch (e) {
console.error(e);
return { rows: [], count: null };
}
};

return query;
Expand Down
1 change: 1 addition & 0 deletions src/typescript/sdk/src/indexer-v2/types/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export type MarketStateQueryArgs = {
orderBy?: OrderBy;
searchEmojis?: string[];
inBondingCurve?: boolean;
count?: boolean;
};

export type PeriodicStateEventQueryArgs = {
Expand Down
Loading