Merge pull request #362 from Hexastack/fix/pagination

fix: pagination
This commit is contained in:
Med Marrouchi 2024-11-22 16:18:26 +01:00 committed by GitHub
commit cf154bfe32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 132 additions and 45 deletions

View File

@ -48,13 +48,13 @@ import { BlockCreateDto, BlockUpdateDto } from '../dto/block.dto';
import { BlockRepository } from '../repositories/block.repository';
import { CategoryRepository } from '../repositories/category.repository';
import { LabelRepository } from '../repositories/label.repository';
import { BlockModel, Block } from '../schemas/block.schema';
import { Block, BlockModel } from '../schemas/block.schema';
import { LabelModel } from '../schemas/label.schema';
import { BlockService } from '../services/block.service';
import { CategoryService } from '../services/category.service';
import { LabelService } from '../services/label.service';
import { CategoryModel, Category } from './../schemas/category.schema';
import { Category, CategoryModel } from './../schemas/category.schema';
import { BlockController } from './block.controller';
describe('BlockController', () => {
@ -167,7 +167,7 @@ describe('BlockController', () => {
blockFixture.name === 'hasNextBlocks' ? [hasPreviousBlocks.id] : [],
}));
expect(blockService.find).toHaveBeenCalledWith({});
expect(blockService.find).toHaveBeenCalledWith({}, undefined);
expect(result).toEqualPayload(blocksWithCategory, [
...IGNORED_TEST_FIELDS,
'attachedToBlock',
@ -187,7 +187,7 @@ describe('BlockController', () => {
blockFixture.name === 'hasNextBlocks' ? [hasPreviousBlocks] : [],
}));
expect(blockService.findAndPopulate).toHaveBeenCalledWith({});
expect(blockService.findAndPopulate).toHaveBeenCalledWith({}, undefined);
expect(result).toEqualPayload(blocksWithCategory);
});
});

View File

