Skip to content

Commit

Permalink
Merge pull request #32 from depromeet/feat/LS-20
Browse files Browse the repository at this point in the history
  • Loading branch information
clean2001 committed Jul 14, 2024
2 parents f389ec4 + b9cd468 commit f9a29a4
Show file tree
Hide file tree
Showing 21 changed files with 561 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# auth
layer-api/src/main/resources/application.yml

# q
layer-domain/src/main/generated/


HELP.md
.gradle
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package org.layer.domain.template.api;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.layer.domain.template.dto.*;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;

@Tag(name = "기본 템플릿 관련 API (ex. KPT, 4L과 같은 고정 템플릿)")
public interface TemplateApi {
@Operation(summary = "템플릿 간단 정보 단건 조회", method = "GET", description = """
특정 템플릿의 간단 정보를 조회합니다.
""")
@ApiResponses({
@ApiResponse(responseCode = "200",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = TemplateSimpleInfoResponse.class)
)
}
)
}
)
ResponseEntity<TemplateSimpleInfoResponse> getTemplateSimpleInfo(@PathVariable Long templateId);


@Operation(summary = "템플릿 상세 정보 단건 조회", method = "GET", description = """
특정 템플릿의 설명이 담긴 상세 정보를 조회합니다.
""")
@ApiResponses({
@ApiResponse(responseCode = "200",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = TemplateDetailInfoResponse.class)
)
}
)
}
)
ResponseEntity<TemplateDetailInfoResponse> getTemplateDetailInfo(@PathVariable Long templateId);

@Operation(summary = "템플릿 [간단 정보 + 모든 질문] 단건 조회", method = "GET", description = """
특정 템플릿의 간단 정보와 그 템플릿에 속한 질문들을 조회합니다.
""")
@ApiResponses({
@ApiResponse(responseCode = "200",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = TemplateQuestionListResponse.class)
)
}
)
}
)
ResponseEntity<TemplateQuestionListResponse> getTemplateQuestionList(@PathVariable Long templateId);


@Operation(summary = "모든 템플릿 간단 정보 조회", method = "GET", description = """
모든 템플릿의 간단 정보를 조회합니다.
""")
@ApiResponses({
@ApiResponse(responseCode = "200",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = TemplateQuestionListResponse.class)
)
}
)
}
)
ResponseEntity<TemplateListResponse> getAllTemplates(AllTemplatesRequest allTemplatesRequest);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.layer.domain.template.controller;

