From b369daa4afbdaf35abe35b91c00f8f45eb452150 Mon Sep 17 00:00:00 2001 From: Lauren Liberda Date: Wed, 21 Jul 2021 23:42:11 +0200 Subject: [PATCH] item list, paginated --- src/items/items.model.ts | 4 ++++ src/items/items.resolver.ts | 9 ++++++++- src/items/items.service.ts | 15 ++++++++++++++- src/paginated.output.ts | 20 ++++++++++++++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/paginated.output.ts diff --git a/src/items/items.model.ts b/src/items/items.model.ts index de5ab8c..cebbf16 100644 --- a/src/items/items.model.ts +++ b/src/items/items.model.ts @@ -1,4 +1,5 @@ import { Field, ID, ObjectType } from '@nestjs/graphql'; +import { Paginated } from '../paginated.output'; @ObjectType('Item', { description: 'Either the inventored thing or a box containing them', @@ -28,3 +29,6 @@ export class ItemModel { @Field((type) => [ItemModel]) descendants: ItemModel[]; } + +@ObjectType() +export class PaginatedItems extends Paginated(ItemModel) {} diff --git a/src/items/items.resolver.ts b/src/items/items.resolver.ts index f980371..ded1df4 100644 --- a/src/items/items.resolver.ts +++ b/src/items/items.resolver.ts @@ -9,7 +9,7 @@ import { } from '@nestjs/graphql'; import { NewItemInput } from './dto/new-item.input'; import { EANService } from './ean/ean.service'; -import { ItemModel } from './items.model'; +import { ItemModel, PaginatedItems } from './items.model'; import { ItemsService } from './items.service'; @Resolver((of) => ItemModel) @@ -21,6 +21,13 @@ export class ItemsResolver { return this.itemsService.getItem(id); } + @Query((returns) => PaginatedItems) + async itemList( + @Args('cursor', { type: () => ID, nullable: true }) cursor?: string, + ) { + return this.itemsService.getItemList(cursor ? parseInt(cursor, 10) : 0); + } + @ResolveField() ean13(@Parent() item: ItemModel) { return this.eans.fromID(item.id); diff --git a/src/items/items.service.ts b/src/items/items.service.ts index 38a657a..7fea028 100644 --- a/src/items/items.service.ts +++ b/src/items/items.service.ts @@ -4,7 +4,7 @@ import { EntityManager, Repository, TreeRepository } from 'typeorm'; import { NewItemInput } from './dto/new-item.input'; import { EANService } from './ean/ean.service'; import { Item } from './items.entity'; -import { ItemModel } from './items.model'; +import { ItemModel, PaginatedItems } from './items.model'; @Injectable() export class ItemsService { @@ -63,6 +63,19 @@ export class ItemsService { return (await this.treeRepository.findDescendants(parentItem)).slice(1); } + async getItemList(cursor: number = 0): Promise { + const [items, count] = await this.itemRepository.findAndCount({ + take: 25, + skip: cursor, + }); + return { + nodes: items, + cursor: cursor + items.length, + totalCount: count, + hasNextPage: count > cursor + items.length, + }; + } + async createItem(input: NewItemInput): Promise { // must use Repository.save() for the closure table to work, // so we have to check whether the provided ID exists in the first place diff --git a/src/paginated.output.ts b/src/paginated.output.ts new file mode 100644 index 0000000..d05972f --- /dev/null +++ b/src/paginated.output.ts @@ -0,0 +1,20 @@ +import { Field, ObjectType, Int, ID } from '@nestjs/graphql'; +import { Type } from '@nestjs/common'; + +export function Paginated(classRef: Type): any { + @ObjectType({ isAbstract: true }) + abstract class PaginatedType { + @Field((type) => [classRef]) + nodes: T[]; + + @Field((type) => ID, { nullable: true }) + cursor?: number; + + @Field((type) => Int) + totalCount: number; + + @Field() + hasNextPage: boolean; + } + return PaginatedType; +}