Skip to content

Commit

Permalink
Release/0.2.0 (#389)
Browse files Browse the repository at this point in the history
* fix: release token expire length (#314)

* 뒤로가기 시 필터와 페이지네이션 유지 (#308)

* feature: url path params for history

* feature: url path params for history

* refactor: filter 중복 함수 훅으로 변경

* fix: 필요하지 않은 props 삭제

* fix: makeFilters 에러처리 추가

* refactor: makeFilters 함수 리팩토링

Co-authored-by: dudtjr913 <64782636+dudtjr913@users.noreply.github.com>

* fix: ProfilePage에서 글 목록 안 나타나는 현상 수정 (#380)

* fix: requestGetPosts 사용방식 통일

* fix: tag 많을 시 스크롤 추가

* 학습로그 검색 기능 버그 수정 및 전반적 기능 변경  (#382)

* fix: StudylogDocumentRepository 응답값 Page로 변경

* feat: StudylogDocument 관리 필드 추가

* feat: SearchDocument에 필드 추가 후 로직 뼈대 잡기

* feat: sample 쿼리 추가 및 studylog-document로 재수정

* feat: TODO 추가 및 일부 수정

* etc: TODO 추가

* feat: StudylogDocumentQueryBuilder 추가

* QueryBuilder 및 SearchPage로 Paging 응답은 잘 받아오지만, 역시나 StudylogRepository 조회 문제로 인해 페이징이 되지 않음.
* local 환경에서 QueryBuilder를 어떤 식으로 동작하게 해야할 지 고민해야함.

* etc: DataLoader 동기화 메서드 추가

* feat: Paging 기능 추가

* feat: local용 FakeStudylogDocumentService 생성

* feat: StudylogDocumentService의 응답을 DTO로 변경

* refactor: FakeStudylogDocumentService 패키지 이동

* feat: FakeStudylogDocumentRepository#findBySearchKeyword 구현

* fix: flyway test 및 local 환경에서 작동하지 않도록 수정

* fix: StudylogDocumentQueryBuilder에서 tagIds만 Filter 적용하고, 나머지는 Bool 쿼리 적용하도록 수정

* 학습로그 목록 조회 시 필요한 쿼리 스트링 변경 (#381)

* fix: 첫 페이지는 쿼리 스트링을 제거한다
fix: 사이즈와 정렬은 쿼리 스트링에서 제거한다
fix: 필터를 제거했을 때 첫 페이지로 이동한다
fix: 프로필>포스트usernames를 쿼리스트링에서 제거한다.

* fix: 메인 페이지 적용

* fix: 키워드가 없을 때 발생하는 에러 수정 (#384)

* fix: 포스트에 포함된 태그만 노출

* fix: 필터 및 페이징이 정상동작하지 않는 이슈 해결 (#387)

연관 이슈
- 2 > 1 페이지 이동 x
- 마지막 필터 취소 시 취소되지 않음

* fix: 머지 이슈 해결

Co-authored-by: dudtjr913 <64782636+dudtjr913@users.noreply.github.com>
Co-authored-by: HyuuunjuKim <43339385+HyuuunjuKim@users.noreply.github.com>
Co-authored-by: 서민정 <seominjeong.dev@gmail.com>
Co-authored-by: sunhpark42 <67677561+sunhpark42@users.noreply.github.com>
  • Loading branch information
5 people authored Sep 13, 2021
1 parent 07785f4 commit 57c47d0
Show file tree
Hide file tree
Showing 33 changed files with 668 additions and 370 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package wooteco.prolog;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import lombok.AllArgsConstructor;
import org.springframework.context.ApplicationListener;
Expand All @@ -10,7 +11,7 @@
import wooteco.prolog.login.application.dto.GithubProfileResponse;
import wooteco.prolog.member.application.MemberService;
import wooteco.prolog.member.domain.Member;
import wooteco.prolog.studylog.application.StudylogDocumentService;
import wooteco.prolog.studylog.application.DocumentService;
import wooteco.prolog.studylog.application.LevelService;
import wooteco.prolog.studylog.application.MissionService;
import wooteco.prolog.studylog.application.StudylogService;
Expand All @@ -36,11 +37,13 @@ public class DataLoaderApplicationListener implements
private TagService tagService;
private MemberService memberService;
private StudylogService studylogService;
private StudylogDocumentService studyLogDocumentService;
private DocumentService studyLogDocumentService;
private UpdatedContentsRepository updatedContentsRepository;

@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
studyLogDocumentService.deleteAll();

// level init
LevelResponse level1 = levelService.create(new LevelRequest("백엔드Java 레벨1 - 2021"));
LevelResponse level2 = levelService.create(new LevelRequest("프론트엔드JS 레벨1 - 2021"));
Expand All @@ -56,41 +59,62 @@ public void onApplicationEvent(ContextRefreshedEvent event) {
MissionResponse mission4 = missionService.create(new MissionRequest("지하철", level4.getId()));

// filter init
List<TagRequest> tagRequests = Arrays.asList(
List<TagRequest> tagRequests_1234 = Arrays.asList(
new TagRequest("자바"),
new TagRequest("자바스크립트"),
new TagRequest("스프링"),
new TagRequest("리액트")
);
tagService.findOrCreate(tagRequests);
List<TagRequest> tagRequests_empty = Collections.emptyList();
List<TagRequest> tagRequests_12 = Arrays.asList(
new TagRequest("자바"),
new TagRequest("자바스크립트")
);
List<TagRequest> tagRequests_34 = Arrays.asList(
new TagRequest("스프링"),
new TagRequest("리액트")
);
List<TagRequest> tagRequests_3 = Collections.singletonList(
new TagRequest("스프링")
);
tagService.findOrCreate(tagRequests_1234);
tagService.findOrCreate(tagRequests_empty);
tagService.findOrCreate(tagRequests_12);
tagService.findOrCreate(tagRequests_34);
tagService.findOrCreate(tagRequests_3);

// member init
Member member = memberService
Member member1 = memberService
.findOrCreateMember(new GithubProfileResponse("류성현", "gracefulBrown", "46308949",
"https://avatars.githubusercontent.com/u/46308949?v=4"));
"https://avatars.githubusercontent.com/u/46308949?v=4"));
Member member2 = memberService
.findOrCreateMember(new GithubProfileResponse("서민정", "seovalue", "123456",
"https://avatars.githubusercontent.com/u/48412963?v=4"));

// post init
studylogService.insertStudylogs(member, Arrays.asList(
studylogService.insertStudylogs(member1, Arrays.asList(
new StudylogRequest("ATDD란 무엇인가", "노션 정리 링크\n개인적으로 친구들에게 한 설명이 참 잘 썼다고 생각한다 호호",
mission1.getId(), tagRequests),
mission1.getId(), tagRequests_1234),
new StudylogRequest("프론트엔드 빌드 툴", "snowpack 사용하기 https://hjuu.tistory.com/6",
mission2.getId(), tagRequests),
new StudylogRequest("페이지네이션 데이터 1", "좋은 내용", mission1.getId(), tagRequests),
new StudylogRequest("페이지네이션 데이터 2", "좋은 내용", mission2.getId(), tagRequests),
new StudylogRequest("페이지네이션 데이터 3", "좋은 내용", mission3.getId(), tagRequests),
new StudylogRequest("페이지네이션 데이터 4", "좋은 내용", mission4.getId(), tagRequests),
new StudylogRequest("페이지네이션 데이터 5", "좋은 내용", mission1.getId(), tagRequests),
new StudylogRequest("페이지네이션 데이터 6", "좋은 내용", mission2.getId(), tagRequests),
new StudylogRequest("페이지네이션 데이터 7", "좋은 내용", mission3.getId(), tagRequests),
new StudylogRequest("페이지네이션 데이터 8", "좋은 내용", mission4.getId(), tagRequests),
new StudylogRequest("페이지네이션 데이터 9", "좋은 내용", mission1.getId(), tagRequests),
new StudylogRequest("페이지네이션 데이터 10", "좋은 내용", mission2.getId(), tagRequests),
new StudylogRequest("페이지네이션 데이터 11", "좋은 내용", mission3.getId(), tagRequests),
new StudylogRequest("페이지네이션 데이터 12", "좋은 내용", mission4.getId(), tagRequests)
mission2.getId(), tagRequests_1234),
new StudylogRequest("페이지네이션 데이터 1", "좋은 내용", mission1.getId(), tagRequests_1234),
new StudylogRequest("페이지네이션 데이터 2", "좋은 내용", mission2.getId(), tagRequests_empty),
new StudylogRequest("페이지네이션 데이터 3", "좋은 내용", mission3.getId(), tagRequests_12),
new StudylogRequest("페이지네이션 데이터 4", "좋은 내용", mission4.getId(), tagRequests_34),
new StudylogRequest("페이지네이션 데이터 5", "좋은 내용", mission1.getId(), tagRequests_3),
new StudylogRequest("페이지네이션 데이터 6", "좋은 내용", mission2.getId(), tagRequests_1234)
));

studylogService.insertStudylogs(member2, Arrays.asList(
new StudylogRequest("페이지네이션 데이터 7", "좋은 내용", mission3.getId(), tagRequests_empty),
new StudylogRequest("페이지네이션 데이터 8", "좋은 내용", mission4.getId(), tagRequests_12),
new StudylogRequest("페이지네이션 데이터 9", "좋은 내용", mission1.getId(), tagRequests_34),
new StudylogRequest("페이지네이션 데이터 10", "좋은 내용", mission2.getId(), tagRequests_3),
new StudylogRequest("페이지네이션 데이터 11", "좋은 내용", mission3.getId(), tagRequests_1234),
new StudylogRequest("페이지네이션 데이터 12", "좋은 내용", mission4.getId(), tagRequests_empty)
));

updatedContentsRepository.save(new UpdatedContents(null, UpdateContent.MEMBER_TAG_UPDATE, 1));

studyLogDocumentService.sync();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package wooteco.prolog.common.exception;

import java.util.Arrays;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand All @@ -19,7 +21,13 @@ public ResponseEntity<ExceptionDto> loginExceptionHandler(BadRequestException e)

@ExceptionHandler(Exception.class)
public ResponseEntity<ExceptionDto> runtimeExceptionHandler(Exception e) {
log.error(e.getMessage());
if (e.getMessage() == null) {
log.error(e.getClass().toString());
log.error(Arrays.stream(e.getStackTrace()).map(it -> it.toString())
.collect(Collectors.joining("\n")));
} else {
log.error(e.getMessage());
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ExceptionDto(500, "알 수 없는 에러"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class ProfileStudylogController {
public ResponseEntity<StudylogsResponse> findAllPostsOfMine(@PathVariable String username,
PostFilterRequest postFilterRequest,
@PageableDefault(size = 20, direction = Direction.DESC, sort = "id") Pageable pageable) {
final StudylogsResponse posts = studylogService.findPostsWithFilter(
final StudylogsResponse posts = studylogService.findPostsWithoutKeyword(
postFilterRequest.levels,
postFilterRequest.missions,
postFilterRequest.tags,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package wooteco.prolog.studylog.application;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import wooteco.prolog.studylog.domain.Studylog;
import wooteco.prolog.studylog.domain.StudylogDocument;
import wooteco.prolog.studylog.domain.repository.StudylogDocumentRepository;
import wooteco.prolog.studylog.domain.repository.StudylogRepository;
import wooteco.prolog.studylog.exception.StudylogDocumentNotFoundException;

public abstract class AbstractStudylogDocumentService implements DocumentService {

private static final String EMPTY = " ";

protected final StudylogDocumentRepository studylogDocumentRepository;
protected final StudylogRepository studylogRepository;

public AbstractStudylogDocumentService(StudylogDocumentRepository studylogDocumentRepository,
StudylogRepository studylogRepository) {
this.studylogDocumentRepository = studylogDocumentRepository;
this.studylogRepository = studylogRepository;
}

@Override
public void save(StudylogDocument studylogDocument) {
studylogDocumentRepository.save(studylogDocument);
}

@Override
public StudylogDocument findById(Long id) {
return studylogDocumentRepository.findById(id)
.orElseThrow(StudylogDocumentNotFoundException::new);
}

@Override
public void delete(StudylogDocument studylogDocument) {
studylogDocumentRepository.delete(studylogDocument);
}

@Override
public void deleteAll() {
studylogDocumentRepository.deleteAll();
}

@Override
public void sync() {
// sync between es and db
studylogDocumentRepository.deleteAll();

List<Studylog> studylogs = studylogRepository.findAll();
studylogDocumentRepository.saveAll(
studylogs.stream()
.map(Studylog::toStudylogDocument)
.collect(Collectors.toList())
);
}

@Override
public void update(StudylogDocument studylogDocument) {
studylogDocumentRepository.save(studylogDocument);
}

protected List<String> preprocess(String searchKeyword) {
String[] split = searchKeyword.split(EMPTY);
List<String> results = new ArrayList<>();
Collections.addAll(results, split);
if (split.length == 1) {
return results;
}
results.add(searchKeyword); // 기존 검색어도 리스트에 포함한다.
return results;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package wooteco.prolog.studylog.application;

import java.time.LocalDate;
import java.util.List;
import org.springframework.data.domain.Pageable;
import wooteco.prolog.studylog.application.dto.StudylogDocumentResponse;
import wooteco.prolog.studylog.domain.StudylogDocument;

public interface DocumentService {

void save(StudylogDocument toStudylogDocument);

StudylogDocument findById(Long id);

void delete(StudylogDocument studylogDocument);

void deleteAll();

void sync();

void update(StudylogDocument studylogDocument);

StudylogDocumentResponse findBySearchKeyword(
String keyword,
List<Long> tags,
List<Long> missions,
List<Long> levels,
List<String> usernames,
LocalDate start,
LocalDate end,
Pageable pageable
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package wooteco.prolog.studylog.application;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.springframework.context.annotation.Profile;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import wooteco.prolog.common.BaseEntity;
import wooteco.prolog.studylog.application.dto.StudylogDocumentResponse;
import wooteco.prolog.studylog.domain.Studylog;
import wooteco.prolog.studylog.domain.repository.StudylogDocumentRepository;
import wooteco.prolog.studylog.domain.repository.StudylogRepository;
import wooteco.prolog.studylog.domain.repository.StudylogSpecification;

@Profile({"local", "test"})
@Service
public class FakeStudylogDocumentService extends AbstractStudylogDocumentService {

public FakeStudylogDocumentService(
StudylogDocumentRepository studylogDocumentRepository,
StudylogRepository studylogRepository) {
super(studylogDocumentRepository, studylogRepository);
}

@Override
public StudylogDocumentResponse findBySearchKeyword(String keyword, List<Long> tags, List<Long> missions,
List<Long> levels, List<String> usernames,
LocalDate start, LocalDate end, Pageable pageable) {
final Page<Studylog> studylogs = studylogRepository.findAll(
makeSpecifications(keyword, tags, missions, levels, usernames, start, end), pageable);

final List<Long> studylogIds = studylogs.stream()
.map(BaseEntity::getId)
.collect(Collectors.toList());

return StudylogDocumentResponse.of(studylogIds,
studylogs.getTotalElements(),
studylogs.getTotalPages(),
studylogs.getNumber());
}

private Specification<Studylog> makeSpecifications(String keyword, List<Long> tags, List<Long> missions,
List<Long> levels, List<String> usernames,
LocalDate start, LocalDate end
) {
List<String> keywords = new ArrayList<>();
if (Objects.nonNull(keyword)) {
keywords = preprocess(keyword);
}

return StudylogSpecification.likeKeyword("title", keywords)
.or(StudylogSpecification.likeKeyword("content", keywords))
.and(StudylogSpecification.findByLevelIn(levels)
.and(StudylogSpecification.equalIn("mission", missions))
.and(StudylogSpecification.findByTagIn(tags))
.and(StudylogSpecification.findByUsernameIn(usernames))
.and(StudylogSpecification.findBetweenDate(start, end))
.and(StudylogSpecification.distinct(true)));
}
}
Loading

0 comments on commit 57c47d0

Please sign in to comment.