diff --git a/backend/src/modules/cards/applications/create-card.use-case.spec.ts b/backend/src/modules/cards/applications/create-card.use-case.spec.ts new file mode 100644 index 000000000..c57f53a9f --- /dev/null +++ b/backend/src/modules/cards/applications/create-card.use-case.spec.ts @@ -0,0 +1,163 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { CreateCardUseCase } from './create-card.use-case'; +import { TYPES } from '../interfaces/types'; +import { DeepMocked, createMock } from '@golevelup/ts-jest'; +import { CardRepositoryInterface } from '../repository/card.repository.interface'; +import faker from '@faker-js/faker'; +import { CardDtoFactory } from 'src/libs/test-utils/mocks/factories/dto/cardDto-factory.mock'; +import CreateCardUseCaseDto from '../dto/useCase/create-card.use-case.dto'; +import { CardFactory } from 'src/libs/test-utils/mocks/factories/card-factory.mock'; +import { BoardFactory } from 'src/libs/test-utils/mocks/factories/board-factory.mock'; +import { CardItemDtoFactory } from 'src/libs/test-utils/mocks/factories/dto/cardItemDto-factory.mock'; +import { CardItemFactory } from 'src/libs/test-utils/mocks/factories/cardItem-factory.mock'; +import { hideText } from 'src/libs/utils/hideText'; +import User from 'src/modules/users/entities/user.schema'; +import { BadRequestException, HttpException } from '@nestjs/common'; + +//Create Card Items Mocks +const cardIdtemDto = CardItemDtoFactory.create({ text: 'New Card', comments: [] }); + +const cardItemFactory = CardItemFactory.create({ + _id: cardIdtemDto._id, + text: cardIdtemDto.text, + comments: [], + anonymous: cardIdtemDto.anonymous, + votes: cardIdtemDto.votes +}); + +//Create Card Mocks +const cardDtoMock = CardDtoFactory.create({ + _id: faker.datatype.uuid(), + text: 'New Card', + comments: [], + votes: [], + items: [cardIdtemDto] +}); + +const newCardMock = CardFactory.create({ + _id: cardDtoMock._id, + text: cardDtoMock.text, + comments: [], + votes: [], + items: [cardItemFactory] +}); + +let boardMock; +let createCardUseCaseDtoMock: CreateCardUseCaseDto; + +describe('CreateCardUseCase', () => { + let useCase: CreateCardUseCase; + let cardRepositoryMock: DeepMocked; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + CreateCardUseCase, + { + provide: TYPES.repository.CardRepository, + useValue: createMock() + } + ] + }).compile(); + useCase = module.get(CreateCardUseCase); + cardRepositoryMock = module.get(TYPES.repository.CardRepository); + }); + + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + + //Create Mock Board + boardMock = BoardFactory.create(); + boardMock.columns[0]._id = 'colId'; + boardMock.columns[0].cards[0] = newCardMock; + cardRepositoryMock.pushCardWithPopulate.mockResolvedValue(boardMock); + + //Create Mock CreateCardUseCaseDto + createCardUseCaseDtoMock = { + boardId: faker.datatype.uuid(), + userId: faker.datatype.uuid(), + createCardDto: { + socketId: faker.datatype.uuid(), + colIdToAdd: 'colId', + card: cardDtoMock, + boardId: faker.datatype.uuid(), + newCard: null + } + }; + }); + + it('should be defined', () => { + expect(useCase).toBeDefined(); + }); + + it('should call cardRepository once', async () => { + await useCase.execute(createCardUseCaseDtoMock); + expect(cardRepositoryMock.pushCardWithPopulate).toHaveBeenCalledTimes(1); + }); + + it('should return new card and send a card with hidden data for the websocket', async () => { + boardMock.hideCards = true; + boardMock.hideVotes = true; + + cardRepositoryMock.pushCardWithPopulate.mockResolvedValueOnce(boardMock); + await expect(useCase.execute(createCardUseCaseDtoMock)).resolves.toEqual( + expect.objectContaining({ + newCardToReturn: expect.objectContaining({ _id: cardDtoMock._id, text: cardDtoMock.text }), + newCardToSocket: expect.objectContaining({ + text: hideText(cardDtoMock.text), + createdBy: expect.objectContaining({ + firstName: hideText((newCardMock.createdBy as User).firstName), + lastName: hideText((newCardMock.createdBy as User).lastName) + }) + }) + }) + ); + }); + + it('should return new card and a card with no hidden data for the websocket', async () => { + boardMock.hideCards = false; + boardMock.hideVotes = false; + boardMock.columns[0].cards[0].anonymous = false; + boardMock.columns[0].cards[0].createdByTeam = null; + + cardRepositoryMock.pushCardWithPopulate.mockResolvedValueOnce(boardMock); + await expect(useCase.execute(createCardUseCaseDtoMock)).resolves.toEqual( + expect.objectContaining({ + newCardToReturn: expect.objectContaining({ _id: cardDtoMock._id, text: cardDtoMock.text }), + newCardToSocket: expect.objectContaining({ + text: cardDtoMock.text, + createdBy: expect.objectContaining({ + firstName: (newCardMock.createdBy as User).firstName, + lastName: (newCardMock.createdBy as User).lastName + }) + }) + }) + ); + }); + + it('should return new card when card.items isEmpty', async () => { + createCardUseCaseDtoMock.createCardDto.card.items = []; + + await expect(useCase.execute(createCardUseCaseDtoMock)).resolves.toEqual( + expect.objectContaining({ + newCardToReturn: expect.objectContaining({ + items: expect.arrayContaining([expect.objectContaining({ text: cardDtoMock.text })]) + }) + }) + ); + }); + + it('should throw error if board.columns doesnt exists', async () => { + boardMock.columns = null; + cardRepositoryMock.pushCardWithPopulate.mockResolvedValueOnce(boardMock); + await expect(useCase.execute(createCardUseCaseDtoMock)).rejects.toThrowError(HttpException); + }); + + it('should return BadRequestException if insert fail ', async () => { + createCardUseCaseDtoMock.createCardDto.colIdToAdd = 'FakeColId'; + await expect(useCase.execute(createCardUseCaseDtoMock)).rejects.toThrowError( + BadRequestException + ); + }); +}); diff --git a/backend/src/modules/cards/applications/create-card.use-case.ts b/backend/src/modules/cards/applications/create-card.use-case.ts new file mode 100644 index 000000000..961c0b59b --- /dev/null +++ b/backend/src/modules/cards/applications/create-card.use-case.ts @@ -0,0 +1,95 @@ +import { BadRequestException, HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common'; +import { TYPES } from '../interfaces/types'; +import { UseCase } from 'src/libs/interfaces/use-case.interface'; +import CreateCardUseCaseDto from '../dto/useCase/create-card.use-case.dto'; +import { CardRepositoryInterface } from '../repository/card.repository.interface'; +import isEmpty from 'src/libs/utils/isEmpty'; +import CardItem from '../entities/card.item.schema'; +import { INSERT_FAILED } from 'src/libs/exceptions/messages'; +import CardCreationPresenter from '../dto/useCase/presenters/create-card-res.use-case.dto'; +import { replaceCard } from 'src/modules/boards/utils/clean-board'; +import Card from '../entities/card.schema'; +import { hideText } from 'src/libs/utils/hideText'; +import CardDto from '../dto/card.dto'; + +@Injectable() +export class CreateCardUseCase implements UseCase { + constructor( + @Inject(TYPES.repository.CardRepository) + private readonly cardRepository: CardRepositoryInterface + ) {} + + async execute(createCardUseCaseDto: CreateCardUseCaseDto) { + const { createCardDto, userId, boardId } = createCardUseCaseDto; + const { card, colIdToAdd } = createCardDto; + + const transformedCard = this.transformCardToStore(card, userId); + + const board = await this.cardRepository.pushCardWithPopulate( + boardId, + colIdToAdd, + 0, + transformedCard + ); + + if (!board.columns) throw new HttpException(INSERT_FAILED, HttpStatus.BAD_REQUEST); + + const newCard = this.extractCardFromBoard(board, colIdToAdd); + + const newCardToSocket = this.transformCardForSocket( + newCard, + userId, + board.hideCards, + board.hideVotes + ); + + return { + newCardToReturn: newCard, + newCardToSocket: newCardToSocket + }; + } + + private transformCardToStore(card: CardDto, userId: string) { + card.createdBy = userId; + + if (isEmpty(card.items)) { + (card.items as CardItem[]).push({ + text: card.text, + createdBy: userId, + comments: [], + votes: [], + anonymous: false, + createdByTeam: undefined, + createdAt: new Date() + }); + } else { + card.items[0].createdBy = userId; + } + + return card; + } + + private transformCardForSocket(newCard, userId: string, hideCards, hideVotes): Card { + const cardWithHiddenInfo = replaceCard( + newCard, + hideText(userId.toString()), + hideCards, + hideVotes + ); + + return cardWithHiddenInfo as Card; + } + + //Extract the card from the populated board + private extractCardFromBoard(board, colIdToAdd) { + try { + const colIndex = board.columns.findIndex((col) => col._id.toString() === colIdToAdd); + + const newCard = board.columns[colIndex].cards[0]; + + return newCard; + } catch { + throw new BadRequestException(INSERT_FAILED); + } + } +} diff --git a/backend/src/modules/cards/applications/create.card.application.ts b/backend/src/modules/cards/applications/create.card.application.ts deleted file mode 100644 index e7ca7401a..000000000 --- a/backend/src/modules/cards/applications/create.card.application.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import CardDto from '../dto/card.dto'; -import { CreateCardApplicationInterface } from '../interfaces/applications/create.card.application.interface'; -import { CreateCardServiceInterface } from '../interfaces/services/create.card.service.interface'; -import { TYPES } from '../interfaces/types'; - -@Injectable() -export class CreateCardApplication implements CreateCardApplicationInterface { - constructor( - @Inject(TYPES.services.CreateCardService) - private createCardService: CreateCardServiceInterface - ) {} - - create(cardId: string, userId: string, card: CardDto, colIdToAdd: string) { - return this.createCardService.create(cardId, userId, card, colIdToAdd); - } -} diff --git a/backend/src/modules/cards/cards.module.ts b/backend/src/modules/cards/cards.module.ts index 9594d5982..b7aee5f7c 100644 --- a/backend/src/modules/cards/cards.module.ts +++ b/backend/src/modules/cards/cards.module.ts @@ -4,8 +4,7 @@ import SocketModule from '../socket/socket.module'; import { VotesModule } from '../votes/votes.module'; import { cardRepository, - createCardApplication, - createCardService, + creacteCardUseCase, deleteCardApplication, deleteCardService, getCardService, @@ -22,19 +21,18 @@ import CardsController from './controller/cards.controller'; imports: [mongooseBoardModule, forwardRef(() => SocketModule), forwardRef(() => VotesModule)], controllers: [CardsController], providers: [ - createCardService, updateCardService, getCardService, deleteCardService, updateCardService, mergeCardService, unmergeCardService, - createCardApplication, updateCardApplication, deleteCardApplication, mergeCardApplication, unmergeCardApplication, - cardRepository + cardRepository, + creacteCardUseCase ], exports: [getCardService, deleteCardService] }) diff --git a/backend/src/modules/cards/cards.providers.ts b/backend/src/modules/cards/cards.providers.ts index 89017e9e8..7e0221693 100644 --- a/backend/src/modules/cards/cards.providers.ts +++ b/backend/src/modules/cards/cards.providers.ts @@ -1,22 +1,16 @@ -import { CreateCardApplication } from './applications/create.card.application'; +import { CreateCardUseCase } from './applications/create-card.use-case'; import { DeleteCardApplication } from './applications/delete.card.application'; import { MergeCardApplication } from './applications/merge.card.application'; import { UnmergeCardApplication } from './applications/unmerge.card.application'; import { UpdateCardApplication } from './applications/update.card.application'; import { TYPES } from './interfaces/types'; import { CardRepository } from './repository/card.repository'; -import CreateCardService from './services/create.card.service'; import DeleteCardService from './services/delete.card.service'; import GetCardService from './services/get.card.service'; import { MergeCardService } from './services/merge.card.service'; import { UnmergeCardService } from './services/unmerge.card.service'; import UpdateCardService from './services/update.card.service'; -export const createCardService = { - provide: TYPES.services.CreateCardService, - useClass: CreateCardService -}; - export const getCardService = { provide: TYPES.services.GetCardService, useClass: GetCardService @@ -42,11 +36,6 @@ export const unmergeCardService = { useClass: UnmergeCardService }; -export const createCardApplication = { - provide: TYPES.applications.CreateCardApplication, - useClass: CreateCardApplication -}; - export const updateCardApplication = { provide: TYPES.applications.UpdateCardApplication, useClass: UpdateCardApplication @@ -71,3 +60,8 @@ export const cardRepository = { provide: TYPES.repository.CardRepository, useClass: CardRepository }; + +export const creacteCardUseCase = { + provide: TYPES.applications.CreateCardUseCase, + useClass: CreateCardUseCase +}; diff --git a/backend/src/modules/cards/controller/cards.controller.ts b/backend/src/modules/cards/controller/cards.controller.ts index 5cb28d79e..fcafe564e 100644 --- a/backend/src/modules/cards/controller/cards.controller.ts +++ b/backend/src/modules/cards/controller/cards.controller.ts @@ -28,7 +28,7 @@ import { CardGroupParams } from 'src/libs/dto/param/card.group.params'; import { CardItemParams } from 'src/libs/dto/param/card.item.params'; import { MergeCardsParams } from 'src/libs/dto/param/merge.cards.params'; import { UnmergeCardsParams } from 'src/libs/dto/param/unmerge.cards.params'; -import { INSERT_FAILED, UPDATE_FAILED } from 'src/libs/exceptions/messages'; +import { UPDATE_FAILED } from 'src/libs/exceptions/messages'; import JwtAuthenticationGuard from 'src/libs/guards/jwtAuth.guard'; import RequestWithUser from 'src/libs/interfaces/requestWithUser.interface'; import { BadRequestResponse } from 'src/libs/swagger/errors/bad-request.swagger'; @@ -43,14 +43,13 @@ import UpdateCardDto from '../dto/update.card.dto'; import { UpdateCardPositionDto } from '../dto/update-position.card.dto'; import { TYPES } from '../interfaces/types'; import { MergeCardDto } from '../dto/group/merge.card.dto'; -import { replaceCard } from 'src/modules/boards/utils/clean-board'; -import Card from '../entities/card.schema'; -import { hideText } from 'src/libs/utils/hideText'; -import { CreateCardApplicationInterface } from '../interfaces/applications/create.card.application.interface'; import { UpdateCardApplicationInterface } from '../interfaces/applications/update.card.application.interface'; import { DeleteCardApplicationInterface } from '../interfaces/applications/delete.card.application.interface'; import { MergeCardApplicationInterface } from '../interfaces/applications/merge.card.application.interface'; import { UnmergeCardApplicationInterface } from '../interfaces/applications/unmerge.card.application.interface'; +import CreateCardUseCaseDto from '../dto/useCase/create-card.use-case.dto'; +import { UseCase } from 'src/libs/interfaces/use-case.interface'; +import CardCreationPresenter from '../dto/useCase/presenters/create-card-res.use-case.dto'; @ApiBearerAuth('access-token') @ApiTags('Cards') @@ -58,8 +57,8 @@ import { UnmergeCardApplicationInterface } from '../interfaces/applications/unme @Controller('boards') export default class CardsController { constructor( - @Inject(TYPES.applications.CreateCardApplication) - private createCardApp: CreateCardApplicationInterface, + @Inject(TYPES.applications.CreateCardUseCase) + private createCardUseCase: UseCase, @Inject(TYPES.applications.UpdateCardApplication) private updateCardApp: UpdateCardApplicationInterface, @Inject(TYPES.applications.DeleteCardApplication) @@ -95,28 +94,18 @@ export default class CardsController { @Param() { boardId }: BaseParam, @Body() createCardDto: CreateCardDto ) { - const { card, colIdToAdd, socketId } = createCardDto; + const { socketId } = createCardDto; - const { newCard, hideCards, hideVotes } = await this.createCardApp.create( + const { newCardToReturn, newCardToSocket } = await this.createCardUseCase.execute({ boardId, - request.user._id, - card, - colIdToAdd - ); - - if (!newCard) throw new BadRequestException(INSERT_FAILED); - - const cardWithHiddenInfo = replaceCard( - newCard, - hideText(request.user._id.toString()), - hideCards, - hideVotes - ); + userId: request.user._id, + createCardDto + }); - createCardDto.newCard = cardWithHiddenInfo as Card; + createCardDto.newCard = newCardToSocket; this.socketService.sendAddCard(socketId, createCardDto); - return newCard; + return newCardToReturn; } @ApiOperation({ summary: 'Delete a specific card' }) diff --git a/backend/src/modules/cards/dto/useCase/create-card.use-case.dto.ts b/backend/src/modules/cards/dto/useCase/create-card.use-case.dto.ts new file mode 100644 index 000000000..ebbe409b9 --- /dev/null +++ b/backend/src/modules/cards/dto/useCase/create-card.use-case.dto.ts @@ -0,0 +1,19 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNotEmpty, IsString } from 'class-validator'; +import { CreateCardDto } from '../create.card.dto'; + +export default class CreateCardUseCaseDto { + @ApiProperty() + @IsNotEmpty() + @IsString() + boardId: string; + + @ApiProperty() + @IsNotEmpty() + @IsString() + userId: string; + + @ApiProperty() + @IsNotEmpty() + createCardDto: CreateCardDto; +} diff --git a/backend/src/modules/cards/dto/useCase/presenters/create-card-res.use-case.dto.ts b/backend/src/modules/cards/dto/useCase/presenters/create-card-res.use-case.dto.ts new file mode 100644 index 000000000..63e235181 --- /dev/null +++ b/backend/src/modules/cards/dto/useCase/presenters/create-card-res.use-case.dto.ts @@ -0,0 +1,13 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNotEmpty } from 'class-validator'; +import Card from 'src/modules/cards/entities/card.schema'; + +export default class CardCreationPresenter { + @ApiProperty() + @IsNotEmpty() + newCardToReturn: Card; + + @ApiProperty() + @IsNotEmpty() + newCardToSocket: Card; +} diff --git a/backend/src/modules/cards/interfaces/applications/create.card.application.interface.ts b/backend/src/modules/cards/interfaces/applications/create.card.application.interface.ts deleted file mode 100644 index 1c15de853..000000000 --- a/backend/src/modules/cards/interfaces/applications/create.card.application.interface.ts +++ /dev/null @@ -1,15 +0,0 @@ -import CardDto from '../../dto/card.dto'; -import Card from '../../entities/card.schema'; - -export interface CreateCardApplicationInterface { - create( - boardId: string, - userId: string, - card: CardDto, - colIdToAdd: string - ): Promise<{ - newCard: Card; - hideCards: boolean; - hideVotes: boolean; - }>; -} diff --git a/backend/src/modules/cards/interfaces/services/create.card.service.interface.ts b/backend/src/modules/cards/interfaces/services/create.card.service.interface.ts deleted file mode 100644 index eddcf3e54..000000000 --- a/backend/src/modules/cards/interfaces/services/create.card.service.interface.ts +++ /dev/null @@ -1,15 +0,0 @@ -import CardDto from '../../dto/card.dto'; -import Card from '../../entities/card.schema'; - -export interface CreateCardServiceInterface { - create( - boardId: string, - userId: string, - card: CardDto, - colIdToAdd: string - ): Promise<{ - newCard: Card; - hideCards: boolean; - hideVotes: boolean; - }>; -} diff --git a/backend/src/modules/cards/interfaces/types.ts b/backend/src/modules/cards/interfaces/types.ts index d01bbe8b4..f494777bf 100644 --- a/backend/src/modules/cards/interfaces/types.ts +++ b/backend/src/modules/cards/interfaces/types.ts @@ -12,7 +12,8 @@ export const TYPES = { DeleteCardApplication: 'DeleteCardApplication', UpdateCardApplication: 'UpdateCardApplication', MergeCardApplication: 'MergeCardApplication', - UnmergeCardApplication: 'UnmergeCardApplication' + UnmergeCardApplication: 'UnmergeCardApplication', + CreateCardUseCase: 'CreateCardUseCase' }, repository: { CardRepository: 'CardRepository' diff --git a/backend/src/modules/cards/services/create.card.service.spec.ts b/backend/src/modules/cards/services/create.card.service.spec.ts deleted file mode 100644 index 262d055da..000000000 --- a/backend/src/modules/cards/services/create.card.service.spec.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { CreateCardServiceInterface } from '../interfaces/services/create.card.service.interface'; -import CreateCardService from './create.card.service'; -import { TYPES } from '../interfaces/types'; -import { DeepMocked, createMock } from '@golevelup/ts-jest'; -import { CardRepositoryInterface } from '../repository/card.repository.interface'; -import { CardDtoFactory } from 'src/libs/test-utils/mocks/factories/dto/cardDto-factory.mock'; -import { BoardFactory } from 'src/libs/test-utils/mocks/factories/board-factory.mock'; -import { HttpException } from '@nestjs/common'; - -const cardDtoMock = CardDtoFactory.create(); -const boardMock = BoardFactory.create(); -describe('CreateCardService', () => { - let service: CreateCardServiceInterface; - let cardRepositoryMock: DeepMocked; - beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - CreateCardService, - { - provide: TYPES.repository.CardRepository, - useValue: createMock() - } - ] - }).compile(); - service = module.get(CreateCardService); - cardRepositoryMock = module.get(TYPES.repository.CardRepository); - cardRepositoryMock.pushCardWithPopulate.mockResolvedValue(boardMock); - }); - - beforeEach(() => { - jest.clearAllMocks(); - jest.restoreAllMocks(); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); - - it('should call cardRepository once', async () => { - await service.create('someBoardId', 'someUserId', cardDtoMock, boardMock.columns[0]._id); - expect(cardRepositoryMock.pushCardWithPopulate).toHaveBeenCalledTimes(1); - }); - - it('should return new card when card.items is not empty', async () => { - const colIndex = boardMock.columns.findIndex( - (col) => col._id.toString() === boardMock.columns[0]._id - ); - - await expect( - service.create('someBoardId', 'someUserId', cardDtoMock, boardMock.columns[0]._id) - ).resolves.toEqual( - expect.objectContaining({ - newCard: boardMock.columns[colIndex].cards[0], - hideCards: boardMock.hideCards, - hideVotes: boardMock.hideVotes - }) - ); - }); - - it('should return new card when card.items isEmpty', async () => { - cardDtoMock.items = []; - const colIndex = boardMock.columns.findIndex( - (col) => col._id.toString() === boardMock.columns[0]._id - ); - - await expect( - service.create('someBoardId', 'someUserId', cardDtoMock, boardMock.columns[0]._id) - ).resolves.toEqual( - expect.objectContaining({ - newCard: boardMock.columns[colIndex].cards[0], - hideCards: boardMock.hideCards, - hideVotes: boardMock.hideVotes - }) - ); - }); - - it('should throw error if board.columns doesnt exists', async () => { - boardMock.columns = null; - await expect( - service.create('someBoardId', 'someUserId', cardDtoMock, 'wrongColId') - ).rejects.toThrowError(HttpException); - }); -}); diff --git a/backend/src/modules/cards/services/create.card.service.ts b/backend/src/modules/cards/services/create.card.service.ts deleted file mode 100644 index 9a74e8b3c..000000000 --- a/backend/src/modules/cards/services/create.card.service.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common'; -import { INSERT_FAILED } from 'src/libs/exceptions/messages'; -import isEmpty from 'src/libs/utils/isEmpty'; -import CardDto from '../dto/card.dto'; -import { CreateCardServiceInterface } from '../interfaces/services/create.card.service.interface'; -import CardItem from '../entities/card.item.schema'; -import { TYPES } from '../interfaces/types'; -import { CardRepositoryInterface } from '../repository/card.repository.interface'; - -@Injectable() -export default class CreateCardService implements CreateCardServiceInterface { - constructor( - @Inject(TYPES.repository.CardRepository) - private readonly cardRepository: CardRepositoryInterface - ) {} - - async create(boardId: string, userId: string, card: CardDto, colIdToAdd: string) { - card.createdBy = userId; - - if (isEmpty(card.items)) { - (card.items as CardItem[]).push({ - text: card.text, - createdBy: userId, - comments: [], - votes: [], - anonymous: false, - createdByTeam: undefined, - createdAt: new Date() - }); - } else { - card.items[0].createdBy = userId; - } - - const board = await this.cardRepository.pushCardWithPopulate(boardId, colIdToAdd, 0, card); - - if (!board.columns) throw new HttpException(INSERT_FAILED, HttpStatus.BAD_REQUEST); - - const colIndex = board.columns.findIndex((col) => col._id.toString() === colIdToAdd); - - return { - newCard: board.columns[colIndex].cards[0], - hideCards: board.hideCards, - hideVotes: board.hideVotes - }; - } -}