mirror of https://github.com/halo-dev/halo
feat: add preventParentPostCascadeQuery option to control visibility of child category posts (#6083)
#### What type of PR is this? /kind feature /area core /milestone 2.17.x #### What this PR does / why we need it: 此次变更为文章分类引入了一个新的 `preventParentPostCascadeQuery` 布尔属性,用于控制分类及其子分类下的文章显示方式。具体变更包括: - 在分类结构中增加了 `preventParentPostCascadeQuery` 属性。 - 当分类的 `preventParentPostCascadeQuery` 属性设置为 `true` 时,该分类的文章数量不会汇总到父分类中。 - 更新了树结构遍历逻辑,以支持对 `preventParentPostCascadeQuery` 属性的处理。 - 确保独立分类中的文章显示受控,不向上级分类进行聚合。 - 增加了相应的测试用例,以验证在不同树结构中 `preventParentPostCascadeQuery` 属性的功能性。 #### Which issue(s) this PR fixes: Fixes #5663 Fixes #4923 Fixes https://github.com/halo-dev/halo/issues/3418 #### Does this PR introduce a user-facing change? ```release-note 新增独立分类选项用于控制关联的子分类下的文章显示以提供更灵活的内容管理方式 ```pull/6113/head^2
parent
db9e0f4ac7
commit
8bdde317e5
|
@ -3205,6 +3205,14 @@
|
|||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Posts filtered by category including sub-categories.",
|
||||
"in": "query",
|
||||
"name": "categoryWithChildren",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
|
@ -13989,6 +13997,14 @@
|
|||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Posts filtered by category including sub-categories.",
|
||||
"in": "query",
|
||||
"name": "categoryWithChildren",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
|
@ -14971,6 +14987,9 @@
|
|||
"maxLength": 255,
|
||||
"type": "string"
|
||||
},
|
||||
"preventParentPostCascadeQuery": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"priority": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
|
@ -19001,12 +19020,12 @@
|
|||
},
|
||||
"visible": {
|
||||
"type": "string",
|
||||
"default": "PUBLIC",
|
||||
"enum": [
|
||||
"PUBLIC",
|
||||
"INTERNAL",
|
||||
"PRIVATE"
|
||||
]
|
||||
],
|
||||
"default": "PUBLIC"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -20702,12 +20721,12 @@
|
|||
},
|
||||
"visible": {
|
||||
"type": "string",
|
||||
"default": "PUBLIC",
|
||||
"enum": [
|
||||
"PUBLIC",
|
||||
"INTERNAL",
|
||||
"PRIVATE"
|
||||
]
|
||||
],
|
||||
"default": "PUBLIC"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -69,6 +69,16 @@ public class Category extends AbstractExtension {
|
|||
private Integer priority;
|
||||
|
||||
private List<String> children;
|
||||
|
||||
/**
|
||||
* <p>if a category is queried for related posts, the default behavior is to
|
||||
* query all posts under the category including its subcategories, but if this field is
|
||||
* set to true, cascade query behavior will be terminated here.</p>
|
||||
* <p>For example, if a category has subcategories A and B, and A has subcategories C and
|
||||
* D and C marked this field as true, when querying posts under A category,all posts under A
|
||||
* and B will be queried, but C and D will not be queried.</p>
|
||||
*/
|
||||
private boolean preventParentPostCascadeQuery;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package run.halo.app.content;
|
||||
|
||||
import org.springframework.lang.NonNull;
|
||||
import reactor.core.publisher.Flux;
|
||||
import run.halo.app.core.extension.content.Category;
|
||||
|
||||
public interface CategoryService {
|
||||
|
||||
Flux<Category> listChildren(@NonNull String categoryName);
|
||||
}
|
|
@ -57,6 +57,12 @@ public class PostQuery extends IListRequest.QueryListRequest {
|
|||
return Post.PostPhase.from(publishPhase);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getCategoryWithChildren() {
|
||||
var value = queryParams.getFirst("categoryWithChildren");
|
||||
return StringUtils.defaultIfBlank(value, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Schema(description = "Posts filtered by keyword.")
|
||||
public String getKeyword() {
|
||||
|
@ -140,6 +146,12 @@ public class PostQuery extends IListRequest.QueryListRequest {
|
|||
.name("keyword")
|
||||
.description("Posts filtered by keyword.")
|
||||
.implementation(String.class)
|
||||
.required(false))
|
||||
.parameter(parameterBuilder()
|
||||
.in(ParameterIn.QUERY)
|
||||
.name("categoryWithChildren")
|
||||
.description("Posts filtered by category including sub-categories.")
|
||||
.implementation(String.class)
|
||||
.required(false));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package run.halo.app.content.impl;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import run.halo.app.content.CategoryService;
|
||||
import run.halo.app.core.extension.content.Category;
|
||||
import run.halo.app.extension.ReactiveExtensionClient;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class CategoryServiceImpl implements CategoryService {
|
||||
private final ReactiveExtensionClient client;
|
||||
|
||||
@Override
|
||||
public Flux<Category> listChildren(@NonNull String categoryName) {
|
||||
return client.fetch(Category.class, categoryName)
|
||||
.expand(category -> {
|
||||
var children = category.getSpec().getChildren();
|
||||
if (children == null || children.isEmpty()) {
|
||||
return Mono.empty();
|
||||
}
|
||||
return Flux.fromIterable(children)
|
||||
.flatMap(name -> client.fetch(Category.class, name))
|
||||
.filter(this::isNotIndependent);
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isNotIndependent(Category category) {
|
||||
return !category.getSpec().isPreventParentPostCascadeQuery();
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ import reactor.core.publisher.Flux;
|
|||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.retry.Retry;
|
||||
import run.halo.app.content.AbstractContentService;
|
||||
import run.halo.app.content.CategoryService;
|
||||
import run.halo.app.content.ContentRequest;
|
||||
import run.halo.app.content.ContentWrapper;
|
||||
import run.halo.app.content.Contributor;
|
||||
|
@ -36,6 +37,7 @@ import run.halo.app.core.extension.content.Tag;
|
|||
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.MetadataOperator;
|
||||
import run.halo.app.extension.PageRequestImpl;
|
||||
import run.halo.app.extension.ReactiveExtensionClient;
|
||||
import run.halo.app.extension.Ref;
|
||||
|
@ -57,20 +59,23 @@ public class PostServiceImpl extends AbstractContentService implements PostServi
|
|||
private final ReactiveExtensionClient client;
|
||||
private final CounterService counterService;
|
||||
private final UserService userService;
|
||||
private final CategoryService categoryService;
|
||||
|
||||
public PostServiceImpl(ReactiveExtensionClient client, CounterService counterService,
|
||||
UserService userService) {
|
||||
UserService userService, CategoryService categoryService) {
|
||||
super(client);
|
||||
this.client = client;
|
||||
this.counterService = counterService;
|
||||
this.userService = userService;
|
||||
this.categoryService = categoryService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ListResult<ListedPost>> listPost(PostQuery query) {
|
||||
return client.listBy(Post.class, query.toListOptions(),
|
||||
return buildListOptions(query)
|
||||
.flatMap(listOptions -> client.listBy(Post.class, listOptions,
|
||||
PageRequestImpl.of(query.getPage(), query.getSize(), query.getSort())
|
||||
)
|
||||
))
|
||||
.flatMap(listResult -> Flux.fromStream(listResult.get())
|
||||
.map(this::getListedPost)
|
||||
.concatMap(Function.identity())
|
||||
|
@ -82,6 +87,26 @@ public class PostServiceImpl extends AbstractContentService implements PostServi
|
|||
);
|
||||
}
|
||||
|
||||
Mono<ListOptions> buildListOptions(PostQuery query) {
|
||||
var categoryName = query.getCategoryWithChildren();
|
||||
if (categoryName == null) {
|
||||
return Mono.just(query.toListOptions());
|
||||
}
|
||||
return categoryService.listChildren(categoryName)
|
||||
.collectList()
|
||||
.map(categories -> {
|
||||
var categoryNames = categories.stream()
|
||||
.map(Category::getMetadata)
|
||||
.map(MetadataOperator::getName)
|
||||
.toList();
|
||||
var listOptions = query.toListOptions();
|
||||
var newFiledSelector = listOptions.getFieldSelector()
|
||||
.andQuery(in("spec.categories", categoryNames));
|
||||
listOptions.setFieldSelector(newFiledSelector);
|
||||
return listOptions;
|
||||
});
|
||||
}
|
||||
|
||||
Mono<Stats> fetchStats(Post post) {
|
||||
Assert.notNull(post, "The post must not be null.");
|
||||
String name = post.getMetadata().getName();
|
||||
|
|
|
@ -17,6 +17,7 @@ import reactor.core.publisher.Mono;
|
|||
import run.halo.app.core.extension.content.Category;
|
||||
import run.halo.app.extension.ListOptions;
|
||||
import run.halo.app.extension.ListResult;
|
||||
import run.halo.app.extension.Metadata;
|
||||
import run.halo.app.extension.PageRequestImpl;
|
||||
import run.halo.app.extension.ReactiveExtensionClient;
|
||||
import run.halo.app.extension.index.query.QueryFactory;
|
||||
|
@ -114,7 +115,9 @@ public class CategoryFinderImpl implements CategoryFinder {
|
|||
}
|
||||
}
|
||||
});
|
||||
return listToTree(nameIdentityMap.values(), name);
|
||||
var tree = listToTree(nameIdentityMap.values(), name);
|
||||
recomputePostCount(tree);
|
||||
return tree;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -139,6 +142,40 @@ public class CategoryFinderImpl implements CategoryFinder {
|
|||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private CategoryTreeVo dummyVirtualRoot(List<CategoryTreeVo> treeNodes) {
|
||||
Category.CategorySpec categorySpec = new Category.CategorySpec();
|
||||
categorySpec.setSlug("/");
|
||||
return CategoryTreeVo.builder()
|
||||
.spec(categorySpec)
|
||||
.postCount(0)
|
||||
.children(treeNodes)
|
||||
.metadata(new Metadata())
|
||||
.build();
|
||||
}
|
||||
|
||||
void recomputePostCount(List<CategoryTreeVo> treeNodes) {
|
||||
var rootNode = dummyVirtualRoot(treeNodes);
|
||||
recomputePostCount(rootNode);
|
||||
}
|
||||
|
||||
private int recomputePostCount(CategoryTreeVo rootNode) {
|
||||
if (rootNode == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int originalPostCount = rootNode.getPostCount();
|
||||
|
||||
for (var child : rootNode.getChildren()) {
|
||||
int childSum = recomputePostCount(child);
|
||||
if (!child.getSpec().isPreventParentPostCascadeQuery()) {
|
||||
rootNode.setPostCount(rootNode.getPostCount() + childSum);
|
||||
}
|
||||
}
|
||||
|
||||
return rootNode.getSpec().isPreventParentPostCascadeQuery() ? originalPostCount
|
||||
: rootNode.getPostCount();
|
||||
}
|
||||
|
||||
static Comparator<CategoryTreeVo> defaultTreeNodeComparator() {
|
||||
Function<CategoryTreeVo, Integer> priority =
|
||||
category -> Objects.requireNonNullElse(category.getSpec().getPriority(), 0);
|
||||
|
|
|
@ -2,6 +2,7 @@ package run.halo.app.theme.finders.impl;
|
|||
|
||||
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.in;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
@ -15,6 +16,8 @@ import org.springframework.lang.NonNull;
|
|||
import org.springframework.util.Assert;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import run.halo.app.content.CategoryService;
|
||||
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;
|
||||
|
@ -52,6 +55,8 @@ public class PostFinderImpl implements PostFinder {
|
|||
|
||||
private final ReactiveQueryPostPredicateResolver postPredicateResolver;
|
||||
|
||||
private final CategoryService categoryService;
|
||||
|
||||
@Override
|
||||
public Mono<PostVo> getByName(String postName) {
|
||||
return postPredicateResolver.getPredicate()
|
||||
|
@ -141,13 +146,24 @@ 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));
|
||||
return listChildrenCategories(categoryName)
|
||||
.map(category -> category.getMetadata().getName())
|
||||
.collectList()
|
||||
.flatMap(categoryNames -> {
|
||||
var listOptions = new ListOptions();
|
||||
var fieldQuery = in("spec.categories", categoryNames);
|
||||
listOptions.setFieldSelector(FieldSelector.of(fieldQuery));
|
||||
return postPublicQueryService.list(listOptions, getPageRequest(page, size));
|
||||
});
|
||||
}
|
||||
|
||||
private Flux<Category> listChildrenCategories(String categoryName) {
|
||||
if (StringUtils.isBlank(categoryName)) {
|
||||
return client.listAll(Category.class, new ListOptions(),
|
||||
Sort.by(Sort.Order.asc("metadata.creationTimeStamp"),
|
||||
Sort.Order.desc("metadata.name")));
|
||||
}
|
||||
var listOptions = new ListOptions();
|
||||
listOptions.setFieldSelector(FieldSelector.of(fieldQuery));
|
||||
return postPublicQueryService.list(listOptions, getPageRequest(page, size));
|
||||
return categoryService.listChildren(categoryName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -53,6 +53,7 @@ public class CategoryTreeVo implements VisualizableTreeNode<CategoryTreeVo>, Ext
|
|||
|
||||
@Override
|
||||
public String nodeText() {
|
||||
return String.format("%s (%s)", getSpec().getDisplayName(), getPostCount());
|
||||
return String.format("%s (%s)%s", getSpec().getDisplayName(), getPostCount(),
|
||||
spec.isPreventParentPostCascadeQuery() ? " (Independent)" : "");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public class CategoryVo implements ExtensionVoOperator {
|
|||
.metadata(category.getMetadata())
|
||||
.spec(category.getSpec())
|
||||
.status(category.getStatus())
|
||||
.postCount(category.getStatusOrDefault().visiblePostCount)
|
||||
.postCount(category.getStatusOrDefault().getVisiblePostCount())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,18 +6,22 @@ import static org.mockito.ArgumentMatchers.eq;
|
|||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import org.json.JSONException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import run.halo.app.core.extension.content.Category;
|
||||
|
@ -73,7 +77,8 @@ class CategoryFinderImplTest {
|
|||
"children": [
|
||||
"C1",
|
||||
"C2"
|
||||
]
|
||||
],
|
||||
"preventParentPostCascadeQuery": false
|
||||
}
|
||||
}
|
||||
""",
|
||||
|
@ -126,14 +131,97 @@ class CategoryFinderImplTest {
|
|||
List<CategoryTreeVo> treeVos = categoryFinder.listAsTree().collectList().block();
|
||||
String s = visualizeTree(treeVos);
|
||||
assertThat(s).isEqualTo("""
|
||||
全部 (5)
|
||||
├── FIT2CLOUD (2)
|
||||
全部 (7)
|
||||
├── FIT2CLOUD (4)
|
||||
│ ├── DataEase (0)
|
||||
│ ├── Halo (2)
|
||||
│ ├── MeterSphere (0)
|
||||
│ └── JumpServer (0)
|
||||
└── 默认分类 (3)
|
||||
""");
|
||||
""");
|
||||
}
|
||||
|
||||
@Nested
|
||||
class CategoryPostCountTest {
|
||||
|
||||
/**
|
||||
* <p>Structure below.</p>
|
||||
* <pre>
|
||||
* 全部 (35)
|
||||
* ├── FIT2CLOUD (15)
|
||||
* │ ├── DataEase (10)
|
||||
* │ │ ├── SubNode1 (4)
|
||||
* │ │ │ ├── Leaf1 (2)
|
||||
* │ │ │ ├── Leaf2 (2)
|
||||
* │ │ ├── SubNode2 (6) (independent)
|
||||
* │ │ ├── IndependentChild1 (3)
|
||||
* │ │ ├── IndependentChild2 (3)
|
||||
* │ ├── IndependentNode (5) (independent)
|
||||
* │ ├── IndependentChild3 (2)
|
||||
* │ ├── IndependentChild4 (3)
|
||||
* ├── AnotherRootChild (20)
|
||||
* │ ├── Child1 (8)
|
||||
* │ │ ├── SubChild1 (3)
|
||||
* │ │ │ ├── DeepNode1 (1)
|
||||
* │ │ │ ├── DeepNode2 (1)
|
||||
* │ │ │ │ ├── DeeperNode (1)
|
||||
* │ │ ├── SubChild2 (5)
|
||||
* │ │ ├── DeepNode3 (2) (independent)
|
||||
* │ │ ├── DeepNode4 (1)
|
||||
* │ │ ├── DeepNode5 (1)
|
||||
* │ ├── Child2 (12)
|
||||
* │ ├── IndependentSubNode (12) (independent)
|
||||
* │ ├── SubNode3 (6)
|
||||
* │ ├── SubNode4 (6)
|
||||
* </pre>
|
||||
*/
|
||||
private List<Category> categories;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws IOException {
|
||||
var file = ResourceUtils.getFile("classpath:categories/independent-post-count.json");
|
||||
var json = Files.readString(file.toPath());
|
||||
categories = JsonUtils.jsonToObject(json, new TypeReference<>() {
|
||||
});
|
||||
when(client.listAll(eq(Category.class), any(ListOptions.class), any(Sort.class)))
|
||||
.thenReturn(Flux.fromIterable(categories));
|
||||
}
|
||||
|
||||
@Test
|
||||
void computePostCountFromTree() {
|
||||
var treeVos = categoryFinder.toCategoryTreeVoFlux("全部")
|
||||
.collectList().block();
|
||||
assertThat(treeVos).hasSize(1);
|
||||
String s = visualizeTree(treeVos.get(0).getChildren());
|
||||
assertThat(s).isEqualTo("""
|
||||
全部 (84)
|
||||
├── AnotherRootChild (51)
|
||||
│ ├── Child1 (19)
|
||||
│ │ ├── SubChild1 (6)
|
||||
│ │ │ ├── DeepNode1 (1)
|
||||
│ │ │ └── DeepNode2 (2)
|
||||
│ │ │ └── DeeperNode (1)
|
||||
│ │ └── SubChild2 (5)
|
||||
│ │ └── DeepNode3 (4) (Independent)
|
||||
│ │ ├── DeepNode4 (1)
|
||||
│ │ └── DeepNode5 (1)
|
||||
│ └── Child2 (12)
|
||||
│ └── IndependentSubNode (24) (Independent)
|
||||
│ ├── SubNode3 (6)
|
||||
│ └── SubNode4 (6)
|
||||
└── FIT2CLOUD (33)
|
||||
├── DataEase (18)
|
||||
│ ├── SubNode1 (8)
|
||||
│ │ ├── Leaf1 (2)
|
||||
│ │ └── Leaf2 (2)
|
||||
│ └── SubNode2 (12) (Independent)
|
||||
│ ├── IndependentChild1 (3)
|
||||
│ └── IndependentChild2 (3)
|
||||
└── IndependentNode (10) (Independent)
|
||||
├── IndependentChild3 (2)
|
||||
└── IndependentChild4 (3)
|
||||
""");
|
||||
}
|
||||
}
|
||||
|
||||
private List<Category> categoriesForTree() {
|
||||
|
@ -204,7 +292,6 @@ class CategoryFinderImplTest {
|
|||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
|
||||
private List<Category> categories() {
|
||||
Category category2 = JsonUtils.deepCopy(category());
|
||||
category2.getMetadata().setName("c2");
|
||||
|
@ -411,4 +498,4 @@ class CategoryFinderImplTest {
|
|||
return JsonUtils.jsonToObject(s, new TypeReference<>() {
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,422 @@
|
|||
[
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "全部",
|
||||
"children": ["FIT2CLOUD", "AnotherRootChild"]
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 35
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "全部",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "FIT2CLOUD",
|
||||
"children": ["DataEase", "IndependentNode"]
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 15
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "FIT2CLOUD",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "DataEase",
|
||||
"children": ["SubNode1", "SubNode2"]
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 10
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "DataEase",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "SubNode1",
|
||||
"children": ["Leaf1", "Leaf2"]
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 4
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "SubNode1",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "Leaf1",
|
||||
"children": []
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 2
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "Leaf1",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "Leaf2",
|
||||
"children": []
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 2
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "Leaf2",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "SubNode2",
|
||||
"preventParentPostCascadeQuery": true,
|
||||
"children": ["IndependentChild1", "IndependentChild2"]
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 6
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "SubNode2",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "IndependentChild1",
|
||||
"children": []
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 3
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "IndependentChild1",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "IndependentChild2",
|
||||
"children": []
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 3
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "IndependentChild2",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "IndependentNode",
|
||||
"preventParentPostCascadeQuery": true,
|
||||
"children": ["IndependentChild3", "IndependentChild4"]
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 5
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "IndependentNode",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "IndependentChild3",
|
||||
"children": []
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 2
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "IndependentChild3",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "IndependentChild4",
|
||||
"children": []
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 3
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "IndependentChild4",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "AnotherRootChild",
|
||||
"children": ["Child1", "Child2"]
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 20
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "AnotherRootChild",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "Child1",
|
||||
"children": ["SubChild1", "SubChild2"]
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 8
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "Child1",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "SubChild1",
|
||||
"children": ["DeepNode1", "DeepNode2"]
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 3
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "SubChild1",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "DeepNode1",
|
||||
"children": []
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 1
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "DeepNode1",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "DeepNode2",
|
||||
"children": ["DeeperNode"]
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 1
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "DeepNode2",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "DeeperNode",
|
||||
"children": []
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 1
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "DeeperNode",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "SubChild2",
|
||||
"children": ["DeepNode3"]
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 5
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "SubChild2",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "DeepNode3",
|
||||
"preventParentPostCascadeQuery": true,
|
||||
"children": ["DeepNode4", "DeepNode5"]
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 2
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "DeepNode3",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "DeepNode4",
|
||||
"children": []
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 1
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "DeepNode4",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "DeepNode5",
|
||||
"children": []
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 1
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "DeepNode5",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "Child2",
|
||||
"children": ["IndependentSubNode"]
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 12
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "Child2",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "IndependentSubNode",
|
||||
"preventParentPostCascadeQuery": true,
|
||||
"children": ["SubNode3", "SubNode4"]
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 12
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "IndependentSubNode",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "SubNode3",
|
||||
"children": []
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 6
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "SubNode3",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"spec": {
|
||||
"displayName": "SubNode4",
|
||||
"children": []
|
||||
},
|
||||
"status": {
|
||||
"visiblePostCount": 6
|
||||
},
|
||||
"apiVersion": "content.halo.run/v1alpha1",
|
||||
"kind": "Category",
|
||||
"metadata": {
|
||||
"name": "SubNode4",
|
||||
"version": 0,
|
||||
"creationTimestamp": "2024-06-14T06:17:47.589181Z"
|
||||
}
|
||||
}
|
||||
]
|
|
@ -1,9 +1,12 @@
|
|||
<script lang="ts" setup>
|
||||
// core libs
|
||||
import { computed, nextTick, onMounted, ref } from "vue";
|
||||
import SubmitButton from "@/components/button/SubmitButton.vue";
|
||||
import AnnotationsForm from "@/components/form/AnnotationsForm.vue";
|
||||
import { setFocus } from "@/formkit/utils/focus";
|
||||
import { FormType } from "@/types/slug";
|
||||
import { apiClient } from "@/utils/api-client";
|
||||
|
||||
// components
|
||||
import useSlugify from "@console/composables/use-slugify";
|
||||
import { useThemeCustomTemplates } from "@console/modules/interface/themes/composables/use-theme";
|
||||
import type { Category } from "@halo-dev/api-client";
|
||||
import {
|
||||
IconRefreshLine,
|
||||
Toast,
|
||||
|
@ -11,20 +14,10 @@ import {
|
|||
VModal,
|
||||
VSpace,
|
||||
} from "@halo-dev/components";
|
||||
import SubmitButton from "@/components/button/SubmitButton.vue";
|
||||
|
||||
// types
|
||||
import type { Category } from "@halo-dev/api-client";
|
||||
|
||||
// libs
|
||||
import { setFocus } from "@/formkit/utils/focus";
|
||||
import { useThemeCustomTemplates } from "@console/modules/interface/themes/composables/use-theme";
|
||||
import AnnotationsForm from "@/components/form/AnnotationsForm.vue";
|
||||
import useSlugify from "@console/composables/use-slugify";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { FormType } from "@/types/slug";
|
||||
import { useQueryClient } from "@tanstack/vue-query";
|
||||
import { cloneDeep } from "lodash-es";
|
||||
import { computed, nextTick, onMounted, ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
|
@ -54,6 +47,7 @@ const formState = ref<Category>({
|
|||
postTemplate: "",
|
||||
priority: 0,
|
||||
children: [],
|
||||
preventParentPostCascadeQuery: false,
|
||||
},
|
||||
status: {},
|
||||
apiVersion: "content.halo.run/v1alpha1",
|
||||
|
@ -274,6 +268,21 @@ const { handleGenerateSlug } = useSlugify(
|
|||
:accepts="['image/*']"
|
||||
validation="length:0,1024"
|
||||
></FormKit>
|
||||
<FormKit
|
||||
v-model="formState.spec.preventParentPostCascadeQuery"
|
||||
:label="
|
||||
$t(
|
||||
'core.post_category.editing_modal.fields.prevent_parent_post_cascade_query.label'
|
||||
)
|
||||
"
|
||||
:help="
|
||||
$t(
|
||||
'core.post_category.editing_modal.fields.prevent_parent_post_cascade_query.help'
|
||||
)
|
||||
"
|
||||
type="checkbox"
|
||||
name="preventParentPostCascadeQuery"
|
||||
></FormKit>
|
||||
<FormKit
|
||||
v-model="formState.spec.description"
|
||||
name="description"
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
<script lang="ts" setup>
|
||||
import { apiClient } from "@/utils/api-client";
|
||||
import { formatDatetime } from "@/utils/date";
|
||||
import { usePermission } from "@/utils/permission";
|
||||
import type { Category } from "@halo-dev/api-client";
|
||||
import {
|
||||
Dialog,
|
||||
IconList,
|
||||
|
@ -8,17 +12,14 @@ import {
|
|||
VEntityField,
|
||||
VStatusDot,
|
||||
} from "@halo-dev/components";
|
||||
import { VueDraggable } from "vue-draggable-plus";
|
||||
import { type CategoryTree, convertCategoryTreeToCategory } from "../utils";
|
||||
import { formatDatetime } from "@/utils/date";
|
||||
import { usePermission } from "@/utils/permission";
|
||||
import { useQueryClient } from "@tanstack/vue-query";
|
||||
import type { PropType } from "vue";
|
||||
import { ref } from "vue";
|
||||
import CategoryEditingModal from "./CategoryEditingModal.vue";
|
||||
import type { Category } from "@halo-dev/api-client";
|
||||
import { VueDraggable } from "vue-draggable-plus";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { apiClient } from "@/utils/api-client";
|
||||
import { useQueryClient } from "@tanstack/vue-query";
|
||||
import GridiconsLinkBreak from "~icons/gridicons/link-break";
|
||||
import { convertCategoryTreeToCategory, type CategoryTree } from "../utils";
|
||||
import CategoryEditingModal from "./CategoryEditingModal.vue";
|
||||
|
||||
const { currentUserHasPermission } = usePermission();
|
||||
|
||||
|
@ -135,6 +136,18 @@ const handleDelete = async (category: CategoryTree) => {
|
|||
/>
|
||||
</template>
|
||||
</VEntityField>
|
||||
<VEntityField v-if="category.spec.preventParentPostCascadeQuery">
|
||||
<template #description>
|
||||
<GridiconsLinkBreak
|
||||
v-tooltip="
|
||||
$t(
|
||||
'core.post_category.list.fields.prevent_parent_post_cascade_query'
|
||||
)
|
||||
"
|
||||
class="cursor-pointer text-sm transition-all hover:text-blue-600"
|
||||
/>
|
||||
</template>
|
||||
</VEntityField>
|
||||
<VEntityField
|
||||
:description="
|
||||
$t('core.common.fields.post_count', {
|
||||
|
|
|
@ -312,10 +312,11 @@ export const ApiConsoleHaloRunV1alpha1PostApiAxiosParamCreator = function (confi
|
|||
* @param {Array<string>} [sort] Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.
|
||||
* @param {ListPostsPublishPhaseEnum} [publishPhase] Posts filtered by publish phase.
|
||||
* @param {string} [keyword] Posts filtered by keyword.
|
||||
* @param {string} [categoryWithChildren] Posts filtered by category including sub-categories.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
listPosts: async (page?: number, size?: number, labelSelector?: Array<string>, fieldSelector?: Array<string>, sort?: Array<string>, publishPhase?: ListPostsPublishPhaseEnum, keyword?: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
listPosts: async (page?: number, size?: number, labelSelector?: Array<string>, fieldSelector?: Array<string>, sort?: Array<string>, publishPhase?: ListPostsPublishPhaseEnum, keyword?: string, categoryWithChildren?: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/apis/api.console.halo.run/v1alpha1/posts`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||
|
@ -364,6 +365,10 @@ export const ApiConsoleHaloRunV1alpha1PostApiAxiosParamCreator = function (confi
|
|||
localVarQueryParameter['keyword'] = keyword;
|
||||
}
|
||||
|
||||
if (categoryWithChildren !== undefined) {
|
||||
localVarQueryParameter['categoryWithChildren'] = categoryWithChildren;
|
||||
}
|
||||
|
||||
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||
|
@ -742,11 +747,12 @@ export const ApiConsoleHaloRunV1alpha1PostApiFp = function(configuration?: Confi
|
|||
* @param {Array<string>} [sort] Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.
|
||||
* @param {ListPostsPublishPhaseEnum} [publishPhase] Posts filtered by publish phase.
|
||||
* @param {string} [keyword] Posts filtered by keyword.
|
||||
* @param {string} [categoryWithChildren] Posts filtered by category including sub-categories.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async listPosts(page?: number, size?: number, labelSelector?: Array<string>, fieldSelector?: Array<string>, sort?: Array<string>, publishPhase?: ListPostsPublishPhaseEnum, keyword?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ListedPostList>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.listPosts(page, size, labelSelector, fieldSelector, sort, publishPhase, keyword, options);
|
||||
async listPosts(page?: number, size?: number, labelSelector?: Array<string>, fieldSelector?: Array<string>, sort?: Array<string>, publishPhase?: ListPostsPublishPhaseEnum, keyword?: string, categoryWithChildren?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ListedPostList>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.listPosts(page, size, labelSelector, fieldSelector, sort, publishPhase, keyword, categoryWithChildren, options);
|
||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
||||
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1PostApi.listPosts']?.[localVarOperationServerIndex]?.url;
|
||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
||||
|
@ -899,7 +905,7 @@ export const ApiConsoleHaloRunV1alpha1PostApiFactory = function (configuration?:
|
|||
* @throws {RequiredError}
|
||||
*/
|
||||
listPosts(requestParameters: ApiConsoleHaloRunV1alpha1PostApiListPostsRequest = {}, options?: RawAxiosRequestConfig): AxiosPromise<ListedPostList> {
|
||||
return localVarFp.listPosts(requestParameters.page, requestParameters.size, requestParameters.labelSelector, requestParameters.fieldSelector, requestParameters.sort, requestParameters.publishPhase, requestParameters.keyword, options).then((request) => request(axios, basePath));
|
||||
return localVarFp.listPosts(requestParameters.page, requestParameters.size, requestParameters.labelSelector, requestParameters.fieldSelector, requestParameters.sort, requestParameters.publishPhase, requestParameters.keyword, requestParameters.categoryWithChildren, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
* Publish a post.
|
||||
|
@ -1110,6 +1116,13 @@ export interface ApiConsoleHaloRunV1alpha1PostApiListPostsRequest {
|
|||
* @memberof ApiConsoleHaloRunV1alpha1PostApiListPosts
|
||||
*/
|
||||
readonly keyword?: string
|
||||
|
||||
/**
|
||||
* Posts filtered by category including sub-categories.
|
||||
* @type {string}
|
||||
* @memberof ApiConsoleHaloRunV1alpha1PostApiListPosts
|
||||
*/
|
||||
readonly categoryWithChildren?: string
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1312,7 +1325,7 @@ export class ApiConsoleHaloRunV1alpha1PostApi extends BaseAPI {
|
|||
* @memberof ApiConsoleHaloRunV1alpha1PostApi
|
||||
*/
|
||||
public listPosts(requestParameters: ApiConsoleHaloRunV1alpha1PostApiListPostsRequest = {}, options?: RawAxiosRequestConfig) {
|
||||
return ApiConsoleHaloRunV1alpha1PostApiFp(this.configuration).listPosts(requestParameters.page, requestParameters.size, requestParameters.labelSelector, requestParameters.fieldSelector, requestParameters.sort, requestParameters.publishPhase, requestParameters.keyword, options).then((request) => request(this.axios, this.basePath));
|
||||
return ApiConsoleHaloRunV1alpha1PostApiFp(this.configuration).listPosts(requestParameters.page, requestParameters.size, requestParameters.labelSelector, requestParameters.fieldSelector, requestParameters.sort, requestParameters.publishPhase, requestParameters.keyword, requestParameters.categoryWithChildren, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -170,10 +170,11 @@ export const UcApiContentHaloRunV1alpha1PostApiAxiosParamCreator = function (con
|
|||
* @param {Array<string>} [sort] Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.
|
||||
* @param {ListMyPostsPublishPhaseEnum} [publishPhase] Posts filtered by publish phase.
|
||||
* @param {string} [keyword] Posts filtered by keyword.
|
||||
* @param {string} [categoryWithChildren] Posts filtered by category including sub-categories.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
listMyPosts: async (page?: number, size?: number, labelSelector?: Array<string>, fieldSelector?: Array<string>, sort?: Array<string>, publishPhase?: ListMyPostsPublishPhaseEnum, keyword?: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
listMyPosts: async (page?: number, size?: number, labelSelector?: Array<string>, fieldSelector?: Array<string>, sort?: Array<string>, publishPhase?: ListMyPostsPublishPhaseEnum, keyword?: string, categoryWithChildren?: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/apis/uc.api.content.halo.run/v1alpha1/posts`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||
|
@ -222,6 +223,10 @@ export const UcApiContentHaloRunV1alpha1PostApiAxiosParamCreator = function (con
|
|||
localVarQueryParameter['keyword'] = keyword;
|
||||
}
|
||||
|
||||
if (categoryWithChildren !== undefined) {
|
||||
localVarQueryParameter['categoryWithChildren'] = categoryWithChildren;
|
||||
}
|
||||
|
||||
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||
|
@ -461,11 +466,12 @@ export const UcApiContentHaloRunV1alpha1PostApiFp = function(configuration?: Con
|
|||
* @param {Array<string>} [sort] Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.
|
||||
* @param {ListMyPostsPublishPhaseEnum} [publishPhase] Posts filtered by publish phase.
|
||||
* @param {string} [keyword] Posts filtered by keyword.
|
||||
* @param {string} [categoryWithChildren] Posts filtered by category including sub-categories.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async listMyPosts(page?: number, size?: number, labelSelector?: Array<string>, fieldSelector?: Array<string>, sort?: Array<string>, publishPhase?: ListMyPostsPublishPhaseEnum, keyword?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ListedPostList>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.listMyPosts(page, size, labelSelector, fieldSelector, sort, publishPhase, keyword, options);
|
||||
async listMyPosts(page?: number, size?: number, labelSelector?: Array<string>, fieldSelector?: Array<string>, sort?: Array<string>, publishPhase?: ListMyPostsPublishPhaseEnum, keyword?: string, categoryWithChildren?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ListedPostList>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.listMyPosts(page, size, labelSelector, fieldSelector, sort, publishPhase, keyword, categoryWithChildren, options);
|
||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
||||
const localVarOperationServerBasePath = operationServerMap['UcApiContentHaloRunV1alpha1PostApi.listMyPosts']?.[localVarOperationServerIndex]?.url;
|
||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
||||
|
@ -564,7 +570,7 @@ export const UcApiContentHaloRunV1alpha1PostApiFactory = function (configuration
|
|||
* @throws {RequiredError}
|
||||
*/
|
||||
listMyPosts(requestParameters: UcApiContentHaloRunV1alpha1PostApiListMyPostsRequest = {}, options?: RawAxiosRequestConfig): AxiosPromise<ListedPostList> {
|
||||
return localVarFp.listMyPosts(requestParameters.page, requestParameters.size, requestParameters.labelSelector, requestParameters.fieldSelector, requestParameters.sort, requestParameters.publishPhase, requestParameters.keyword, options).then((request) => request(axios, basePath));
|
||||
return localVarFp.listMyPosts(requestParameters.page, requestParameters.size, requestParameters.labelSelector, requestParameters.fieldSelector, requestParameters.sort, requestParameters.publishPhase, requestParameters.keyword, requestParameters.categoryWithChildren, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
* Publish my post.
|
||||
|
@ -708,6 +714,13 @@ export interface UcApiContentHaloRunV1alpha1PostApiListMyPostsRequest {
|
|||
* @memberof UcApiContentHaloRunV1alpha1PostApiListMyPosts
|
||||
*/
|
||||
readonly keyword?: string
|
||||
|
||||
/**
|
||||
* Posts filtered by category including sub-categories.
|
||||
* @type {string}
|
||||
* @memberof UcApiContentHaloRunV1alpha1PostApiListMyPosts
|
||||
*/
|
||||
readonly categoryWithChildren?: string
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -828,7 +841,7 @@ export class UcApiContentHaloRunV1alpha1PostApi extends BaseAPI {
|
|||
* @memberof UcApiContentHaloRunV1alpha1PostApi
|
||||
*/
|
||||
public listMyPosts(requestParameters: UcApiContentHaloRunV1alpha1PostApiListMyPostsRequest = {}, options?: RawAxiosRequestConfig) {
|
||||
return UcApiContentHaloRunV1alpha1PostApiFp(this.configuration).listMyPosts(requestParameters.page, requestParameters.size, requestParameters.labelSelector, requestParameters.fieldSelector, requestParameters.sort, requestParameters.publishPhase, requestParameters.keyword, options).then((request) => request(this.axios, this.basePath));
|
||||
return UcApiContentHaloRunV1alpha1PostApiFp(this.configuration).listMyPosts(requestParameters.page, requestParameters.size, requestParameters.labelSelector, requestParameters.fieldSelector, requestParameters.sort, requestParameters.publishPhase, requestParameters.keyword, requestParameters.categoryWithChildren, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -50,6 +50,12 @@ export interface CategorySpec {
|
|||
* @memberof CategorySpec
|
||||
*/
|
||||
'postTemplate'?: string;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof CategorySpec
|
||||
*/
|
||||
'preventParentPostCascadeQuery'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
|
|
|
@ -375,11 +375,21 @@ core:
|
|||
description:
|
||||
label: Description
|
||||
help: Theme adaptation is required to support
|
||||
prevent_parent_post_cascade_query:
|
||||
label: Prevent Parent Post Cascade Query
|
||||
help: >-
|
||||
Prevent parent category from including this category and its
|
||||
subcategories in cascade post queries
|
||||
post_template:
|
||||
label: Custom post template
|
||||
help: >-
|
||||
Customize the rendering template of posts in the current category,
|
||||
which requires support from the theme
|
||||
list:
|
||||
fields:
|
||||
prevent_parent_post_cascade_query: >-
|
||||
Prevent parent category from including this category and its
|
||||
subcategories in cascade post queries
|
||||
page:
|
||||
title: Pages
|
||||
actions:
|
||||
|
|
|
@ -337,6 +337,11 @@ core:
|
|||
description:
|
||||
label: Descripción
|
||||
help: Se requiere adaptación del tema para ser compatible
|
||||
prevent_parent_post_cascade_query:
|
||||
label: Evitar consulta en cascada de publicación principal
|
||||
help: >-
|
||||
Si se selecciona, las publicaciones de las subcategorías no se
|
||||
agregarán a la categoría principal
|
||||
page:
|
||||
title: Páginas
|
||||
actions:
|
||||
|
|
|
@ -373,9 +373,15 @@ core:
|
|||
description:
|
||||
label: 描述
|
||||
help: 需要主题适配以支持
|
||||
prevent_parent_post_cascade_query:
|
||||
label: 阻止文章级联查询
|
||||
help: 阻止父级分类在级联文章查询中包含此分类及其子分类
|
||||
post_template:
|
||||
label: 自定义文章模板
|
||||
help: 自定义当前分类下文章的渲染模版,需要主题提供支持
|
||||
list:
|
||||
fields:
|
||||
prevent_parent_post_cascade_query: 阻止父级分类在级联文章查询中包含此分类及其子分类
|
||||
page:
|
||||
title: 页面
|
||||
actions:
|
||||
|
|
|
@ -353,9 +353,15 @@ core:
|
|||
description:
|
||||
label: 描述
|
||||
help: 需要主題適配以支持
|
||||
prevent_parent_post_cascade_query:
|
||||
label: 防止父級聯查詢
|
||||
help: 阻止父級分類在級聯文章查詢中包含此分類及其子分類
|
||||
post_template:
|
||||
label: 自定義文章模板
|
||||
help: 自定義當前分類下文章的渲染模板,需要主題提供支持
|
||||
list:
|
||||
fields:
|
||||
prevent_parent_post_cascade_query: 阻止父級分類在級聯文章查詢中包含此分類及其子分類
|
||||
page:
|
||||
title: 頁面
|
||||
actions:
|
||||
|
|
Loading…
Reference in New Issue