diff --git a/src/items/dto/new-item.input.ts b/src/items/dto/new-item.input.ts index f8bbce1..bcd221e 100644 --- a/src/items/dto/new-item.input.ts +++ b/src/items/dto/new-item.input.ts @@ -7,4 +7,7 @@ export class NewItemInput { @Field({ nullable: true }) notes?: string; + + @Field((type) => ID, { nullable: true }) + parent?: number; } diff --git a/src/items/items.entity.ts b/src/items/items.entity.ts index 783ab8d..fc2dfaf 100644 --- a/src/items/items.entity.ts +++ b/src/items/items.entity.ts @@ -1,13 +1,29 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { + Column, + Entity, + PrimaryGeneratedColumn, + Tree, + TreeChildren, + TreeParent, +} from 'typeorm'; @Entity() +@Tree('closure-table', { + closureTableName: 'item_closure', +}) export class Item { - @PrimaryGeneratedColumn('increment') - id: number; + @PrimaryGeneratedColumn('increment', { type: 'bigint' }) + id: string; @Column() name: string; @Column({ nullable: true }) notes?: string; + + @TreeParent() + parent?: Item; + + @TreeChildren() + children: Item[]; } diff --git a/src/items/items.model.ts b/src/items/items.model.ts index b4028a8..fabb7ad 100644 --- a/src/items/items.model.ts +++ b/src/items/items.model.ts @@ -12,4 +12,7 @@ export class ItemModel { @Field({ nullable: true }) notes?: string; + + @Field({ nullable: true }) + parent?: ItemModel; } diff --git a/src/items/items.resolver.ts b/src/items/items.resolver.ts index e67b5c7..b1b4697 100644 --- a/src/items/items.resolver.ts +++ b/src/items/items.resolver.ts @@ -1,4 +1,12 @@ -import { Args, ID, Mutation, Query, Resolver } from '@nestjs/graphql'; +import { + Args, + ID, + Mutation, + Parent, + Query, + ResolveField, + Resolver, +} from '@nestjs/graphql'; import { NewItemInput } from './dto/new-item.input'; import { ItemModel } from './items.model'; import { ItemsService } from './items.service'; @@ -12,6 +20,12 @@ export class ItemsResolver { return this.itemsService.getItem(id); } + @ResolveField() + async parent(@Parent() item: ItemModel) { + if (item.parent) return item.parent; + return this.itemsService.getItemParent(item); + } + @Mutation((returns) => ItemModel) async createItem(@Args('itemData') itemData: NewItemInput) { return this.itemsService.createItem(itemData); diff --git a/src/items/items.service.ts b/src/items/items.service.ts index 7b93af6..f3ce947 100644 --- a/src/items/items.service.ts +++ b/src/items/items.service.ts @@ -1,24 +1,39 @@ import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; +import { InjectEntityManager, InjectRepository } from '@nestjs/typeorm'; +import { EntityManager, Repository, TreeRepository } from 'typeorm'; import { NewItemInput } from './dto/new-item.input'; import { Item } from './items.entity'; +import { ItemModel } from './items.model'; @Injectable() export class ItemsService { constructor( @InjectRepository(Item) private itemRepository: Repository, - ) {} + @InjectEntityManager() + private entityManager: EntityManager, + ) { + this.treeRepository = this.entityManager.getTreeRepository(Item); + } + treeRepository: TreeRepository; async getItem(id: string): Promise { return this.itemRepository.findOne(id); } + async getItemParent(item: ItemModel) { + const itemE = await this.itemRepository.findOneOrFail(item.id); + return (await this.treeRepository.findAncestorsTree(itemE)).parent; + } + async createItem(input: NewItemInput): Promise { const item = new Item(); item.name = input.name; item.notes = input.notes; + if (input.parent) { + const parent = await this.itemRepository.findOneOrFail(input.parent); + item.parent = parent; + } return this.itemRepository.save(item); } }