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 구현 #320

Merged
merged 5 commits into from
Aug 2, 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
67 changes: 41 additions & 26 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"cookie-parser": "^1.4.6",
"lexorank": "^1.0.5",
"mysql2": "^3.9.1",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",
Expand Down
18 changes: 18 additions & 0 deletions backend/src/common/decorator/IsLexoRankValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { registerDecorator } from 'class-validator';

export function IsLexoRankValue() {
return function (object: Object, propertyName: string) {
registerDecorator({
name: 'IsLexoRankValue',
target: object.constructor,
propertyName: propertyName,
options: { message: 'invalid LexoRank format' },
validator: {
validate(value: any) {
const lexorankPattern = new RegExp(`^[012]\\|.*`, 'i');
return lexorankPattern.test(value);
},
},
});
};
}
6 changes: 6 additions & 0 deletions backend/src/project/dto/InitBacklogResponse.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class TaskDto {
actualTime: number | null;
status: TaskStatus;
assignedMemberId: number | null;
rankValue: string;

static of(task: Task): TaskDto {
const dto = new TaskDto();
Expand All @@ -20,6 +21,7 @@ class TaskDto {
dto.actualTime = task.actualTime;
dto.status = task.status;
dto.assignedMemberId = task.assignedMemberId;
dto.rankValue = task.rankValue;
return dto;
}
}
Expand All @@ -29,6 +31,7 @@ class StoryDto {
title: string;
point: number | null;
status: StoryStatus;
rankValue: string;
taskList: TaskDto[];

static of(story: Story): StoryDto {
Expand All @@ -37,6 +40,7 @@ class StoryDto {
dto.title = story.title;
dto.point = story.point;
dto.status = story.status;
dto.rankValue = story.rankValue;
dto.taskList = story.taskList.map(TaskDto.of);
return dto;
}
Expand All @@ -46,13 +50,15 @@ class EpicDto {
id: number;
name: string;
color: EpicColor;
rankValue: string;
storyList: StoryDto[];

static of(epic: Epic): EpicDto {
const dto = new EpicDto();
dto.id = epic.id;
dto.name = epic.name;
dto.color = epic.color;
dto.rankValue = epic.rankValue;
dto.storyList = epic.storyList.map(StoryDto.of);
return dto;
}
Expand Down
9 changes: 6 additions & 3 deletions backend/src/project/dto/epic/EpicCreateNotify.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ class Epic {
id: number;
name: string;
color: EpicColor;
static of(id: number, name: string, color: EpicColor) {
rankValue: string;

static of(id: number, name: string, color: EpicColor, rankValue: string) {
const dto = new Epic();
dto.id = id;
dto.name = name;
dto.color = color;
dto.rankValue = rankValue;
return dto;
}
}
Expand All @@ -18,11 +21,11 @@ export class EpicCreateNotifyDto {
action: string;
content: Epic;

static of(id: number, name: string, color: EpicColor) {
static of(id: number, name: string, color: EpicColor, rankValue: string) {
const dto = new EpicCreateNotifyDto();
dto.domain = 'epic';
dto.action = 'create';
dto.content = Epic.of(id, name, color);
dto.content = Epic.of(id, name, color, rankValue);
return dto;
}
}
6 changes: 6 additions & 0 deletions backend/src/project/dto/epic/EpicCreateRequest.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Matches,
ValidateNested,
} from 'class-validator';
import { IsLexoRankValue } from 'src/common/decorator/IsLexoRankValue';
import { EpicColor } from 'src/project/entity/epic.entity';

class Epic {
Expand All @@ -16,6 +17,11 @@ class Epic {

@IsEnum(EpicColor)
color: EpicColor;

@IsString()
@IsLexoRankValue()
@Length(2, 255)
rankValue: string;
}

export class EpicCreateRequestDto {
Expand Down
8 changes: 5 additions & 3 deletions backend/src/project/dto/epic/EpicUpdateNotify.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ class Epic {
id: number;
name?: string;
color?: EpicColor;
static of(id: number, name: string, color: EpicColor) {
rankValue?: string;
static of(id: number, name: string, color: EpicColor, rankValue: string) {
const dto = new Epic();
dto.id = id;
if (name !== undefined) dto.name = name;
if (color !== undefined) dto.color = color;
if (rankValue !== undefined) dto.rankValue = rankValue;
return dto;
}
}
Expand All @@ -18,11 +20,11 @@ export class EpicUpdateNotifyDto {
action: string;
content: Epic;

static of(id: number, name: string, color: EpicColor) {
static of(id: number, name: string, color: EpicColor, rankValue: string) {
const dto = new EpicUpdateNotifyDto();
dto.domain = 'epic';
dto.action = 'update';
dto.content = Epic.of(id, name, color);
dto.content = Epic.of(id, name, color, rankValue);
return dto;
}
}
8 changes: 7 additions & 1 deletion backend/src/project/dto/epic/EpicUpdateRequest.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import {
ValidateNested,
Length,
} from 'class-validator';
import { IsLexoRankValue } from 'src/common/decorator/IsLexoRankValue';
import { EpicColor } from 'src/project/entity/epic.entity';
import { AtLeastOneProperty } from 'src/project/util/validation.util';

class Epic {
@IsNotEmpty()
@IsInt()
@AtLeastOneProperty(['name', 'color'])
@AtLeastOneProperty(['name', 'color', 'rankValue'])
id: number;

@IsOptional()
Expand All @@ -26,6 +27,11 @@ class Epic {
@IsOptional()
@IsEnum(EpicColor)
color?: EpicColor;

@IsOptional()
@IsLexoRankValue()
@Length(2, 255)
rankValue?: string;
}

export class EpicUpdateRequestDto {
Expand Down
3 changes: 3 additions & 0 deletions backend/src/project/dto/story/StoryCreateNotify.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ class StoryDto {
point: number;
status: StoryStatus;
epicId: number;
rankValue: string;

static of(story: Story) {
const dto = new StoryDto();
dto.id = story.id;
dto.title = story.title;
dto.point = story.point;
dto.status = story.status;
dto.epicId = story.epicId;
dto.rankValue = story.rankValue;
return dto;
}
}
Expand Down
6 changes: 6 additions & 0 deletions backend/src/project/dto/story/StoryCreateRequest.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
Min,
ValidateNested,
} from 'class-validator';
import { IsLexoRankValue } from 'src/common/decorator/IsLexoRankValue';
import { StoryStatus } from 'src/project/entity/story.entity';

class Story {
Expand All @@ -27,6 +28,11 @@ class Story {

@IsInt()
epicId: number;

@IsString()
@IsLexoRankValue()
@Length(2, 255)
rankValue: string;
}

export class StoryCreateRequestDto {
Expand Down
Loading
Loading