import lombok.RequiredArgsConstructor;
import org.layer.domain.template.api.TemplateApi;
import org.layer.domain.template.dto.*;
import org.layer.domain.template.service.TemplateService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@RequiredArgsConstructor
@RequestMapping("/api/template")
@Controller
public class TemplateController implements TemplateApi {
private final TemplateService templateService;

//== 간단 정보 단건 조회 ==//
@Override
@GetMapping("/{templateId}/simple-info")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<TemplateSimpleInfoResponse> getTemplateSimpleInfo(@PathVariable("templateId") Long templateId) {
TemplateSimpleInfoResponse templateSimpleInfo = templateService.getTemplateSimpleInfo(templateId);
return new ResponseEntity<>(templateSimpleInfo, HttpStatus.OK);
}

//== 상세 정보 단건 조회 ==//
@Override
@GetMapping("/{templateId}/detail-info")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<TemplateDetailInfoResponse> getTemplateDetailInfo(@PathVariable("templateId") Long templateId) {
TemplateDetailInfoResponse templateDetailInfo = templateService.getTemplateDetailInfo(templateId);
return new ResponseEntity<>(templateDetailInfo, HttpStatus.OK);
}

//== 질문을 포함한 간단 정보 ==//
@Override
@GetMapping("/{templateId}/question-list")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<TemplateQuestionListResponse> getTemplateQuestionList(@PathVariable("templateId") Long templateId) {
TemplateQuestionListResponse templateQuestions = templateService.getTemplateQuestions(templateId);
return new ResponseEntity<>(templateQuestions, HttpStatus.OK);
}


//== 모든 템플릿 ==//
@Override
@GetMapping("/all")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<TemplateListResponse> getAllTemplates(AllTemplatesRequest allTemplatesRequest) {
return new ResponseEntity<>(templateService.getAllTemplates(allTemplatesRequest.page(), allTemplatesRequest.size()), HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.layer.domain.template.dto;

import io.swagger.v3.oas.annotations.media.Schema;

@Schema
public record AllTemplatesRequest(@Schema(description = "페이지 번호(0번부터 시작)") int page,
@Schema(description = "한 페이지에 보여줄 개수") int size) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.layer.domain.template.dto;

import jakarta.validation.constraints.NotNull;
import org.layer.domain.question.enums.QuestionType;

public record QuestionResponse(
@NotNull
String question,
@NotNull
QuestionType questionType
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.layer.domain.template.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import org.layer.domain.template.entity.Template;
import org.layer.domain.template.entity.TemplateQuestion;
import org.layer.domain.template.exception.TemplateException;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static org.layer.domain.template.exception.TemplateExceptionType.INVALID_TEMPLATE;

@Builder
@Schema
public record TemplateDetailInfoResponse(
@Schema(description = "템플릿 ID", example = "1")
@NotNull
Long id,
@Schema(description = "템플릿 제목", example = "빠르고 효율적인 회고")
@NotNull
String title, // ex. 빠르고 효율적인 회고
@Schema(description = "템플릿 명칭", example = "KPT 회고")
@NotNull
String templateName, // ex. KPT 회고
@Schema(description = "템플릿 대표 사진", example = "[이미지 url]")
@NotNull
String templateImageUrl,
@Schema(description = "템플릿 관련 태그 1", example = "간단한 프로세스")
String firstTag, // 첫번째 태그. ex) 간단한 프로세스
@Schema(description = "템플릿 관련 태그 2", example = "다음 목표 설정")
String secondTag, // 두번째 태그. ex) 다음 목표 설정
//== 회고 설명에 대한 부분 ==//
@Schema(description = "회고에 대한 설명", example = "회고 내용을 Keep, Problem, Try 세가지 관점으로 분류하여... [생략]")
@NotNull
String description, // 회고에 대한 설명
@Schema(description = "회고 팁 제목", example = "회고는 빠르고 간단하게!")
@NotNull
String tipTitle, // ex) 회고는 빠르고 간단하게!
@Schema(description = "회고 팁 설명", example = "KPT 회고는 짧은 시간에 구성원의 생각을... [생략]")
@NotNull
String tipDescription, // 팁에 대한 설명

@Schema(description = "템플릿 질문과 그 설명 리스트")
@NotNull
List<TemplateDetailQuestionResponse> templateDetailQuestionList // 질문(회고 과정)에 대한 설명

) {
public static TemplateDetailInfoResponse toResponse(Template template, List<TemplateQuestion> templateQuestionList) {
List<TemplateDetailQuestionResponse> templateDetailQuestionList = templateQuestionList
.stream()
.map(TemplateDetailQuestionResponse::toResponse)
.toList();

return Optional.ofNullable(template)
.map(it -> TemplateDetailInfoResponse.builder()
.id(it.getId())
.title(it.getTitle())
.templateName(it.getTemplateName())
.templateImageUrl(it.getTemplateImageUrl())
.firstTag(it.getFirstTag())
.secondTag(it.getSecondTag())
.description(it.getDescription())
.tipTitle(it.getTipTitle())
.tipDescription(it.getTipDescription())
.templateDetailQuestionList(templateDetailQuestionList)
.build())
.orElseThrow(() -> new TemplateException(INVALID_TEMPLATE));

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.layer.domain.template.dto;

import lombok.Builder;
import org.layer.domain.template.entity.TemplateQuestion;

@Builder
public record TemplateDetailQuestionResponse(Long id, String entryWord, String description) {
public static TemplateDetailQuestionResponse toResponse(TemplateQuestion templateQuestion) {
return TemplateDetailQuestionResponse.builder()
.id(templateQuestion.getId())
.entryWord(templateQuestion.getEntryWord())
.description(templateQuestion.getDescription())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.layer.domain.template.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;

@Schema
public record TemplateInfoRequest(@NotNull @Schema(description = "템플릿 ID") Long id) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.layer.domain.template.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import org.layer.domain.template.entity.Template;
import org.springframework.data.domain.Slice;

import java.util.List;
import java.util.stream.Collectors;

public record TemplateListResponse(
@Schema(description = "템플릿") List<TemplateSimpleInfoResponse> templateInfoList,
@Schema(description = "마지막 페이지 여부") Boolean last
) {
public static TemplateListResponse toResponse(Slice<Template> templateSlice) {
List<TemplateSimpleInfoResponse> simpleInfoList = templateSlice.getContent().stream()
.map(TemplateSimpleInfoResponse::toResponse)
.collect(Collectors.toList());
return new TemplateListResponse(simpleInfoList, templateSlice.isLast());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.layer.domain.template.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import org.layer.domain.template.entity.Template;
import org.layer.domain.template.entity.TemplateQuestion;

import java.util.List;
import java.util.stream.Collectors;


@Builder
public record TemplateQuestionListResponse(
@Schema(description = "템플릿 ID")
@NotNull
Long id,
@Schema(description = "템플릿 제목", example = "빠르고 효율적인 회고")
@NotNull
String title,
@Schema(description = "템플릿 명칭", example = "KPT 회고")
@NotNull
String templateName,
@Schema(description = "템플릿에 속한 질문 리스트")
List<TemplateQuestionResponse> questionList
) {

public static TemplateQuestionListResponse toResponse(Template template, List<TemplateQuestion> questionList) {
List<TemplateQuestionResponse> questionResponseList = questionList.stream().map(TemplateQuestionResponse::toResponse).collect(Collectors.toList());
return TemplateQuestionListResponse.builder()
.id(template.getId())
.title(template.getTitle())
.templateName(template.getTemplateName())
.questionList(questionResponseList)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.layer.domain.template.dto;

import lombok.Builder;
import org.layer.domain.question.entity.Question;
import org.layer.domain.question.enums.QuestionType;
import org.layer.domain.template.entity.TemplateQuestion;
@Builder
public record TemplateQuestionResponse(Long id, String content, QuestionType questionType) {
public static TemplateQuestionResponse toResponse(TemplateQuestion templateQuestion) {
return TemplateQuestionResponse.builder()
.id(templateQuestion.getId())
.content(templateQuestion.getContent())
.questionType(templateQuestion.getQuestionType())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.layer.domain.template.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import org.layer.common.exception.BaseCustomException;
import org.layer.domain.space.dto.SpaceResponse;
import org.layer.domain.space.dto.SpaceWithMemberCount;
import org.layer.domain.template.entity.Template;
import org.layer.domain.template.exception.TemplateException;

import java.util.Optional;

import static org.layer.domain.auth.exception.TokenExceptionType.INVALID_REFRESH_TOKEN;
import static org.layer.domain.template.exception.TemplateExceptionType.INVALID_TEMPLATE;

@Builder
@Schema(description = "템플릿 간단 정보 단건 조회 응답")
public record TemplateSimpleInfoResponse(
@Schema(description = "템플릿 ID")
@NotNull
Long id,
@Schema(description = "템플릿 제목", example = "빠르고 효율적인 회고")
@NotNull
String title,
@Schema(description = "템플릿 명칭", example = "KPT 회고")
@NotNull
String templateName,

@Schema(description = "템플릿 사진 url", example = "[url]")
String imageUrl
) {

public static TemplateSimpleInfoResponse toResponse(Template template) {
return Optional.ofNullable(template)
.map(it -> TemplateSimpleInfoResponse.builder().id(it.getId()).title(it.getTitle())
.templateName(it.getTemplateName()).imageUrl(it.getTemplateImageUrl()).build())
.orElseThrow(() -> new TemplateException(INVALID_TEMPLATE));
}
}
Loading

0 comments on commit f9a29a4

Please sign in to comment.