mirror of https://github.com/halo-dev/halo
refactor: using index mechanisms to optimize comment queries (#5453)
#### What type of PR is this? /kind improvement /area core /milestone 2.14.x #### What this PR does / why we need it: 使用索引机制优化评论数据查询以提高效率 how to test it? - 测试 console 评论列表和筛选条件是否正确 - 测试主题端评论显示是否正确 #### Does this PR introduce a user-facing change? ```release-note 使用索引机制优化评论数据查询以提高效率 ```pull/5494/head
parent
92f2229460
commit
20d80f8f65
|
@ -116,6 +116,10 @@ public class Comment extends AbstractExtension {
|
||||||
public String getAnnotation(String key) {
|
public String getAnnotation(String key) {
|
||||||
return annotations == null ? null : annotations.get(key);
|
return annotations == null ? null : annotations.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String ownerIdentity(String kind, String name) {
|
||||||
|
return kind + "#" + name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@ -132,6 +136,10 @@ public class Comment extends AbstractExtension {
|
||||||
private Boolean hasNewReply;
|
private Boolean hasNewReply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String toSubjectRefKey(Ref subjectRef) {
|
||||||
|
return subjectRef.getGroup() + "/" + subjectRef.getKind() + "/" + subjectRef.getName();
|
||||||
|
}
|
||||||
|
|
||||||
public static int getUnreadReplyCount(List<Reply> replies, Instant lastReadTime) {
|
public static int getUnreadReplyCount(List<Reply> replies, Instant lastReadTime) {
|
||||||
if (CollectionUtils.isEmpty(replies)) {
|
if (CollectionUtils.isEmpty(replies)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -120,7 +120,7 @@ public class QueryFactory {
|
||||||
return new And(queries);
|
return new And(queries);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static And and(Query query1, Query query2) {
|
public static Query and(Query query1, Query query2) {
|
||||||
Collection<Query> queries = Arrays.asList(query1, query2);
|
Collection<Query> queries = Arrays.asList(query1, query2);
|
||||||
return new And(queries);
|
return new And(queries);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,24 @@
|
||||||
package run.halo.app.content.comment;
|
package run.halo.app.content.comment;
|
||||||
|
|
||||||
import static java.util.Comparator.comparing;
|
import static run.halo.app.extension.index.query.QueryFactory.and;
|
||||||
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
import static run.halo.app.extension.index.query.QueryFactory.contains;
|
||||||
import static run.halo.app.extension.router.selector.SelectorUtil.labelAndFieldSelectorToPredicate;
|
import static run.halo.app.extension.index.query.QueryFactory.equal;
|
||||||
|
import static run.halo.app.extension.router.selector.SelectorUtil.labelAndFieldSelectorToListOptions;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
import run.halo.app.core.extension.User;
|
||||||
import run.halo.app.core.extension.content.Comment;
|
import run.halo.app.core.extension.content.Comment;
|
||||||
import run.halo.app.core.extension.endpoint.SortResolver;
|
import run.halo.app.core.extension.endpoint.SortResolver;
|
||||||
import run.halo.app.extension.Comparators;
|
import run.halo.app.extension.ListOptions;
|
||||||
import run.halo.app.extension.Extension;
|
import run.halo.app.extension.PageRequest;
|
||||||
import run.halo.app.extension.Ref;
|
import run.halo.app.extension.PageRequestImpl;
|
||||||
import run.halo.app.extension.router.IListRequest;
|
import run.halo.app.extension.router.IListRequest;
|
||||||
|
import run.halo.app.extension.router.selector.FieldSelector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query criteria for comment list.
|
* Query criteria for comment list.
|
||||||
|
@ -34,12 +29,6 @@ import run.halo.app.extension.router.IListRequest;
|
||||||
public class CommentQuery extends IListRequest.QueryListRequest {
|
public class CommentQuery extends IListRequest.QueryListRequest {
|
||||||
|
|
||||||
private final ServerWebExchange exchange;
|
private final ServerWebExchange exchange;
|
||||||
static final Function<Comment, Instant> LAST_REPLY_TIME_FUNC =
|
|
||||||
comment -> {
|
|
||||||
Instant lastReplyTime = comment.getStatusOrDefault().getLastReplyTime();
|
|
||||||
return Optional.ofNullable(lastReplyTime)
|
|
||||||
.orElse(comment.getSpec().getCreationTime());
|
|
||||||
};
|
|
||||||
|
|
||||||
public CommentQuery(ServerRequest request) {
|
public CommentQuery(ServerRequest request) {
|
||||||
super(request.queryParams());
|
super(request.queryParams());
|
||||||
|
@ -52,26 +41,6 @@ public class CommentQuery extends IListRequest.QueryListRequest {
|
||||||
return StringUtils.isBlank(keyword) ? null : keyword;
|
return StringUtils.isBlank(keyword) ? null : keyword;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Schema(description = "Comments approved.")
|
|
||||||
public Boolean getApproved() {
|
|
||||||
return convertBooleanOrNull(queryParams.getFirst("approved"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Schema(description = "The comment is hidden from the theme side.")
|
|
||||||
public Boolean getHidden() {
|
|
||||||
return convertBooleanOrNull(queryParams.getFirst("hidden"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Schema(description = "Send notifications when there are new replies.")
|
|
||||||
public Boolean getAllowNotification() {
|
|
||||||
return convertBooleanOrNull(queryParams.getFirst("allowNotification"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Schema(description = "Comment top display.")
|
|
||||||
public Boolean getTop() {
|
|
||||||
return convertBooleanOrNull(queryParams.getFirst("top"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Schema(description = "Commenter kind.")
|
@Schema(description = "Commenter kind.")
|
||||||
public String getOwnerKind() {
|
public String getOwnerKind() {
|
||||||
String ownerKind = queryParams.getFirst("ownerKind");
|
String ownerKind = queryParams.getFirst("ownerKind");
|
||||||
|
@ -84,18 +53,6 @@ public class CommentQuery extends IListRequest.QueryListRequest {
|
||||||
return StringUtils.isBlank(ownerName) ? null : ownerName;
|
return StringUtils.isBlank(ownerName) ? null : ownerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Schema(description = "Comment subject kind.")
|
|
||||||
public String getSubjectKind() {
|
|
||||||
String subjectKind = queryParams.getFirst("subjectKind");
|
|
||||||
return StringUtils.isBlank(subjectKind) ? null : subjectKind;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Schema(description = "Comment subject name.")
|
|
||||||
public String getSubjectName() {
|
|
||||||
String subjectName = queryParams.getFirst("subjectName");
|
|
||||||
return StringUtils.isBlank(subjectName) ? null : subjectName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ArraySchema(uniqueItems = true,
|
@ArraySchema(uniqueItems = true,
|
||||||
arraySchema = @Schema(name = "sort",
|
arraySchema = @Schema(name = "sort",
|
||||||
description = "Sort property and direction of the list result. Supported fields: "
|
description = "Sort property and direction of the list result. Supported fields: "
|
||||||
|
@ -104,139 +61,35 @@ public class CommentQuery extends IListRequest.QueryListRequest {
|
||||||
implementation = String.class,
|
implementation = String.class,
|
||||||
example = "creationTimestamp,desc"))
|
example = "creationTimestamp,desc"))
|
||||||
public Sort getSort() {
|
public Sort getSort() {
|
||||||
return SortResolver.defaultInstance.resolve(exchange);
|
var sort = SortResolver.defaultInstance.resolve(exchange);
|
||||||
|
return sort.and(Sort.by("spec.creationTime", "metadata.name").descending());
|
||||||
|
}
|
||||||
|
|
||||||
|
public PageRequest toPageRequest() {
|
||||||
|
return PageRequestImpl.of(getPage(), getSize(), getSort());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a comparator from the query.
|
* Convert to list options.
|
||||||
*
|
|
||||||
* @return comparator
|
|
||||||
*/
|
*/
|
||||||
public Comparator<Comment> toComparator() {
|
public ListOptions toListOptions() {
|
||||||
var sort = getSort();
|
var listOptions =
|
||||||
var creationTimestampOrder = sort.getOrderFor("creationTimestamp");
|
labelAndFieldSelectorToListOptions(getLabelSelector(), getFieldSelector());
|
||||||
List<Comparator<Comment>> comparators = new ArrayList<>();
|
var fieldQuery = listOptions.getFieldSelector().query();
|
||||||
if (creationTimestampOrder != null) {
|
|
||||||
Comparator<Comment> comparator =
|
|
||||||
comparing(comment -> comment.getMetadata().getCreationTimestamp());
|
|
||||||
if (creationTimestampOrder.isDescending()) {
|
|
||||||
comparator = comparator.reversed();
|
|
||||||
}
|
|
||||||
comparators.add(comparator);
|
|
||||||
}
|
|
||||||
|
|
||||||
var replyCountOrder = sort.getOrderFor("replyCount");
|
|
||||||
if (replyCountOrder != null) {
|
|
||||||
Comparator<Comment> comparator = comparing(
|
|
||||||
comment -> defaultIfNull(comment.getStatusOrDefault().getReplyCount(), 0));
|
|
||||||
if (replyCountOrder.isDescending()) {
|
|
||||||
comparator = comparator.reversed();
|
|
||||||
}
|
|
||||||
comparators.add(comparator);
|
|
||||||
}
|
|
||||||
|
|
||||||
var lastReplyTimeOrder = sort.getOrderFor("lastReplyTime");
|
|
||||||
if (lastReplyTimeOrder == null) {
|
|
||||||
lastReplyTimeOrder = new Sort.Order(Sort.Direction.DESC, "lastReplyTime");
|
|
||||||
}
|
|
||||||
Comparator<Comment> comparator = comparing(LAST_REPLY_TIME_FUNC,
|
|
||||||
Comparators.nullsComparator(lastReplyTimeOrder.isAscending()));
|
|
||||||
if (lastReplyTimeOrder.isDescending()) {
|
|
||||||
comparator = comparator.reversed();
|
|
||||||
}
|
|
||||||
comparators.add(comparator);
|
|
||||||
comparators.add(Comparators.compareCreationTimestamp(false));
|
|
||||||
comparators.add(Comparators.compareName(true));
|
|
||||||
return comparators.stream()
|
|
||||||
.reduce(Comparator::thenComparing)
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a predicate from the query.
|
|
||||||
*
|
|
||||||
* @return predicate
|
|
||||||
*/
|
|
||||||
Predicate<Comment> toPredicate() {
|
|
||||||
Predicate<Comment> predicate = comment -> true;
|
|
||||||
|
|
||||||
String keyword = getKeyword();
|
String keyword = getKeyword();
|
||||||
if (keyword != null) {
|
if (StringUtils.isNotBlank(keyword)) {
|
||||||
predicate = predicate.and(comment -> {
|
fieldQuery = and(fieldQuery, contains("spec.raw", keyword));
|
||||||
String raw = comment.getSpec().getRaw();
|
|
||||||
return StringUtils.containsIgnoreCase(raw, keyword);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Boolean approved = getApproved();
|
|
||||||
if (approved != null) {
|
|
||||||
predicate =
|
|
||||||
predicate.and(comment -> Objects.equals(comment.getSpec().getApproved(), approved));
|
|
||||||
}
|
|
||||||
Boolean hidden = getHidden();
|
|
||||||
if (hidden != null) {
|
|
||||||
predicate =
|
|
||||||
predicate.and(comment -> Objects.equals(comment.getSpec().getHidden(), hidden));
|
|
||||||
}
|
|
||||||
|
|
||||||
Boolean top = getTop();
|
|
||||||
if (top != null) {
|
|
||||||
predicate = predicate.and(comment -> Objects.equals(comment.getSpec().getTop(), top));
|
|
||||||
}
|
|
||||||
|
|
||||||
Boolean allowNotification = getAllowNotification();
|
|
||||||
if (allowNotification != null) {
|
|
||||||
predicate = predicate.and(
|
|
||||||
comment -> Objects.equals(comment.getSpec().getAllowNotification(),
|
|
||||||
allowNotification));
|
|
||||||
}
|
|
||||||
|
|
||||||
String ownerKind = getOwnerKind();
|
|
||||||
if (ownerKind != null) {
|
|
||||||
predicate = predicate.and(comment -> {
|
|
||||||
Comment.CommentOwner owner = comment.getSpec().getOwner();
|
|
||||||
return Objects.equals(owner.getKind(), ownerKind);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String ownerName = getOwnerName();
|
String ownerName = getOwnerName();
|
||||||
if (ownerName != null) {
|
if (StringUtils.isNotBlank(ownerName)) {
|
||||||
predicate = predicate.and(comment -> {
|
String ownerKind = StringUtils.defaultIfBlank(getOwnerKind(), User.KIND);
|
||||||
Comment.CommentOwner owner = comment.getSpec().getOwner();
|
fieldQuery = and(fieldQuery,
|
||||||
if (Comment.CommentOwner.KIND_EMAIL.equals(owner.getKind())) {
|
equal("spec.owner", Comment.CommentOwner.ownerIdentity(ownerKind, ownerName)));
|
||||||
return Objects.equals(owner.getKind(), ownerKind)
|
|
||||||
&& (StringUtils.containsIgnoreCase(owner.getName(), ownerName)
|
|
||||||
|| StringUtils.containsIgnoreCase(owner.getDisplayName(), ownerName));
|
|
||||||
}
|
|
||||||
return Objects.equals(owner.getKind(), ownerKind)
|
|
||||||
&& StringUtils.containsIgnoreCase(owner.getName(), ownerName);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String subjectKind = getSubjectKind();
|
listOptions.setFieldSelector(FieldSelector.of(fieldQuery));
|
||||||
if (subjectKind != null) {
|
return listOptions;
|
||||||
predicate = predicate.and(comment -> {
|
|
||||||
Ref subjectRef = comment.getSpec().getSubjectRef();
|
|
||||||
return Objects.equals(subjectRef.getKind(), subjectKind);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
String subjectName = getSubjectName();
|
|
||||||
if (subjectName != null) {
|
|
||||||
predicate = predicate.and(comment -> {
|
|
||||||
Ref subjectRef = comment.getSpec().getSubjectRef();
|
|
||||||
return Objects.equals(subjectRef.getKind(), subjectKind)
|
|
||||||
&& StringUtils.containsIgnoreCase(subjectRef.getName(), subjectName);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Predicate<Extension> labelAndFieldSelectorPredicate =
|
|
||||||
labelAndFieldSelectorToPredicate(getLabelSelector(),
|
|
||||||
getFieldSelector());
|
|
||||||
return predicate.and(labelAndFieldSelectorPredicate);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Boolean convertBooleanOrNull(String value) {
|
|
||||||
return StringUtils.isBlank(value) ? null : Boolean.parseBoolean(value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,9 +50,8 @@ public class CommentServiceImpl implements CommentService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<ListResult<ListedComment>> listComment(CommentQuery commentQuery) {
|
public Mono<ListResult<ListedComment>> listComment(CommentQuery commentQuery) {
|
||||||
return this.client.list(Comment.class, commentQuery.toPredicate(),
|
return this.client.listBy(Comment.class, commentQuery.toListOptions(),
|
||||||
commentQuery.toComparator(),
|
commentQuery.toPageRequest())
|
||||||
commentQuery.getPage(), commentQuery.getSize())
|
|
||||||
.flatMap(comments -> Flux.fromStream(comments.get()
|
.flatMap(comments -> Flux.fromStream(comments.get()
|
||||||
.map(this::toListedComment))
|
.map(this::toListedComment))
|
||||||
.concatMap(Function.identity())
|
.concatMap(Function.identity())
|
||||||
|
@ -138,32 +137,21 @@ public class CommentServiceImpl implements CommentService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<ListedComment> toListedComment(Comment comment) {
|
private Mono<ListedComment> toListedComment(Comment comment) {
|
||||||
ListedComment.ListedCommentBuilder commentBuilder = ListedComment.builder()
|
var builder = ListedComment.builder().comment(comment);
|
||||||
.comment(comment);
|
// not empty
|
||||||
return Mono.just(commentBuilder)
|
var ownerInfoMono = getCommentOwnerInfo(comment.getSpec().getOwner())
|
||||||
.flatMap(builder -> {
|
.doOnNext(builder::owner);
|
||||||
Comment.CommentOwner owner = comment.getSpec().getOwner();
|
var subjectMono = getCommentSubject(comment.getSpec().getSubjectRef())
|
||||||
// not empty
|
.doOnNext(builder::subject);
|
||||||
return getCommentOwnerInfo(owner)
|
var statsMono = fetchStats(comment.getMetadata().getName())
|
||||||
.map(builder::owner);
|
.doOnNext(builder::stats);
|
||||||
})
|
return Mono.when(ownerInfoMono, subjectMono, statsMono)
|
||||||
.flatMap(builder -> getCommentSubject(comment.getSpec().getSubjectRef())
|
.then(Mono.fromSupplier(builder::build));
|
||||||
.map(subject -> {
|
|
||||||
builder.subject(subject);
|
|
||||||
return builder;
|
|
||||||
})
|
|
||||||
.switchIfEmpty(Mono.just(builder))
|
|
||||||
)
|
|
||||||
.map(ListedComment.ListedCommentBuilder::build)
|
|
||||||
.flatMap(lc -> fetchStats(comment)
|
|
||||||
.doOnNext(lc::setStats)
|
|
||||||
.thenReturn(lc));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Mono<CommentStats> fetchStats(Comment comment) {
|
Mono<CommentStats> fetchStats(String commentName) {
|
||||||
Assert.notNull(comment, "The comment must not be null.");
|
Assert.notNull(commentName, "The commentName must not be null.");
|
||||||
String name = comment.getMetadata().getName();
|
return counterService.getByName(MeterUtils.nameOf(Comment.class, commentName))
|
||||||
return counterService.getByName(MeterUtils.nameOf(Comment.class, name))
|
|
||||||
.map(counter -> CommentStats.builder()
|
.map(counter -> CommentStats.builder()
|
||||||
.upvote(counter.getUpvote())
|
.upvote(counter.getUpvote())
|
||||||
.build()
|
.build()
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package run.halo.app.infra;
|
package run.halo.app.infra;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.BooleanUtils.isTrue;
|
||||||
|
import static org.apache.commons.lang3.BooleanUtils.toStringTrueFalse;
|
||||||
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||||
import static run.halo.app.extension.index.IndexAttributeFactory.multiValueAttribute;
|
import static run.halo.app.extension.index.IndexAttributeFactory.multiValueAttribute;
|
||||||
import static run.halo.app.extension.index.IndexAttributeFactory.simpleAttribute;
|
import static run.halo.app.extension.index.IndexAttributeFactory.simpleAttribute;
|
||||||
|
@ -206,7 +208,69 @@ public class SchemeInitializer implements ApplicationListener<ApplicationContext
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
schemeManager.register(Comment.class);
|
schemeManager.register(Comment.class, indexSpecs -> {
|
||||||
|
indexSpecs.add(new IndexSpec()
|
||||||
|
.setName("spec.creationTime")
|
||||||
|
.setIndexFunc(simpleAttribute(Comment.class,
|
||||||
|
comment -> comment.getSpec().getCreationTime().toString())
|
||||||
|
));
|
||||||
|
indexSpecs.add(new IndexSpec()
|
||||||
|
.setName("spec.approved")
|
||||||
|
.setIndexFunc(simpleAttribute(Comment.class,
|
||||||
|
comment -> toStringTrueFalse(isTrue(comment.getSpec().getApproved())))
|
||||||
|
));
|
||||||
|
indexSpecs.add(new IndexSpec()
|
||||||
|
.setName("spec.owner")
|
||||||
|
.setIndexFunc(simpleAttribute(Comment.class, comment -> {
|
||||||
|
var owner = comment.getSpec().getOwner();
|
||||||
|
return Comment.CommentOwner.ownerIdentity(owner.getKind(), owner.getName());
|
||||||
|
})));
|
||||||
|
indexSpecs.add(new IndexSpec()
|
||||||
|
.setName("spec.subjectRef")
|
||||||
|
.setIndexFunc(simpleAttribute(Comment.class,
|
||||||
|
comment -> Comment.toSubjectRefKey(comment.getSpec().getSubjectRef()))
|
||||||
|
));
|
||||||
|
indexSpecs.add(new IndexSpec()
|
||||||
|
.setName("spec.top")
|
||||||
|
.setIndexFunc(simpleAttribute(Comment.class,
|
||||||
|
comment -> toStringTrueFalse(isTrue(comment.getSpec().getTop())))
|
||||||
|
));
|
||||||
|
indexSpecs.add(new IndexSpec()
|
||||||
|
.setName("spec.hidden")
|
||||||
|
.setIndexFunc(simpleAttribute(Comment.class,
|
||||||
|
comment -> toStringTrueFalse(isTrue(comment.getSpec().getHidden())))
|
||||||
|
));
|
||||||
|
indexSpecs.add(new IndexSpec()
|
||||||
|
.setName("spec.priority")
|
||||||
|
.setIndexFunc(simpleAttribute(Comment.class,
|
||||||
|
comment -> {
|
||||||
|
var isTop = comment.getSpec().getTop();
|
||||||
|
// only top comments have priority
|
||||||
|
if (!isTop) {
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
return defaultIfNull(comment.getSpec().getPriority(), 0).toString();
|
||||||
|
})
|
||||||
|
));
|
||||||
|
indexSpecs.add(new IndexSpec()
|
||||||
|
.setName("spec.raw")
|
||||||
|
.setIndexFunc(simpleAttribute(Comment.class,
|
||||||
|
comment -> comment.getSpec().getRaw())
|
||||||
|
));
|
||||||
|
indexSpecs.add(new IndexSpec()
|
||||||
|
.setName("status.lastReplyTime")
|
||||||
|
.setIndexFunc(simpleAttribute(Comment.class, comment -> {
|
||||||
|
var lastReplyTime = comment.getStatusOrDefault().getLastReplyTime();
|
||||||
|
return defaultIfNull(lastReplyTime,
|
||||||
|
comment.getSpec().getCreationTime()).toString();
|
||||||
|
})));
|
||||||
|
indexSpecs.add(new IndexSpec()
|
||||||
|
.setName("status.replyCount")
|
||||||
|
.setIndexFunc(simpleAttribute(Comment.class, comment -> {
|
||||||
|
var replyCount = comment.getStatusOrDefault().getReplyCount();
|
||||||
|
return defaultIfNull(replyCount, 0).toString();
|
||||||
|
})));
|
||||||
|
});
|
||||||
schemeManager.register(Reply.class);
|
schemeManager.register(Reply.class);
|
||||||
schemeManager.register(SinglePage.class);
|
schemeManager.register(SinglePage.class);
|
||||||
// storage.halo.run
|
// storage.halo.run
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package run.halo.app.theme.endpoint;
|
package run.halo.app.theme.endpoint;
|
||||||
|
|
||||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||||
import static java.util.Comparator.comparing;
|
|
||||||
import static org.apache.commons.lang3.BooleanUtils.isFalse;
|
import static org.apache.commons.lang3.BooleanUtils.isFalse;
|
||||||
import static org.apache.commons.lang3.BooleanUtils.isTrue;
|
import static org.apache.commons.lang3.BooleanUtils.isTrue;
|
||||||
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
|
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
|
||||||
|
@ -16,8 +15,6 @@ import io.github.resilience4j.reactor.ratelimiter.operator.RateLimiterOperator;
|
||||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||||
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
@ -43,9 +40,10 @@ import run.halo.app.core.extension.content.Comment;
|
||||||
import run.halo.app.core.extension.content.Reply;
|
import run.halo.app.core.extension.content.Reply;
|
||||||
import run.halo.app.core.extension.endpoint.CustomEndpoint;
|
import run.halo.app.core.extension.endpoint.CustomEndpoint;
|
||||||
import run.halo.app.core.extension.endpoint.SortResolver;
|
import run.halo.app.core.extension.endpoint.SortResolver;
|
||||||
import run.halo.app.extension.Comparators;
|
|
||||||
import run.halo.app.extension.GroupVersion;
|
import run.halo.app.extension.GroupVersion;
|
||||||
import run.halo.app.extension.ListResult;
|
import run.halo.app.extension.ListResult;
|
||||||
|
import run.halo.app.extension.PageRequest;
|
||||||
|
import run.halo.app.extension.PageRequestImpl;
|
||||||
import run.halo.app.extension.Ref;
|
import run.halo.app.extension.Ref;
|
||||||
import run.halo.app.extension.router.IListRequest;
|
import run.halo.app.extension.router.IListRequest;
|
||||||
import run.halo.app.extension.router.QueryParamBuildUtil;
|
import run.halo.app.extension.router.QueryParamBuildUtil;
|
||||||
|
@ -213,9 +211,7 @@ public class CommentFinderEndpoint implements CustomEndpoint {
|
||||||
|
|
||||||
Mono<ServerResponse> listComments(ServerRequest request) {
|
Mono<ServerResponse> listComments(ServerRequest request) {
|
||||||
CommentQuery commentQuery = new CommentQuery(request);
|
CommentQuery commentQuery = new CommentQuery(request);
|
||||||
var comparator = commentQuery.toComparator();
|
return commentPublicQueryService.list(commentQuery.toRef(), commentQuery.toPageRequest())
|
||||||
return commentPublicQueryService.list(commentQuery.toRef(), commentQuery.getPage(),
|
|
||||||
commentQuery.getSize(), comparator)
|
|
||||||
.flatMap(list -> ServerResponse.ok().bodyValue(list));
|
.flatMap(list -> ServerResponse.ok().bodyValue(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,26 +298,12 @@ public class CommentFinderEndpoint implements CustomEndpoint {
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
String emptyToNull(String str) {
|
public PageRequest toPageRequest() {
|
||||||
return StringUtils.isBlank(str) ? null : str;
|
return PageRequestImpl.of(getPage(), getSize(), getSort());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Comparator<Comment> toComparator() {
|
String emptyToNull(String str) {
|
||||||
var sort = getSort();
|
return StringUtils.isBlank(str) ? null : str;
|
||||||
var ctOrder = sort.getOrderFor("creationTimestamp");
|
|
||||||
List<Comparator<Comment>> comparators = new ArrayList<>();
|
|
||||||
if (ctOrder != null) {
|
|
||||||
Comparator<Comment> comparator =
|
|
||||||
comparing(comment -> comment.getMetadata().getCreationTimestamp());
|
|
||||||
if (ctOrder.isDescending()) {
|
|
||||||
comparator = comparator.reversed();
|
|
||||||
}
|
|
||||||
comparators.add(comparator);
|
|
||||||
comparators.add(Comparators.compareName(true));
|
|
||||||
}
|
|
||||||
return comparators.stream()
|
|
||||||
.reduce(Comparator::thenComparing)
|
|
||||||
.orElse(null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@ package run.halo.app.theme.finders;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import run.halo.app.core.extension.content.Comment;
|
|
||||||
import run.halo.app.core.extension.content.Reply;
|
import run.halo.app.core.extension.content.Reply;
|
||||||
import run.halo.app.extension.ListResult;
|
import run.halo.app.extension.ListResult;
|
||||||
|
import run.halo.app.extension.PageRequest;
|
||||||
import run.halo.app.extension.Ref;
|
import run.halo.app.extension.Ref;
|
||||||
import run.halo.app.theme.finders.vo.CommentVo;
|
import run.halo.app.theme.finders.vo.CommentVo;
|
||||||
import run.halo.app.theme.finders.vo.ReplyVo;
|
import run.halo.app.theme.finders.vo.ReplyVo;
|
||||||
|
@ -21,8 +21,7 @@ public interface CommentPublicQueryService {
|
||||||
Mono<ListResult<CommentVo>> list(Ref ref, @Nullable Integer page,
|
Mono<ListResult<CommentVo>> list(Ref ref, @Nullable Integer page,
|
||||||
@Nullable Integer size);
|
@Nullable Integer size);
|
||||||
|
|
||||||
Mono<ListResult<CommentVo>> list(Ref ref, @Nullable Integer page,
|
Mono<ListResult<CommentVo>> list(Ref ref, @Nullable PageRequest pageRequest);
|
||||||
@Nullable Integer size, @Nullable Comparator<Comment> comparator);
|
|
||||||
|
|
||||||
Mono<ListResult<ReplyVo>> listReply(String commentName, @Nullable Integer page,
|
Mono<ListResult<ReplyVo>> listReply(String commentName, @Nullable Integer page,
|
||||||
@Nullable Integer size);
|
@Nullable Integer size);
|
||||||
|
|
|
@ -2,34 +2,42 @@ package run.halo.app.theme.finders.impl;
|
||||||
|
|
||||||
|
|
||||||
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||||
|
import static run.halo.app.extension.index.query.QueryFactory.and;
|
||||||
|
import static run.halo.app.extension.index.query.QueryFactory.equal;
|
||||||
|
import static run.halo.app.extension.index.query.QueryFactory.or;
|
||||||
|
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.comparator.Comparators;
|
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import run.halo.app.content.comment.OwnerInfo;
|
import run.halo.app.content.comment.OwnerInfo;
|
||||||
import run.halo.app.content.comment.ReplyService;
|
import run.halo.app.content.comment.ReplyService;
|
||||||
|
import run.halo.app.core.extension.User;
|
||||||
import run.halo.app.core.extension.content.Comment;
|
import run.halo.app.core.extension.content.Comment;
|
||||||
import run.halo.app.core.extension.content.Reply;
|
import run.halo.app.core.extension.content.Reply;
|
||||||
import run.halo.app.core.extension.service.UserService;
|
import run.halo.app.core.extension.service.UserService;
|
||||||
import run.halo.app.extension.AbstractExtension;
|
import run.halo.app.extension.AbstractExtension;
|
||||||
|
import run.halo.app.extension.ListOptions;
|
||||||
import run.halo.app.extension.ListResult;
|
import run.halo.app.extension.ListResult;
|
||||||
|
import run.halo.app.extension.PageRequest;
|
||||||
|
import run.halo.app.extension.PageRequestImpl;
|
||||||
import run.halo.app.extension.ReactiveExtensionClient;
|
import run.halo.app.extension.ReactiveExtensionClient;
|
||||||
import run.halo.app.extension.Ref;
|
import run.halo.app.extension.Ref;
|
||||||
|
import run.halo.app.extension.index.query.QueryFactory;
|
||||||
|
import run.halo.app.extension.router.selector.FieldSelector;
|
||||||
import run.halo.app.infra.AnonymousUserConst;
|
import run.halo.app.infra.AnonymousUserConst;
|
||||||
import run.halo.app.metrics.CounterService;
|
import run.halo.app.metrics.CounterService;
|
||||||
import run.halo.app.metrics.MeterUtils;
|
import run.halo.app.metrics.MeterUtils;
|
||||||
|
@ -43,6 +51,7 @@ import run.halo.app.theme.finders.vo.ReplyVo;
|
||||||
* comment public query service implementation.
|
* comment public query service implementation.
|
||||||
*
|
*
|
||||||
* @author LIlGG
|
* @author LIlGG
|
||||||
|
* @author guqing
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@ -61,30 +70,31 @@ public class CommentPublicQueryServiceImpl implements CommentPublicQueryService
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<ListResult<CommentVo>> list(Ref ref, Integer page, Integer size) {
|
public Mono<ListResult<CommentVo>> list(Ref ref, Integer page, Integer size) {
|
||||||
return list(ref, page, size, defaultComparator());
|
return list(ref, PageRequestImpl.of(pageNullSafe(page), sizeNullSafe(size), defaultSort()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<ListResult<CommentVo>> list(Ref ref, Integer page, Integer size,
|
public Mono<ListResult<CommentVo>> list(Ref ref, PageRequest pageParam) {
|
||||||
Comparator<Comment> comparator) {
|
var pageRequest = Optional.ofNullable(pageParam)
|
||||||
final Comparator<Comment> commentComparator =
|
.map(page -> page.withSort(page.getSort().and(defaultSort())))
|
||||||
Objects.isNull(comparator) ? defaultComparator()
|
.orElse(PageRequestImpl.ofSize(0));
|
||||||
: comparator.thenComparing(defaultComparator());
|
return fixedCommentFieldQuery(ref)
|
||||||
return fixedCommentPredicate(ref)
|
.flatMap(fixedFieldQuery -> {
|
||||||
.flatMap(fixedPredicate ->
|
var listOptions = new ListOptions();
|
||||||
client.list(Comment.class, fixedPredicate,
|
listOptions.setFieldSelector(fixedFieldQuery);
|
||||||
commentComparator,
|
return client.listBy(Comment.class, listOptions, pageRequest)
|
||||||
pageNullSafe(page), sizeNullSafe(size))
|
.flatMap(listResult -> Flux.fromStream(listResult.get())
|
||||||
.flatMap(list -> Flux.fromStream(list.get().map(this::toCommentVo))
|
.map(this::toCommentVo)
|
||||||
.concatMap(Function.identity())
|
.concatMap(Function.identity())
|
||||||
.collectList()
|
.collectList()
|
||||||
.map(commentVos -> new ListResult<>(list.getPage(), list.getSize(),
|
.map(commentVos -> new ListResult<>(listResult.getPage(),
|
||||||
list.getTotal(),
|
listResult.getSize(),
|
||||||
|
listResult.getTotal(),
|
||||||
commentVos)
|
commentVos)
|
||||||
)
|
)
|
||||||
)
|
);
|
||||||
.defaultIfEmpty(new ListResult<>(page, size, 0L, List.of()))
|
})
|
||||||
);
|
.defaultIfEmpty(ListResult.emptyResult());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -193,28 +203,31 @@ public class CommentPublicQueryServiceImpl implements CommentPublicQueryService
|
||||||
.map(OwnerInfo::from);
|
.map(OwnerInfo::from);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<Predicate<Comment>> fixedCommentPredicate(@Nullable Ref ref) {
|
private Mono<FieldSelector> fixedCommentFieldQuery(@Nullable Ref ref) {
|
||||||
Predicate<Comment> basePredicate =
|
return Mono.fromSupplier(
|
||||||
comment -> comment.getMetadata().getDeletionTimestamp() == null;
|
() -> {
|
||||||
if (ref != null) {
|
var baseQuery = QueryFactory.isNull("metadata.deletionTimestamp");
|
||||||
basePredicate = basePredicate
|
if (ref != null) {
|
||||||
.and(comment -> comment.getSpec().getSubjectRef().equals(ref));
|
baseQuery =
|
||||||
}
|
and(baseQuery,
|
||||||
|
equal("spec.subjectRef", Comment.toSubjectRefKey(ref)));
|
||||||
// is approved and not hidden
|
}
|
||||||
Predicate<Comment> approvedPredicate =
|
return baseQuery;
|
||||||
comment -> BooleanUtils.isFalse(comment.getSpec().getHidden())
|
})
|
||||||
&& BooleanUtils.isTrue(comment.getSpec().getApproved());
|
.flatMap(query -> {
|
||||||
return getCurrentUserWithoutAnonymous()
|
var approvedQuery = and(
|
||||||
.map(username -> {
|
equal("spec.approved", BooleanUtils.TRUE),
|
||||||
Predicate<Comment> isOwner = comment -> {
|
equal("spec.hidden", BooleanUtils.FALSE)
|
||||||
Comment.CommentOwner owner = comment.getSpec().getOwner();
|
);
|
||||||
return owner != null && StringUtils.equals(username, owner.getName());
|
// we should list all comments that the user owns
|
||||||
};
|
return getCurrentUserWithoutAnonymous()
|
||||||
return approvedPredicate.or(isOwner);
|
.map(username -> or(approvedQuery, equal("spec.owner",
|
||||||
|
Comment.CommentOwner.ownerIdentity(User.KIND, username)))
|
||||||
|
)
|
||||||
|
.defaultIfEmpty(approvedQuery)
|
||||||
|
.map(compositeQuery -> and(query, compositeQuery));
|
||||||
})
|
})
|
||||||
.defaultIfEmpty(approvedPredicate)
|
.map(FieldSelector::of);
|
||||||
.map(basePredicate::and);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<Predicate<Reply>> fixedReplyPredicate(String commentName) {
|
private Mono<Predicate<Reply>> fixedReplyPredicate(String commentName) {
|
||||||
|
@ -247,43 +260,12 @@ public class CommentPublicQueryServiceImpl implements CommentPublicQueryService
|
||||||
.filter(username -> !AnonymousUserConst.PRINCIPAL.equals(username));
|
.filter(username -> !AnonymousUserConst.PRINCIPAL.equals(username));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Comparator<Comment> defaultComparator() {
|
static Sort defaultSort() {
|
||||||
return new CommentComparator();
|
return Sort.by(Sort.Order.desc("spec.top"),
|
||||||
}
|
Sort.Order.asc("spec.priority"),
|
||||||
|
Sort.Order.desc("spec.creationTime"),
|
||||||
static class CommentComparator implements Comparator<Comment> {
|
Sort.Order.asc("metadata.name")
|
||||||
@Override
|
);
|
||||||
public int compare(Comment c1, Comment c2) {
|
|
||||||
boolean c1Top = BooleanUtils.isTrue(c1.getSpec().getTop());
|
|
||||||
boolean c2Top = BooleanUtils.isTrue(c2.getSpec().getTop());
|
|
||||||
|
|
||||||
// c1 top = true && c2 top = false
|
|
||||||
if (c1Top && !c2Top) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// c1 top = false && c2 top = true
|
|
||||||
if (!c1Top && c2Top) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// c1 top = c2 top = true || c1 top = c2 top = false
|
|
||||||
var priorityComparator = Comparator.<Comment, Integer>comparing(
|
|
||||||
comment -> defaultIfNull(comment.getSpec().getPriority(), 0));
|
|
||||||
|
|
||||||
var creationTimeComparator = Comparator.<Comment, Instant>comparing(
|
|
||||||
comment -> comment.getSpec().getCreationTime(),
|
|
||||||
Comparators.nullsHigh(Comparator.<Instant>reverseOrder()));
|
|
||||||
|
|
||||||
var nameComparator = Comparator.<Comment, String>comparing(
|
|
||||||
comment -> comment.getMetadata().getName());
|
|
||||||
|
|
||||||
if (c1Top) {
|
|
||||||
return priorityComparator.thenComparing(creationTimeComparator)
|
|
||||||
.thenComparing(nameComparator)
|
|
||||||
.compare(c1, c2);
|
|
||||||
}
|
|
||||||
return creationTimeComparator.thenComparing(nameComparator).compare(c1, c2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int pageNullSafe(Integer page) {
|
int pageNullSafe(Integer page) {
|
||||||
|
|
|
@ -1,361 +0,0 @@
|
||||||
package run.halo.app.content.comment;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.mockito.Mockito.lenient;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import org.junit.jupiter.api.Nested;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
|
||||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
|
||||||
import org.springframework.mock.web.reactive.function.server.MockServerRequest;
|
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
|
||||||
import org.springframework.util.MultiValueMap;
|
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
|
||||||
import run.halo.app.core.extension.content.Comment;
|
|
||||||
import run.halo.app.extension.Metadata;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link CommentQuery}.
|
|
||||||
*
|
|
||||||
* @author guqing
|
|
||||||
* @since 2.0.0
|
|
||||||
*/
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
|
||||||
class CommentQueryTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getKeyword() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.add("keyword", "test");
|
|
||||||
CommentQuery commentQuery = getCommentQuery(queryParams);
|
|
||||||
assertThat(commentQuery.getKeyword()).isEqualTo("test");
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("keyword", "");
|
|
||||||
assertThat(commentQuery.getKeyword()).isNull();
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("keyword", null);
|
|
||||||
assertThat(commentQuery.getKeyword()).isNull();
|
|
||||||
queryParams.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getApproved() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.add("approved", "true");
|
|
||||||
CommentQuery commentQuery = getCommentQuery(queryParams);
|
|
||||||
assertThat(commentQuery.getApproved()).isTrue();
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("approved", "");
|
|
||||||
assertThat(commentQuery.getApproved()).isNull();
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("approved", "1");
|
|
||||||
assertThat(commentQuery.getApproved()).isFalse();
|
|
||||||
queryParams.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private CommentQuery getCommentQuery(MultiValueMap<String, String> queryParams) {
|
|
||||||
ServerWebExchange exchange = mock(ServerWebExchange.class);
|
|
||||||
MockServerRequest request = MockServerRequest.builder()
|
|
||||||
.queryParams(queryParams)
|
|
||||||
.exchange(exchange)
|
|
||||||
.build();
|
|
||||||
ServerHttpRequest httpRequest = mock(ServerHttpRequest.class);
|
|
||||||
lenient().when(exchange.getRequest()).thenReturn(httpRequest);
|
|
||||||
lenient().when(httpRequest.getQueryParams()).thenReturn(queryParams);
|
|
||||||
return new CommentQuery(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getHidden() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.add("hidden", "true");
|
|
||||||
CommentQuery commentQuery = getCommentQuery(queryParams);
|
|
||||||
assertThat(commentQuery.getHidden()).isTrue();
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("hidden", "");
|
|
||||||
assertThat(commentQuery.getHidden()).isNull();
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("hidden", "1");
|
|
||||||
assertThat(commentQuery.getHidden()).isFalse();
|
|
||||||
queryParams.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getAllowNotification() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.add("allowNotification", "true");
|
|
||||||
CommentQuery commentQuery = getCommentQuery(queryParams);
|
|
||||||
assertThat(commentQuery.getAllowNotification()).isTrue();
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("allowNotification", "");
|
|
||||||
assertThat(commentQuery.getAllowNotification()).isNull();
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("allowNotification", "1");
|
|
||||||
assertThat(commentQuery.getAllowNotification()).isFalse();
|
|
||||||
queryParams.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getTop() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.add("top", "true");
|
|
||||||
CommentQuery commentQuery = getCommentQuery(queryParams);
|
|
||||||
assertThat(commentQuery.getTop()).isTrue();
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("top", "");
|
|
||||||
assertThat(commentQuery.getTop()).isNull();
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("top", "1");
|
|
||||||
assertThat(commentQuery.getTop()).isFalse();
|
|
||||||
queryParams.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getOwnerKind() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.add("ownerKind", "test-owner-kind");
|
|
||||||
CommentQuery commentQuery = getCommentQuery(queryParams);
|
|
||||||
assertThat(commentQuery.getOwnerKind()).isEqualTo("test-owner-kind");
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("ownerKind", "");
|
|
||||||
assertThat(commentQuery.getOwnerKind()).isNull();
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("ownerKind", null);
|
|
||||||
assertThat(commentQuery.getOwnerKind()).isNull();
|
|
||||||
queryParams.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getOwnerName() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.add("ownerName", "test-owner-name");
|
|
||||||
CommentQuery commentQuery = getCommentQuery(queryParams);
|
|
||||||
assertThat(commentQuery.getOwnerName()).isEqualTo("test-owner-name");
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("ownerName", "");
|
|
||||||
assertThat(commentQuery.getOwnerName()).isNull();
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("ownerName", null);
|
|
||||||
assertThat(commentQuery.getOwnerName()).isNull();
|
|
||||||
queryParams.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getSubjectKind() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.add("subjectKind", "test-subject-kind");
|
|
||||||
CommentQuery commentQuery = getCommentQuery(queryParams);
|
|
||||||
assertThat(commentQuery.getSubjectKind()).isEqualTo("test-subject-kind");
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("subjectKind", "");
|
|
||||||
assertThat(commentQuery.getSubjectKind()).isNull();
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("subjectKind", null);
|
|
||||||
assertThat(commentQuery.getSubjectKind()).isNull();
|
|
||||||
queryParams.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getSubjectName() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.add("subjectName", "test-subject-name");
|
|
||||||
CommentQuery commentQuery = getCommentQuery(queryParams);
|
|
||||||
assertThat(commentQuery.getSubjectName()).isEqualTo("test-subject-name");
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("subjectName", "");
|
|
||||||
assertThat(commentQuery.getSubjectName()).isNull();
|
|
||||||
queryParams.clear();
|
|
||||||
|
|
||||||
queryParams.add("subjectName", null);
|
|
||||||
assertThat(commentQuery.getSubjectName()).isNull();
|
|
||||||
queryParams.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nested
|
|
||||||
class CommentSortTest {
|
|
||||||
@Test
|
|
||||||
void sortByCreateTimeAsc() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.set("sort", "creationTimestamp,asc");
|
|
||||||
CommentQuery commentQuery = getCommentQuery(queryParams);
|
|
||||||
Comparator<Comment> createTimeSorter = commentQuery.toComparator();
|
|
||||||
List<String> commentNames = comments().stream()
|
|
||||||
.sorted(createTimeSorter)
|
|
||||||
.map(comment -> comment.getMetadata().getName())
|
|
||||||
.toList();
|
|
||||||
assertThat(commentNames).isEqualTo(List.of("B", "C", "A"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void sortByCreateTimeDesc() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.add("sort", "creationTimestamp,desc");
|
|
||||||
Comparator<Comment> createTimeSorter = getCommentQuery(queryParams).toComparator();
|
|
||||||
List<String> commentNames = comments().stream()
|
|
||||||
.sorted(createTimeSorter)
|
|
||||||
.map(comment -> comment.getMetadata().getName())
|
|
||||||
.toList();
|
|
||||||
assertThat(commentNames).isEqualTo(List.of("A", "B", "C"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void sortByReplyCountAsc() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.add("sort", "replyCount,asc");
|
|
||||||
Comparator<Comment> comparator = getCommentQuery(queryParams).toComparator();
|
|
||||||
List<String> commentNames = comments().stream()
|
|
||||||
.sorted(comparator)
|
|
||||||
.map(comment -> comment.getMetadata().getName())
|
|
||||||
.toList();
|
|
||||||
assertThat(commentNames).isEqualTo(List.of("A", "B", "C"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void sortByReplyCountDesc() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.add("sort", "replyCount,desc");
|
|
||||||
Comparator<Comment> comparator = getCommentQuery(queryParams).toComparator();
|
|
||||||
List<String> commentNames = comments().stream()
|
|
||||||
.sorted(comparator)
|
|
||||||
.map(comment -> comment.getMetadata().getName())
|
|
||||||
.toList();
|
|
||||||
assertThat(commentNames).isEqualTo(List.of("C", "B", "A"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void sortByLastReplyTimeAsc() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.add("sort", "lastReplyTime,asc");
|
|
||||||
Comparator<Comment> comparator = getCommentQuery(queryParams).toComparator();
|
|
||||||
List<String> commentNames = comments().stream()
|
|
||||||
.sorted(comparator)
|
|
||||||
.map(comment -> comment.getMetadata().getName())
|
|
||||||
.toList();
|
|
||||||
assertThat(commentNames).isEqualTo(List.of("C", "A", "B"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void sortByLastReplyTimeDesc() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.add("sort", "lastReplyTime,desc");
|
|
||||||
Comparator<Comment> comparator = getCommentQuery(queryParams).toComparator();
|
|
||||||
List<String> commentNames = comments().stream()
|
|
||||||
.sorted(comparator)
|
|
||||||
.map(comment -> comment.getMetadata().getName())
|
|
||||||
.toList();
|
|
||||||
assertThat(commentNames).isEqualTo(List.of("B", "A", "C"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void sortByDefaultDesc() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
Comparator<Comment> comparator = getCommentQuery(queryParams).toComparator();
|
|
||||||
List<String> commentNames = comments().stream()
|
|
||||||
.sorted(comparator)
|
|
||||||
.map(comment -> comment.getMetadata().getName())
|
|
||||||
.toList();
|
|
||||||
assertThat(commentNames).isEqualTo(List.of("B", "A", "C"));
|
|
||||||
|
|
||||||
List<String> commentList = commentsIncludeNoReply().stream()
|
|
||||||
.sorted(comparator)
|
|
||||||
.map(comment -> comment.getMetadata().getName())
|
|
||||||
.toList();
|
|
||||||
assertThat(commentList).isEqualTo(List.of("D", "E", "B", "A", "C"));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Comment> comments() {
|
|
||||||
final Instant now = Instant.now();
|
|
||||||
Comment commentA = new Comment();
|
|
||||||
commentA.setMetadata(new Metadata());
|
|
||||||
commentA.getMetadata().setName("A");
|
|
||||||
// create time
|
|
||||||
commentA.getMetadata().setCreationTimestamp(now.plusSeconds(10));
|
|
||||||
commentA.setSpec(new Comment.CommentSpec());
|
|
||||||
commentA.getSpec().setCreationTime(commentA.getMetadata().getCreationTimestamp());
|
|
||||||
|
|
||||||
commentA.setStatus(new Comment.CommentStatus());
|
|
||||||
// last reply time
|
|
||||||
commentA.getStatus().setLastReplyTime(now.plusSeconds(5));
|
|
||||||
// reply count
|
|
||||||
commentA.getStatus().setReplyCount(3);
|
|
||||||
|
|
||||||
Comment commentB = new Comment();
|
|
||||||
commentB.setMetadata(new Metadata());
|
|
||||||
commentB.getMetadata().setName("B");
|
|
||||||
commentB.getMetadata().setCreationTimestamp(now.plusSeconds(5));
|
|
||||||
commentB.setSpec(new Comment.CommentSpec());
|
|
||||||
commentB.setStatus(new Comment.CommentStatus());
|
|
||||||
commentB.getStatus().setLastReplyTime(now.plusSeconds(15));
|
|
||||||
commentB.getStatus().setReplyCount(8);
|
|
||||||
commentB.getSpec().setCreationTime(commentB.getMetadata().getCreationTimestamp());
|
|
||||||
|
|
||||||
Comment commentC = new Comment();
|
|
||||||
commentC.setMetadata(new Metadata());
|
|
||||||
commentC.getMetadata().setName("C");
|
|
||||||
|
|
||||||
commentC.getMetadata().setCreationTimestamp(now.plusSeconds(5));
|
|
||||||
|
|
||||||
commentC.setSpec(new Comment.CommentSpec());
|
|
||||||
commentC.setStatus(new Comment.CommentStatus());
|
|
||||||
commentC.getStatus().setLastReplyTime(now.plusSeconds(3));
|
|
||||||
commentC.getStatus().setReplyCount(10);
|
|
||||||
commentC.getSpec().setCreationTime(commentC.getMetadata().getCreationTimestamp());
|
|
||||||
|
|
||||||
return List.of(commentA, commentB, commentC);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Comment> commentsIncludeNoReply() {
|
|
||||||
|
|
||||||
final Instant now = Instant.now();
|
|
||||||
Comment commentD = new Comment();
|
|
||||||
commentD.setMetadata(new Metadata());
|
|
||||||
commentD.getMetadata().setName("D");
|
|
||||||
|
|
||||||
commentD.getMetadata().setCreationTimestamp(now.plusSeconds(50));
|
|
||||||
|
|
||||||
commentD.setSpec(new Comment.CommentSpec());
|
|
||||||
commentD.getSpec().setCreationTime(commentD.getMetadata().getCreationTimestamp());
|
|
||||||
commentD.setStatus(new Comment.CommentStatus());
|
|
||||||
|
|
||||||
Comment commentE = new Comment();
|
|
||||||
commentE.setMetadata(new Metadata());
|
|
||||||
commentE.getMetadata().setName("E");
|
|
||||||
|
|
||||||
commentE.getMetadata().setCreationTimestamp(now.plusSeconds(20));
|
|
||||||
commentE.setSpec(new Comment.CommentSpec());
|
|
||||||
commentE.getSpec().setCreationTime(commentE.getMetadata().getCreationTimestamp());
|
|
||||||
commentE.setStatus(new Comment.CommentStatus());
|
|
||||||
|
|
||||||
List<Comment> comments = new ArrayList<>(comments());
|
|
||||||
comments.add(commentD);
|
|
||||||
comments.add(commentE);
|
|
||||||
|
|
||||||
return comments;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +1,6 @@
|
||||||
package run.halo.app.content.comment;
|
package run.halo.app.content.comment;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.lenient;
|
import static org.mockito.Mockito.lenient;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
@ -12,7 +10,6 @@ import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Predicate;
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -37,8 +34,10 @@ import run.halo.app.core.extension.User;
|
||||||
import run.halo.app.core.extension.content.Comment;
|
import run.halo.app.core.extension.content.Comment;
|
||||||
import run.halo.app.core.extension.content.Post;
|
import run.halo.app.core.extension.content.Post;
|
||||||
import run.halo.app.core.extension.service.UserService;
|
import run.halo.app.core.extension.service.UserService;
|
||||||
|
import run.halo.app.extension.ListOptions;
|
||||||
import run.halo.app.extension.ListResult;
|
import run.halo.app.extension.ListResult;
|
||||||
import run.halo.app.extension.Metadata;
|
import run.halo.app.extension.Metadata;
|
||||||
|
import run.halo.app.extension.PageRequest;
|
||||||
import run.halo.app.extension.ReactiveExtensionClient;
|
import run.halo.app.extension.ReactiveExtensionClient;
|
||||||
import run.halo.app.extension.Ref;
|
import run.halo.app.extension.Ref;
|
||||||
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
|
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
|
||||||
|
@ -81,13 +80,13 @@ class CommentServiceImplTest {
|
||||||
lenient().when(environmentFetcher.fetchComment()).thenReturn(Mono.just(commentSetting));
|
lenient().when(environmentFetcher.fetchComment()).thenReturn(Mono.just(commentSetting));
|
||||||
|
|
||||||
ListResult<Comment> comments = new ListResult<>(1, 10, 3, comments());
|
ListResult<Comment> comments = new ListResult<>(1, 10, 3, comments());
|
||||||
when(client.list(eq(Comment.class), any(), any(), anyInt(), anyInt()))
|
when(client.listBy(eq(Comment.class), any(ListOptions.class), any(PageRequest.class)))
|
||||||
.thenReturn(Mono.just(comments));
|
.thenReturn(Mono.just(comments));
|
||||||
|
|
||||||
when(userService.getUserOrGhost(eq("A-owner")))
|
when(userService.getUserOrGhost(eq("A-owner")))
|
||||||
.thenReturn(Mono.just(createUser("A-owner")));
|
.thenReturn(Mono.just(createUser("A-owner")));
|
||||||
when(userService.getUserOrGhost(eq("B-owner")))
|
when(userService.getUserOrGhost(eq("B-owner")))
|
||||||
.thenReturn(Mono.just(createUser("B-owner")));
|
.thenReturn(Mono.just(createUser("B-owner")));
|
||||||
when(client.fetch(eq(User.class), eq("C-owner")))
|
when(client.fetch(eq(User.class), eq("C-owner")))
|
||||||
.thenReturn(Mono.empty());
|
.thenReturn(Mono.empty());
|
||||||
|
|
||||||
|
@ -128,8 +127,7 @@ class CommentServiceImplTest {
|
||||||
ServerHttpRequest httpRequest = mock(ServerHttpRequest.class);
|
ServerHttpRequest httpRequest = mock(ServerHttpRequest.class);
|
||||||
when(exchange.getRequest()).thenReturn(httpRequest);
|
when(exchange.getRequest()).thenReturn(httpRequest);
|
||||||
when(httpRequest.getQueryParams()).thenReturn(queryParams);
|
when(httpRequest.getQueryParams()).thenReturn(queryParams);
|
||||||
Mono<ListResult<ListedComment>> listResultMono =
|
final var listResultMono = commentService.listComment(new CommentQuery(request));
|
||||||
commentService.listComment(new CommentQuery(request));
|
|
||||||
Counter counterA = new Counter();
|
Counter counterA = new Counter();
|
||||||
counterA.setUpvote(3);
|
counterA.setUpvote(3);
|
||||||
String commentACounter = MeterUtils.nameOf(Comment.class, "A");
|
String commentACounter = MeterUtils.nameOf(Comment.class, "A");
|
||||||
|
@ -170,7 +168,7 @@ class CommentServiceImplTest {
|
||||||
ArgumentCaptor<Comment> captor = ArgumentCaptor.forClass(Comment.class);
|
ArgumentCaptor<Comment> captor = ArgumentCaptor.forClass(Comment.class);
|
||||||
|
|
||||||
when(client.fetch(eq(User.class), eq("B-owner")))
|
when(client.fetch(eq(User.class), eq("B-owner")))
|
||||||
.thenReturn(Mono.just(createUser("B-owner")));
|
.thenReturn(Mono.just(createUser("B-owner")));
|
||||||
Comment commentToCreate = commentRequest.toComment();
|
Comment commentToCreate = commentRequest.toComment();
|
||||||
commentToCreate.getMetadata().setName("fake");
|
commentToCreate.getMetadata().setName("fake");
|
||||||
Mono<Comment> commentMono = commentService.create(commentToCreate);
|
Mono<Comment> commentMono = commentService.create(commentToCreate);
|
||||||
|
@ -214,49 +212,6 @@ class CommentServiceImplTest {
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void commentPredicate() {
|
|
||||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
|
||||||
queryParams.add("keyword", "hello");
|
|
||||||
queryParams.add("approved", "true");
|
|
||||||
queryParams.add("hidden", "false");
|
|
||||||
queryParams.add("allowNotification", "true");
|
|
||||||
queryParams.add("top", "false");
|
|
||||||
queryParams.add("ownerKind", "User");
|
|
||||||
queryParams.add("ownerName", "fake-user");
|
|
||||||
queryParams.add("subjectKind", "Post");
|
|
||||||
queryParams.add("subjectName", "fake-post");
|
|
||||||
|
|
||||||
MockServerRequest request = MockServerRequest.builder()
|
|
||||||
.queryParams(queryParams)
|
|
||||||
.exchange(mock(ServerWebExchange.class))
|
|
||||||
.build();
|
|
||||||
final Predicate<Comment> predicate = new CommentQuery(request).toPredicate();
|
|
||||||
|
|
||||||
Comment comment = comment("A");
|
|
||||||
comment.getSpec().setRaw("hello-world");
|
|
||||||
comment.getSpec().setApproved(true);
|
|
||||||
comment.getSpec().setHidden(false);
|
|
||||||
comment.getSpec().setAllowNotification(true);
|
|
||||||
comment.getSpec().setTop(false);
|
|
||||||
Comment.CommentOwner commentOwner = new Comment.CommentOwner();
|
|
||||||
commentOwner.setKind("User");
|
|
||||||
commentOwner.setName("fake-user");
|
|
||||||
commentOwner.setDisplayName("fake-user-display-name");
|
|
||||||
comment.getSpec().setOwner(commentOwner);
|
|
||||||
comment.getSpec().setSubjectRef(Ref.of(post()));
|
|
||||||
assertThat(predicate.test(comment)).isTrue();
|
|
||||||
|
|
||||||
queryParams.remove("keyword");
|
|
||||||
queryParams.add("keyword", "nothing");
|
|
||||||
request = MockServerRequest.builder()
|
|
||||||
.queryParams(queryParams)
|
|
||||||
.exchange(mock(ServerWebExchange.class))
|
|
||||||
.build();
|
|
||||||
final Predicate<Comment> predicateTwo = new CommentQuery(request).toPredicate();
|
|
||||||
assertThat(predicateTwo.test(comment)).isFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Comment> comments() {
|
private List<Comment> comments() {
|
||||||
Comment a = comment("A");
|
Comment a = comment("A");
|
||||||
a.getSpec().getOwner().setKind(Comment.CommentOwner.KIND_EMAIL);
|
a.getSpec().getOwner().setKind(Comment.CommentOwner.KIND_EMAIL);
|
||||||
|
|
|
@ -31,6 +31,7 @@ import run.halo.app.content.comment.ReplyService;
|
||||||
import run.halo.app.core.extension.content.Comment;
|
import run.halo.app.core.extension.content.Comment;
|
||||||
import run.halo.app.core.extension.content.Reply;
|
import run.halo.app.core.extension.content.Reply;
|
||||||
import run.halo.app.extension.ListResult;
|
import run.halo.app.extension.ListResult;
|
||||||
|
import run.halo.app.extension.PageRequest;
|
||||||
import run.halo.app.extension.Ref;
|
import run.halo.app.extension.Ref;
|
||||||
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
|
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
|
||||||
import run.halo.app.theme.finders.CommentFinder;
|
import run.halo.app.theme.finders.CommentFinder;
|
||||||
|
@ -77,7 +78,7 @@ class CommentFinderEndpointTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void listComments() {
|
void listComments() {
|
||||||
when(commentPublicQueryService.list(any(), anyInt(), anyInt(), any()))
|
when(commentPublicQueryService.list(any(), any(PageRequest.class)))
|
||||||
.thenReturn(Mono.just(new ListResult<>(1, 10, 0, List.of())));
|
.thenReturn(Mono.just(new ListResult<>(1, 10, 0, List.of())));
|
||||||
|
|
||||||
Ref ref = new Ref();
|
Ref ref = new Ref();
|
||||||
|
@ -86,21 +87,20 @@ class CommentFinderEndpointTest {
|
||||||
ref.setKind("Post");
|
ref.setKind("Post");
|
||||||
ref.setName("test");
|
ref.setName("test");
|
||||||
webTestClient.get()
|
webTestClient.get()
|
||||||
.uri(uriBuilder -> {
|
.uri(uriBuilder -> uriBuilder.path("/comments")
|
||||||
return uriBuilder.path("/comments")
|
.queryParam("group", ref.getGroup())
|
||||||
.queryParam("group", ref.getGroup())
|
.queryParam("version", ref.getVersion())
|
||||||
.queryParam("version", ref.getVersion())
|
.queryParam("kind", ref.getKind())
|
||||||
.queryParam("kind", ref.getKind())
|
.queryParam("name", ref.getName())
|
||||||
.queryParam("name", ref.getName())
|
.queryParam("page", 1)
|
||||||
.queryParam("page", 1)
|
.queryParam("size", 10)
|
||||||
.queryParam("size", 10)
|
.build())
|
||||||
.build();
|
|
||||||
})
|
|
||||||
.exchange()
|
.exchange()
|
||||||
.expectStatus()
|
.expectStatus()
|
||||||
.isOk();
|
.isOk();
|
||||||
ArgumentCaptor<Ref> refCaptor = ArgumentCaptor.forClass(Ref.class);
|
ArgumentCaptor<Ref> refCaptor = ArgumentCaptor.forClass(Ref.class);
|
||||||
verify(commentPublicQueryService, times(1)).list(refCaptor.capture(), eq(1), eq(10), any());
|
verify(commentPublicQueryService, times(1))
|
||||||
|
.list(refCaptor.capture(), any(PageRequest.class));
|
||||||
Ref value = refCaptor.getValue();
|
Ref value = refCaptor.getValue();
|
||||||
assertThat(value).isEqualTo(ref);
|
assertThat(value).isEqualTo(ref);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import java.time.Instant;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
@ -33,7 +32,6 @@ import run.halo.app.core.extension.service.UserService;
|
||||||
import run.halo.app.extension.GroupVersionKind;
|
import run.halo.app.extension.GroupVersionKind;
|
||||||
import run.halo.app.extension.ListResult;
|
import run.halo.app.extension.ListResult;
|
||||||
import run.halo.app.extension.Metadata;
|
import run.halo.app.extension.Metadata;
|
||||||
import run.halo.app.extension.MetadataOperator;
|
|
||||||
import run.halo.app.extension.ReactiveExtensionClient;
|
import run.halo.app.extension.ReactiveExtensionClient;
|
||||||
import run.halo.app.extension.Ref;
|
import run.halo.app.extension.Ref;
|
||||||
import run.halo.app.infra.AnonymousUserConst;
|
import run.halo.app.infra.AnonymousUserConst;
|
||||||
|
@ -70,103 +68,6 @@ class CommentPublicQueryServiceImplTest {
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
class ListCommentTest {
|
class ListCommentTest {
|
||||||
@Test
|
|
||||||
void listWhenUserNotLogin() {
|
|
||||||
// Mock
|
|
||||||
mockWhenListComment();
|
|
||||||
|
|
||||||
Ref ref = Ref.of("fake-post", GroupVersionKind.fromExtension(Post.class));
|
|
||||||
commentPublicQueryService.list(ref, 1, 10)
|
|
||||||
.as(StepVerifier::create)
|
|
||||||
.consumeNextWith(listResult -> {
|
|
||||||
assertThat(listResult.getTotal()).isEqualTo(2);
|
|
||||||
assertThat(listResult.getItems().size()).isEqualTo(2);
|
|
||||||
assertThat(listResult.getItems().get(0).getMetadata().getName())
|
|
||||||
.isEqualTo("comment-approved");
|
|
||||||
})
|
|
||||||
.verifyComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@WithMockUser(username = AnonymousUserConst.PRINCIPAL)
|
|
||||||
void listWhenUserIsAnonymous() {
|
|
||||||
// Mock
|
|
||||||
mockWhenListComment();
|
|
||||||
|
|
||||||
Ref ref = Ref.of("fake-post", GroupVersionKind.fromExtension(Post.class));
|
|
||||||
commentPublicQueryService.list(ref, 1, 10)
|
|
||||||
.as(StepVerifier::create)
|
|
||||||
.consumeNextWith(listResult -> {
|
|
||||||
assertThat(listResult.getTotal()).isEqualTo(2);
|
|
||||||
assertThat(listResult.getItems().size()).isEqualTo(2);
|
|
||||||
assertThat(listResult.getItems().get(0).getMetadata().getName())
|
|
||||||
.isEqualTo("comment-approved");
|
|
||||||
assertThat(listResult.getItems().get(0).getStats().getUpvote()).isEqualTo(9);
|
|
||||||
})
|
|
||||||
.verifyComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@WithMockUser(username = "fake-user")
|
|
||||||
void listWhenUserLoggedIn() {
|
|
||||||
mockWhenListComment();
|
|
||||||
|
|
||||||
Ref ref = Ref.of("fake-post", GroupVersionKind.fromExtension(Post.class));
|
|
||||||
commentPublicQueryService.list(ref, 1, 10)
|
|
||||||
.as(StepVerifier::create)
|
|
||||||
.consumeNextWith(listResult -> {
|
|
||||||
assertThat(listResult.getTotal()).isEqualTo(3);
|
|
||||||
assertThat(listResult.getItems().size()).isEqualTo(3);
|
|
||||||
assertThat(listResult.getItems().get(0).getMetadata().getName())
|
|
||||||
.isEqualTo("comment-not-approved");
|
|
||||||
assertThat(listResult.getItems().get(1).getMetadata().getName())
|
|
||||||
.isEqualTo("comment-approved");
|
|
||||||
})
|
|
||||||
.verifyComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void commentComparator() {
|
|
||||||
// 1, now + 1s, top, 0
|
|
||||||
// 2, now + 2s, top, 1
|
|
||||||
// 3, now + 3s, top, 2
|
|
||||||
// 4, now + 4s, top, 2
|
|
||||||
// 5, now + 4s, top, 3
|
|
||||||
// 6, now + 1s, no, 0
|
|
||||||
// 7, now + 2s, no, 0
|
|
||||||
// 8, now + 3s, no, 0
|
|
||||||
// 9, now + 3s, no, 0
|
|
||||||
// 10, null, no, 0
|
|
||||||
// 11, null, no, 1
|
|
||||||
// 12, null, no, 3
|
|
||||||
// 13, now + 3s, no, 3
|
|
||||||
Instant now = Instant.now();
|
|
||||||
var comment1 = commentForCompare("1", now.plusSeconds(1), true, 0);
|
|
||||||
var comment2 = commentForCompare("2", now.plusSeconds(2), true, 1);
|
|
||||||
var comment3 = commentForCompare("3", now.plusSeconds(3), true, 2);
|
|
||||||
var comment4 = commentForCompare("4", now.plusSeconds(4), true, 2);
|
|
||||||
var comment5 = commentForCompare("5", now.plusSeconds(4), true, 3);
|
|
||||||
var comment6 = commentForCompare("6", now.plusSeconds(4), true, 3);
|
|
||||||
var comment7 = commentForCompare("7", now.plusSeconds(1), false, 0);
|
|
||||||
var comment8 = commentForCompare("8", now.plusSeconds(2), false, 0);
|
|
||||||
var comment9 = commentForCompare("9", now.plusSeconds(3), false, 0);
|
|
||||||
var comment10 = commentForCompare("10", now.plusSeconds(3), false, 0);
|
|
||||||
var comment11 = commentForCompare("11", null, false, 0);
|
|
||||||
var comment12 = commentForCompare("12", null, false, 1);
|
|
||||||
var comment13 = commentForCompare("13", null, false, 3);
|
|
||||||
var comment14 = commentForCompare("14", now.plusSeconds(3), false, 3);
|
|
||||||
|
|
||||||
var result = Stream.of(comment1, comment2, comment3, comment4, comment5, comment6,
|
|
||||||
comment7, comment8, comment9, comment10, comment11, comment12, comment13,
|
|
||||||
comment14)
|
|
||||||
.sorted(CommentPublicQueryServiceImpl.defaultComparator())
|
|
||||||
.map(Comment::getMetadata)
|
|
||||||
.map(MetadataOperator::getName)
|
|
||||||
.collect(Collectors.joining(", "));
|
|
||||||
assertThat(result).isEqualTo("1, 2, 4, 3, 5, 6, 10, 14, 9, 8, 7, 11, 12, 13");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void desensitizeComment() throws JSONException {
|
void desensitizeComment() throws JSONException {
|
||||||
var commentOwner = new Comment.CommentOwner();
|
var commentOwner = new Comment.CommentOwner();
|
||||||
|
|
|
@ -0,0 +1,318 @@
|
||||||
|
package run.halo.app.theme.finders.impl;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.security.test.context.support.WithMockUser;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
import reactor.test.StepVerifier;
|
||||||
|
import run.halo.app.core.extension.User;
|
||||||
|
import run.halo.app.core.extension.content.Comment;
|
||||||
|
import run.halo.app.core.extension.content.Post;
|
||||||
|
import run.halo.app.extension.Extension;
|
||||||
|
import run.halo.app.extension.ExtensionStoreUtil;
|
||||||
|
import run.halo.app.extension.GroupVersionKind;
|
||||||
|
import run.halo.app.extension.ListOptions;
|
||||||
|
import run.halo.app.extension.ReactiveExtensionClient;
|
||||||
|
import run.halo.app.extension.Ref;
|
||||||
|
import run.halo.app.extension.SchemeManager;
|
||||||
|
import run.halo.app.extension.index.IndexerFactory;
|
||||||
|
import run.halo.app.extension.store.ReactiveExtensionStoreClient;
|
||||||
|
import run.halo.app.infra.AnonymousUserConst;
|
||||||
|
import run.halo.app.infra.utils.JsonUtils;
|
||||||
|
|
||||||
|
@DirtiesContext
|
||||||
|
@SpringBootTest
|
||||||
|
class CommentPublicQueryServiceIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SchemeManager schemeManager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ReactiveExtensionClient client;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ReactiveExtensionStoreClient storeClient;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IndexerFactory indexerFactory;
|
||||||
|
|
||||||
|
Mono<Extension> deleteImmediately(Extension extension) {
|
||||||
|
var name = extension.getMetadata().getName();
|
||||||
|
var scheme = schemeManager.get(extension.getClass());
|
||||||
|
// un-index
|
||||||
|
var indexer = indexerFactory.getIndexer(extension.groupVersionKind());
|
||||||
|
indexer.unIndexRecord(extension.getMetadata().getName());
|
||||||
|
|
||||||
|
// delete from db
|
||||||
|
var storeName = ExtensionStoreUtil.buildStoreName(scheme, name);
|
||||||
|
return storeClient.delete(storeName, extension.getMetadata().getVersion())
|
||||||
|
.thenReturn(extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class CommentListTest {
|
||||||
|
private final List<Comment> storedComments = commentsForStore();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CommentPublicQueryServiceImpl commentPublicQueryService;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
Flux.fromIterable(storedComments)
|
||||||
|
.flatMap(comment -> client.create(comment))
|
||||||
|
.as(StepVerifier::create)
|
||||||
|
.expectNextCount(storedComments.size())
|
||||||
|
.verifyComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void tearDown() {
|
||||||
|
Flux.fromIterable(storedComments)
|
||||||
|
.flatMap(CommentPublicQueryServiceIntegrationTest.this::deleteImmediately)
|
||||||
|
.as(StepVerifier::create)
|
||||||
|
.expectNextCount(storedComments.size())
|
||||||
|
.verifyComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listWhenUserNotLogin() {
|
||||||
|
Ref ref = Ref.of("fake-post", GroupVersionKind.fromExtension(Post.class));
|
||||||
|
commentPublicQueryService.list(ref, 1, 10)
|
||||||
|
.as(StepVerifier::create)
|
||||||
|
.consumeNextWith(listResult -> {
|
||||||
|
assertThat(listResult.getTotal()).isEqualTo(2);
|
||||||
|
assertThat(listResult.getItems().size()).isEqualTo(2);
|
||||||
|
assertThat(listResult.getItems().get(0).getMetadata().getName())
|
||||||
|
.isEqualTo("comment-approved");
|
||||||
|
})
|
||||||
|
.verifyComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username = AnonymousUserConst.PRINCIPAL)
|
||||||
|
void listWhenUserIsAnonymous() {
|
||||||
|
Ref ref = Ref.of("fake-post", GroupVersionKind.fromExtension(Post.class));
|
||||||
|
commentPublicQueryService.list(ref, 1, 10)
|
||||||
|
.as(StepVerifier::create)
|
||||||
|
.consumeNextWith(listResult -> {
|
||||||
|
assertThat(listResult.getTotal()).isEqualTo(2);
|
||||||
|
assertThat(listResult.getItems().size()).isEqualTo(2);
|
||||||
|
assertThat(listResult.getItems().get(0).getMetadata().getName())
|
||||||
|
.isEqualTo("comment-approved");
|
||||||
|
})
|
||||||
|
.verifyComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username = "fake-user")
|
||||||
|
void listWhenUserLoggedIn() {
|
||||||
|
Ref ref = Ref.of("fake-post", GroupVersionKind.fromExtension(Post.class));
|
||||||
|
commentPublicQueryService.list(ref, 1, 10)
|
||||||
|
.as(StepVerifier::create)
|
||||||
|
.consumeNextWith(listResult -> {
|
||||||
|
assertThat(listResult.getTotal()).isEqualTo(3);
|
||||||
|
assertThat(listResult.getItems().size()).isEqualTo(3);
|
||||||
|
assertThat(listResult.getItems().get(0).getMetadata().getName())
|
||||||
|
.isEqualTo("comment-approved");
|
||||||
|
assertThat(listResult.getItems().get(1).getMetadata().getName())
|
||||||
|
.isEqualTo("comment-approved-but-another-owner");
|
||||||
|
assertThat(listResult.getItems().get(2).getMetadata().getName())
|
||||||
|
.isEqualTo("comment-not-approved");
|
||||||
|
})
|
||||||
|
.verifyComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Comment> commentsForStore() {
|
||||||
|
// Mock
|
||||||
|
Comment commentNotApproved = fakeComment();
|
||||||
|
commentNotApproved.getMetadata().setName("comment-not-approved");
|
||||||
|
commentNotApproved.getSpec().setApproved(false);
|
||||||
|
|
||||||
|
Comment commentApproved = fakeComment();
|
||||||
|
commentApproved.getMetadata().setName("comment-approved");
|
||||||
|
commentApproved.getSpec().setApproved(true);
|
||||||
|
|
||||||
|
Comment notApprovedWithAnonymous = fakeComment();
|
||||||
|
notApprovedWithAnonymous.getMetadata().setName("comment-not-approved-anonymous");
|
||||||
|
notApprovedWithAnonymous.getSpec().setApproved(false);
|
||||||
|
notApprovedWithAnonymous.getSpec().getOwner().setName(AnonymousUserConst.PRINCIPAL);
|
||||||
|
|
||||||
|
Comment commentApprovedButAnotherOwner = fakeComment();
|
||||||
|
commentApprovedButAnotherOwner.getMetadata()
|
||||||
|
.setName("comment-approved-but-another-owner");
|
||||||
|
commentApprovedButAnotherOwner.getSpec().setApproved(true);
|
||||||
|
commentApprovedButAnotherOwner.getSpec().getOwner().setName("another");
|
||||||
|
|
||||||
|
Comment commentNotApprovedAndAnotherOwner = fakeComment();
|
||||||
|
commentNotApprovedAndAnotherOwner.getMetadata()
|
||||||
|
.setName("comment-not-approved-and-another");
|
||||||
|
commentNotApprovedAndAnotherOwner.getSpec().setApproved(false);
|
||||||
|
commentNotApprovedAndAnotherOwner.getSpec().getOwner().setName("another");
|
||||||
|
|
||||||
|
Comment notApprovedAndAnotherRef = fakeComment();
|
||||||
|
notApprovedAndAnotherRef.getMetadata()
|
||||||
|
.setName("comment-not-approved-and-another-ref");
|
||||||
|
notApprovedAndAnotherRef.getSpec().setApproved(false);
|
||||||
|
Ref anotherRef =
|
||||||
|
Ref.of("another-fake-post", GroupVersionKind.fromExtension(Post.class));
|
||||||
|
notApprovedAndAnotherRef.getSpec().setSubjectRef(anotherRef);
|
||||||
|
|
||||||
|
return List.of(
|
||||||
|
commentNotApproved,
|
||||||
|
commentApproved,
|
||||||
|
commentApprovedButAnotherOwner,
|
||||||
|
commentNotApprovedAndAnotherOwner,
|
||||||
|
notApprovedWithAnonymous,
|
||||||
|
notApprovedAndAnotherRef
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Comment fakeComment() {
|
||||||
|
Comment comment = createComment();
|
||||||
|
comment.getMetadata().setDeletionTimestamp(null);
|
||||||
|
comment.getMetadata().setName("fake-comment");
|
||||||
|
|
||||||
|
comment.getSpec().setRaw("fake-raw");
|
||||||
|
comment.getSpec().setContent("fake-content");
|
||||||
|
comment.getSpec().setHidden(false);
|
||||||
|
comment.getSpec()
|
||||||
|
.setSubjectRef(Ref.of("fake-post", GroupVersionKind.fromExtension(Post.class)));
|
||||||
|
Comment.CommentOwner commentOwner = new Comment.CommentOwner();
|
||||||
|
commentOwner.setKind(User.KIND);
|
||||||
|
commentOwner.setName("fake-user");
|
||||||
|
commentOwner.setDisplayName("fake-display-name");
|
||||||
|
comment.getSpec().setOwner(commentOwner);
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class CommentDefaultSortTest {
|
||||||
|
private final List<Comment> commentList = createCommentList();
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
Flux.fromIterable(commentList)
|
||||||
|
.flatMap(comment -> client.create(comment))
|
||||||
|
.as(StepVerifier::create)
|
||||||
|
.expectNextCount(commentList.size())
|
||||||
|
.verifyComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void tearDown() {
|
||||||
|
Flux.fromIterable(commentList)
|
||||||
|
.flatMap(CommentPublicQueryServiceIntegrationTest.this::deleteImmediately)
|
||||||
|
.as(StepVerifier::create)
|
||||||
|
.expectNextCount(commentList.size())
|
||||||
|
.verifyComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void sortTest() {
|
||||||
|
var comments =
|
||||||
|
client.listAll(Comment.class, new ListOptions(),
|
||||||
|
CommentPublicQueryServiceImpl.defaultSort())
|
||||||
|
.collectList()
|
||||||
|
.block();
|
||||||
|
assertThat(comments).isNotNull();
|
||||||
|
|
||||||
|
var result = comments.stream()
|
||||||
|
.map(comment -> comment.getMetadata().getName())
|
||||||
|
.collect(Collectors.joining(", "));
|
||||||
|
assertThat(result).isEqualTo("1, 2, 4, 3, 5, 6, 9, 10, 14, 8, 7, 11, 12, 13");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Comment> createCommentList() {
|
||||||
|
// 1, now + 1s, top, 0
|
||||||
|
// 2, now + 2s, top, 1
|
||||||
|
// 3, now + 3s, top, 2
|
||||||
|
// 4, now + 4s, top, 2
|
||||||
|
// 5, now + 4s, top, 3
|
||||||
|
// 6, now + 1s, no, 0
|
||||||
|
// 7, now + 2s, no, 0
|
||||||
|
// 8, now + 3s, no, 0
|
||||||
|
// 9, now + 3s, no, 0
|
||||||
|
// 10, null, no, 0
|
||||||
|
// 11, null, no, 1
|
||||||
|
// 12, null, no, 3
|
||||||
|
// 13, now + 3s, no, 3
|
||||||
|
Instant now = Instant.now();
|
||||||
|
var comment1 = commentForCompare("1", now.plusSeconds(1), true, 0);
|
||||||
|
var comment2 = commentForCompare("2", now.plusSeconds(2), true, 1);
|
||||||
|
var comment3 = commentForCompare("3", now.plusSeconds(3), true, 2);
|
||||||
|
var comment4 = commentForCompare("4", now.plusSeconds(4), true, 2);
|
||||||
|
var comment5 = commentForCompare("5", now.plusSeconds(4), true, 3);
|
||||||
|
var comment6 = commentForCompare("6", now.plusSeconds(4), true, 3);
|
||||||
|
var comment7 = commentForCompare("7", now.plusSeconds(1), false, 0);
|
||||||
|
var comment8 = commentForCompare("8", now.plusSeconds(2), false, 0);
|
||||||
|
var comment9 = commentForCompare("9", now.plusSeconds(3), false, 0);
|
||||||
|
var comment10 = commentForCompare("10", now.plusSeconds(3), false, 0);
|
||||||
|
var comment11 = commentForCompare("11", now, false, 0);
|
||||||
|
var comment12 = commentForCompare("12", now, false, 1);
|
||||||
|
var comment13 = commentForCompare("13", now, false, 3);
|
||||||
|
var comment14 = commentForCompare("14", now.plusSeconds(3), false, 3);
|
||||||
|
|
||||||
|
return List.of(comment1, comment2, comment3, comment4, comment5, comment6, comment7,
|
||||||
|
comment8, comment9, comment10, comment11, comment12, comment13, comment14);
|
||||||
|
}
|
||||||
|
|
||||||
|
Comment commentForCompare(String name, Instant creationTime, boolean top, int priority) {
|
||||||
|
var comment = createComment();
|
||||||
|
comment.getMetadata().setName(name);
|
||||||
|
comment.getMetadata().setCreationTimestamp(creationTime);
|
||||||
|
comment.getSpec().setCreationTime(creationTime);
|
||||||
|
comment.getSpec().setTop(top);
|
||||||
|
comment.getSpec().setPriority(priority);
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Comment createComment() {
|
||||||
|
return JsonUtils.jsonToObject("""
|
||||||
|
{
|
||||||
|
"spec": {
|
||||||
|
"raw": "fake-raw",
|
||||||
|
"content": "fake-content",
|
||||||
|
"owner": {
|
||||||
|
"kind": "User",
|
||||||
|
"name": "fake-user"
|
||||||
|
},
|
||||||
|
"userAgent": "",
|
||||||
|
"ipAddress": "",
|
||||||
|
"approvedTime": "2024-02-28T09:15:16.095Z",
|
||||||
|
"creationTime": "2024-02-28T06:23:42.923294424Z",
|
||||||
|
"priority": 0,
|
||||||
|
"top": false,
|
||||||
|
"allowNotification": false,
|
||||||
|
"approved": true,
|
||||||
|
"hidden": false,
|
||||||
|
"subjectRef": {
|
||||||
|
"group": "content.halo.run",
|
||||||
|
"version": "v1alpha1",
|
||||||
|
"kind": "SinglePage",
|
||||||
|
"name": "67"
|
||||||
|
},
|
||||||
|
"lastReadTime": "2024-02-29T03:39:04.230Z"
|
||||||
|
},
|
||||||
|
"apiVersion": "content.halo.run/v1alpha1",
|
||||||
|
"kind": "Comment",
|
||||||
|
"metadata": {
|
||||||
|
"name": "fake-comment",
|
||||||
|
"creationTimestamp": "2024-02-28T06:23:42.923439037Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""", Comment.class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -89,10 +89,22 @@ const {
|
||||||
keyword,
|
keyword,
|
||||||
],
|
],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
|
const fieldSelectorMap: Record<string, string | boolean | undefined> = {
|
||||||
|
"spec.approved": selectedApprovedStatus.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
const fieldSelector = Object.entries(fieldSelectorMap)
|
||||||
|
.map(([key, value]) => {
|
||||||
|
if (value !== undefined) {
|
||||||
|
return `${key}=${value}`;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Boolean) as string[];
|
||||||
|
|
||||||
const { data } = await apiClient.comment.listComments({
|
const { data } = await apiClient.comment.listComments({
|
||||||
|
fieldSelector,
|
||||||
page: page.value,
|
page: page.value,
|
||||||
size: size.value,
|
size: size.value,
|
||||||
approved: selectedApprovedStatus.value,
|
|
||||||
sort: [selectedSort.value].filter(Boolean) as string[],
|
sort: [selectedSort.value].filter(Boolean) as string[],
|
||||||
keyword: keyword.value,
|
keyword: keyword.value,
|
||||||
ownerName: selectedUser.value,
|
ownerName: selectedUser.value,
|
||||||
|
@ -105,10 +117,10 @@ const {
|
||||||
return data.items;
|
return data.items;
|
||||||
},
|
},
|
||||||
refetchInterval(data) {
|
refetchInterval(data) {
|
||||||
const deletingComments = data?.filter(
|
const hasDeletingData = data?.some(
|
||||||
(comment) => !!comment.comment.metadata.deletionTimestamp
|
(comment) => !!comment.comment.metadata.deletionTimestamp
|
||||||
);
|
);
|
||||||
return deletingComments?.length ? 1000 : false;
|
return hasDeletingData ? 1000 : false;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -299,33 +311,33 @@ const handleApproveInBatch = async () => {
|
||||||
label: t(
|
label: t(
|
||||||
'core.comment.filters.sort.items.last_reply_time_desc'
|
'core.comment.filters.sort.items.last_reply_time_desc'
|
||||||
),
|
),
|
||||||
value: 'lastReplyTime,desc',
|
value: 'status.lastReplyTime,desc',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t(
|
label: t(
|
||||||
'core.comment.filters.sort.items.last_reply_time_asc'
|
'core.comment.filters.sort.items.last_reply_time_asc'
|
||||||
),
|
),
|
||||||
value: 'lastReplyTime,asc',
|
value: 'status.lastReplyTime,asc',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t(
|
label: t(
|
||||||
'core.comment.filters.sort.items.reply_count_desc'
|
'core.comment.filters.sort.items.reply_count_desc'
|
||||||
),
|
),
|
||||||
value: 'replyCount,desc',
|
value: 'status.replyCount,desc',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('core.comment.filters.sort.items.reply_count_asc'),
|
label: t('core.comment.filters.sort.items.reply_count_asc'),
|
||||||
value: 'replyCount,asc',
|
value: 'status.replyCount,asc',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t(
|
label: t(
|
||||||
'core.comment.filters.sort.items.create_time_desc'
|
'core.comment.filters.sort.items.create_time_desc'
|
||||||
),
|
),
|
||||||
value: 'creationTimestamp,desc',
|
value: 'metadata.creationTimestamp,desc',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('core.comment.filters.sort.items.create_time_asc'),
|
label: t('core.comment.filters.sort.items.create_time_asc'),
|
||||||
value: 'creationTimestamp,asc',
|
value: 'metadata.creationTimestamp,asc',
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -179,10 +179,7 @@ export const ApiConsoleHaloRunV1alpha1CommentApiAxiosParamCreator = function (
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* List comments.
|
* List comments.
|
||||||
* @param {boolean} [allowNotification] Send notifications when there are new replies.
|
|
||||||
* @param {boolean} [approved] Comments approved.
|
|
||||||
* @param {Array<string>} [fieldSelector] Field selector for filtering.
|
* @param {Array<string>} [fieldSelector] Field selector for filtering.
|
||||||
* @param {boolean} [hidden] The comment is hidden from the theme side.
|
|
||||||
* @param {string} [keyword] Comments filtered by keyword.
|
* @param {string} [keyword] Comments filtered by keyword.
|
||||||
* @param {Array<string>} [labelSelector] Label selector for filtering.
|
* @param {Array<string>} [labelSelector] Label selector for filtering.
|
||||||
* @param {string} [ownerKind] Commenter kind.
|
* @param {string} [ownerKind] Commenter kind.
|
||||||
|
@ -190,17 +187,11 @@ export const ApiConsoleHaloRunV1alpha1CommentApiAxiosParamCreator = function (
|
||||||
* @param {number} [page] The page number. Zero indicates no page.
|
* @param {number} [page] The page number. Zero indicates no page.
|
||||||
* @param {number} [size] Size of one page. Zero indicates no limit.
|
* @param {number} [size] Size of one page. Zero indicates no limit.
|
||||||
* @param {Array<string>} [sort] Sort property and direction of the list result. Supported fields: creationTimestamp,replyCount,lastReplyTime
|
* @param {Array<string>} [sort] Sort property and direction of the list result. Supported fields: creationTimestamp,replyCount,lastReplyTime
|
||||||
* @param {string} [subjectKind] Comment subject kind.
|
|
||||||
* @param {string} [subjectName] Comment subject name.
|
|
||||||
* @param {boolean} [top] Comment top display.
|
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
listComments: async (
|
listComments: async (
|
||||||
allowNotification?: boolean,
|
|
||||||
approved?: boolean,
|
|
||||||
fieldSelector?: Array<string>,
|
fieldSelector?: Array<string>,
|
||||||
hidden?: boolean,
|
|
||||||
keyword?: string,
|
keyword?: string,
|
||||||
labelSelector?: Array<string>,
|
labelSelector?: Array<string>,
|
||||||
ownerKind?: string,
|
ownerKind?: string,
|
||||||
|
@ -208,9 +199,6 @@ export const ApiConsoleHaloRunV1alpha1CommentApiAxiosParamCreator = function (
|
||||||
page?: number,
|
page?: number,
|
||||||
size?: number,
|
size?: number,
|
||||||
sort?: Array<string>,
|
sort?: Array<string>,
|
||||||
subjectKind?: string,
|
|
||||||
subjectName?: string,
|
|
||||||
top?: boolean,
|
|
||||||
options: AxiosRequestConfig = {}
|
options: AxiosRequestConfig = {}
|
||||||
): Promise<RequestArgs> => {
|
): Promise<RequestArgs> => {
|
||||||
const localVarPath = `/apis/api.console.halo.run/v1alpha1/comments`;
|
const localVarPath = `/apis/api.console.halo.run/v1alpha1/comments`;
|
||||||
|
@ -237,22 +225,10 @@ export const ApiConsoleHaloRunV1alpha1CommentApiAxiosParamCreator = function (
|
||||||
// http bearer authentication required
|
// http bearer authentication required
|
||||||
await setBearerAuthToObject(localVarHeaderParameter, configuration);
|
await setBearerAuthToObject(localVarHeaderParameter, configuration);
|
||||||
|
|
||||||
if (allowNotification !== undefined) {
|
|
||||||
localVarQueryParameter["allowNotification"] = allowNotification;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (approved !== undefined) {
|
|
||||||
localVarQueryParameter["approved"] = approved;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldSelector) {
|
if (fieldSelector) {
|
||||||
localVarQueryParameter["fieldSelector"] = fieldSelector;
|
localVarQueryParameter["fieldSelector"] = fieldSelector;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hidden !== undefined) {
|
|
||||||
localVarQueryParameter["hidden"] = hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyword !== undefined) {
|
if (keyword !== undefined) {
|
||||||
localVarQueryParameter["keyword"] = keyword;
|
localVarQueryParameter["keyword"] = keyword;
|
||||||
}
|
}
|
||||||
|
@ -281,18 +257,6 @@ export const ApiConsoleHaloRunV1alpha1CommentApiAxiosParamCreator = function (
|
||||||
localVarQueryParameter["sort"] = Array.from(sort);
|
localVarQueryParameter["sort"] = Array.from(sort);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subjectKind !== undefined) {
|
|
||||||
localVarQueryParameter["subjectKind"] = subjectKind;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subjectName !== undefined) {
|
|
||||||
localVarQueryParameter["subjectName"] = subjectName;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (top !== undefined) {
|
|
||||||
localVarQueryParameter["top"] = top;
|
|
||||||
}
|
|
||||||
|
|
||||||
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||||
let headersFromBaseOptions =
|
let headersFromBaseOptions =
|
||||||
baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||||
|
@ -371,10 +335,7 @@ export const ApiConsoleHaloRunV1alpha1CommentApiFp = function (
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* List comments.
|
* List comments.
|
||||||
* @param {boolean} [allowNotification] Send notifications when there are new replies.
|
|
||||||
* @param {boolean} [approved] Comments approved.
|
|
||||||
* @param {Array<string>} [fieldSelector] Field selector for filtering.
|
* @param {Array<string>} [fieldSelector] Field selector for filtering.
|
||||||
* @param {boolean} [hidden] The comment is hidden from the theme side.
|
|
||||||
* @param {string} [keyword] Comments filtered by keyword.
|
* @param {string} [keyword] Comments filtered by keyword.
|
||||||
* @param {Array<string>} [labelSelector] Label selector for filtering.
|
* @param {Array<string>} [labelSelector] Label selector for filtering.
|
||||||
* @param {string} [ownerKind] Commenter kind.
|
* @param {string} [ownerKind] Commenter kind.
|
||||||
|
@ -382,17 +343,11 @@ export const ApiConsoleHaloRunV1alpha1CommentApiFp = function (
|
||||||
* @param {number} [page] The page number. Zero indicates no page.
|
* @param {number} [page] The page number. Zero indicates no page.
|
||||||
* @param {number} [size] Size of one page. Zero indicates no limit.
|
* @param {number} [size] Size of one page. Zero indicates no limit.
|
||||||
* @param {Array<string>} [sort] Sort property and direction of the list result. Supported fields: creationTimestamp,replyCount,lastReplyTime
|
* @param {Array<string>} [sort] Sort property and direction of the list result. Supported fields: creationTimestamp,replyCount,lastReplyTime
|
||||||
* @param {string} [subjectKind] Comment subject kind.
|
|
||||||
* @param {string} [subjectName] Comment subject name.
|
|
||||||
* @param {boolean} [top] Comment top display.
|
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
async listComments(
|
async listComments(
|
||||||
allowNotification?: boolean,
|
|
||||||
approved?: boolean,
|
|
||||||
fieldSelector?: Array<string>,
|
fieldSelector?: Array<string>,
|
||||||
hidden?: boolean,
|
|
||||||
keyword?: string,
|
keyword?: string,
|
||||||
labelSelector?: Array<string>,
|
labelSelector?: Array<string>,
|
||||||
ownerKind?: string,
|
ownerKind?: string,
|
||||||
|
@ -400,9 +355,6 @@ export const ApiConsoleHaloRunV1alpha1CommentApiFp = function (
|
||||||
page?: number,
|
page?: number,
|
||||||
size?: number,
|
size?: number,
|
||||||
sort?: Array<string>,
|
sort?: Array<string>,
|
||||||
subjectKind?: string,
|
|
||||||
subjectName?: string,
|
|
||||||
top?: boolean,
|
|
||||||
options?: AxiosRequestConfig
|
options?: AxiosRequestConfig
|
||||||
): Promise<
|
): Promise<
|
||||||
(
|
(
|
||||||
|
@ -411,10 +363,7 @@ export const ApiConsoleHaloRunV1alpha1CommentApiFp = function (
|
||||||
) => AxiosPromise<ListedCommentList>
|
) => AxiosPromise<ListedCommentList>
|
||||||
> {
|
> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.listComments(
|
const localVarAxiosArgs = await localVarAxiosParamCreator.listComments(
|
||||||
allowNotification,
|
|
||||||
approved,
|
|
||||||
fieldSelector,
|
fieldSelector,
|
||||||
hidden,
|
|
||||||
keyword,
|
keyword,
|
||||||
labelSelector,
|
labelSelector,
|
||||||
ownerKind,
|
ownerKind,
|
||||||
|
@ -422,9 +371,6 @@ export const ApiConsoleHaloRunV1alpha1CommentApiFp = function (
|
||||||
page,
|
page,
|
||||||
size,
|
size,
|
||||||
sort,
|
sort,
|
||||||
subjectKind,
|
|
||||||
subjectName,
|
|
||||||
top,
|
|
||||||
options
|
options
|
||||||
);
|
);
|
||||||
return createRequestFunction(
|
return createRequestFunction(
|
||||||
|
@ -492,10 +438,7 @@ export const ApiConsoleHaloRunV1alpha1CommentApiFactory = function (
|
||||||
): AxiosPromise<ListedCommentList> {
|
): AxiosPromise<ListedCommentList> {
|
||||||
return localVarFp
|
return localVarFp
|
||||||
.listComments(
|
.listComments(
|
||||||
requestParameters.allowNotification,
|
|
||||||
requestParameters.approved,
|
|
||||||
requestParameters.fieldSelector,
|
requestParameters.fieldSelector,
|
||||||
requestParameters.hidden,
|
|
||||||
requestParameters.keyword,
|
requestParameters.keyword,
|
||||||
requestParameters.labelSelector,
|
requestParameters.labelSelector,
|
||||||
requestParameters.ownerKind,
|
requestParameters.ownerKind,
|
||||||
|
@ -503,9 +446,6 @@ export const ApiConsoleHaloRunV1alpha1CommentApiFactory = function (
|
||||||
requestParameters.page,
|
requestParameters.page,
|
||||||
requestParameters.size,
|
requestParameters.size,
|
||||||
requestParameters.sort,
|
requestParameters.sort,
|
||||||
requestParameters.subjectKind,
|
|
||||||
requestParameters.subjectName,
|
|
||||||
requestParameters.top,
|
|
||||||
options
|
options
|
||||||
)
|
)
|
||||||
.then((request) => request(axios, basePath));
|
.then((request) => request(axios, basePath));
|
||||||
|
@ -554,20 +494,6 @@ export interface ApiConsoleHaloRunV1alpha1CommentApiCreateReplyRequest {
|
||||||
* @interface ApiConsoleHaloRunV1alpha1CommentApiListCommentsRequest
|
* @interface ApiConsoleHaloRunV1alpha1CommentApiListCommentsRequest
|
||||||
*/
|
*/
|
||||||
export interface ApiConsoleHaloRunV1alpha1CommentApiListCommentsRequest {
|
export interface ApiConsoleHaloRunV1alpha1CommentApiListCommentsRequest {
|
||||||
/**
|
|
||||||
* Send notifications when there are new replies.
|
|
||||||
* @type {boolean}
|
|
||||||
* @memberof ApiConsoleHaloRunV1alpha1CommentApiListComments
|
|
||||||
*/
|
|
||||||
readonly allowNotification?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Comments approved.
|
|
||||||
* @type {boolean}
|
|
||||||
* @memberof ApiConsoleHaloRunV1alpha1CommentApiListComments
|
|
||||||
*/
|
|
||||||
readonly approved?: boolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Field selector for filtering.
|
* Field selector for filtering.
|
||||||
* @type {Array<string>}
|
* @type {Array<string>}
|
||||||
|
@ -575,13 +501,6 @@ export interface ApiConsoleHaloRunV1alpha1CommentApiListCommentsRequest {
|
||||||
*/
|
*/
|
||||||
readonly fieldSelector?: Array<string>;
|
readonly fieldSelector?: Array<string>;
|
||||||
|
|
||||||
/**
|
|
||||||
* The comment is hidden from the theme side.
|
|
||||||
* @type {boolean}
|
|
||||||
* @memberof ApiConsoleHaloRunV1alpha1CommentApiListComments
|
|
||||||
*/
|
|
||||||
readonly hidden?: boolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comments filtered by keyword.
|
* Comments filtered by keyword.
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -630,27 +549,6 @@ export interface ApiConsoleHaloRunV1alpha1CommentApiListCommentsRequest {
|
||||||
* @memberof ApiConsoleHaloRunV1alpha1CommentApiListComments
|
* @memberof ApiConsoleHaloRunV1alpha1CommentApiListComments
|
||||||
*/
|
*/
|
||||||
readonly sort?: Array<string>;
|
readonly sort?: Array<string>;
|
||||||
|
|
||||||
/**
|
|
||||||
* Comment subject kind.
|
|
||||||
* @type {string}
|
|
||||||
* @memberof ApiConsoleHaloRunV1alpha1CommentApiListComments
|
|
||||||
*/
|
|
||||||
readonly subjectKind?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Comment subject name.
|
|
||||||
* @type {string}
|
|
||||||
* @memberof ApiConsoleHaloRunV1alpha1CommentApiListComments
|
|
||||||
*/
|
|
||||||
readonly subjectName?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Comment top display.
|
|
||||||
* @type {boolean}
|
|
||||||
* @memberof ApiConsoleHaloRunV1alpha1CommentApiListComments
|
|
||||||
*/
|
|
||||||
readonly top?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -709,10 +607,7 @@ export class ApiConsoleHaloRunV1alpha1CommentApi extends BaseAPI {
|
||||||
) {
|
) {
|
||||||
return ApiConsoleHaloRunV1alpha1CommentApiFp(this.configuration)
|
return ApiConsoleHaloRunV1alpha1CommentApiFp(this.configuration)
|
||||||
.listComments(
|
.listComments(
|
||||||
requestParameters.allowNotification,
|
|
||||||
requestParameters.approved,
|
|
||||||
requestParameters.fieldSelector,
|
requestParameters.fieldSelector,
|
||||||
requestParameters.hidden,
|
|
||||||
requestParameters.keyword,
|
requestParameters.keyword,
|
||||||
requestParameters.labelSelector,
|
requestParameters.labelSelector,
|
||||||
requestParameters.ownerKind,
|
requestParameters.ownerKind,
|
||||||
|
@ -720,9 +615,6 @@ export class ApiConsoleHaloRunV1alpha1CommentApi extends BaseAPI {
|
||||||
requestParameters.page,
|
requestParameters.page,
|
||||||
requestParameters.size,
|
requestParameters.size,
|
||||||
requestParameters.sort,
|
requestParameters.sort,
|
||||||
requestParameters.subjectKind,
|
|
||||||
requestParameters.subjectName,
|
|
||||||
requestParameters.top,
|
|
||||||
options
|
options
|
||||||
)
|
)
|
||||||
.then((request) => request(this.axios, this.basePath));
|
.then((request) => request(this.axios, this.basePath));
|
||||||
|
|
Loading…
Reference in New Issue