Merge remote-tracking branch 'origin/v1' into v1

pull/146/head
ruibaby 2019-04-25 11:54:07 +08:00
commit 6cfca880ab
12 changed files with 269 additions and 36 deletions

View File

@ -5,7 +5,7 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault; import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import run.halo.app.model.dto.CommentDTO; import run.halo.app.model.dto.BaseCommentDTO;
import run.halo.app.model.entity.Comment; import run.halo.app.model.entity.Comment;
import run.halo.app.model.enums.CommentStatus; import run.halo.app.model.enums.CommentStatus;
import run.halo.app.model.params.CommentParam; import run.halo.app.model.params.CommentParam;
@ -57,29 +57,26 @@ public class CommentController {
@PostMapping @PostMapping
@ApiOperation("Creates a comment (new or reply)") @ApiOperation("Creates a comment (new or reply)")
public CommentDTO createBy(@RequestBody CommentParam commentParam) { public BaseCommentDTO createBy(@RequestBody CommentParam commentParam) {
return new CommentDTO().convertFrom(commentService.createBy(commentParam)); Comment createdComment = commentService.createBy(commentParam);
return commentService.convertTo(createdComment);
} }
@PutMapping("{commentId:\\d+}/status/{status}") @PutMapping("{commentId:\\d+}/status/{status}")
@ApiOperation("Updates comment status") @ApiOperation("Updates comment status")
public CommentDTO updateStatusBy(@PathVariable("commentId") Long commentId, public BaseCommentDTO updateStatusBy(@PathVariable("commentId") Long commentId,
@PathVariable("status") CommentStatus status) { @PathVariable("status") CommentStatus status) {
// Update comment status // Update comment status
Comment updatedComment = commentService.updateStatus(commentId, status); Comment updatedComment = commentService.updateStatus(commentId, status);
return new CommentDTO().convertFrom(updatedComment); return commentService.convertTo(updatedComment);
} }
@DeleteMapping("{commentId:\\d+}") @DeleteMapping("{commentId:\\d+}")
@ApiOperation("Deletes comment permanently and recursively") @ApiOperation("Deletes comment permanently and recursively")
public CommentDTO deleteBy(@PathVariable("commentId") Long commentId) { public BaseCommentDTO deleteBy(@PathVariable("commentId") Long commentId) {
// Get comment by id Comment deletedComment = commentService.removeById(commentId);
Comment comment = commentService.getById(commentId);
// Remove it return commentService.convertTo(deletedComment);
commentService.remove(comment);
return new CommentDTO().convertFrom(comment);
} }
} }

View File

@ -0,0 +1,51 @@
package run.halo.app.controller.admin.api;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;
import run.halo.app.model.dto.BaseCommentDTO;
import run.halo.app.model.entity.Journal;
import run.halo.app.model.params.JournalParam;
import run.halo.app.service.JournalService;
import java.util.List;
/**
* Journal controller.
*
* @author johnniang
* @date 19-4-25
*/
@RestController
@RequestMapping("/api/admin/journals")
public class JournalController {
private final JournalService journalService;
public JournalController(JournalService journalService) {
this.journalService = journalService;
}
@GetMapping
@ApiOperation("Gets latest journals")
public Page<BaseCommentDTO> pageBy(Pageable pageable) {
Page<Journal> journalPage = journalService.pageBy(pageable);
return journalService.convertTo(journalPage);
}
@GetMapping("latest")
@ApiOperation("Gets latest journals")
public List<BaseCommentDTO> pageLatest(@RequestParam(name = "top", defaultValue = "10") int top) {
List<Journal> journals = journalService.pageLatest(top).getContent();
return journalService.convertTo(journals);
}
@PostMapping
@ApiOperation("Creates a journal")
public BaseCommentDTO createBy(@RequestBody JournalParam journalParam) {
Journal createdJournal = journalService.createBy(journalParam);
return journalService.convertTo(createdJournal);
}
}

View File

@ -10,8 +10,8 @@ import lombok.ToString;
* @author johnniang * @author johnniang
*/ */
@Data @Data
@ToString @ToString(callSuper = true)
@EqualsAndHashCode @EqualsAndHashCode(callSuper = true)
public class CommentDTO extends BaseCommentDTO { public class CommentDTO extends BaseCommentDTO {
} }

View File

