solutions system

This commit is contained in:
mmacierzanka committed 2023-05-27 02:29:40 +02:00
1 parent 9216dd0726
commit 7dd7000885
6 files changed
+157 -2

No files matched your search

+37 -2
View File
@@ -13,10 +13,14 @@ import { IssuesService } from './issues/issues.service';
import { IssueType } from './issues/entities/issue-type.enum'; import { IssueType } from './issues/entities/issue-type.enum';
import { CreateIssueDto } from './issues/dto/create-issue.dto'; import { CreateIssueDto } from './issues/dto/create-issue.dto';
import { CreateIssueCommentDto } from './issues/dto/create-issue-comment.dto'; import { CreateIssueCommentDto } from './issues/dto/create-issue-comment.dto';
import { SolutionsService } from './solutions/solutions.service';
@Controller() @Controller()
export class AppController { export class AppController {
constructor(private readonly issues: IssuesService) {} constructor(
private readonly issues: IssuesService,
private readonly solutions: SolutionsService,
) {}
@Get('/issues/problems') @Get('/issues/problems')
listProblems() { listProblems() {
@@ -36,7 +40,14 @@ export class AppController {
async getIssue(@Param('id', ParseUUIDPipe) id: string) { async getIssue(@Param('id', ParseUUIDPipe) id: string) {
const data = await this.issues.findOne(id).then((i) => i.toDto()); const data = await this.issues.findOne(id).then((i) => i.toDto());
const comments = await this.issues.getCommentsForIssue(id); const comments = await this.issues.getCommentsForIssue(id);
return { data, comments }; const solution =
(await this.solutions.getForIssue(id))?.toList() ?? undefined;
return { data, comments, solution };
}
@Get('/issues/:id/solution')
async getSolution(@Param('id', ParseUUIDPipe) id: string) {
return this.solutions.getForIssue(id).then((i) => i.toDto());
} }
@Post('/issues') @Post('/issues')
@@ -64,6 +75,18 @@ export class AppController {
await this.issues.dislike(id); await this.issues.dislike(id);
} }
@Post('/issues/:id/solution/like')
@HttpCode(HttpStatus.ACCEPTED)
async addLikeToSolution(@Param('id', ParseUUIDPipe) id: string) {
await this.solutions.like(id);
}
@Post('/issues/:id/solution/dislike')
@HttpCode(HttpStatus.ACCEPTED)
async addDislikeToSolution(@Param('id', ParseUUIDPipe) id: string) {
await this.solutions.dislike(id);
}
@Delete('/issues/:id/like') @Delete('/issues/:id/like')
@HttpCode(HttpStatus.ACCEPTED) @HttpCode(HttpStatus.ACCEPTED)
async removeLike(@Param('id', ParseUUIDPipe) id: string) { async removeLike(@Param('id', ParseUUIDPipe) id: string) {
@@ -75,4 +98,16 @@ export class AppController {
async removeDislike(@Param('id', ParseUUIDPipe) id: string) { async removeDislike(@Param('id', ParseUUIDPipe) id: string) {
await this.issues.dislike(id, true); await this.issues.dislike(id, true);
} }
@Delete('/issues/:id/solution/like')
@HttpCode(HttpStatus.ACCEPTED)
async removeLikeToSolution(@Param('id', ParseUUIDPipe) id: string) {
await this.solutions.like(id, true);
}
@Delete('/issues/:id/solution/dislike')
@HttpCode(HttpStatus.ACCEPTED)
async removeDislikeToSolution(@Param('id', ParseUUIDPipe) id: string) {
await this.solutions.dislike(id, true);
}
} }
+2
View File
@@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { IssuesModule } from './issues/issues.module'; import { IssuesModule } from './issues/issues.module';
import { AppController } from './app.controller'; import { AppController } from './app.controller';
import { SolutionsModule } from './solutions/solutions.module';
@Module({ @Module({
controllers: [AppController], controllers: [AppController],
@@ -17,6 +18,7 @@ import { AppController } from './app.controller';
synchronize: process.env.NODE_ENV !== 'production', synchronize: process.env.NODE_ENV !== 'production',
}), }),
IssuesModule, IssuesModule,
SolutionsModule,
], ],
}) })
export class AppModule {} export class AppModule {}
@@ -0,0 +1,13 @@
import { IsString, MaxLength, MinLength } from 'class-validator';
export class CreateSolutionDto {
@IsString()
@MinLength(1)
@MaxLength(32)
title: string;
@IsString()
@MinLength(1)
@MaxLength(255)
description: string;
}
@@ -0,0 +1,53 @@
import { Issue } from 'src/issues/entities/issue.entity';
import {
Column,
CreateDateColumn,
Entity,
ManyToOne,
PrimaryGeneratedColumn,
} from 'typeorm';
@Entity('solutions')
export class Solution {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
title: string;
@Column()
username: string;
@Column()
description: string;
@CreateDateColumn()
createdAt: Date;
@ManyToOne(() => Issue, { lazy: true, onDelete: 'CASCADE' })
issue: Promise<Issue>;
@Column({ default: 0 })
likes: number;
@Column({ default: 0 })
dislikes: number;
async toDto() {
return {
...this.toList(),
description: this.description,
issue: (await this.issue).toList(),
};
}
toList() {
return {
title: this.title,
username: this.username,
likes: this.likes,
dislikes: this.dislikes,
createdAt: this.createdAt.toISOString(),
};
}
}
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { SolutionsService } from './solutions.service';
import { IssuesModule } from 'src/issues/issues.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Solution } from './entities/solution.entity';
@Module({
imports: [IssuesModule, TypeOrmModule.forFeature([Solution])],
providers: [SolutionsService],
exports: [SolutionsService],
})
export class SolutionsModule {}
@@ -0,0 +1,40 @@
import { ConflictException, Injectable } from '@nestjs/common';
import { CreateSolutionDto } from './dto/create-solution.dto';
import { IssuesService } from 'src/issues/issues.service';
import { InjectRepository } from '@nestjs/typeorm';
import { Solution } from './entities/solution.entity';
import { Repository } from 'typeorm';
@Injectable()
export class SolutionsService {
constructor(
@InjectRepository(Solution)
private readonly repository: Repository<Solution>,
private readonly issues: IssuesService,
) {}
async create(issueId: string, createSolutionDto: CreateSolutionDto) {
if ((await this.getForIssue(issueId)) !== null)
throw new ConflictException('This issue already has a solution');
const solution = this.repository.create({ ...createSolutionDto });
const issue = await this.issues.findOne(issueId);
solution.issue = Promise.resolve(issue);
return this.repository.save(solution);
}
async getForIssue(issueId: string): Promise<Solution | null> {
return this.repository.findOneBy({ issue: { id: issueId } });
}
async like(issueId: string, remove?: boolean) {
const ent = await this.getForIssue(issueId);
ent.likes = remove ? ent.likes - 1 : ent.likes + 1;
return this.repository.save(ent);
}
async dislike(issueId: string, remove?: boolean) {
const ent = await this.getForIssue(issueId);
ent.dislikes = remove ? ent.dislikes - 1 : ent.dislikes + 1;
return this.repository.save(ent);
}
}