@ -30,6 +30,8 @@ import { PluginName, PluginType } from '@/plugins/types';
import { UserService } from '@/user/services/user.service';
import { BaseController } from '@/utils/generics/base-controller';
import { DeleteResult } from '@/utils/generics/base-repository';
import { PageQueryDto } from '@/utils/pagination/pagination-query.dto';
import { PageQueryPipe } from '@/utils/pagination/pagination-query.pipe';
import { PopulatePipe } from '@/utils/pipes/populate.pipe';
import { SearchFilterPipe } from '@/utils/pipes/search-filter.pipe';
import { TFilterQuery } from '@/utils/types/filter.types';
@ -63,23 +65,29 @@ export class BlockController extends BaseController<
) {
super(blockService);
}
/**
* Finds blocks based on the provided query parameters.
* @param populate - An array of fields to populate in the returned blocks.
* @param filters - Query filters to apply to the block search.
* @returns A Promise that resolves to an array of found blocks.
*/
@Get()
async find(
@Query(PopulatePipe)
populate: string[],
@Query(new SearchFilterPipe<Block>({ allowedFields: ['category'] }))
filters: TFilterQuery<Block>,
@Query(PageQueryPipe) pageQuery?: PageQueryDto<Block>,
): Promise<Block[] | BlockFull[]> {
if (pageQuery?.limit) {
return this.canPopulate(populate)
? await this.blockService.findAndPopulate(filters)
: await this.blockService.find(filters);
? await this.blockService.findPageAndPopulate(filters, pageQuery)
: await this.blockService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.blockService.findAndPopulate(filters, pageQuery?.sort)
: await this.blockService.find(filters, pageQuery?.sort);
}
/**

View File

@ -57,9 +57,13 @@ export class CategoryController extends BaseController<Category> {
@Query(new SearchFilterPipe<Category>({ allowedFields: ['label'] }))
filters: TFilterQuery<Category>,
) {
if (pageQuery.limit) {
return await this.categoryService.findPage(filters, pageQuery);
}
return await this.categoryService.find(filters, pageQuery.sort);
}
/**
* Counts the filtered number of categories.
* @returns A promise that resolves to an object representing the filtered number of categories.

View File

@ -60,9 +60,13 @@ export class ContextVarController extends BaseController<ContextVar> {
@Query(new SearchFilterPipe<ContextVar>({ allowedFields: ['label'] }))
filters: TFilterQuery<ContextVar>,
): Promise<ContextVar[]> {
if (pageQuery.limit) {
return await this.contextVarService.findPage(filters, pageQuery);
}
return await this.contextVarService.find(filters, pageQuery.sort);
}
/**
* Counts the filtered number of contextVars.
* @returns A promise that resolves to an object representing the filtered number of contextVars.

View File

@ -62,11 +62,17 @@ export class LabelController extends BaseController<
@Query(new SearchFilterPipe<Label>({ allowedFields: ['name', 'title'] }))
filters: TFilterQuery<Label>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.labelService.findPageAndPopulate(filters, pageQuery)
: await this.labelService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.labelService.findAndPopulate(filters, pageQuery.sort)
: await this.labelService.find(filters, pageQuery.sort);
}
/**
* Counts the filtered number of labels.
* @returns A promise that resolves to an object representing the filtered number of labels.

View File

@ -42,6 +42,7 @@ import {
MessageStub,
} from '../schemas/message.schema';
import {
AnyMessage,
OutgoingMessage,
OutgoingMessageFormat,
StdOutgoingEnvelope,
@ -71,7 +72,7 @@ export class MessageController extends BaseController<
@Get()
async findPage(
@Query(PageQueryPipe) pageQuery: PageQueryDto<Message>,
@Query(PageQueryPipe) pageQuery: PageQueryDto<AnyMessage>,
@Query(PopulatePipe)
populate: string[],
@Query(
@ -79,11 +80,17 @@ export class MessageController extends BaseController<
)
filters: TFilterQuery<Message>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.messageService.findPageAndPopulate(filters, pageQuery)
: await this.messageService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.messageService.findAndPopulate(filters, pageQuery.sort)
: await this.messageService.find(filters, pageQuery.sort);
}
/**
* Counts the filtered number of messages.
* @returns A promise that resolves to an object representing the filtered number of messages.

View File

@ -73,11 +73,17 @@ export class SubscriberController extends BaseController<
)
filters: TFilterQuery<Subscriber>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.subscriberService.findPageAndPopulate(filters, pageQuery)
: await this.subscriberService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.subscriberService.findAndPopulate(filters, pageQuery.sort)
: await this.subscriberService.find(filters, pageQuery.sort);
}
/**
* Counts the filtered number of subscribers.
* @returns A promise that resolves to an object representing the filtered number of subscribers.

View File

@ -75,9 +75,13 @@ export class ContentTypeController extends BaseController<ContentType> {
@Query(new SearchFilterPipe<ContentType>({ allowedFields: ['name'] }))
filters: TFilterQuery<ContentType>,
) {
if (pageQuery.limit) {
return await this.contentTypeService.findPage(filters, pageQuery);
}
return await this.contentTypeService.find(filters, pageQuery.sort);
}
/**
* Retrieves the count of content types matching the provided filters.
*

View File

@ -194,10 +194,15 @@ export class ContentController extends BaseController<
)
filters: TFilterQuery<Content>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.contentService.findPageAndPopulate(filters, pageQuery)
: await this.contentService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.contentService.findAndPopulate(filters, pageQuery.sort)
: await this.contentService.find(filters, pageQuery.sort);
}
/**
* Counts the filtered number of contents based on the provided filters.

View File

@ -76,9 +76,13 @@ export class MenuController extends BaseController<
@Query(new SearchFilterPipe<Menu>({ allowedFields: ['parent'] }))
filters: TFilterQuery<Menu>,
) {
if (pageQuery.limit) {
return await this.menuService.findPage(filters, pageQuery);
}
return await this.menuService.find(filters, pageQuery.sort);
}
/**
* Creates a new menu item.
*

View File

@ -57,9 +57,13 @@ export class LanguageController extends BaseController<Language> {
@Query(new SearchFilterPipe<Language>({ allowedFields: ['title', 'code'] }))
filters: TFilterQuery<Language>,
) {
if (pageQuery.limit) {
return await this.languageService.findPage(filters, pageQuery);
}
return await this.languageService.find(filters, pageQuery.sort);
}
/**
* Counts the filtered number of languages.
* @returns A promise that resolves to an object representing the filtered number of languages.

View File

@ -55,8 +55,11 @@ export class TranslationController extends BaseController<Translation> {
@Query(new SearchFilterPipe<Translation>({ allowedFields: ['str'] }))
filters: TFilterQuery<Translation>,
) {
if (pageQuery.limit) {
return await this.translationService.findPage(filters, pageQuery);
}
return await this.translationService.find(filters, pageQuery.sort);
}
/**
* Counts the filtered number of translations.

View File

@ -135,11 +135,17 @@ export class NlpEntityController extends BaseController<
@Query(new SearchFilterPipe<NlpEntity>({ allowedFields: ['name', 'doc'] }))
filters: TFilterQuery<NlpEntity>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.nlpEntityService.findPageAndPopulate(filters, pageQuery)
: await this.nlpEntityService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.nlpEntityService.findAndPopulate(filters)
: await this.nlpEntityService.find(filters, pageQuery.sort);
}
/**
* Updates an NLP entity by ID.
*

View File

@ -280,11 +280,17 @@ export class NlpSampleController extends BaseController<
)
filters: TFilterQuery<NlpSample>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.nlpSampleService.findPageAndPopulate(filters, pageQuery)
: await this.nlpSampleService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.nlpSampleService.findAndPopulate(filters, pageQuery.sort)
: await this.nlpSampleService.find(filters, pageQuery.sort);
}
/**
* Updates an existing NLP sample by its ID.
*

View File

@ -146,11 +146,17 @@ export class NlpValueController extends BaseController<
)
filters: TFilterQuery<NlpValue>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.nlpValueService.findPageAndPopulate(filters, pageQuery)
: await this.nlpValueService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.nlpValueService.findAndPopulate(filters, pageQuery.sort)
: await this.nlpValueService.find(filters, pageQuery.sort);
}
/**
* Updates an existing NLP value by ID.
*

View File

@ -68,11 +68,17 @@ export class RoleController extends BaseController<
@Query(new SearchFilterPipe<Role>({ allowedFields: ['name'] }))
filters: TFilterQuery<Role>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.roleService.findPageAndPopulate(filters, pageQuery)
: await this.roleService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.roleService.findAndPopulate(filters, pageQuery.sort)
: await this.roleService.find(filters, pageQuery.sort);
}
/**
* Counts the number of roles that match the provided filters.
*

View File

@ -168,9 +168,15 @@ export class ReadOnlyUserController extends BaseController<
)
filters: TFilterQuery<User>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.userService.findPageAndPopulate(filters, pageQuery)
: await this.userService.find(filters);
: await this.userService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.userService.findAndPopulate(filters, pageQuery.sort)
: await this.userService.find(filters, pageQuery.sort);
}
/**

View File

@ -16,7 +16,7 @@ export type QuerySortDto<T> = [
];
export type PageQueryDto<T> = {
skip: number;
limit: number;
skip: number | undefined;
limit: number | undefined;
sort: QuerySortDto<T>;
};

View File

@ -14,19 +14,21 @@ import { PageQueryDto } from './pagination-query.dto';
const sortTypes = ['asc', 'desc'];
export type PageQueryParams = { skip?: string; limit?: string; sort?: string };
export class PageQueryPipe<T>
implements
PipeTransform<
{ skip: string; limit: string; sort: string },
PageQueryDto<T>
>
implements PipeTransform<PageQueryParams, PageQueryDto<T>>
{
transform(value: { skip: string; limit: string; sort: string }) {
const skip = parseInt(value.skip) > -1 ? parseInt(value.skip) : 0;
const limit =
transform(value: PageQueryParams) {
let skip: number | undefined = undefined;
let limit: number | undefined = undefined;
if ('limit' in value) {
skip = parseInt(value.skip) > -1 ? parseInt(value.skip) : 0;
limit =
parseInt(value.limit) > 0
? parseInt(value.limit)
: config.pagination.limit;
}
const [sortName = 'createdAt', sortType = 'desc'] =
value.sort?.split(' ') || [];