@ -0,0 +1,39 @@
package run.halo.app.model.params;
import lombok.Data;
import run.halo.app.model.dto.base.InputConverter;
import run.halo.app.model.entity.Journal;
import javax.validation.constraints.Email;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
/**
* Journal param.
*
* @author johnniang
* @date 19-4-25
*/
@Data
public class JournalParam implements InputConverter<Journal> {
@NotBlank(message = "Author name must not be blank")
@Size(max = 50, message = "Length of comment author name must not be more than {max}")
private String author;
@NotBlank(message = "Email must not be blank")
@Email(message = "Email's format is incorrect")
@Size(max = 255, message = "Length of comment email must not be more than {max}")
private String email;
@Size(max = 127, message = "Length of comment author url must not be more than {max}")
private String authorUrl;
@NotBlank(message = "Content must not be blank")
@Size(max = 511, message = "Length of comment content must not be more than {max}")
private String content;
@Min(value = 0, message = "Parent id must not be less than {value}")
private Long parentId = 0L;
}

View File

@ -1,6 +1,5 @@
package run.halo.app.model.properties; package run.halo.app.model.properties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;

View File

@ -1,5 +1,7 @@
package run.halo.app.repository; package run.halo.app.repository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import run.halo.app.model.entity.Journal; import run.halo.app.model.entity.Journal;
@ -25,4 +27,13 @@ public interface JournalRepository extends BaseCommentRepository<Journal> {
@Query("select new run.halo.app.model.projection.CommentCountProjection(count(comment.id), comment.postId) from Journal comment where comment.postId in ?1 group by comment.postId") @Query("select new run.halo.app.model.projection.CommentCountProjection(count(comment.id), comment.postId) from Journal comment where comment.postId in ?1 group by comment.postId")
@NonNull @NonNull
List<CommentCountProjection> countByPostIds(@NonNull Iterable<Integer> postIds); List<CommentCountProjection> countByPostIds(@NonNull Iterable<Integer> postIds);
/**
* Finds all journals by parent id.
*
* @param parentId parent id must not be null
* @param pageable page info must not be null
* @return a page of journal
*/
Page<Journal> findAllByParentId(@NonNull Long parentId, @NonNull Pageable pageable);
} }

View File

@ -1,7 +1,11 @@
package run.halo.app.service; package run.halo.app.service;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.lang.NonNull;
import run.halo.app.model.entity.Journal; import run.halo.app.model.entity.Journal;
import run.halo.app.service.base.CrudService; import run.halo.app.model.params.JournalParam;
import run.halo.app.service.base.BaseCommentService;
/** /**
* Journal service interface. * Journal service interface.
@ -9,6 +13,22 @@ import run.halo.app.service.base.CrudService;
* @author johnniang * @author johnniang
* @date 19-4-24 * @date 19-4-24
*/ */
public interface JournalService extends CrudService<Journal, Long> { public interface JournalService extends BaseCommentService<Journal> {
/**
* Creates a journal.
*
* @param journalParam journal param must not be null
* @return created journal
*/
@NonNull
Journal createBy(@NonNull JournalParam journalParam);
/**
* Gets a page of journal
*
* @param pageable page info must not be null
* @return a page of journal
*/
Page<Journal> pageBy(@NonNull Pageable pageable);
} }

View File

@ -4,6 +4,7 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import run.halo.app.model.dto.BaseCommentDTO;
import run.halo.app.model.entity.BaseComment; import run.halo.app.model.entity.BaseComment;
import run.halo.app.model.enums.CommentStatus; import run.halo.app.model.enums.CommentStatus;
import run.halo.app.model.params.CommentQuery; import run.halo.app.model.params.CommentQuery;
@ -13,7 +14,6 @@ import run.halo.app.model.vo.BaseCommentWithParentVO;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Function;
/** /**
* Base comment service interface. * Base comment service interface.
@ -115,4 +115,31 @@ public interface BaseCommentService<COMMENT extends BaseComment> extends CrudSer
*/ */
@NonNull @NonNull
COMMENT updateStatus(@NonNull Long commentId, @NonNull CommentStatus status); COMMENT updateStatus(@NonNull Long commentId, @NonNull CommentStatus status);
/**
* Converts to base comment dto.
*
* @param comment comment must not be null
* @return base comment dto
*/
@NonNull
BaseCommentDTO convertTo(@NonNull COMMENT comment);
/**
* Converts to base comment dto list.
*
* @param comments comment list must not be null
* @return a list of base comment dto
*/
@NonNull
List<BaseCommentDTO> convertTo(@NonNull List<COMMENT> comments);
/**
* Converts to base comment dto page.
*
* @param commentPage comment page must not be null
* @return a page of base comment dto
*/
@NonNull
Page<BaseCommentDTO> convertTo(@NonNull Page<COMMENT> commentPage);
} }

View File

