Archived
solutions system
This commit is contained in:
6 files changed
+157
-2
No files matched your search
@@ -13,10 +13,14 @@ import { IssuesService } from './issues/issues.service';
|
||||
import { IssueType } from './issues/entities/issue-type.enum';
|
||||
import { CreateIssueDto } from './issues/dto/create-issue.dto';
|
||||
import { CreateIssueCommentDto } from './issues/dto/create-issue-comment.dto';
|
||||
import { SolutionsService } from './solutions/solutions.service';
|
||||
|
||||
@Controller()
|
||||
export class AppController {
|
||||
constructor(private readonly issues: IssuesService) {}
|
||||
constructor(
|
||||
private readonly issues: IssuesService,
|
||||
private readonly solutions: SolutionsService,
|
||||
) {}
|
||||
|
||||
@Get('/issues/problems')
|
||||
listProblems() {
|
||||
@@ -36,7 +40,14 @@ export class AppController {
|
||||
async getIssue(@Param('id', ParseUUIDPipe) id: string) {
|
||||
const data = await this.issues.findOne(id).then((i) => i.toDto());
|
||||
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')
|
||||
@@ -64,6 +75,18 @@ export class AppController {
|
||||
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')
|
||||
@HttpCode(HttpStatus.ACCEPTED)
|
||||
async removeLike(@Param('id', ParseUUIDPipe) id: string) {
|
||||
@@ -75,4 +98,16 @@ export class AppController {
|
||||
async removeDislike(@Param('id', ParseUUIDPipe) id: string) {
|
||||
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,6 +2,7 @@ import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { IssuesModule } from './issues/issues.module';
|
||||
import { AppController } from './app.controller';
|
||||
import { SolutionsModule } from './solutions/solutions.module';
|
||||
|
||||
@Module({
|
||||
controllers: [AppController],
|
||||
@@ -17,6 +18,7 @@ import { AppController } from './app.controller';
|
||||
synchronize: process.env.NODE_ENV !== 'production',
|
||||
}),
|
||||
IssuesModule,
|
||||
SolutionsModule,
|
||||
],
|
||||
})
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user