Compare commits
3 Commits
b53d693446
...
fb880f776f
Author | SHA1 | Date |
---|---|---|
AirboZH | fb880f776f | |
guqing | 9b3f00dab0 | |
AirboZH | f16d73f8b4 |
|
@ -59,6 +59,8 @@ public class Category extends AbstractExtension {
|
|||
private Integer priority;
|
||||
|
||||
private List<String> children;
|
||||
|
||||
private boolean independent;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.springframework.stereotype.Component;
|
|||
import org.springframework.util.CollectionUtils;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import run.halo.app.extension.ExtensionUtil;
|
||||
import run.halo.app.extension.ReactiveExtensionClient;
|
||||
import run.halo.app.extension.Unstructured;
|
||||
import run.halo.app.infra.properties.HaloProperties;
|
||||
|
@ -96,7 +97,13 @@ public class ExtensionResourceInitializer implements ApplicationListener<Applica
|
|||
extension.getMetadata().setVersion(existingExt.getMetadata().getVersion());
|
||||
return extensionClient.update(extension);
|
||||
})
|
||||
.switchIfEmpty(Mono.defer(() -> extensionClient.create(extension)));
|
||||
.switchIfEmpty(Mono.defer(() -> {
|
||||
if (ExtensionUtil.isDeleted(extension)) {
|
||||
// skip deleted extension
|
||||
return Mono.empty();
|
||||
}
|
||||
return extensionClient.create(extension);
|
||||
}));
|
||||
}
|
||||
|
||||
private List<Resource> listResources(String location) {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package run.halo.app.theme.finders.impl;
|
||||
|
||||
import static run.halo.app.extension.index.query.QueryFactory.all;
|
||||
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.util.Comparator;
|
||||
import java.util.List;
|
||||
|
@ -15,12 +17,14 @@ import org.springframework.lang.NonNull;
|
|||
import org.springframework.util.Assert;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import run.halo.app.core.extension.content.Category;
|
||||
import run.halo.app.core.extension.content.Post;
|
||||
import run.halo.app.extension.ListOptions;
|
||||
import run.halo.app.extension.ListResult;
|
||||
import run.halo.app.extension.PageRequestImpl;
|
||||
import run.halo.app.extension.ReactiveExtensionClient;
|
||||
import run.halo.app.extension.exception.ExtensionNotFoundException;
|
||||
import run.halo.app.extension.index.query.Query;
|
||||
import run.halo.app.extension.index.query.QueryFactory;
|
||||
import run.halo.app.extension.router.selector.FieldSelector;
|
||||
import run.halo.app.extension.router.selector.LabelSelector;
|
||||
|
@ -141,13 +145,45 @@ public class PostFinderImpl implements PostFinder {
|
|||
@Override
|
||||
public Mono<ListResult<ListedPostVo>> listByCategory(Integer page, Integer size,
|
||||
String categoryName) {
|
||||
var fieldQuery = QueryFactory.all();
|
||||
if (StringUtils.isNotBlank(categoryName)) {
|
||||
fieldQuery = and(fieldQuery, equal("spec.categories", categoryName));
|
||||
}
|
||||
var listOptions = new ListOptions();
|
||||
listOptions.setFieldSelector(FieldSelector.of(fieldQuery));
|
||||
return postPublicQueryService.list(listOptions, getPageRequest(page, size));
|
||||
var pageRequest = getPageRequest(page, size);
|
||||
|
||||
if (StringUtils.isNotBlank(categoryName)) {
|
||||
return childrenCategoryQuery(categoryName).flatMap(fieldQuery -> {
|
||||
listOptions.setFieldSelector(FieldSelector.of(fieldQuery));
|
||||
return postPublicQueryService.list(listOptions, pageRequest);
|
||||
});
|
||||
} else {
|
||||
return postPublicQueryService.list(listOptions, pageRequest);
|
||||
}
|
||||
}
|
||||
|
||||
private Mono<Query> childrenCategoryQuery(String categoryName) {
|
||||
if (categoryName == null) {
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
return traverseCategories(categoryName)
|
||||
.map(childrenCategory -> equal("spec.categories", childrenCategory))
|
||||
.collect(Collectors.toList())
|
||||
.flatMap(this::mergeQuery);
|
||||
}
|
||||
|
||||
Mono<Query> mergeQuery(List<Query> childrenQueryList) {
|
||||
if (childrenQueryList.size() < 2) {
|
||||
return Mono.just(and(all(), childrenQueryList.get(0)));
|
||||
}
|
||||
return Mono.just(
|
||||
or(childrenQueryList.get(0), childrenQueryList.get(1), childrenQueryList)
|
||||
);
|
||||
}
|
||||
|
||||
private Flux<String> traverseCategories(String categoryName) {
|
||||
return client.fetch(Category.class, categoryName).expand(
|
||||
rootCategory -> Flux.fromIterable(rootCategory.getSpec().getChildren())
|
||||
.flatMap(childCategory -> client.fetch(Category.class, childCategory)
|
||||
.filter(category -> !category.getSpec().isIndependent()))
|
||||
).map(category -> category.getMetadata().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -55,6 +55,7 @@ const initialFormState: Category = {
|
|||
template: "",
|
||||
priority: 0,
|
||||
children: [],
|
||||
isIndependent: false,
|
||||
},
|
||||
status: {},
|
||||
apiVersion: "content.halo.run/v1alpha1",
|
||||
|
@ -279,6 +280,17 @@ const { handleGenerateSlug } = useSlugify(
|
|||
type="select"
|
||||
name="template"
|
||||
></FormKit>
|
||||
<FormKit
|
||||
v-model="formState.spec.independent"
|
||||
:label="
|
||||
$t('core.post_category.editing_modal.fields.independent.label')
|
||||
"
|
||||
:help="
|
||||
$t('core.post_category.editing_modal.fields.independent.help')
|
||||
"
|
||||
type="checkbox"
|
||||
name="includeChildren"
|
||||
></FormKit>
|
||||
<FormKit
|
||||
v-model="formState.spec.cover"
|
||||
:help="$t('core.post_category.editing_modal.fields.cover.help')"
|
||||
|
|
|
@ -28,6 +28,12 @@ export interface CategorySpec {
|
|||
'children'?: Array<string>;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof CategorySpec
|
||||
*/
|
||||
'independent'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof CategorySpec
|
||||
*/
|
||||
|
|
|
@ -359,6 +359,9 @@ core:
|
|||
refresh_message: Regenerate slug based on display name.
|
||||
template:
|
||||
label: Custom template
|
||||
independent:
|
||||
label: Independent Category
|
||||
help: Articles and the number of articles will not be counted towards the parent category.
|
||||
cover:
|
||||
label: Cover
|
||||
help: Theme adaptation is required to support
|
||||
|
|
|
@ -303,6 +303,9 @@ core:
|
|||
refresh_message: Regenerar slug basado en el nombre para mostrar.
|
||||
template:
|
||||
label: Plantilla personalizada
|
||||
independent:
|
||||
label: Categoría independiente
|
||||
help: El número de artículos y artículos no se incluirá en la categoría padre.
|
||||
cover:
|
||||
label: Portada
|
||||
help: Se requiere adaptación del tema para ser compatible
|
||||
|
|
|
@ -359,6 +359,9 @@ core:
|
|||
refresh_message: 根据名称重新生成别名
|
||||
template:
|
||||
label: 自定义模板
|
||||
independent:
|
||||
label: 独立分类
|
||||
help: 文章和文章数将不计入父级分类
|
||||
cover:
|
||||
label: 封面图
|
||||
help: 需要主题适配以支持
|
||||
|
|
|
@ -339,6 +339,9 @@ core:
|
|||
refresh_message: 根據名稱重新生成別名
|
||||
template:
|
||||
label: 自定義模板
|
||||
independent:
|
||||
label: 獨立分類
|
||||
help: 文章和文章數將不計入父級分類
|
||||
cover:
|
||||
label: 封面圖
|
||||
help: 需要主題適配以支持
|
||||
|
|
Loading…
Reference in New Issue