@ -18,6 +18,7 @@ import run.halo.app.event.comment.CommentNewEvent;
import run.halo.app.event.comment.CommentPassEvent; import run.halo.app.event.comment.CommentPassEvent;
import run.halo.app.event.comment.CommentReplyEvent; import run.halo.app.event.comment.CommentReplyEvent;
import run.halo.app.exception.NotFoundException; import run.halo.app.exception.NotFoundException;
import run.halo.app.model.dto.BaseCommentDTO;
import run.halo.app.model.entity.BaseComment; import run.halo.app.model.entity.BaseComment;
import run.halo.app.model.enums.CommentStatus; import run.halo.app.model.enums.CommentStatus;
import run.halo.app.model.params.CommentQuery; import run.halo.app.model.params.CommentQuery;
@ -38,6 +39,7 @@ import run.halo.app.utils.ServletUtils;
import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Predicate;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
/** /**
* Base comment service implementation. * Base comment service implementation.
@ -76,12 +78,7 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment> extend
@Override @Override
public Page<COMMENT> pageLatest(int top) { public Page<COMMENT> pageLatest(int top) {
Assert.isTrue(top > 0, "Top number must not be less than 0"); return listAll(buildLatestPageable(top));
// Build page request
PageRequest latestPageable = PageRequest.of(0, top, Sort.by(Sort.Direction.DESC, "createTime"));
return listAll(latestPageable);
} }
@Override @Override
@ -281,8 +278,32 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment> extend
return updatedComment; return updatedComment;
} }
@Override
public List<BaseCommentDTO> convertTo(List<COMMENT> comments) {
if (CollectionUtils.isEmpty(comments)) {
return Collections.emptyList();
}
return comments.stream()
.map(this::convertTo)
.collect(Collectors.toList());
}
@Override
public Page<BaseCommentDTO> convertTo(Page<COMMENT> commentPage) {
Assert.notNull(commentPage, "Comment page must not be null");
return commentPage.map(this::convertTo);
}
@Override
public BaseCommentDTO convertTo(COMMENT comment) {
Assert.notNull(comment, "Comment must not be null");
return new BaseCommentDTO().convertFrom(comment);
}
@NonNull @NonNull
private Specification<COMMENT> buildSpecByQuery(@NonNull CommentQuery commentQuery) { protected Specification<COMMENT> buildSpecByQuery(@NonNull CommentQuery commentQuery) {
Assert.notNull(commentQuery, "Comment query must not be null"); Assert.notNull(commentQuery, "Comment query must not be null");
return (Specification<COMMENT>) (root, query, criteriaBuilder) -> { return (Specification<COMMENT>) (root, query, criteriaBuilder) -> {
@ -313,7 +334,7 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment> extend
* @param sort sort info * @param sort sort info
* @return comment comparator * @return comment comparator
*/ */
private Comparator<BaseCommentVO> buildCommentComparator(Sort sort) { protected Comparator<BaseCommentVO> buildCommentComparator(Sort sort) {
return (currentComment, toCompareComment) -> { return (currentComment, toCompareComment) -> {
Assert.notNull(currentComment, "Current comment must not be null"); Assert.notNull(currentComment, "Current comment must not be null");
Assert.notNull(toCompareComment, "Comment to compare must not be null"); Assert.notNull(toCompareComment, "Comment to compare must not be null");
@ -339,9 +360,9 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment> extend
* @param comments comment list must not null * @param comments comment list must not null
* @param commentComparator comment vo comparator * @param commentComparator comment vo comparator
*/ */
private void concreteTree(@NonNull BaseCommentVO parentComment, protected void concreteTree(@NonNull BaseCommentVO parentComment,
@Nullable Collection<COMMENT> comments, @Nullable Collection<COMMENT> comments,
@NonNull Comparator<BaseCommentVO> commentComparator) { @NonNull Comparator<BaseCommentVO> commentComparator) {
Assert.notNull(parentComment, "Parent comment must not be null"); Assert.notNull(parentComment, "Parent comment must not be null");
Assert.notNull(commentComparator, "Comment comparator must not be null"); Assert.notNull(commentComparator, "Comment comparator must not be null");
@ -384,4 +405,17 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment> extend
parentComment.getChildren().sort(commentComparator); parentComment.getChildren().sort(commentComparator);
} }
} }
/**
* Builds latest page request.
*
* @param top top must not be less than 1
* @return latest page request
*/
@NonNull
Pageable buildLatestPageable(int top) {
Assert.isTrue(top > 0, "Top number must not be less than 0");
return PageRequest.of(0, top, Sort.by(Sort.Direction.DESC, "createTime"));
}
} }

View File

