Refactor all api instances in components

This commit is contained in:
jeffvli 2023-04-30 22:01:52 -07:00
parent bdd023fde3
commit 314bd766df
56 changed files with 879 additions and 755 deletions

View file

@ -1,13 +1,5 @@
import { MutableRefObject, useCallback, useMemo } from 'react';
import {
Button,
getColumnDefs,
GridCarousel,
Text,
TextTitle,
useFixedTableHeader,
VirtualTable,
} from '/@/renderer/components';
import { Button, GridCarousel, Text, TextTitle } from '/@/renderer/components';
import { ColDef, RowDoubleClickedEvent, RowHeightParams, RowNode } from '@ag-grid-community/core';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { Box, Group, Stack } from '@mantine/core';
@ -33,6 +25,12 @@ import { PlayButton, useCreateFavorite, useDeleteFavorite } from '/@/renderer/fe
import { useAlbumList } from '/@/renderer/features/albums/queries/album-list-query';
import { AlbumListSort, LibraryItem, QueueSong, SortOrder } from '/@/renderer/api/types';
import { usePlayQueueAdd } from '/@/renderer/features/player';
import { useCurrentServer } from '/@/renderer/store';
import {
getColumnDefs,
useFixedTableHeader,
VirtualTable,
} from '/@/renderer/components/virtual-table';
const isFullWidthRow = (node: RowNode) => {
return node.id?.includes('disc-');
@ -60,7 +58,8 @@ interface AlbumDetailContentProps {
export const AlbumDetailContent = ({ tableRef }: AlbumDetailContentProps) => {
const { albumId } = useParams() as { albumId: string };
const detailQuery = useAlbumDetail({ id: albumId });
const server = useCurrentServer();
const detailQuery = useAlbumDetail({ query: { id: albumId }, serverId: server?.id });
const cq = useContainerQuery();
const handlePlayQueueAdd = usePlayQueueAdd();
@ -165,26 +164,29 @@ export const AlbumDetailContent = ({ tableRef }: AlbumDetailContentProps) => {
const itemsPerPage = cq.isXl ? 9 : cq.isLg ? 7 : cq.isMd ? 5 : cq.isSm ? 4 : 3;
const artistQuery = useAlbumList(
{
jfParams: {
albumArtistIds: detailQuery?.data?.albumArtists[0]?.id,
},
limit: itemsPerPage,
ndParams: {
artist_id: detailQuery?.data?.albumArtists[0]?.id,
},
sortBy: AlbumListSort.YEAR,
sortOrder: SortOrder.DESC,
startIndex: pagination.artist * itemsPerPage,
},
{
const artistQuery = useAlbumList({
options: {
cacheTime: 1000 * 60,
enabled: detailQuery?.data?.albumArtists[0]?.id !== undefined,
keepPreviousData: true,
staleTime: 1000 * 60,
},
);
query: {
_custom: {
jellyfin: {
albumArtistIds: detailQuery?.data?.albumArtists[0]?.id,
},
navidrome: {
artist_id: detailQuery?.data?.albumArtists[0]?.id,
},
},
limit: itemsPerPage,
sortBy: AlbumListSort.YEAR,
sortOrder: SortOrder.DESC,
startIndex: pagination.artist * itemsPerPage,
},
serverId: server?.id,
});
const carousels = [
{
@ -227,8 +229,8 @@ export const AlbumDetailContent = ({ tableRef }: AlbumDetailContentProps) => {
});
};
const createFavoriteMutation = useCreateFavorite();
const deleteFavoriteMutation = useDeleteFavorite();
const createFavoriteMutation = useCreateFavorite({});
const deleteFavoriteMutation = useDeleteFavorite({});
const handleFavorite = () => {
if (!detailQuery?.data) return;

View file

@ -5,9 +5,10 @@ import { Link } from 'react-router-dom';
import { LibraryItem, ServerType } from '/@/renderer/api/types';
import { Button, Rating, Text } from '/@/renderer/components';
import { useAlbumDetail } from '/@/renderer/features/albums/queries/album-detail-query';
import { LibraryHeader, useUpdateRating } from '/@/renderer/features/shared';
import { LibraryHeader, useSetRating } from '/@/renderer/features/shared';
import { useContainerQuery } from '/@/renderer/hooks';
import { AppRoute } from '/@/renderer/router/routes';
import { useCurrentServer } from '/@/renderer/store';
import { formatDurationString } from '/@/renderer/utils';
interface AlbumDetailHeaderProps {
@ -17,7 +18,8 @@ interface AlbumDetailHeaderProps {
export const AlbumDetailHeader = forwardRef(
({ background }: AlbumDetailHeaderProps, ref: Ref<HTMLDivElement>) => {
const { albumId } = useParams() as { albumId: string };
const detailQuery = useAlbumDetail({ id: albumId });
const server = useCurrentServer();
const detailQuery = useAlbumDetail({ query: { id: albumId }, serverId: server?.id });
const cq = useContainerQuery();
const metadataItems = [
@ -38,17 +40,17 @@ export const AlbumDetailHeader = forwardRef(
},
];
const updateRatingMutation = useUpdateRating();
const updateRatingMutation = useSetRating({});
const handleUpdateRating = (rating: number) => {
if (!detailQuery?.data) return;
updateRatingMutation.mutate({
_serverId: detailQuery?.data.serverId,
query: {
item: [detailQuery.data],
rating,
},
serverId: detailQuery.data.serverId,
});
};
@ -56,11 +58,11 @@ export const AlbumDetailHeader = forwardRef(
if (!detailQuery?.data || !detailQuery?.data.userRating) return;
updateRatingMutation.mutate({
_serverId: detailQuery.data.serverId,
query: {
item: [detailQuery.data],
rating: 0,
},
serverId: detailQuery.data.serverId,
});
};

View file

@ -1,12 +1,4 @@
import {
ALBUM_CARD_ROWS,
getColumnDefs,
TablePagination,
VirtualGridAutoSizerContainer,
VirtualInfiniteGrid,
VirtualInfiniteGridRef,
VirtualTable,
} from '/@/renderer/components';
import { ALBUM_CARD_ROWS } from '/@/renderer/components';
import { AppRoute } from '/@/renderer/router/routes';
import { ListDisplayType, CardRow } from '/@/renderer/types';
import AutoSizer from 'react-virtualized-auto-sizer';
@ -40,6 +32,12 @@ import { generatePath, useNavigate } from 'react-router';
import { usePlayQueueAdd } from '/@/renderer/features/player';
import { useCreateFavorite, useDeleteFavorite } from '/@/renderer/features/shared';
import { useAlbumListContext } from '/@/renderer/features/albums/context/album-list-context';
import {
VirtualInfiniteGridRef,
VirtualGridAutoSizerContainer,
VirtualInfiniteGrid,
} from '/@/renderer/components/virtual-grid';
import { getColumnDefs, VirtualTable, TablePagination } from '/@/renderer/components/virtual-table';
interface AlbumListContentProps {
gridRef: MutableRefObject<VirtualInfiniteGridRef | null>;
@ -71,29 +69,36 @@ export const AlbumListContent = ({ itemCount, gridRef, tableRef }: AlbumListCont
limit,
startIndex,
...filter,
jfParams: {
...filter.jfParams,
},
ndParams: {
...filter.ndParams,
_custom: {
jellyfin: {
...filter._custom?.jellyfin,
},
navidrome: {
...filter._custom?.navidrome,
},
},
};
const queryKey = queryKeys.albums.list(server?.id || '', query);
if (!server) {
return params.failCallback();
}
const albumsRes = await queryClient.fetchQuery(
queryKey,
async ({ signal }) =>
api.controller.getAlbumList({
apiClientProps: {
server,
signal,
},
query,
server,
signal,
}),
{ cacheTime: 1000 * 60 * 1 },
);
const albums = api.normalize.albumList(albumsRes, server);
params.successCallback(albums?.items || [], albumsRes?.totalRecordCount || 0);
return params.successCallback(albumsRes?.items || [], albumsRes?.totalRecordCount || 0);
},
rowCount: undefined,
};
@ -165,15 +170,21 @@ export const AlbumListContent = ({ itemCount, gridRef, tableRef }: AlbumListCont
const fetch = useCallback(
async ({ skip, take }: { skip: number; take: number }) => {
if (!server) {
return [];
}
const query: AlbumListQuery = {
limit: take,
startIndex: skip,
...filter,
jfParams: {
...filter.jfParams,
},
ndParams: {
...filter.ndParams,
_custom: {
jellyfin: {
...filter._custom?.jellyfin,
},
navidrome: {
...filter._custom?.navidrome,
},
},
};
@ -181,13 +192,15 @@ export const AlbumListContent = ({ itemCount, gridRef, tableRef }: AlbumListCont
const albums = await queryClient.fetchQuery(queryKey, async ({ signal }) =>
controller.getAlbumList({
apiClientProps: {
server,
signal,
},
query,
server,
signal,
}),
);
return api.normalize.albumList(albums, server);
return albums;
},
[filter, queryClient, server],
);
@ -268,8 +281,8 @@ export const AlbumListContent = ({ itemCount, gridRef, tableRef }: AlbumListCont
navigate(generatePath(AppRoute.LIBRARY_ALBUMS_DETAIL, { albumId: e.data.id }));
};
const createFavoriteMutation = useCreateFavorite();
const deleteFavoriteMutation = useDeleteFavorite();
const createFavoriteMutation = useCreateFavorite({});
const deleteFavoriteMutation = useDeleteFavorite({});
const handleFavorite = (options: {
id: string[];

View file

@ -20,16 +20,7 @@ import {
import { api } from '/@/renderer/api';
import { queryKeys } from '/@/renderer/api/query-keys';
import { AlbumListQuery, AlbumListSort, LibraryItem, SortOrder } from '/@/renderer/api/types';
import {
ALBUM_TABLE_COLUMNS,
Button,
DropdownMenu,
MultiSelect,
Slider,
Switch,
Text,
VirtualInfiniteGridRef,
} from '/@/renderer/components';
import { Button, DropdownMenu, MultiSelect, Slider, Switch, Text } from '/@/renderer/components';
import { useContainerQuery } from '/@/renderer/hooks';
import {
AlbumListFilter,
@ -43,6 +34,8 @@ import { usePlayQueueAdd } from '/@/renderer/features/player';
import { JellyfinAlbumFilters } from '/@/renderer/features/albums/components/jellyfin-album-filters';
import { NavidromeAlbumFilters } from '/@/renderer/features/albums/components/navidrome-album-filters';
import { useAlbumListContext } from '/@/renderer/features/albums/context/album-list-context';
import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';
import { ALBUM_TABLE_COLUMNS } from '/@/renderer/components/virtual-table';
const FILTERS = {
jellyfin: [
@ -100,7 +93,7 @@ export const AlbumListHeaderFilters = ({
const { display, filter, table, grid } = useAlbumListStore({ id, key: pageKey });
const cq = useContainerQuery();
const musicFoldersQuery = useMusicFolders();
const musicFoldersQuery = useMusicFolders({ query: null, serverId: server?.id });
const sortByLabel =
(server?.type &&
@ -115,13 +108,15 @@ export const AlbumListHeaderFilters = ({
limit: take,
startIndex: skip,
...filters,
jfParams: {
...filters.jfParams,
...customFilters?.jfParams,
},
ndParams: {
...filters.ndParams,
...customFilters?.ndParams,
_custom: {
jellyfin: {
...filters._custom?.jellyfin,
...customFilters?._custom?.jellyfin,
},
navidrome: {
...filters._custom?.navidrome,
...customFilters?._custom?.navidrome,
},
},
...customFilters,
};
@ -132,14 +127,16 @@ export const AlbumListHeaderFilters = ({
queryKey,
async ({ signal }) =>
api.controller.getAlbumList({
apiClientProps: {
server,
signal,
},
query,
server,
signal,
}),
{ cacheTime: 1000 * 60 * 1 },
);
return api.normalize.albumList(albums, server);
return albums;
},
[customFilters, queryClient, server],
);
@ -157,13 +154,15 @@ export const AlbumListHeaderFilters = ({
startIndex,
...filters,
...customFilters,
jfParams: {
...filters.jfParams,
...customFilters?.jfParams,
},
ndParams: {
...filters.ndParams,
...customFilters?.ndParams,
_custom: {
jellyfin: {
...filters._custom?.jellyfin,
...customFilters?._custom?.jellyfin,
},
navidrome: {
...filters._custom?.navidrome,
...customFilters?._custom?.navidrome,
},
},
};
@ -173,15 +172,16 @@ export const AlbumListHeaderFilters = ({
queryKey,
async ({ signal }) =>
api.controller.getAlbumList({
apiClientProps: {
server,
signal,
},
query,
server,
signal,
}),
{ cacheTime: 1000 * 60 * 1 },
);
const albums = api.normalize.albumList(albumsRes, server);
params.successCallback(albums?.items || [], albumsRes?.totalRecordCount || 0);
return params.successCallback(albumsRes?.items || [], albumsRes?.totalRecordCount || 0);
},
rowCount: undefined,
};
@ -218,6 +218,7 @@ export const AlbumListHeaderFilters = ({
handleFilterChange={handleFilterChange}
id={id}
pageKey={pageKey}
serverId={server?.id}
/>
) : (
<JellyfinAlbumFilters
@ -225,6 +226,7 @@ export const AlbumListHeaderFilters = ({
handleFilterChange={handleFilterChange}
id={id}
pageKey={pageKey}
serverId={server?.id}
/>
)}
</>
@ -293,30 +295,32 @@ export const AlbumListHeaderFilters = ({
const handlePlayQueueAdd = usePlayQueueAdd();
const handlePlay = async (play: Play) => {
if (!itemCount || itemCount === 0) return;
if (!itemCount || itemCount === 0 || !server) return;
const query = {
startIndex: 0,
...filter,
...customFilters,
jfParams: {
...filter.jfParams,
...customFilters?.jfParams,
},
ndParams: {
...filter.ndParams,
...customFilters?.ndParams,
_custom: {
jellyfin: {
...filter._custom?.jellyfin,
...customFilters?._custom?.jellyfin,
},
navidrome: {
...filter._custom?.navidrome,
...customFilters?._custom?.navidrome,
},
},
};
const queryKey = queryKeys.albums.list(server?.id || '', query);
const albumListRes = await queryClient.fetchQuery({
queryFn: ({ signal }) => api.controller.getAlbumList({ query, server, signal }),
queryFn: ({ signal }) =>
api.controller.getAlbumList({ apiClientProps: { server, signal }, query }),
queryKey,
});
const albumIds =
api.normalize.albumList(albumListRes, server).items?.map((item) => item.id) || [];
const albumIds = albumListRes?.items?.map((a) => a.id) || [];
handlePlayQueueAdd?.({
byItemType: {
@ -382,16 +386,16 @@ export const AlbumListHeaderFilters = ({
const isFilterApplied = useMemo(() => {
const isNavidromeFilterApplied =
server?.type === ServerType.NAVIDROME &&
filter.ndParams &&
Object.values(filter.ndParams).some((value) => value !== undefined);
filter?._custom.navidrome &&
Object.values(filter._custom.navidrome).some((value) => value !== undefined);
const isJellyfinFilterApplied =
server?.type === ServerType.JELLYFIN &&
filter.jfParams &&
Object.values(filter.jfParams).some((value) => value !== undefined);
filter?._custom.jellyfin &&
Object.values(filter._custom.jellyfin).some((value) => value !== undefined);
return isNavidromeFilterApplied || isJellyfinFilterApplied;
}, [filter.jfParams, filter.ndParams, server?.type]);
}, [filter._custom.jellyfin, filter._custom.navidrome, server?.type]);
return (
<Flex justify="space-between">
@ -456,7 +460,7 @@ export const AlbumListHeaderFilters = ({
</Button>
</DropdownMenu.Target>
<DropdownMenu.Dropdown>
{musicFoldersQuery.data?.map((folder) => (
{musicFoldersQuery.data?.items.map((folder) => (
<DropdownMenu.Item
key={`musicFolder-${folder.id}`}
$isActive={filter.musicFolderId === folder.id}

View file

@ -9,7 +9,7 @@ import { api } from '/@/renderer/api';
import { controller } from '/@/renderer/api/controller';
import { queryKeys } from '/@/renderer/api/query-keys';
import { AlbumListQuery, LibraryItem } from '/@/renderer/api/types';
import { PageHeader, SearchInput, VirtualInfiniteGridRef } from '/@/renderer/components';
import { PageHeader, SearchInput } from '/@/renderer/components';
import { FilterBar, LibraryHeaderBar } from '/@/renderer/features/shared';
import { useContainerQuery } from '/@/renderer/hooks';
import {
@ -24,6 +24,7 @@ import { AlbumListHeaderFilters } from '/@/renderer/features/albums/components/a
import { usePlayQueueAdd } from '/@/renderer/features/player';
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
import { useAlbumListContext } from '/@/renderer/features/albums/context/album-list-context';
import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';
interface AlbumListHeaderProps {
customFilters?: Partial<AlbumListFilter>;
@ -54,15 +55,17 @@ export const AlbumListHeader = ({
limit: take,
startIndex: skip,
...filters,
jfParams: {
...filters.jfParams,
...customFilters?.jfParams,
},
ndParams: {
...filters.ndParams,
...customFilters?.ndParams,
},
...customFilters,
_custom: {
jellyfin: {
...filters._custom?.jellyfin,
...customFilters?._custom?.jellyfin,
},
navidrome: {
...filters._custom?.navidrome,
...customFilters?._custom?.navidrome,
},
},
};
const queryKey = queryKeys.albums.list(server?.id || '', query);
@ -71,14 +74,16 @@ export const AlbumListHeader = ({
queryKey,
async ({ signal }) =>
controller.getAlbumList({
apiClientProps: {
server,
signal,
},
query,
server,
signal,
}),
{ cacheTime: 1000 * 60 * 1 },
);
return api.normalize.albumList(albums, server);
return albums;
},
[customFilters, queryClient, server],
);
@ -96,13 +101,15 @@ export const AlbumListHeader = ({
startIndex,
...filters,
...customFilters,
jfParams: {
...filters.jfParams,
...customFilters?.jfParams,
},
ndParams: {
...filters.ndParams,
...customFilters?.ndParams,
_custom: {
jellyfin: {
...filters._custom?.jellyfin,
...customFilters?._custom?.jellyfin,
},
navidrome: {
...filters._custom?.navidrome,
...customFilters?._custom?.navidrome,
},
},
};
@ -112,15 +119,16 @@ export const AlbumListHeader = ({
queryKey,
async ({ signal }) =>
api.controller.getAlbumList({
apiClientProps: {
server,
signal,
},
query,
server,
signal,
}),
{ cacheTime: 1000 * 60 * 1 },
);
const albums = api.normalize.albumList(albumsRes, server);
params.successCallback(albums?.items || [], albumsRes?.totalRecordCount || 0);
params.successCallback(albumsRes?.items || [], albumsRes?.totalRecordCount || 0);
},
rowCount: undefined,
};
@ -164,24 +172,26 @@ export const AlbumListHeader = ({
startIndex: 0,
...filter,
...customFilters,
jfParams: {
...filter.jfParams,
...customFilters?.jfParams,
},
ndParams: {
...filter.ndParams,
...customFilters?.ndParams,
_custom: {
jellyfin: {
...filter._custom?.jellyfin,
...customFilters?._custom?.jellyfin,
},
navidrome: {
...filter._custom?.navidrome,
...customFilters?._custom?.navidrome,
},
},
};
const queryKey = queryKeys.albums.list(server?.id || '', query);
const albumListRes = await queryClient.fetchQuery({
queryFn: ({ signal }) => api.controller.getAlbumList({ query, server, signal }),
queryFn: ({ signal }) =>
api.controller.getAlbumList({ apiClientProps: { server, signal }, query }),
queryKey,
});
const albumIds =
api.normalize.albumList(albumListRes, server).items?.map((item) => item.id) || [];
const albumIds = albumListRes?.items?.map((item) => item.id) || [];
handlePlayQueueAdd?.({
byItemType: {

View file

@ -12,6 +12,7 @@ interface JellyfinAlbumFiltersProps {
handleFilterChange: (filters: AlbumListFilter) => void;
id?: string;
pageKey: string;
serverId?: string;
}
export const JellyfinAlbumFilters = ({
@ -19,24 +20,25 @@ export const JellyfinAlbumFilters = ({
handleFilterChange,
pageKey,
id,
serverId,
}: JellyfinAlbumFiltersProps) => {
const filter = useAlbumListFilter({ id, key: pageKey });
const { setFilter } = useListStoreActions();
// TODO - eventually replace with /items/filters endpoint to fetch genres and tags specific to the selected library
const genreListQuery = useGenreList(null);
const genreListQuery = useGenreList({ query: null, serverId });
const genreList = useMemo(() => {
if (!genreListQuery?.data) return [];
return genreListQuery.data.map((genre) => ({
return genreListQuery.data.items.map((genre) => ({
label: genre.name,
value: genre.id,
}));
}, [genreListQuery.data]);
const selectedGenres = useMemo(() => {
return filter.jfParams?.genreIds?.split(',');
}, [filter.jfParams?.genreIds]);
return filter._custom?.jellyfin?.genreIds?.split(',');
}, [filter._custom?.jellyfin?.genreIds]);
const toggleFilters = [
{
@ -44,17 +46,19 @@ export const JellyfinAlbumFilters = ({
onChange: (e: ChangeEvent<HTMLInputElement>) => {
const updatedFilters = setFilter({
data: {
jfParams: {
...filter.jfParams,
includeItemTypes: 'Audio',
isFavorite: e.currentTarget.checked ? true : undefined,
_custom: {
...filter._custom,
jellyfin: {
...filter._custom?.jellyfin,
isFavorite: e.currentTarget.checked ? true : undefined,
},
},
},
key: pageKey,
}) as AlbumListFilter;
handleFilterChange(updatedFilters);
},
value: filter.jfParams?.isFavorite,
value: filter._custom?.jellyfin?.isFavorite,
},
];
@ -62,9 +66,12 @@ export const JellyfinAlbumFilters = ({
if (typeof e === 'number' && (e < 1700 || e > 2300)) return;
const updatedFilters = setFilter({
data: {
jfParams: {
...filter.jfParams,
minYear: e === '' ? undefined : (e as number),
_custom: {
...filter._custom,
jellyfin: {
...filter._custom?.jellyfin,
minYear: e === '' ? undefined : (e as number),
},
},
},
key: pageKey,
@ -76,9 +83,12 @@ export const JellyfinAlbumFilters = ({
if (typeof e === 'number' && (e < 1700 || e > 2300)) return;
const updatedFilters = setFilter({
data: {
jfParams: {
...filter.jfParams,
maxYear: e === '' ? undefined : (e as number),
_custom: {
...filter._custom,
jellyfin: {
...filter._custom?.jellyfin,
maxYear: e === '' ? undefined : (e as number),
},
},
},
key: pageKey,
@ -90,9 +100,12 @@ export const JellyfinAlbumFilters = ({
const genreFilterString = e?.length ? e.join(',') : undefined;
const updatedFilters = setFilter({
data: {
jfParams: {
...filter.jfParams,
genreIds: genreFilterString,
_custom: {
...filter._custom,
jellyfin: {
...filter._custom?.jellyfin,
genreIds: genreFilterString,
},
},
},
key: pageKey,
@ -102,17 +115,18 @@ export const JellyfinAlbumFilters = ({
const [albumArtistSearchTerm, setAlbumArtistSearchTerm] = useState<string>('');
const albumArtistListQuery = useAlbumArtistList(
{
const albumArtistListQuery = useAlbumArtistList({
options: {
cacheTime: 1000 * 60 * 2,
staleTime: 1000 * 60 * 1,
},
query: {
sortBy: AlbumArtistListSort.NAME,
sortOrder: SortOrder.ASC,
startIndex: 0,
},
{
cacheTime: 1000 * 60 * 2,
staleTime: 1000 * 60 * 1,
},
);
serverId,
});
const selectableAlbumArtists = useMemo(() => {
if (!albumArtistListQuery?.data?.items) return [];
@ -127,9 +141,12 @@ export const JellyfinAlbumFilters = ({
const albumArtistFilterString = e?.length ? e.join(',') : undefined;
const updatedFilters = setFilter({
data: {
jfParams: {
...filter.jfParams,
albumArtistIds: albumArtistFilterString,
_custom: {
...filter._custom,
jellyfin: {
...filter._custom?.jellyfin,
albumArtistIds: albumArtistFilterString,
},
},
},
key: pageKey,
@ -155,21 +172,21 @@ export const JellyfinAlbumFilters = ({
<Divider my="0.5rem" />
<Group grow>
<NumberInput
defaultValue={filter.jfParams?.minYear}
defaultValue={filter._custom?.jellyfin?.minYear}
hideControls={false}
label="From year"
max={2300}
min={1700}
required={!!filter.jfParams?.maxYear}
required={!!filter._custom?.jellyfin?.maxYear}
onChange={(e) => handleMinYearFilter(e)}
/>
<NumberInput
defaultValue={filter.jfParams?.maxYear}
defaultValue={filter._custom?.jellyfin?.maxYear}
hideControls={false}
label="To year"
max={2300}
min={1700}
required={!!filter.jfParams?.minYear}
required={!!filter._custom?.jellyfin?.minYear}
onChange={(e) => handleMaxYearFilter(e)}
/>
</Group>
@ -189,7 +206,7 @@ export const JellyfinAlbumFilters = ({
clearable
searchable
data={selectableAlbumArtists}
defaultValue={filter.jfParams?.albumArtistIds?.split(',')}
defaultValue={filter._custom?.jellyfin?.albumArtistIds?.split(',')}
disabled={disableArtistFilter}
label="Artist"
limit={300}

View file

@ -12,6 +12,7 @@ interface NavidromeAlbumFiltersProps {
handleFilterChange: (filters: AlbumListFilter) => void;
id?: string;
pageKey: string;
serverId?: string;
}
export const NavidromeAlbumFilters = ({
@ -19,15 +20,16 @@ export const NavidromeAlbumFilters = ({
disableArtistFilter,
pageKey,
id,
serverId,
}: NavidromeAlbumFiltersProps) => {
const filter = useAlbumListFilter({ id, key: pageKey });
const { setFilter } = useListStoreActions();
const genreListQuery = useGenreList(null);
const genreListQuery = useGenreList({ query: null, serverId });
const genreList = useMemo(() => {
if (!genreListQuery?.data) return [];
return genreListQuery.data.map((genre) => ({
return genreListQuery.data.items.map((genre) => ({
label: genre.name,
value: genre.id,
}));
@ -36,9 +38,12 @@ export const NavidromeAlbumFilters = ({
const handleGenresFilter = debounce((e: string | null) => {
const updatedFilters = setFilter({
data: {
ndParams: {
...filter.ndParams,
genre_id: e || undefined,
_custom: {
...filter._custom,
navidrome: {
...filter._custom?.navidrome,
genre_id: e || undefined,
},
},
},
key: 'album',
@ -52,70 +57,89 @@ export const NavidromeAlbumFilters = ({
onChange: (e: ChangeEvent<HTMLInputElement>) => {
const updatedFilters = setFilter({
data: {
ndParams: {
...filter.ndParams,
has_rating: e.currentTarget.checked ? true : undefined,
_custom: {
...filter._custom,
navidrome: {
...filter._custom?.navidrome,
has_rating: e.currentTarget.checked ? true : undefined,
},
},
},
key: pageKey,
}) as AlbumListFilter;
handleFilterChange(updatedFilters);
},
value: filter.ndParams?.has_rating,
value: filter._custom?.navidrome?.has_rating,
},
{
label: 'Is favorited',
onChange: (e: ChangeEvent<HTMLInputElement>) => {
console.log('e.currentTarget.checked :>> ', e.currentTarget.checked);
const updatedFilters = setFilter({
data: {
ndParams: { ...filter.ndParams, starred: e.currentTarget.checked ? true : undefined },
_custom: {
...filter._custom,
navidrome: {
...filter._custom?.navidrome,
starred: e.currentTarget.checked ? true : undefined,
},
},
},
key: pageKey,
}) as AlbumListFilter;
handleFilterChange(updatedFilters);
},
value: filter.ndParams?.starred,
value: filter._custom?.navidrome?.starred,
},
{
label: 'Is compilation',
onChange: (e: ChangeEvent<HTMLInputElement>) => {
const updatedFilters = setFilter({
data: {
ndParams: {
...filter.ndParams,
compilation: e.currentTarget.checked ? true : undefined,
_custom: {
...filter._custom,
navidrome: {
...filter._custom?.navidrome,
compilation: e.currentTarget.checked ? true : undefined,
},
},
},
key: pageKey,
}) as AlbumListFilter;
handleFilterChange(updatedFilters);
},
value: filter.ndParams?.compilation,
value: filter._custom?.navidrome?.compilation,
},
{
label: 'Is recently played',
onChange: (e: ChangeEvent<HTMLInputElement>) => {
const updatedFilters = setFilter({
data: {
ndParams: {
...filter.ndParams,
recently_played: e.currentTarget.checked ? true : undefined,
_custom: {
...filter._custom,
navidrome: {
...filter._custom?.navidrome,
recently_played: e.currentTarget.checked ? true : undefined,
},
},
},
key: pageKey,
}) as AlbumListFilter;
handleFilterChange(updatedFilters);
},
value: filter.ndParams?.recently_played,
value: filter._custom?.navidrome?.recently_played,
},
];
const handleYearFilter = debounce((e: number | string) => {
const updatedFilters = setFilter({
data: {
ndParams: {
...filter.ndParams,
year: e === '' ? undefined : (e as number),
_custom: {
navidrome: {
...filter._custom?.navidrome,
year: e === '' ? undefined : (e as number),
},
...filter._custom,
},
},
key: pageKey,
@ -125,18 +149,19 @@ export const NavidromeAlbumFilters = ({
const [albumArtistSearchTerm, setAlbumArtistSearchTerm] = useState<string>('');
const albumArtistListQuery = useAlbumArtistList(
{
const albumArtistListQuery = useAlbumArtistList({
options: {
cacheTime: 1000 * 60 * 2,
staleTime: 1000 * 60 * 1,
},
query: {
// searchTerm: debouncedSearchTerm,
sortBy: AlbumArtistListSort.NAME,
sortOrder: SortOrder.ASC,
startIndex: 0,
},
{
cacheTime: 1000 * 60 * 2,
staleTime: 1000 * 60 * 1,
},
);
serverId,
});
const selectableAlbumArtists = useMemo(() => {
if (!albumArtistListQuery?.data?.items) return [];
@ -150,9 +175,12 @@ export const NavidromeAlbumFilters = ({
const handleAlbumArtistFilter = (e: string | null) => {
const updatedFilters = setFilter({
data: {
ndParams: {
...filter.ndParams,
artist_id: e || undefined,
_custom: {
...filter._custom,
navidrome: {
...filter._custom?.navidrome,
artist_id: e || undefined,
},
},
},
key: pageKey,
@ -177,7 +205,7 @@ export const NavidromeAlbumFilters = ({
<Divider my="0.5rem" />
<Group grow>
<NumberInput
defaultValue={filter.ndParams?.year}
defaultValue={filter._custom?.navidrome?.year}
hideControls={false}
label="Year"
max={5000}
@ -188,7 +216,7 @@ export const NavidromeAlbumFilters = ({
clearable
searchable
data={genreList}
defaultValue={filter.ndParams?.genre_id}
defaultValue={filter._custom?.navidrome?.genre_id}
label="Genre"
onChange={handleGenresFilter}
/>
@ -198,7 +226,7 @@ export const NavidromeAlbumFilters = ({
clearable
searchable
data={selectableAlbumArtists}
defaultValue={filter.ndParams?.artist_id}
defaultValue={filter._custom?.navidrome?.artist_id}
disabled={disableArtistFilter}
label="Artist"
limit={300}