Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat] 태스크 위치 이동 API 구현 #53

Merged
merged 8 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"dotenv": "^16.4.5",
"lexorank": "^1.0.5",
"mysql2": "^3.11.4",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
Expand Down
8 changes: 7 additions & 1 deletion apps/server/src/task/controller/task.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Body, Controller, Param, Patch, Post } from '@nestjs/common';
import { TaskService } from '../service/task.service';
import { CreateTaskRequest } from '../dto/create-task-request.dto';
import { UpdateTaskRequest } from '../dto/update-task-request.dto';
import { MoveTaskRequest } from '../dto/move-task-request.dto';

@Controller('task')
export class TaskController {
Expand All @@ -12,8 +13,13 @@ export class TaskController {
return this.taskService.create(createTaskRequest);
}

@Patch(':id')
@Patch(':id/status')
update(@Param('id') id: number, @Body() updateTaskRequest: UpdateTaskRequest) {
return this.taskService.update(id, updateTaskRequest);
}

@Patch(':id/position')
move(@Param('id') id: number, @Body() moveTaskRequest: MoveTaskRequest) {
return this.taskService.move(id, moveTaskRequest);
}
}
2 changes: 1 addition & 1 deletion apps/server/src/task/domain/task.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class Task {
description: string;

@Column()
position: number;
position: string;

@ManyToOne(() => Section)
@JoinColumn({ name: 'section_id' })
Expand Down
4 changes: 1 addition & 3 deletions apps/server/src/task/dto/create-task-request.dto.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
export class CreateTaskRequest {
position: number;

sectionId: number;
lastTaskPosition: string;
}
3 changes: 3 additions & 0 deletions apps/server/src/task/dto/create-task-response.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { Task } from '../domain/task.entity';
export class CreateTaskResponse {
constructor(task: Task) {
this.id = task.id;
this.position = task.position;
}

id: number;

position: string;
}
7 changes: 7 additions & 0 deletions apps/server/src/task/dto/move-task-request.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export class MoveTaskRequest {
sectionId: number;

beforePosition: string;

afterPosition: string;
}
21 changes: 21 additions & 0 deletions apps/server/src/task/dto/move-task-response.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Task } from '../domain/task.entity';

export class MoveTaskResponse {
constructor(task: Task) {
this.id = task.id;
this.title = task.title;
this.description = task.description;
this.sectionId = task.section.id;
this.position = task.position;
}

id: number;

title: string;

description: string;

sectionId: number;

position: string;
}
2 changes: 1 addition & 1 deletion apps/server/src/task/dto/update-task-response.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ export class UpdateTaskResponse {

sectionId: number;

position: number;
position: string;
}
33 changes: 27 additions & 6 deletions apps/server/src/task/service/task.service.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { LexoRank } from 'lexorank';
import { Task } from '../domain/task.entity';
import { CreateTaskRequest } from '../dto/create-task-request.dto';
import { CreateTaskResponse } from '../dto/create-task-response.dto';
import { Section } from '../domain/section.entity';
import { UpdateTaskRequest } from '../dto/update-task-request.dto';
import { UpdateTaskResponse } from '../dto/update-task-response.dto';
import { MoveTaskRequest } from '../dto/move-task-request.dto';
import { MoveTaskResponse } from '../dto/move-task-response.dto';

@Injectable()
export class TaskService {
Expand All @@ -18,14 +21,12 @@ export class TaskService {
) {}

async create(createTaskRequest: CreateTaskRequest) {
const section = await this.sectionRepository.findOneBy({ id: createTaskRequest.sectionId });
if (!section) {
throw new NotFoundException('Section not found');
}
const position: string = createTaskRequest.lastTaskPosition
? LexoRank.parse(createTaskRequest.lastTaskPosition).genNext().toString()
: LexoRank.min().toString();

const task = await this.taskRepository.save({
position: createTaskRequest.position,
section,
position,
});
return new CreateTaskResponse(task);
}
Expand All @@ -48,4 +49,24 @@ export class TaskService {
await this.taskRepository.save(task);
return new UpdateTaskResponse(task);
}

async move(id: number, moveTaskRequest: MoveTaskRequest) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡
updatemove 사이에는 많은 공통 로직이 있어보입니다.
update 를 더 확장성을 고려해서 만들고 그 로직을 활용하는 방향으로 move 를 구현하는 것이 좋을 것 같아요!

그동안 마스터님들의 말슴은
보통 세번 반복되면 리팩토링한다는 것이긴 합니다.

한번 더 겹치면 고려해주세용~

Copy link
Collaborator Author

@yangchef1 yangchef1 Nov 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updatemove는 별도의 스토리로 구성한 만큼, 서로 의존성을 갖지 않게 하고 싶어서 update를 move에서 활용하는 설계는 고려하지 않았던 것 같습니다.

대신에 ,, 사실 같은 코드가 반복되다 보니, 아래 2가지 부분을 별도 메서드로 분리할까 고민했었습니다.
아래 코드를 분리하면 update, move외에 다른 메서드에서도 재사용할 수 있을 것 같아서용 ,,

작성할 때는 분리할 정도의 코드는 아니라고 생각했었는데, 말씀 듣고 다시 한번 생각해보니 다른 생성, 조회, 삭제 메서드에서도 활용될 수 있는 재사용성 높은 코드라서 분리하는게 여러모로 좋아보이네요 ...!

const task = await this.taskRepository.findOneBy({ id });
if (!task) {
	throw new NotFoundException('Task not found');
}
const section = await this.sectionRepository.findOneBy({ id: updateTaskRequest.sectionId });
if (!section) {
	throw new NotFoundException('Section not found');
}

const task = await this.taskRepository.findOneBy({ id });
if (!task) {
throw new NotFoundException('Task not found');
}

const section = await this.sectionRepository.findOneBy({ id: moveTaskRequest.sectionId });
if (!section) {
throw new NotFoundException('Section not found');
}
task.section = section;

const beforePostion = LexoRank.parse(moveTaskRequest.beforePosition);
const afterPosition = LexoRank.parse(moveTaskRequest.afterPosition);
task.position = beforePostion.between(afterPosition).toString();
Comment on lines +65 to +67
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lexo rank 사용법이 굉장히 간단하고 좋네요.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞습니다 ㅋㅋㅋ
비슷한 기능의 메서드가 많아서 공부할 땐 좀 헷갈렸는데, 사용법 자체는 굉장히 간단하더라구요 !


await this.taskRepository.save(task);
return new MoveTaskResponse(task);
}
}
Loading
Loading