@ -59,7 +59,7 @@ public class CommentServiceImpl extends BaseCommentServiceImpl<Comment> implemen
if (authentication != null) { if (authentication != null) {
User user = authentication.getDetail().getUser(); User user = authentication.getDetail().getUser();
commentParam.setAuthor(StringUtils.isEmpty(user.getNickname()) ? user.getUsername() : user.getNickname()); commentParam.setAuthor(StringUtils.isBlank(user.getNickname()) ? user.getUsername() : user.getNickname());
commentParam.setEmail(user.getEmail()); commentParam.setEmail(user.getEmail());
commentParam.setAuthorUrl(optionService.getByPropertyOfNullable(BlogProperties.BLOG_URL)); commentParam.setAuthorUrl(optionService.getByPropertyOfNullable(BlogProperties.BLOG_URL));
} }

View File

@ -1,9 +1,22 @@
package run.halo.app.service.impl; package run.halo.app.service.impl;
import cn.hutool.core.lang.Assert;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import run.halo.app.model.entity.Journal; import run.halo.app.model.entity.Journal;
import run.halo.app.model.entity.User;
import run.halo.app.model.params.JournalParam;
import run.halo.app.model.properties.BlogProperties;
import run.halo.app.repository.JournalRepository; import run.halo.app.repository.JournalRepository;
import run.halo.app.repository.PostRepository;
import run.halo.app.security.authentication.Authentication;
import run.halo.app.security.context.SecurityContextHolder;
import run.halo.app.service.JournalService; import run.halo.app.service.JournalService;
import run.halo.app.service.base.AbstractCrudService; import run.halo.app.service.OptionService;
import run.halo.app.utils.ValidationUtils;
/** /**
* Journal service implementation. * Journal service implementation.
@ -11,12 +24,52 @@ import run.halo.app.service.base.AbstractCrudService;
* @author johnniang * @author johnniang
* @date 19-4-24 * @date 19-4-24
*/ */
public class JournalServiceImpl extends AbstractCrudService<Journal, Long> implements JournalService { @Service
public class JournalServiceImpl extends BaseCommentServiceImpl<Journal> implements JournalService {
private final JournalRepository journalRepository; private final JournalRepository journalRepository;
public JournalServiceImpl(JournalRepository journalRepository) { public JournalServiceImpl(JournalRepository journalRepository,
super(journalRepository); PostRepository postRepository,
OptionService optionService,
ApplicationEventPublisher eventPublisher) {
super(journalRepository, postRepository, optionService, eventPublisher);
this.journalRepository = journalRepository; this.journalRepository = journalRepository;
} }
@Override
public Journal createBy(JournalParam journalParam) {
Assert.notNull(journalParam, "Journal param must not be null");
// Check user login status
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
// Get user detail
User user = authentication.getDetail().getUser();
// Set some default value
journalParam.setAuthor(StringUtils.isBlank(user.getNickname()) ? user.getUsername() : user.getNickname());
journalParam.setAuthorUrl(optionService.getByPropertyOfNullable(BlogProperties.BLOG_URL));
journalParam.setEmail(user.getEmail());
}
// Validate the journal param
ValidationUtils.validate(journalParam);
// Convert, create and return
return createBy(journalParam.convertTo());
}
@Override
public Page<Journal> pageBy(Pageable pageable) {
Assert.notNull(pageable, "Page info must not be null");
return journalRepository.findAllByParentId(0L, pageable);
}
@Override
public Page<Journal> pageLatest(int top) {
return pageBy(buildLatestPageable(top));
}
} }

View File

@ -130,7 +130,7 @@ public class OptionServiceImpl extends AbstractCrudService<Option, Integer> impl
Set<String> keys = ServiceUtils.fetchProperty(options, Option::getKey); Set<String> keys = ServiceUtils.fetchProperty(options, Option::getKey);
Map<String, Object> result = ServiceUtils.convertToMap(options, Option::getKey, option -> { Map<String, Object> userDefinedOptionMap = ServiceUtils.convertToMap(options, Option::getKey, option -> {
String key = option.getKey(); String key = option.getKey();
PropertyEnum propertyEnum = propertyEnumMap.get(key); PropertyEnum propertyEnum = propertyEnumMap.get(key);
@ -142,6 +142,8 @@ public class OptionServiceImpl extends AbstractCrudService<Option, Integer> impl
return PropertyEnum.convertTo(option.getValue(), propertyEnum); return PropertyEnum.convertTo(option.getValue(), propertyEnum);
}); });
Map<String, Object> result = new HashMap<>(userDefinedOptionMap);
// Add default property // Add default property
propertyEnumMap.keySet() propertyEnumMap.keySet()
.stream() .stream()