From 3c70b83c1daa84bca087c7b4affb571e72579c41 Mon Sep 17 00:00:00 2001 From: johnniang Date: Tue, 2 Apr 2019 17:43:27 +0800 Subject: [PATCH] Complete ArchiveController#listYearArchives --- .../halo/config/SwaggerConfiguration.java | 2 +- .../ryanc/halo/model/vo/ArchiveMonthVO.java | 30 ++++++++++ .../cc/ryanc/halo/model/vo/ArchiveYearVO.java | 30 ++++++++++ .../repository/base/BasePostRepository.java | 29 +++++++-- .../cc/ryanc/halo/service/PostService.java | 19 ++++++ .../halo/service/impl/OptionServiceImpl.java | 4 +- .../service/impl/PostCategoryServiceImpl.java | 3 +- .../halo/service/impl/PostServiceImpl.java | 59 ++++++++++++++++++- .../java/cc/ryanc/halo/utils/DateUtils.java | 17 ++++++ .../controller/admin/api/ThemeController.java | 2 + .../controller/admin/api/UserController.java | 2 + .../portal/api/ArchiveController.java | 37 ++++++++++++ 12 files changed, 226 insertions(+), 8 deletions(-) create mode 100644 src/main/java/cc/ryanc/halo/model/vo/ArchiveMonthVO.java create mode 100644 src/main/java/cc/ryanc/halo/model/vo/ArchiveYearVO.java create mode 100644 src/main/java/cc/ryanc/halo/web/controller/portal/api/ArchiveController.java diff --git a/src/main/java/cc/ryanc/halo/config/SwaggerConfiguration.java b/src/main/java/cc/ryanc/halo/config/SwaggerConfiguration.java index 6b2b5a647..65b52ddcc 100644 --- a/src/main/java/cc/ryanc/halo/config/SwaggerConfiguration.java +++ b/src/main/java/cc/ryanc/halo/config/SwaggerConfiguration.java @@ -63,7 +63,7 @@ public class SwaggerConfiguration { public Docket haloDefaultApi() { log.debug("Doc disabled: [{}]", haloProperties.getDocDisabled()); return buildApiDocket("cc.ryanc.halo.default", - "cc.ryanc.halo.web.controller.api", + "cc.ryanc.halo.web.controller.portal.api", "/api/**") .enable(!haloProperties.getDocDisabled()); } diff --git a/src/main/java/cc/ryanc/halo/model/vo/ArchiveMonthVO.java b/src/main/java/cc/ryanc/halo/model/vo/ArchiveMonthVO.java new file mode 100644 index 000000000..1400f846a --- /dev/null +++ b/src/main/java/cc/ryanc/halo/model/vo/ArchiveMonthVO.java @@ -0,0 +1,30 @@ +package cc.ryanc.halo.model.vo; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * Archive vo. + * + * @author johnniang + * @date 4/2/19 + */ +@Data +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class ArchiveMonthVO extends ArchiveYearVO { + + private Integer month; + + @Override + public int compare(ArchiveYearVO current, ArchiveYearVO other) { + int compare = super.compare(current, other); + + if (compare != 0) { + return compare; + } + + return ((ArchiveMonthVO) current).month - ((ArchiveMonthVO) other).month; + } +} diff --git a/src/main/java/cc/ryanc/halo/model/vo/ArchiveYearVO.java b/src/main/java/cc/ryanc/halo/model/vo/ArchiveYearVO.java new file mode 100644 index 000000000..23225da64 --- /dev/null +++ b/src/main/java/cc/ryanc/halo/model/vo/ArchiveYearVO.java @@ -0,0 +1,30 @@ +package cc.ryanc.halo.model.vo; + +import cc.ryanc.halo.model.dto.post.PostMinimalOutputDTO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.Comparator; +import java.util.List; + +/** + * Archive vo. + * + * @author johnniang + * @date 4/2/19 + */ +@Data +@ToString +@EqualsAndHashCode +public class ArchiveYearVO implements Comparator { + + private Integer year; + + private List posts; + + @Override + public int compare(ArchiveYearVO current, ArchiveYearVO other) { + return current.year - other.year; + } +} diff --git a/src/main/java/cc/ryanc/halo/repository/base/BasePostRepository.java b/src/main/java/cc/ryanc/halo/repository/base/BasePostRepository.java index 150325c74..fb062a9f3 100644 --- a/src/main/java/cc/ryanc/halo/repository/base/BasePostRepository.java +++ b/src/main/java/cc/ryanc/halo/repository/base/BasePostRepository.java @@ -4,9 +4,11 @@ import cc.ryanc.halo.model.entity.BasePost; import cc.ryanc.halo.model.enums.PostStatus; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.data.repository.NoRepositoryBean; import org.springframework.lang.NonNull; +import java.util.List; import java.util.Optional; /** @@ -19,15 +21,34 @@ import java.util.Optional; public interface BasePostRepository extends BaseRepository { /** - * Finds posts by status and type. + * Finds posts by status and pageable. * - * @param status status - * @param pageable pageable - * @return Page + * @param status post status must not be null + * @param pageable page info must not be null + * @return a page of post */ @NonNull Page findAllByStatus(@NonNull PostStatus status, @NonNull Pageable pageable); + /** + * Finds posts by status. + * + * @param status post staus must not be null + * @return a list of post + */ + @NonNull + List findAllByStatus(@NonNull PostStatus status); + + /** + * Finds posts by status. + * + * @param status post staus must not be null + * @param sort sort info must not be null + * @return a list of post + */ + @NonNull + List findAllByStatus(@NonNull PostStatus status, @NonNull Sort sort); + /** * Counts posts by status and type. * diff --git a/src/main/java/cc/ryanc/halo/service/PostService.java b/src/main/java/cc/ryanc/halo/service/PostService.java index 6ac817125..1106f3d8c 100755 --- a/src/main/java/cc/ryanc/halo/service/PostService.java +++ b/src/main/java/cc/ryanc/halo/service/PostService.java @@ -4,6 +4,8 @@ import cc.ryanc.halo.model.dto.post.PostMinimalOutputDTO; import cc.ryanc.halo.model.dto.post.PostSimpleOutputDTO; import cc.ryanc.halo.model.entity.Post; import cc.ryanc.halo.model.enums.PostStatus; +import cc.ryanc.halo.model.vo.ArchiveMonthVO; +import cc.ryanc.halo.model.vo.ArchiveYearVO; import cc.ryanc.halo.model.vo.PostDetailVO; import cc.ryanc.halo.model.vo.PostListVO; import cc.ryanc.halo.service.base.CrudService; @@ -12,6 +14,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.lang.NonNull; import org.springframework.transaction.annotation.Transactional; +import java.util.List; import java.util.Set; /** @@ -144,4 +147,20 @@ public interface PostService extends CrudService { * @return like total number */ long countLike(); + + /** + * Lists year archives. + * + * @return a list of year archive + */ + @NonNull + List listYearArchives(); + + /** + * Lists month archives. + * + * @return a list of month archive + */ + @NonNull + List listMonthArchives(); } diff --git a/src/main/java/cc/ryanc/halo/service/impl/OptionServiceImpl.java b/src/main/java/cc/ryanc/halo/service/impl/OptionServiceImpl.java index 8ff0cb78b..e98d3727a 100644 --- a/src/main/java/cc/ryanc/halo/service/impl/OptionServiceImpl.java +++ b/src/main/java/cc/ryanc/halo/service/impl/OptionServiceImpl.java @@ -58,6 +58,7 @@ public class OptionServiceImpl extends AbstractCrudService impl return; } + // TODO Consider cache options with map Option option = optionRepository.findByOptionKey(key).map(anOption -> { // Exist anOption.setOptionValue(value); @@ -87,6 +88,7 @@ public class OptionServiceImpl extends AbstractCrudService impl return; } + // TODO Optimize the queries options.forEach((key, value) -> save(key, value, source)); } @@ -121,7 +123,7 @@ public class OptionServiceImpl extends AbstractCrudService impl @Override public List listDtos() { - return listAll().stream().map(option -> (OptionOutputDTO) new OptionOutputDTO().convertFrom(option)).collect(Collectors.toList()); + return listAll().stream().map(option -> new OptionOutputDTO().convertFrom(option)).collect(Collectors.toList()); } /** diff --git a/src/main/java/cc/ryanc/halo/service/impl/PostCategoryServiceImpl.java b/src/main/java/cc/ryanc/halo/service/impl/PostCategoryServiceImpl.java index b8b51a911..8b281f12a 100644 --- a/src/main/java/cc/ryanc/halo/service/impl/PostCategoryServiceImpl.java +++ b/src/main/java/cc/ryanc/halo/service/impl/PostCategoryServiceImpl.java @@ -72,7 +72,8 @@ public class PostCategoryServiceImpl extends AbstractCrudService> categoryListMap = new HashMap<>(); // Foreach and collect - postCategories.forEach(postCategory -> categoryListMap.computeIfAbsent(postCategory.getPostId(), postId -> new LinkedList<>()).add(categoryMap.get(postCategory.getCategoryId()))); + postCategories.forEach(postCategory -> categoryListMap.computeIfAbsent(postCategory.getPostId(), postId -> new LinkedList<>()) + .add(categoryMap.get(postCategory.getCategoryId()))); return categoryListMap; } diff --git a/src/main/java/cc/ryanc/halo/service/impl/PostServiceImpl.java b/src/main/java/cc/ryanc/halo/service/impl/PostServiceImpl.java index 11ba0c0e4..c37e72dd4 100644 --- a/src/main/java/cc/ryanc/halo/service/impl/PostServiceImpl.java +++ b/src/main/java/cc/ryanc/halo/service/impl/PostServiceImpl.java @@ -8,6 +8,8 @@ import cc.ryanc.halo.model.dto.post.PostMinimalOutputDTO; import cc.ryanc.halo.model.dto.post.PostSimpleOutputDTO; import cc.ryanc.halo.model.entity.*; import cc.ryanc.halo.model.enums.PostStatus; +import cc.ryanc.halo.model.vo.ArchiveMonthVO; +import cc.ryanc.halo.model.vo.ArchiveYearVO; import cc.ryanc.halo.model.vo.PostDetailVO; import cc.ryanc.halo.model.vo.PostListVO; import cc.ryanc.halo.repository.PostRepository; @@ -26,12 +28,15 @@ import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; import java.util.*; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; +import static org.springframework.data.domain.Sort.Direction.DESC; + /** * Post service implementation. * @@ -83,7 +88,7 @@ public class PostServiceImpl extends AbstractCrudService implemen public Page pageLatest(int top) { Assert.isTrue(top > 0, "Top number must not be less than 0"); - PageRequest latestPageable = PageRequest.of(0, top, Sort.by(Sort.Direction.DESC, "editTime")); + PageRequest latestPageable = PageRequest.of(0, top, Sort.by(DESC, "editTime")); return listAll(latestPageable); } @@ -253,6 +258,41 @@ public class PostServiceImpl extends AbstractCrudService implemen return Optional.ofNullable(postRepository.countLike()).orElse(0L); } + @Override + public List listYearArchives() { + // Get all posts + List posts = postRepository.findAllByStatus(PostStatus.PUBLISHED, Sort.by(DESC, "createTime")); + + Map> yearPostMap = new HashMap<>(); + + posts.forEach(post -> { + Calendar calendar = DateUtils.convertTo(post.getCreateTime()); + yearPostMap.computeIfAbsent(calendar.get(Calendar.YEAR), year -> new LinkedList<>()) + .add(post); + }); + + List archives = new LinkedList<>(); + + yearPostMap.forEach((year, postList) -> { + // Build archive + ArchiveYearVO archive = new ArchiveYearVO(); + archive.setYear(year); + archive.setPosts(convertTo(postList)); + + // Add archive + archives.add(archive); + }); + + // TODO Sort this list and inner list + + return archives; + } + + @Override + public List listMonthArchives() { + return null; + } + @Override @Transactional public Post removeById(Integer postId) { @@ -273,6 +313,23 @@ public class PostServiceImpl extends AbstractCrudService implemen return super.removeById(postId); } + /** + * Converts to post minimal output dto. + * + * @param posts a list of post + * @return a list of post minimal output dto + */ + @NonNull + private List convertTo(@NonNull List posts) { + if (CollectionUtils.isEmpty(posts)) { + return Collections.emptyList(); + } + + // Convert + return posts.stream().map(post -> new PostMinimalOutputDTO().convertFrom(post)) + .collect(Collectors.toList()); + } + /** * Converts to post detail vo. * diff --git a/src/main/java/cc/ryanc/halo/utils/DateUtils.java b/src/main/java/cc/ryanc/halo/utils/DateUtils.java index f1699b3a6..dea717fb3 100644 --- a/src/main/java/cc/ryanc/halo/utils/DateUtils.java +++ b/src/main/java/cc/ryanc/halo/utils/DateUtils.java @@ -1,7 +1,9 @@ package cc.ryanc.halo.utils; import org.springframework.lang.NonNull; +import org.springframework.util.Assert; +import java.util.Calendar; import java.util.Date; /** @@ -24,4 +26,19 @@ public class DateUtils { public static Date now() { return new Date(); } + + /** + * Converts from date into a calendar instance. + * + * @param date date instance must not be null + * @return calendar instance + */ + @NonNull + public static Calendar convertTo(@NonNull Date date) { + Assert.notNull(date, "Date must not be null"); + + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + return calendar; + } } diff --git a/src/main/java/cc/ryanc/halo/web/controller/admin/api/ThemeController.java b/src/main/java/cc/ryanc/halo/web/controller/admin/api/ThemeController.java index 187c001f2..558450f1e 100644 --- a/src/main/java/cc/ryanc/halo/web/controller/admin/api/ThemeController.java +++ b/src/main/java/cc/ryanc/halo/web/controller/admin/api/ThemeController.java @@ -21,6 +21,8 @@ import java.util.List; import java.util.Map; /** + * Theme controller. + * * @author : RYAN0UP * @date : 2019/3/20 */ diff --git a/src/main/java/cc/ryanc/halo/web/controller/admin/api/UserController.java b/src/main/java/cc/ryanc/halo/web/controller/admin/api/UserController.java index 27d010706..4eccb6779 100644 --- a/src/main/java/cc/ryanc/halo/web/controller/admin/api/UserController.java +++ b/src/main/java/cc/ryanc/halo/web/controller/admin/api/UserController.java @@ -10,6 +10,8 @@ import org.springframework.web.bind.annotation.*; import javax.validation.Valid; /** + * User controller. + * * @author johnniang * @date 3/19/19 */ diff --git a/src/main/java/cc/ryanc/halo/web/controller/portal/api/ArchiveController.java b/src/main/java/cc/ryanc/halo/web/controller/portal/api/ArchiveController.java new file mode 100644 index 000000000..b28821edc --- /dev/null +++ b/src/main/java/cc/ryanc/halo/web/controller/portal/api/ArchiveController.java @@ -0,0 +1,37 @@ +package cc.ryanc.halo.web.controller.portal.api; + +import cc.ryanc.halo.model.vo.ArchiveMonthVO; +import cc.ryanc.halo.model.vo.ArchiveYearVO; +import cc.ryanc.halo.service.PostService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * Archive portal controller. + * + * @author johnniang + * @date 4/2/19 + */ +@RestController +@RequestMapping("/api/archives") +public class ArchiveController { + + private final PostService postService; + + public ArchiveController(PostService postService) { + this.postService = postService; + } + + @GetMapping("years") + public List listYearArchives() { + return postService.listYearArchives(); + } + + @GetMapping("months") + public List listMonthArchives() { + return postService.listMonthArchives(); + } +}