Skip to content

Commit

Permalink
Front: Infinite Query: Return concatenated list of all items
Browse files Browse the repository at this point in the history
  • Loading branch information
Arthi-chaud committed Feb 4, 2025
1 parent b122a48 commit b150907
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 81 deletions.
10 changes: 8 additions & 2 deletions front/src/api/use-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

/* eslint-disable no-restricted-imports */

import { useEffect, useState } from "react";
import {
type QueryFunctionContext,
useInfiniteQuery as useReactInfiniteQuery,
Expand Down Expand Up @@ -172,8 +173,7 @@ const useInfiniteQuery = <ReturnType extends Resource, Params extends any[]>(
...queryParams: Partial<Params>
) => {
const pageSize = API.defaultPageSize;

return useReactInfiniteQuery({
const { data, ...res } = useReactInfiniteQuery({
...prepareMeeloInfiniteQuery(query, ...queryParams),
getNextPageParam: (
lastPage: Page<ReturnType>,
Expand All @@ -184,6 +184,12 @@ const useInfiniteQuery = <ReturnType extends Resource, Params extends any[]>(
return lastPage;
},
});
const [items, setItems] = useState(data?.pages.at(0)?.items);
useEffect(() => {
setItems(data?.pages.flatMap((p) => p.items));
}, [data?.pages]);

return { ...res, data, items };
};

/**
Expand Down
9 changes: 2 additions & 7 deletions front/src/components/admin-grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,14 @@ const AdminGrid = <DataType extends Resource>({
}: AdminGridProps<DataType>) => {
const {
data,
items,
hasNextPage,
hasPreviousPage,
fetchNextPage,
fetchPreviousPage,
} = useInfiniteQuery(infiniteQuery);
const [currentPage, setCurrentPage] = useState(0);
const itemsCount = useMemo(
() =>
data?.pages
.map((page) => page.items.length)
.reduce((pageSize, sum) => pageSize + sum, 0) ?? 0,
[data?.pages],
);
const itemsCount = useMemo(() => items?.length, [items]);

useEffect(() => {
hasNextPage && fetchNextPage();
Expand Down
6 changes: 3 additions & 3 deletions front/src/components/infinite/infinite-scroll.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export type Page<T> = {
* @returns a dynamic list component
*/
const InfiniteScroll = <T extends Resource>(props: InfiniteScrollProps<T>) => {
const { data, hasNextPage, fetchNextPage, isFetchingNextPage } =
const { items, hasNextPage, fetchNextPage, isFetchingNextPage } =
useInfiniteQuery(props.query);

return (
Expand All @@ -96,10 +96,10 @@ const InfiniteScroll = <T extends Resource>(props: InfiniteScrollProps<T>) => {
threshold={500}
>
{props.render(
data === undefined
items === undefined
? generateArray(3)
: [
...data.pages.flatMap((page) => page.items),
...items,
...(isFetchingNextPage ? generateArray(3) : []),
],
)}
Expand Down
25 changes: 14 additions & 11 deletions front/src/components/page-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ import { Box, Button, Grid } from "@mui/material";
import Link from "next/link";
import { type ComponentProps, Fragment } from "react";
import { useTranslation } from "react-i18next";
import type { UseInfiniteQueryResult, UseQueryResult } from "react-query";
import type { UseQueryResult } from "react-query";
import type { useInfiniteQuery } from "../api/use-query";
import type { TranslationKey } from "../i18n/i18n";
import type { AlbumWithRelations } from "../models/album";
import type Artist from "../models/artist";
import type Resource from "../models/resource";
import type { SongWithRelations } from "../models/song";
import type { VideoWithRelations } from "../models/video";
import { generateArray } from "../utils/gen-list";
Expand All @@ -38,13 +40,16 @@ import VideoTile from "./tile/video-tile";

export const SectionPadding = 4;

export type PageSectionProps<T> = {
export type PageSectionProps<
T extends Resource,
QT extends typeof useInfiniteQuery<T, []> = typeof useInfiniteQuery<T, []>,
> = {
title: TranslationKey;
artist: UseQueryResult<Artist>;
seeMoreHref?: string;
maxItemCount: number;
child: (items: T[] | undefined) => JSX.Element;
query?: UseInfiniteQueryResult<{ items: T[] }>;
query?: ReturnType<QT>;
items?: T[] | undefined;
minimizePadding?: true;
};
Expand Down Expand Up @@ -84,7 +89,7 @@ export const SongGridPageSection = (
);
};

export const ListPageSection = <T,>(
export const ListPageSection = <T extends Resource>(
props: Omit<PageSectionProps<T>, "child"> & {
builder: (item: T | undefined, index: number) => JSX.Element;
},
Expand Down Expand Up @@ -171,13 +176,12 @@ export const VideoListPageSection = (
);
};

const PageSection = <T,>(props: PageSectionProps<T>) => {
const PageSection = <T extends Resource>(props: PageSectionProps<T>) => {
const { t } = useTranslation();
const data = props.query?.data || props.items;
const firstPage = props.query?.data?.pages.at(0)?.items ?? props.items;
const data = props.query?.items || props.items;
return (
<>
{firstPage?.length !== 0 && (
{data?.length !== 0 && (
<>
<SectionHeader
heading={
Expand All @@ -187,8 +191,7 @@ const PageSection = <T,>(props: PageSectionProps<T>) => {
props.seeMoreHref ? (
<Fade
in={
(firstPage?.length ?? 0) >
props.maxItemCount
(data?.length ?? 0) > props.maxItemCount
}
>
<Link href={props.seeMoreHref}>
Expand All @@ -208,7 +211,7 @@ const PageSection = <T,>(props: PageSectionProps<T>) => {
) : undefined
}
/>
{props.child(firstPage)}
{props.child(data)}
<Box
sx={{
paddingBottom: props.minimizePadding
Expand Down
9 changes: 4 additions & 5 deletions front/src/pages/artists/[slugOrId]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,16 @@ const ArtistPage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
const appearances = useInfiniteQuery(appearanceQuery, artistIdentifier);
const externalMetadata = useQuery(externalMetadataQuery, artistIdentifier);
const { musicVideos, liveVideos, extras } = useMemo(() => {
const firstPage = videos.data?.pages.at(0)?.items;
return {
musicVideos:
firstPage?.filter(
videos.items?.filter(
(video) =>
!VideoTypeIsExtra(video.type) && video.type !== "Live",
) ?? [],
liveVideos:
firstPage?.filter((video) => video.type === "Live") ?? [],
videos.items?.filter((video) => video.type === "Live") ?? [],
extras:
firstPage?.filter((video) => VideoTypeIsExtra(video.type)) ??
videos.items?.filter((video) => VideoTypeIsExtra(video.type)) ??
[],
};
}, [videos]);
Expand Down Expand Up @@ -170,7 +169,7 @@ const ArtistPage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
.map(({ type, query }) => ({
type,
query,
queryData: query.data?.pages.at(0)?.items,
queryData: query.items,
}))
.filter(
({ queryData }) =>
Expand Down
28 changes: 13 additions & 15 deletions front/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ const albumRecommendations = (seed: number) =>

const HomePageSection = <T,>(props: {
heading: string | JSX.Element;
queryData: { data?: { pages?: { items?: T[] }[] } };
queryData: { items?: T[] };
render: (items: (T | undefined)[]) => JSX.Element;
}) => {
const items = props.queryData.data?.pages?.at(0)?.items;
const items = props.queryData.items;

// Remove the section if its content is empty
if (items !== undefined && items.length === 0) {
Expand Down Expand Up @@ -134,18 +134,16 @@ const HomePage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
props?.recommendationSeed ?? seed,
);
const featuredAlbumsExternalMetadata = useQueries(
...(featuredAlbums.data?.pages
.at(0)
?.items.map(
(
album,
): Parameters<
typeof useQuery<
AlbumExternalMetadata | null,
Parameters<typeof API.getAlbumExternalMetadata>
>
> => [API.getAlbumExternalMetadata, album.id],
) ?? []),
...(featuredAlbums.items?.map(
(
album,
): Parameters<
typeof useQuery<
AlbumExternalMetadata | null,
Parameters<typeof API.getAlbumExternalMetadata>
>
> => [API.getAlbumExternalMetadata, album.id],
) ?? []),
);

const newlyAddedAlbums = useInfiniteQuery(() => newlyAddedAlbumsQuery);
Expand All @@ -169,7 +167,7 @@ const HomePage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
newlyAddedReleases,
];
const illustrations = queries
.flatMap((query) => query.data?.pages.at(0)?.items ?? [])
.flatMap((query) => query.items ?? [])
.map(({ illustration }) => illustration)
.filter((illustration) => illustration !== null);
const selectedIllustrationColor = useMemo(() => {
Expand Down
43 changes: 18 additions & 25 deletions front/src/pages/releases/[slugOrId].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ const ReleasePage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
albumGenreQuery,
release.data?.albumId,
);
const hasGenres = (albumGenres.data?.pages.at(0)?.items.length ?? 1) > 0;
const hasGenres = (albumGenres.items?.length ?? 1) > 0;
const artists = useQuery(artistsOnAlbumQuery, release.data?.albumId);
const albumVideos = useInfiniteQuery(
albumVideosQuery,
Expand All @@ -242,12 +242,12 @@ const ReleasePage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
[artistId, artists],
);
const playlists = useMemo(
() => relatedPlaylists.data?.pages.at(0)?.items,
[relatedPlaylists.data],
() => relatedPlaylists.items,
[relatedPlaylists.items],
);
const { bSides, extras } = useMemo(
() =>
(bSidesQuery.data?.pages.at(0)?.items ?? []).reduce(
(bSidesQuery.items ?? []).reduce(
(prev, current) => {
if (["NonMusic", "Medley"].includes(current.type)) {
return {
Expand All @@ -267,7 +267,7 @@ const ReleasePage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
>[]
>,
),
[bSidesQuery.data],
[bSidesQuery.items],
);
const [tracks, totalDuration, trackList] = useMemo(() => {
if (tracklistQuery.data) {
Expand All @@ -288,7 +288,7 @@ const ReleasePage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
}, [tracklistQuery.data]);
const { videos, liveVideos, videoExtras } = useMemo(
() =>
(albumVideos.data?.pages.at(0)?.items ?? [])
(albumVideos.items ?? [])
.map((video) => {
const videoIndex = tracks.findIndex(
(track) =>
Expand Down Expand Up @@ -352,7 +352,7 @@ const ReleasePage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
VideoWithRelations<"master" | "illustration">[]
>,
),
[albumVideos.data, tracks],
[albumVideos.items, tracks],
);
const illustration = useMemo(
() => release.data?.illustration,
Expand Down Expand Up @@ -606,8 +606,8 @@ const ReleasePage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
</ListSubheader>
</Grid>
{(
albumGenres.data?.pages.at(0)
?.items ?? generateArray(3)
albumGenres?.items ??
generateArray(3)
)
.sort(
(a, b) =>
Expand Down Expand Up @@ -709,19 +709,15 @@ const ReleasePage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
/>
</RelatedContentSection>
<RelatedContentSection
display={
(relatedReleases.data?.pages.at(0)?.items?.length ??
0) > 1
}
display={(relatedReleases.items?.length ?? 0) > 1}
title={t("otherAlbumReleases")}
>
<TileRow
tiles={
relatedReleases.data?.pages
.at(0)
?.items?.filter(
relatedReleases.items
?.filter(
(relatedRelease) =>
relatedRelease.id !== release.data!.id,
relatedRelease.id !== release.data?.id,
)
.map((otherRelease, otherReleaseIndex) => (
<ReleaseTile
Expand Down Expand Up @@ -790,17 +786,13 @@ const ReleasePage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
)}
</RelatedContentSection>
<RelatedContentSection
display={
(relatedAlbums.data?.pages.at(0)?.items?.length ?? 0) >
0
}
display={(relatedAlbums.items?.length ?? 0) > 0}
title={t("relatedAlbums")}
>
<TileRow
tiles={
relatedAlbums.data?.pages
.at(0)
?.items?.map((otherAlbum, otherAlbumIndex) => (
relatedAlbums.items?.map(
(otherAlbum, otherAlbumIndex) => (
<AlbumTile
key={otherAlbumIndex}
album={otherAlbum}
Expand All @@ -810,7 +802,8 @@ const ReleasePage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
)?.toString() ?? ""
}
/>
)) ?? []
),
) ?? []
}
/>
</RelatedContentSection>
Expand Down
24 changes: 11 additions & 13 deletions front/src/pages/songs/[slugOrId]/[...tab].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,8 @@ const SongPage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
`${song.data?.name} (${t("moreInfo")})`
}
/>
{(!genres.data ||
(genres.data.pages.at(0)?.items.length ?? 0) !==
0) && (
{(genres.items === undefined ||
genres.items.length !== 0) && (
<Stack
direction="row"
sx={{
Expand All @@ -192,16 +191,15 @@ const SongPage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
<Typography sx={{ overflow: "unset" }}>
{`${t("genres")}: `}
</Typography>
{(
genres.data?.pages.at(0)?.items ??
generateArray(2)
).map((genre, index) => (
<GenreButton
sx={genreButtonOutline}
key={index}
genre={genre}
/>
))}
{(genres.items ?? generateArray(2)).map(
(genre, index) => (
<GenreButton
sx={genreButtonOutline}
key={index}
genre={genre}
/>
),
)}
</Stack>
)}
{(song.data === undefined ||
Expand Down

0 comments on commit b150907

Please sign in to comment.