Skip to content

Commit 7a2472b

Browse files
committed
add & test update/comments module
1 parent 5c1f8ac commit 7a2472b

16 files changed

+498
-3
lines changed

src/app.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { ProjectModule } from './project/project.module';
1212
import { TaskModule } from './task/task.module';
1313
import { ProjectTaskModule } from './project-task/project-task.module';
1414
import { UpdateModule } from './task-update/task-update.module';
15+
import { UpdateCommentModule } from './update-comment/update-comment.module';
1516

1617
@Module({
1718
imports: [
@@ -22,6 +23,7 @@ import { UpdateModule } from './task-update/task-update.module';
2223
TaskModule,
2324
ProjectTaskModule,
2425
UpdateModule,
26+
UpdateCommentModule,
2527
],
2628
providers: [
2729
{

src/database/entity/comment.entity.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
2+
import { Exclude } from 'class-transformer';
3+
import { Update, Employee } from './';
4+
5+
@Entity()
6+
export class Comment {
7+
@PrimaryGeneratedColumn()
8+
id: number;
9+
10+
@Column()
11+
body: string;
12+
13+
@ManyToOne(
14+
() => Update,
15+
update => update.comments,
16+
)
17+
@Exclude()
18+
update: Update;
19+
20+
@ManyToOne(
21+
() => Employee,
22+
employee => employee.comments,
23+
{ eager: true },
24+
)
25+
creator: Employee;
26+
27+
isCreator(employee: Employee): boolean {
28+
return this.creator.id === employee.id;
29+
}
30+
}

src/database/entity/employee.entity.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { Exclude, Expose } from 'class-transformer';
1010
import { Role } from '../enum/role.enum';
1111
import { Project } from './project.entity';
1212
import { Task } from './task.entity';
13+
import { Comment } from './comment.entity';
1314

1415
@Entity()
1516
@Unique(['username'])
@@ -28,14 +29,23 @@ export class Employee {
2829
() => Project,
2930
project => project.manager,
3031
)
32+
@Exclude()
3133
managedProject: Project[];
3234

3335
@OneToMany(
3436
() => Task,
3537
task => task.staff,
3638
)
39+
@Exclude()
3740
assignedTask: Task[];
3841

42+
@OneToMany(
43+
() => Comment,
44+
comment => comment.creator,
45+
)
46+
@Exclude()
47+
comments: Comment[];
48+
3949
@Column()
4050
@Exclude()
4151
password: string;

src/database/entity/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from './employee.entity';
22
export * from './project.entity';
33
export * from './task.entity';
44
export * from './update.entity';
5+
export * from './comment.entity';

src/database/entity/update.entity.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1-
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
1+
import {
2+
Entity,
3+
PrimaryGeneratedColumn,
4+
Column,
5+
ManyToOne,
6+
OneToMany,
7+
} from 'typeorm';
28
import { Exclude } from 'class-transformer';
39
import { UpdateType } from '../enum';
4-
import { Task } from './task.entity';
10+
import { Task, Comment } from './';
511

612
@Entity()
713
export class Update {
@@ -23,4 +29,11 @@ export class Update {
2329
)
2430
@Exclude()
2531
task: Task;
32+
33+
@OneToMany(
34+
() => Comment,
35+
comment => comment.update,
36+
)
37+
@Exclude()
38+
comments: Comment[];
2639
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { EntityRepository } from 'typeorm';
2+
import { Comment } from '../entity';
3+
import { AppRepository } from '../../core/app.repository';
4+
5+
@EntityRepository(Comment)
6+
export class CommentRepository extends AppRepository<Comment> {
7+
constructor() {
8+
super('Comment');
9+
}
10+
}

src/database/repository/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from './employee.repository';
22
export * from './project.repository';
33
export * from './task.repository';
44
export * from './update.repository';
5+
export * from './comment.repository ';
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { ManageCommentDTO } from './manage-comment.dto';
2+
3+
export class CreateCommentDTO extends ManageCommentDTO {}

src/update-comment/dto/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './create-comment.dto';
2+
export * from './update-comment.dto';
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { IsString } from 'class-validator';
2+
3+
export class ManageCommentDTO {
4+
@IsString()
5+
body: string;
6+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { ManageCommentDTO } from './manage-comment.dto';
2+
3+
export class UpdateCommentDTO extends ManageCommentDTO {}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import {
2+
Controller,
3+
Get,
4+
Param,
5+
Post,
6+
Body,
7+
Put,
8+
Delete,
9+
} from '@nestjs/common';
10+
import { UpdateCommentService } from './update-comment.service';
11+
import { Auth, CurrentEmployee } from '../core/decorator';
12+
import { Comment, Employee } from '../database/entity';
13+
import { CreateCommentDTO, UpdateCommentDTO } from './dto';
14+
15+
@Controller('update/:updateId/comment')
16+
export class UpdateCommentController {
17+
constructor(private updateCommService: UpdateCommentService) {}
18+
19+
@Get('/')
20+
@Auth()
21+
async getAll(@Param('updateId') updateId: number): Promise<Comment[]> {
22+
return this.updateCommService.getAll(updateId);
23+
}
24+
25+
@Post('/')
26+
@Auth()
27+
async create(
28+
@Param('updateId') updateId: number,
29+
@Body() createDto: CreateCommentDTO,
30+
@CurrentEmployee() employee: Employee,
31+
): Promise<Comment> {
32+
return this.updateCommService.create(updateId, createDto, employee);
33+
}
34+
35+
@Get('/:commentId')
36+
@Auth()
37+
async get(
38+
@Param('updateId') updateId: number,
39+
@Param('commentId') commentId: number,
40+
): Promise<Comment> {
41+
return this.updateCommService.get(updateId, commentId);
42+
}
43+
44+
@Put('/:commentId')
45+
@Auth()
46+
async update(
47+
@Param('updateId') updateId: number,
48+
@Param('commentId') commentId: number,
49+
@Body() commentDto: UpdateCommentDTO,
50+
@CurrentEmployee() employee: Employee,
51+
): Promise<Comment> {
52+
return this.updateCommService.update(
53+
updateId,
54+
commentId,
55+
commentDto,
56+
employee,
57+
);
58+
}
59+
60+
@Delete('/:commentId')
61+
@Auth()
62+
async delete(
63+
@Param('updateId') updateId: number,
64+
@Param('commentId') commentId: number,
65+
@CurrentEmployee() employee: Employee,
66+
): Promise<void> {
67+
return this.updateCommService.delete(updateId, commentId, employee);
68+
}
69+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Module } from '@nestjs/common';
2+
import { UpdateCommentController } from './update-comment.controller';
3+
import { UpdateCommentService } from './update-comment.service';
4+
import { TypeOrmModule } from '@nestjs/typeorm';
5+
import { UpdateRepository, CommentRepository } from '../database/repository';
6+
import { AuthModule } from '../auth/auth.module';
7+
8+
@Module({
9+
imports: [
10+
TypeOrmModule.forFeature([UpdateRepository]),
11+
TypeOrmModule.forFeature([CommentRepository]),
12+
AuthModule,
13+
],
14+
controllers: [UpdateCommentController],
15+
providers: [UpdateCommentService],
16+
})
17+
export class UpdateCommentModule {}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { Injectable } from '@nestjs/common';
2+
import { InjectRepository } from '@nestjs/typeorm';
3+
import { AppService } from '../core/app.service';
4+
import { Comment, Employee } from '../database/entity';
5+
import { CreateCommentDTO, UpdateCommentDTO } from './dto';
6+
import { UpdateRepository, CommentRepository } from '../database/repository';
7+
8+
@Injectable()
9+
export class UpdateCommentService extends AppService {
10+
constructor(
11+
@InjectRepository(UpdateRepository) private updateRepo: UpdateRepository,
12+
@InjectRepository(CommentRepository) private commentRepo: CommentRepository,
13+
) {
14+
super();
15+
}
16+
17+
async getAll(updateId: number): Promise<Comment[]> {
18+
const update = await this.updateRepo.findOneOrException(updateId);
19+
return this.commentRepo.find({ where: { update } });
20+
}
21+
22+
async create(
23+
updateId: number,
24+
createDto: CreateCommentDTO,
25+
employee: Employee,
26+
): Promise<Comment> {
27+
const update = await this.updateRepo.findOneOrException(updateId, {
28+
relations: ['task', 'task.project'],
29+
});
30+
31+
const can =
32+
update.task.isStaff(employee) || update.task.project.isManager(employee);
33+
this.canManage(can, 'Update');
34+
35+
const comment = new Comment();
36+
comment.body = createDto.body;
37+
comment.update = update;
38+
comment.creator = employee;
39+
40+
return this.commentRepo.save(comment);
41+
}
42+
43+
async get(updateId: number, commentId: number): Promise<Comment> {
44+
return this.commentRepo.findOneOrException({
45+
id: commentId,
46+
update: { id: updateId },
47+
});
48+
}
49+
50+
async update(
51+
updateId: number,
52+
commentId: number,
53+
commentDto: UpdateCommentDTO,
54+
employee: Employee,
55+
): Promise<Comment> {
56+
const where = { id: commentId, update: { id: updateId } };
57+
const comment = await this.commentRepo.findOneOrException(where);
58+
59+
this.canManage(comment.isCreator(employee), 'Comment');
60+
61+
comment.body = commentDto.body;
62+
63+
return this.commentRepo.save(comment);
64+
}
65+
66+
async delete(
67+
updateId: number,
68+
commentId: number,
69+
employee: Employee,
70+
): Promise<void> {
71+
const where = { id: commentId, update: { id: updateId } };
72+
const comment = await this.commentRepo.findOneOrException(where);
73+
74+
this.canManage(comment.isCreator(employee), 'Comment');
75+
76+
await this.commentRepo.delete(comment);
77+
}
78+
}

test/helper/repo.helper.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,15 @@ import {
33
ProjectRepository,
44
TaskRepository,
55
UpdateRepository,
6+
CommentRepository,
67
} from '../../src/database/repository';
7-
import { Employee, Project, Task, Update } from '../../src/database/entity';
8+
import {
9+
Employee,
10+
Project,
11+
Task,
12+
Update,
13+
Comment,
14+
} from '../../src/database/entity';
815
import {
916
ProjectStatus,
1017
TaskStatus,
@@ -17,12 +24,14 @@ class RepoHelper {
1724
private proRepo: ProjectRepository;
1825
private taskRepo: TaskRepository;
1926
private updateRepo: UpdateRepository;
27+
private commRepo: CommentRepository;
2028
private auth: AuthHelper;
2129

2230
constructor(app: INestApplication, auth: AuthHelper) {
2331
this.proRepo = app.get(ProjectRepository);
2432
this.taskRepo = app.get(TaskRepository);
2533
this.updateRepo = app.get(UpdateRepository);
34+
this.commRepo = app.get(CommentRepository);
2635
this.auth = auth;
2736
}
2837

@@ -63,6 +72,18 @@ class RepoHelper {
6372
}),
6473
);
6574
}
75+
76+
async createAComment(update?: Update, creator?: Employee): Promise<Comment> {
77+
if (!update) update = await this.createAnUpdate();
78+
if (!creator) creator = update.task.staff;
79+
return await this.commRepo.save(
80+
this.commRepo.create({
81+
body: 'comment body',
82+
update: update,
83+
creator: creator,
84+
}),
85+
);
86+
}
6687
}
6788

6889
export { RepoHelper };

0 commit comments

Comments
 (0)