mirror of https://github.com/halo-dev/halo
Refine UI for categories hiden
parent
0196315228
commit
bc1033611e
|
@ -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.</p>
|
||||
*/
|
||||
private boolean preventParentPostCascadeQuery;
|
||||
|
||||
/**
|
||||
* <p>Whether to hide the category from the category list.</p>
|
||||
* <p>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.</p>
|
||||
* <p>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.</p>
|
||||
*/
|
||||
private boolean hideFromList;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
|
|
|
@ -168,6 +168,11 @@ public class Post extends AbstractExtension {
|
|||
|
||||
private List<String> contributors;
|
||||
|
||||
/**
|
||||
* see {@link Category.CategorySpec#isHideFromList()}.
|
||||
*/
|
||||
private Boolean hideFromList;
|
||||
|
||||
private Instant lastModifyTime;
|
||||
|
||||
private Long observedVersion;
|
||||
|
|
|
@ -21,7 +21,7 @@ public class NotEqual extends SimpleQuery {
|
|||
indexView.acquireReadLock();
|
||||
try {
|
||||
NavigableSet<String> equalNames = equalQuery.matches(indexView);
|
||||
NavigableSet<String> allNames = indexView.getIdsForField(fieldName);
|
||||
NavigableSet<String> allNames = indexView.getAllIds();
|
||||
allNames.removeAll(equalNames);
|
||||
return allNames;
|
||||
} finally {
|
||||
|
|
|
@ -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"
|
||||
></FormKit>
|
||||
<FormKit
|
||||
v-model="formState.spec.hideFromList"
|
||||
:disabled="isChildLevelCategory"
|
||||
:label="
|
||||
$t(
|
||||
'core.post_category.editing_modal.fields.hide_from_list.label'
|
||||
)
|
||||
"
|
||||
:help="
|
||||
$t(
|
||||
'core.post_category.editing_modal.fields.hide_from_list.help'
|
||||
)
|
||||
"
|
||||
type="checkbox"
|
||||
name="hideFromList"
|
||||
></FormKit>
|
||||
<FormKit
|
||||
v-model="formState.spec.preventParentPostCascadeQuery"
|
||||
:label="
|
||||
|
|
|
@ -5,6 +5,7 @@ import type { Category } from "@halo-dev/api-client";
|
|||
import { coreApiClient } from "@halo-dev/api-client";
|
||||
import {
|
||||
Dialog,
|
||||
IconEyeOff,
|
||||
IconList,
|
||||
Toast,
|
||||
VDropdownItem,
|
||||
|
@ -23,6 +24,8 @@ import CategoryEditingModal from "./CategoryEditingModal.vue";
|
|||
|
||||
const { currentUserHasPermission } = usePermission();
|
||||
|
||||
withDefaults(defineProps<{ isChildLevel?: boolean }>(), {});
|
||||
|
||||
const categories = defineModel({
|
||||
type: Array as PropType<CategoryTree[]>,
|
||||
default: [],
|
||||
|
@ -95,6 +98,7 @@ const handleDelete = async (category: CategoryTree) => {
|
|||
>
|
||||
<CategoryEditingModal
|
||||
v-if="editingModal"
|
||||
:is-child-level-category="isChildLevel"
|
||||
:category="selectedCategory"
|
||||
:parent-category="selectedParentCategory"
|
||||
@close="onEditingModalClose"
|
||||
|
@ -134,6 +138,14 @@ const handleDelete = async (category: CategoryTree) => {
|
|||
/>
|
||||
</template>
|
||||
</VEntityField>
|
||||
<VEntityField v-if="category.spec.hideFromList">
|
||||
<template #description>
|
||||
<IconEyeOff
|
||||
v-tooltip="$t('core.post_category.list.fields.hide_from_list')"
|
||||
class="cursor-pointer text-sm transition-all hover:text-blue-600"
|
||||
/>
|
||||
</template>
|
||||
</VEntityField>
|
||||
<VEntityField v-if="category.spec.preventParentPostCascadeQuery">
|
||||
<template #description>
|
||||
<GridiconsLinkBreak
|
||||
|
@ -185,6 +197,7 @@ const handleDelete = async (category: CategoryTree) => {
|
|||
</VEntity>
|
||||
<CategoryListItem
|
||||
v-model="category.spec.children"
|
||||
is-child-level
|
||||
class="pl-10 transition-all duration-300"
|
||||
@change="onChange"
|
||||
/>
|
||||
|
|
|
@ -44,6 +44,12 @@ export interface CategorySpec {
|
|||
* @memberof CategorySpec
|
||||
*/
|
||||
'displayName': string;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof CategorySpec
|
||||
*/
|
||||
'hideFromList'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
|
|
|
@ -47,6 +47,12 @@ export interface PostStatus {
|
|||
* @memberof PostStatus
|
||||
*/
|
||||
'excerpt'?: string;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof PostStatus
|
||||
*/
|
||||
'hideFromList'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
|
|
|
@ -47,6 +47,12 @@ export interface SinglePageStatus {
|
|||
* @memberof SinglePageStatus
|
||||
*/
|
||||
'excerpt'?: string;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof SinglePageStatus
|
||||
*/
|
||||
'hideFromList'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue