feat: catalogue server side filtering, ordering, pagination

This commit is contained in:
Aleksi Lassila
2025-03-29 15:16:29 +02:00
parent 3e88d42a24
commit 3c775492ea
13 changed files with 403 additions and 105 deletions

View File

@@ -22,7 +22,7 @@ import {
SuccessResponseDto,
} from 'src/common/common.dto';
import {
CatalogueFilter,
CatalogueTypeFilter as CatalogueTypeFilter,
LibraryItemDto,
MyListOrder,
MyListStatusFilter,
@@ -75,20 +75,29 @@ export class LibraryController {
}
@Get('catalogue/:sourceId')
@ApiQuery({ name: 'type', enum: CatalogueTypeFilter, required: false })
@ApiQuery({ name: 'order', required: false })
@ApiQuery({ name: 'direction', required: false })
@PaginatedApiOkResponse(LibraryItemDto)
async getCatalogue(
@GetPaginationParams() pagination: PaginationParamsDto,
@Param('userId') userId: string,
@Param('sourceId') sourceId: string,
@GetAuthToken() token: string,
@Query('filter', new ParseEnumPipe(CatalogueFilter, { optional: true }))
filter: CatalogueFilter = CatalogueFilter.All,
@Query('type', new ParseEnumPipe(CatalogueTypeFilter, { optional: true }))
type?: CatalogueTypeFilter,
@Query('order')
order?: string,
@Query('direction')
direction?: string,
): Promise<PaginatedResponseDto<LibraryItemDto>> {
const items = this.libraryService.getCatalogueItems({
sourceId,
token,
pagination,
filter,
type,
order,
direction,
});
if (!items) {

View File

@@ -28,7 +28,7 @@ export enum MyListTypeFilter {
All = 'all',
}
export enum CatalogueFilter {
export enum CatalogueTypeFilter {
All = 'all',
Movies = 'movies',
Series = 'series',

View File

@@ -14,6 +14,7 @@ import {
MyListOrder,
OrderDirection,
MyListStatusFilter,
CatalogueTypeFilter,
} from './library.dto';
import { LibraryItem } from './library.entity';
import { USER_LIBRARY_REPOSITORY } from './library.providers';
@@ -244,9 +245,18 @@ export class LibraryService {
sourceId: string;
token: string;
pagination: PaginationParamsDto;
filter?: 'all' | 'movies' | 'series' | 'missing';
type?: CatalogueTypeFilter;
order?: string;
direction?: string;
}): Promise<PaginatedResponseDto<LibraryItemDto> | undefined> {
const { sourceId, token, pagination, filter = 'all' } = options;
const {
sourceId,
token,
pagination,
type = CatalogueTypeFilter.All,
order,
direction,
} = options;
const connection = await this.mediaSourceService.getConnection(sourceId);
@@ -256,16 +266,18 @@ export class LibraryService {
const movies = connection.provider.catalogueProvider.getMovieCatalogue;
const series = connection.provider.catalogueProvider.getSeriesCatalogue;
const missing = connection.provider.catalogueProvider.getMissingInCatalogue;
if (filter === 'all' && combined) {
const response = await combined(
{
if (type === CatalogueTypeFilter.All && combined) {
const response = await combined({
context: {
userId: connection.mediaSource.userId,
settings: connection.mediaSource.pluginSettings,
sourceId: connection.mediaSource.id,
token,
},
pagination,
);
order,
direction,
});
return {
...response,
@@ -273,16 +285,18 @@ export class LibraryService {
response.items.map(async (item) => this.getLibraryItemDto(item)),
),
};
} else if (filter === 'movies' && movies) {
const response = await movies(
{
} else if (type === CatalogueTypeFilter.Movies && movies) {
const response = await movies({
context: {
userId: connection.mediaSource.userId,
settings: connection.mediaSource.pluginSettings,
sourceId: connection.mediaSource.id,
token,
},
pagination,
);
order,
direction,
});
return {
...response,
@@ -290,16 +304,18 @@ export class LibraryService {
response.items.map(async (item) => this.getLibraryItemDto(item)),
),
};
} else if (filter === 'series' && series) {
const response = await series(
{
} else if (type === CatalogueTypeFilter.Series && series) {
const response = await series({
context: {
userId: connection.mediaSource.userId,
settings: connection.mediaSource.pluginSettings,
sourceId: connection.mediaSource.id,
token,
},
pagination,
);
order,
direction,
});
return {
...response,
@@ -307,7 +323,7 @@ export class LibraryService {
response.items.map(async (item) => this.getLibraryItemDto(item)),
),
};
} else if (filter === 'missing' && missing) {
} else if (type === CatalogueTypeFilter.Missing && missing) {
const tmdbIdToMyListItem: Record<string, LibraryItem> = {};
const myListItems = await this.getMyList({
pagination: {
@@ -324,16 +340,18 @@ export class LibraryService {
tmdbIdToMyListItem[i.tmdbId] = i;
});
const response = await missing(
{
const response = await missing({
context: {
userId: connection.mediaSource.userId,
settings: connection.mediaSource.pluginSettings,
sourceId: connection.mediaSource.id,
token,
},
pagination,
tmdbIdToMyListItem,
);
myListItems: tmdbIdToMyListItem,
order,
direction,
});
return {
...response,