From bc1033611e273479e0af8738614df3020c867907 Mon Sep 17 00:00:00 2001
From: Ryan Wang
Date: Wed, 26 Jun 2024 19:25:10 +0800
Subject: [PATCH] Refine UI for categories hiden
---
.../app/core/extension/content/Category.java | 10 ++++++++++
.../halo/app/core/extension/content/Post.java | 5 +++++
.../app/extension/index/query/NotEqual.java | 2 +-
.../components/CategoryEditingModal.vue | 18 ++++++++++++++++++
.../categories/components/CategoryListItem.vue | 13 +++++++++++++
.../api-client/src/models/category-spec.ts | 6 ++++++
.../api-client/src/models/post-status.ts | 6 ++++++
.../src/models/single-page-status.ts | 6 ++++++
ui/src/locales/en.yaml | 8 ++++++++
ui/src/locales/zh-CN.yaml | 4 ++++
ui/src/locales/zh-TW.yaml | 4 ++++
11 files changed, 81 insertions(+), 1 deletion(-)
diff --git a/api/src/main/java/run/halo/app/core/extension/content/Category.java b/api/src/main/java/run/halo/app/core/extension/content/Category.java
index a2ddb04b1..245f681b4 100644
--- a/api/src/main/java/run/halo/app/core/extension/content/Category.java
+++ b/api/src/main/java/run/halo/app/core/extension/content/Category.java
@@ -27,6 +27,7 @@ import run.halo.app.extension.GroupVersionKind;
public class Category extends AbstractExtension {
public static final String KIND = "Category";
+ public static final String LAST_HIDDEN_STATE_ANNO = "content.halo.run/last-hidden-state";
public static final GroupVersionKind GVK = GroupVersionKind.fromExtension(Category.class);
@@ -79,6 +80,15 @@ public class Category extends AbstractExtension {
* and B will be queried, but C and D will not be queried.
*/
private boolean preventParentPostCascadeQuery;
+
+ /**
+ * Whether to hide the category from the category list.
+ * When set to true, the category including its subcategories and related posts will
+ * not be displayed in the category list, but it can still be accessed by permalink.
+ * Limitation: It only takes effect on the theme-side categorized list and it only
+ * allows to be set to true on the first level(root node) of categories.
+ */
+ private boolean hideFromList;
}
@JsonIgnore
diff --git a/api/src/main/java/run/halo/app/core/extension/content/Post.java b/api/src/main/java/run/halo/app/core/extension/content/Post.java
index b9209688b..4ea16e74a 100644
--- a/api/src/main/java/run/halo/app/core/extension/content/Post.java
+++ b/api/src/main/java/run/halo/app/core/extension/content/Post.java
@@ -168,6 +168,11 @@ public class Post extends AbstractExtension {
private List contributors;
+ /**
+ * see {@link Category.CategorySpec#isHideFromList()}.
+ */
+ private Boolean hideFromList;
+
private Instant lastModifyTime;
private Long observedVersion;
diff --git a/api/src/main/java/run/halo/app/extension/index/query/NotEqual.java b/api/src/main/java/run/halo/app/extension/index/query/NotEqual.java
index 3ffa33ff0..af8f694dd 100644
--- a/api/src/main/java/run/halo/app/extension/index/query/NotEqual.java
+++ b/api/src/main/java/run/halo/app/extension/index/query/NotEqual.java
@@ -21,7 +21,7 @@ public class NotEqual extends SimpleQuery {
indexView.acquireReadLock();
try {
NavigableSet equalNames = equalQuery.matches(indexView);
- NavigableSet allNames = indexView.getIdsForField(fieldName);
+ NavigableSet allNames = indexView.getAllIds();
allNames.removeAll(equalNames);
return allNames;
} finally {
diff --git a/ui/console-src/modules/contents/posts/categories/components/CategoryEditingModal.vue b/ui/console-src/modules/contents/posts/categories/components/CategoryEditingModal.vue
index b90c8c448..84394a1fd 100644
--- a/ui/console-src/modules/contents/posts/categories/components/CategoryEditingModal.vue
+++ b/ui/console-src/modules/contents/posts/categories/components/CategoryEditingModal.vue
@@ -26,10 +26,12 @@ const props = withDefaults(
defineProps<{
category?: Category;
parentCategory?: Category;
+ isChildLevelCategory: boolean;
}>(),
{
category: undefined,
parentCategory: undefined,
+ isChildLevelCategory: false,
}
);
@@ -266,6 +268,22 @@ const { handleGenerateSlug } = useSlugify(
:accepts="['image/*']"
validation="length:0,1024"
>
+
(), {});
+
const categories = defineModel({
type: Array as PropType,
default: [],
@@ -95,6 +98,7 @@ const handleDelete = async (category: CategoryTree) => {
>
{
/>
+
+
+
+
+
{
diff --git a/ui/packages/api-client/src/models/category-spec.ts b/ui/packages/api-client/src/models/category-spec.ts
index ba762b17b..b066b64bc 100644
--- a/ui/packages/api-client/src/models/category-spec.ts
+++ b/ui/packages/api-client/src/models/category-spec.ts
@@ -44,6 +44,12 @@ export interface CategorySpec {
* @memberof CategorySpec
*/
'displayName': string;
+ /**
+ *
+ * @type {boolean}
+ * @memberof CategorySpec
+ */
+ 'hideFromList'?: boolean;
/**
*
* @type {string}
diff --git a/ui/packages/api-client/src/models/post-status.ts b/ui/packages/api-client/src/models/post-status.ts
index 8a89e30a6..8d6b02274 100644
--- a/ui/packages/api-client/src/models/post-status.ts
+++ b/ui/packages/api-client/src/models/post-status.ts
@@ -47,6 +47,12 @@ export interface PostStatus {
* @memberof PostStatus
*/
'excerpt'?: string;
+ /**
+ *
+ * @type {boolean}
+ * @memberof PostStatus
+ */
+ 'hideFromList'?: boolean;
/**
*
* @type {boolean}
diff --git a/ui/packages/api-client/src/models/single-page-status.ts b/ui/packages/api-client/src/models/single-page-status.ts
index 210999e26..3329d3f59 100644
--- a/ui/packages/api-client/src/models/single-page-status.ts
+++ b/ui/packages/api-client/src/models/single-page-status.ts
@@ -47,6 +47,12 @@ export interface SinglePageStatus {
* @memberof SinglePageStatus
*/
'excerpt'?: string;
+ /**
+ *
+ * @type {boolean}
+ * @memberof SinglePageStatus
+ */
+ 'hideFromList'?: boolean;
/**
*
* @type {boolean}
diff --git a/ui/src/locales/en.yaml b/ui/src/locales/en.yaml
index 7b3aa29cb..1d5bb924d 100644
--- a/ui/src/locales/en.yaml
+++ b/ui/src/locales/en.yaml
@@ -416,11 +416,19 @@ core:
help: >-
Customize the rendering template of posts in the current category,
which requires support from the theme
+ hide_from_list:
+ label: Hide from list
+ help: >-
+ After turning on this option, this category and its subcategories,
+ as well as its posts, will not be displayed in the front-end list.
+ You need to actively visit the category archive page. This feature
+ is only effective for the first-level directory.
list:
fields:
prevent_parent_post_cascade_query: >-
Prevent parent category from including this category and its
subcategories in cascade post queries
+ hide_from_list: This category is hidden, This category and its subcategories, as well as its posts, will not be displayed in the front-end list. You need to actively visit the category archive page
page:
title: Pages
actions:
diff --git a/ui/src/locales/zh-CN.yaml b/ui/src/locales/zh-CN.yaml
index a6eb90b16..880797a37 100644
--- a/ui/src/locales/zh-CN.yaml
+++ b/ui/src/locales/zh-CN.yaml
@@ -406,9 +406,13 @@ core:
post_template:
label: 自定义文章模板
help: 自定义当前分类下文章的渲染模版,需要主题提供支持
+ hide_from_list:
+ label: 在列表中隐藏
+ help: 开启此选项后,此分类和其下子分类,以及其下文章将不会显示在前台的列表中,需要主动访问分类归档页面,此功能仅对第一级目录生效
list:
fields:
prevent_parent_post_cascade_query: 阻止父级分类在级联文章查询中包含此分类及其子分类
+ hide_from_list: 已隐藏,此分类和其下子分类,以及其下文章将不会显示在前台的列表中
page:
title: 页面
actions:
diff --git a/ui/src/locales/zh-TW.yaml b/ui/src/locales/zh-TW.yaml
index 2bd937f4a..162df9c24 100644
--- a/ui/src/locales/zh-TW.yaml
+++ b/ui/src/locales/zh-TW.yaml
@@ -386,9 +386,13 @@ core:
post_template:
label: 自定義文章模板
help: 自定義當前分類下文章的渲染模板,需要主題提供支持
+ hide_from_list:
+ label: 在列表中隱藏
+ help: 開啟此選項後,此分類和其下子分類,以及其下文章將不會顯示在前臺的列表中,需要主動訪問分類歸檔頁面,此功能僅對第一級目錄生效
list:
fields:
prevent_parent_post_cascade_query: 阻止父級分類在級聯文章查詢中包含此分類及其子分類
+ hide_from_list: 已隱藏,此分類和其下子分類,以及其下文章將不會顯示在前臺的列表中,需要主動訪問分類歸檔頁面
page:
title: 頁面
actions: