mirror of https://github.com/halo-dev/halo
feat: add more query params and sorter for single page (#2481)
#### What type of PR is this? /kind feature /milestone 2.0 /area core /kind api-change #### What this PR does / why we need it: 自定义页面增加排序和筛选: 筛选: 关键词 状态 可见性 作者 排序: 发布时间 创建时间 #### Which issue(s) this PR fixes: Fixes #2469 #### Special notes for your reviewer: /cc @halo-dev/sig-halo #### Does this PR introduce a user-facing change? ```release-note None ```pull/2493/head
parent
27e151a574
commit
98829f0a3e
|
@ -1,9 +1,12 @@
|
|||
package run.halo.app.content;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import run.halo.app.core.extension.Post;
|
||||
import run.halo.app.core.extension.SinglePage;
|
||||
import run.halo.app.extension.router.IListRequest;
|
||||
|
||||
|
@ -20,8 +23,43 @@ public class SinglePageQuery extends IListRequest.QueryListRequest {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
@Schema(name = "contributor")
|
||||
public Set<String> getContributors() {
|
||||
List<String> contributorList = queryParams.get("contributor");
|
||||
return contributorList == null ? null : Set.copyOf(contributorList);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Post.PostPhase getPublishPhase() {
|
||||
String publishPhase = queryParams.getFirst("publishPhase");
|
||||
return Post.PostPhase.from(publishPhase);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Post.VisibleEnum getVisible() {
|
||||
String visible = queryParams.getFirst("visible");
|
||||
return Post.VisibleEnum.from(visible);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Schema(description = "SinglePages filtered by keyword.")
|
||||
public String getKeyword() {
|
||||
return StringUtils.defaultIfBlank(queryParams.getFirst("keyword"), null);
|
||||
}
|
||||
|
||||
@Schema(description = "SinglePage collation.")
|
||||
public SinglePageSorter getSort() {
|
||||
String sort = queryParams.getFirst("sort");
|
||||
return SinglePageSorter.convertFrom(sort);
|
||||
}
|
||||
|
||||
@Schema(description = "ascending order If it is true; otherwise, it is in descending order.")
|
||||
public Boolean getSortOrder() {
|
||||
String sortOrder = queryParams.getFirst("sortOrder");
|
||||
return convertBooleanOrNull(sortOrder);
|
||||
}
|
||||
|
||||
private Boolean convertBooleanOrNull(String value) {
|
||||
return StringUtils.isBlank(value) ? null : Boolean.parseBoolean(value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
package run.halo.app.content;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Comparator;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import org.springframework.util.comparator.Comparators;
|
||||
import run.halo.app.core.extension.SinglePage;
|
||||
|
||||
/**
|
||||
* A sorter for {@link SinglePage}.
|
||||
*
|
||||
* @author guqing
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public enum SinglePageSorter {
|
||||
PUBLISH_TIME,
|
||||
CREATE_TIME;
|
||||
|
||||
static final Function<SinglePage, String> name = page -> page.getMetadata().getName();
|
||||
|
||||
/**
|
||||
* Converts {@link Comparator} from {@link SinglePageSorter} and ascending.
|
||||
*
|
||||
* @param sorter a {@link SinglePageSorter}
|
||||
* @param ascending ascending if true, otherwise descending
|
||||
* @return a {@link Comparator} of {@link SinglePage}
|
||||
*/
|
||||
public static Comparator<SinglePage> from(SinglePageSorter sorter, Boolean ascending) {
|
||||
if (Objects.equals(true, ascending)) {
|
||||
return from(sorter);
|
||||
}
|
||||
return from(sorter).reversed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts {@link Comparator} from {@link SinglePageSorter}.
|
||||
*
|
||||
* @param sorter a {@link SinglePageSorter}
|
||||
* @return a {@link Comparator} of {@link SinglePage}
|
||||
*/
|
||||
public static Comparator<SinglePage> from(SinglePageSorter sorter) {
|
||||
if (sorter == null) {
|
||||
return defaultComparator();
|
||||
}
|
||||
if (CREATE_TIME.equals(sorter)) {
|
||||
Function<SinglePage, Instant> comparatorFunc =
|
||||
page -> page.getMetadata().getCreationTimestamp();
|
||||
return Comparator.comparing(comparatorFunc)
|
||||
.thenComparing(name);
|
||||
}
|
||||
|
||||
if (PUBLISH_TIME.equals(sorter)) {
|
||||
Function<SinglePage, Instant> comparatorFunc =
|
||||
page -> page.getSpec().getPublishTime();
|
||||
return Comparator.comparing(comparatorFunc, Comparators.nullsLow())
|
||||
.thenComparing(name);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unsupported sort value: " + sorter);
|
||||
}
|
||||
|
||||
static SinglePageSorter convertFrom(String sort) {
|
||||
for (SinglePageSorter sorter : values()) {
|
||||
if (sorter.name().equalsIgnoreCase(sort)) {
|
||||
return sorter;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static Comparator<SinglePage> defaultComparator() {
|
||||
Function<SinglePage, Instant> createTime =
|
||||
page -> page.getMetadata().getCreationTimestamp();
|
||||
return Comparator.comparing(createTime)
|
||||
.thenComparing(name);
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import java.util.List;
|
|||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -22,6 +23,7 @@ import run.halo.app.content.ListedSinglePage;
|
|||
import run.halo.app.content.SinglePageQuery;
|
||||
import run.halo.app.content.SinglePageRequest;
|
||||
import run.halo.app.content.SinglePageService;
|
||||
import run.halo.app.content.SinglePageSorter;
|
||||
import run.halo.app.core.extension.Post;
|
||||
import run.halo.app.core.extension.SinglePage;
|
||||
import run.halo.app.core.extension.Snapshot;
|
||||
|
@ -39,9 +41,6 @@ import run.halo.app.infra.ConditionStatus;
|
|||
*/
|
||||
@Service
|
||||
public class SinglePageServiceImpl implements SinglePageService {
|
||||
private static final Comparator<SinglePage> DEFAULT_PAGE_COMPARATOR =
|
||||
Comparator.comparing(page -> page.getMetadata().getCreationTimestamp());
|
||||
|
||||
private final ContentService contentService;
|
||||
|
||||
private final ReactiveExtensionClient client;
|
||||
|
@ -53,8 +52,10 @@ public class SinglePageServiceImpl implements SinglePageService {
|
|||
|
||||
@Override
|
||||
public Mono<ListResult<ListedSinglePage>> list(SinglePageQuery query) {
|
||||
Comparator<SinglePage> comparator =
|
||||
SinglePageSorter.from(query.getSort(), query.getSortOrder());
|
||||
return client.list(SinglePage.class, pageListPredicate(query),
|
||||
DEFAULT_PAGE_COMPARATOR.reversed(), query.getPage(), query.getSize())
|
||||
comparator, query.getPage(), query.getSize())
|
||||
.flatMap(listResult -> Flux.fromStream(
|
||||
listResult.get().map(this::getListedSinglePage)
|
||||
)
|
||||
|
@ -133,6 +134,40 @@ public class SinglePageServiceImpl implements SinglePageService {
|
|||
Predicate<SinglePage> pageListPredicate(SinglePageQuery query) {
|
||||
Predicate<SinglePage> paramPredicate = singlePage -> contains(query.getContributors(),
|
||||
singlePage.getStatusOrDefault().getContributors());
|
||||
|
||||
String keyword = query.getKeyword();
|
||||
if (keyword != null) {
|
||||
paramPredicate = paramPredicate.and(page -> {
|
||||
String excerpt = page.getStatusOrDefault().getExcerpt();
|
||||
return StringUtils.containsIgnoreCase(excerpt, keyword)
|
||||
|| StringUtils.containsIgnoreCase(page.getSpec().getSlug(), keyword)
|
||||
|| StringUtils.containsIgnoreCase(page.getSpec().getTitle(), keyword);
|
||||
});
|
||||
}
|
||||
|
||||
Post.PostPhase publishPhase = query.getPublishPhase();
|
||||
if (publishPhase != null) {
|
||||
paramPredicate = paramPredicate.and(page -> {
|
||||
if (Post.PostPhase.PENDING_APPROVAL.equals(publishPhase)) {
|
||||
return !page.isPublished()
|
||||
&& Post.PostPhase.PENDING_APPROVAL.name()
|
||||
.equalsIgnoreCase(page.getStatusOrDefault().getPhase());
|
||||
}
|
||||
// published
|
||||
if (Post.PostPhase.PUBLISHED.equals(publishPhase)) {
|
||||
return page.isPublished();
|
||||
}
|
||||
// draft
|
||||
return !page.isPublished();
|
||||
});
|
||||
}
|
||||
|
||||
Post.VisibleEnum visible = query.getVisible();
|
||||
if (visible != null) {
|
||||
paramPredicate =
|
||||
paramPredicate.and(post -> visible.equals(post.getSpec().getVisible()));
|
||||
}
|
||||
|
||||
Predicate<SinglePage> predicate = labelAndFieldSelectorToPredicate(query.getLabelSelector(),
|
||||
query.getFieldSelector());
|
||||
return predicate.and(paramPredicate);
|
||||
|
|
|
@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
@ -43,6 +44,11 @@ public class SinglePage extends AbstractExtension {
|
|||
return this.status;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isPublished() {
|
||||
return Objects.equals(true, spec.getPublished());
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class SinglePageSpec {
|
||||
@Schema(required = true, minLength = 1)
|
||||
|
|
Loading…
Reference in New Issue