mirror of https://github.com/halo-dev/halo
feat: add cleanup feature for post snapshots (#5822)
#### What type of PR is this? /area ui /kind feature /milestone 2.15.x #### What this PR does / why we need it: 支持清理所有无用的文章历史快照,仅保留已发布、基础版本、正在编辑的版本。 #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/5817 #### Special notes for your reviewer: 需要在历史版本页面测试清理功能是否符合预期。 #### Does this PR introduce a user-facing change? ```release-note None ```pull/5838/head
parent
d1d4705705
commit
966558d1ce
|
@ -1,12 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import {
|
||||
Dialog,
|
||||
IconHistoryLine,
|
||||
Toast,
|
||||
VButton,
|
||||
VCard,
|
||||
VLoading,
|
||||
VPageHeader,
|
||||
VSpace,
|
||||
} from "@halo-dev/components";
|
||||
import { useQuery } from "@tanstack/vue-query";
|
||||
import { useQuery, useQueryClient } from "@tanstack/vue-query";
|
||||
import { useRoute } from "vue-router";
|
||||
import { apiClient } from "@/utils/api-client";
|
||||
import { computed, watch } from "vue";
|
||||
|
@ -14,8 +17,11 @@ import { OverlayScrollbarsComponent } from "overlayscrollbars-vue";
|
|||
import { useRouteQuery } from "@vueuse/router";
|
||||
import SnapshotContent from "./components/SnapshotContent.vue";
|
||||
import SnapshotListItem from "./components/SnapshotListItem.vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
|
||||
const singlePageName = computed(() => route.query.name as string);
|
||||
|
||||
|
@ -70,6 +76,43 @@ watch(
|
|||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
function handleCleanup() {
|
||||
Dialog.warning({
|
||||
title: t("core.page_snapshots.operations.cleanup.title"),
|
||||
description: t("core.page_snapshots.operations.cleanup.description"),
|
||||
confirmText: t("core.common.buttons.confirm"),
|
||||
cancelText: t("core.common.buttons.cancel"),
|
||||
async onConfirm() {
|
||||
const { releaseSnapshot, baseSnapshot, headSnapshot } =
|
||||
singlePage.value?.spec || {};
|
||||
const snapshotsToDelete = snapshots.value?.filter((snapshot) => {
|
||||
const { name } = snapshot.metadata;
|
||||
return ![releaseSnapshot, baseSnapshot, headSnapshot]
|
||||
.filter(Boolean)
|
||||
.includes(name);
|
||||
});
|
||||
|
||||
if (!snapshotsToDelete?.length) {
|
||||
Toast.info(t("core.page_snapshots.operations.cleanup.toast_empty"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < snapshotsToDelete?.length; i++) {
|
||||
await apiClient.singlePage.deleteSinglePageContent({
|
||||
name: singlePageName.value,
|
||||
snapshotName: snapshotsToDelete[i].metadata.name,
|
||||
});
|
||||
}
|
||||
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ["singlePage-snapshots-by-singlePage-name", singlePageName],
|
||||
});
|
||||
|
||||
Toast.success(t("core.page_snapshots.operations.cleanup.toast_success"));
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -78,9 +121,14 @@ watch(
|
|||
<IconHistoryLine class="mr-2 self-center" />
|
||||
</template>
|
||||
<template #actions>
|
||||
<VButton size="sm" @click="$router.back()">
|
||||
{{ $t("core.common.buttons.back") }}
|
||||
</VButton>
|
||||
<VSpace>
|
||||
<VButton size="sm" @click="$router.back()">
|
||||
{{ $t("core.common.buttons.back") }}
|
||||
</VButton>
|
||||
<VButton size="sm" type="danger" @click="handleCleanup">
|
||||
{{ $t("core.page_snapshots.operations.cleanup.button") }}
|
||||
</VButton>
|
||||
</VSpace>
|
||||
</template>
|
||||
</VPageHeader>
|
||||
|
||||
|
|
|
@ -109,6 +109,9 @@ const isBase = computed(() => {
|
|||
<VTag v-if="isHead">
|
||||
{{ $t("core.page_snapshots.status.draft") }}
|
||||
</VTag>
|
||||
<VTag v-if="isBase">
|
||||
{{ $t("core.page_snapshots.status.base") }}
|
||||
</VTag>
|
||||
<VStatusDot
|
||||
v-if="snapshot.metadata.deletionTimestamp"
|
||||
v-tooltip="$t('core.common.status.deleting')"
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import {
|
||||
Dialog,
|
||||
IconHistoryLine,
|
||||
Toast,
|
||||
VButton,
|
||||
VCard,
|
||||
VLoading,
|
||||
VPageHeader,
|
||||
VSpace,
|
||||
} from "@halo-dev/components";
|
||||
import { useQuery } from "@tanstack/vue-query";
|
||||
import { useQuery, useQueryClient } from "@tanstack/vue-query";
|
||||
import { useRoute } from "vue-router";
|
||||
import { apiClient } from "@/utils/api-client";
|
||||
import { computed, watch } from "vue";
|
||||
|
@ -14,8 +17,11 @@ import { OverlayScrollbarsComponent } from "overlayscrollbars-vue";
|
|||
import { useRouteQuery } from "@vueuse/router";
|
||||
import SnapshotContent from "@console/modules/contents/posts/components/SnapshotContent.vue";
|
||||
import SnapshotListItem from "@console/modules/contents/posts/components/SnapshotListItem.vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const postName = computed(() => route.query.name as string);
|
||||
|
||||
|
@ -70,6 +76,43 @@ watch(
|
|||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
function handleCleanup() {
|
||||
Dialog.warning({
|
||||
title: t("core.post_snapshots.operations.cleanup.title"),
|
||||
description: t("core.post_snapshots.operations.cleanup.description"),
|
||||
confirmText: t("core.common.buttons.confirm"),
|
||||
cancelText: t("core.common.buttons.cancel"),
|
||||
async onConfirm() {
|
||||
const { releaseSnapshot, baseSnapshot, headSnapshot } =
|
||||
post.value?.spec || {};
|
||||
const snapshotsToDelete = snapshots.value?.filter((snapshot) => {
|
||||
const { name } = snapshot.metadata;
|
||||
return ![releaseSnapshot, baseSnapshot, headSnapshot]
|
||||
.filter(Boolean)
|
||||
.includes(name);
|
||||
});
|
||||
|
||||
if (!snapshotsToDelete?.length) {
|
||||
Toast.info(t("core.post_snapshots.operations.cleanup.toast_empty"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < snapshotsToDelete?.length; i++) {
|
||||
await apiClient.post.deletePostContent({
|
||||
name: postName.value,
|
||||
snapshotName: snapshotsToDelete[i].metadata.name,
|
||||
});
|
||||
}
|
||||
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ["post-snapshots-by-post-name", postName],
|
||||
});
|
||||
|
||||
Toast.success(t("core.post_snapshots.operations.cleanup.toast_success"));
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -78,9 +121,14 @@ watch(
|
|||
<IconHistoryLine class="mr-2 self-center" />
|
||||
</template>
|
||||
<template #actions>
|
||||
<VButton size="sm" @click="$router.back()">
|
||||
{{ $t("core.common.buttons.back") }}
|
||||
</VButton>
|
||||
<VSpace>
|
||||
<VButton size="sm" @click="$router.back()">
|
||||
{{ $t("core.common.buttons.back") }}
|
||||
</VButton>
|
||||
<VButton size="sm" type="danger" @click="handleCleanup">
|
||||
{{ $t("core.post_snapshots.operations.cleanup.button") }}
|
||||
</VButton>
|
||||
</VSpace>
|
||||
</template>
|
||||
</VPageHeader>
|
||||
|
||||
|
|
|
@ -107,6 +107,9 @@ const isBase = computed(() => {
|
|||
<VTag v-if="isHead">
|
||||
{{ $t("core.post_snapshots.status.draft") }}
|
||||
</VTag>
|
||||
<VTag v-if="isBase">
|
||||
{{ $t("core.post_snapshots.status.base") }}
|
||||
</VTag>
|
||||
<VStatusDot
|
||||
v-if="snapshot.metadata.deletionTimestamp"
|
||||
v-tooltip="$t('core.common.status.deleting')"
|
||||
|
|
|
@ -1692,9 +1692,18 @@ core:
|
|||
description: >-
|
||||
Are you sure you want to delete this snapshot? This operation is
|
||||
irreversible.
|
||||
cleanup:
|
||||
button: Cleanup
|
||||
title: Cleanup snapshots
|
||||
description: >-
|
||||
Are you sure you want to delete all unused snapshots? Only published,
|
||||
base version, and draft versions will be retained.
|
||||
toast_empty: There are no snapshots to be cleaned up
|
||||
toast_success: Cleanup completed
|
||||
status:
|
||||
released: Released
|
||||
draft: Draft
|
||||
base: Base
|
||||
title: Post snapshots
|
||||
page_snapshots:
|
||||
operations:
|
||||
|
@ -1710,7 +1719,16 @@ core:
|
|||
description: >-
|
||||
Are you sure you want to delete this snapshot? This operation is
|
||||
irreversible.
|
||||
cleanup:
|
||||
button: Cleanup
|
||||
title: Cleanup snapshots
|
||||
description: >-
|
||||
Are you sure you want to delete all unused snapshots? Only published,
|
||||
base version, and draft versions will be retained.
|
||||
toast_empty: There are no snapshots to be cleaned up
|
||||
toast_success: Cleanup completed
|
||||
status:
|
||||
released: Released
|
||||
draft: Draft
|
||||
base: Base
|
||||
title: Page snapshots
|
||||
|
|
|
@ -1592,9 +1592,16 @@ core:
|
|||
delete:
|
||||
title: 删除快照
|
||||
description: 确定要删除该快照吗?此操作无法恢复。
|
||||
cleanup:
|
||||
button: 清理
|
||||
title: 清理快照
|
||||
description: 确定要清理所有不再使用的快照吗?只会保留已发布、基础和草稿版本。
|
||||
toast_empty: 没有需要清理的快照
|
||||
toast_success: 清理完成
|
||||
status:
|
||||
released: 已发布
|
||||
draft: 草稿
|
||||
base: 基础
|
||||
title: 文章版本历史
|
||||
page_snapshots:
|
||||
operations:
|
||||
|
@ -1606,7 +1613,14 @@ core:
|
|||
delete:
|
||||
title: 删除快照
|
||||
description: 确定要删除该快照吗?此操作无法恢复。
|
||||
cleanup:
|
||||
button: 清理
|
||||
title: 清理快照
|
||||
description: 确定要清理所有不再使用的快照吗?只会保留已发布、基础和草稿版本。
|
||||
toast_empty: 没有需要清理的快照
|
||||
toast_success: 清理完成
|
||||
status:
|
||||
released: 已发布
|
||||
draft: 草稿
|
||||
base: 基础
|
||||
title: 页面版本历史
|
||||
|
|
|
@ -1586,9 +1586,16 @@ core:
|
|||
delete:
|
||||
title: 刪除快照
|
||||
description: 確定要刪除該快照嗎?此操作無法恢復。
|
||||
cleanup:
|
||||
button: 清理
|
||||
title: 清理快照
|
||||
description: 確定要清理所有不再使用的快照嗎?只會保留已發佈、基礎和草稿版本。
|
||||
toast_empty: 沒有需要清理的快照
|
||||
toast_success: 清理完成
|
||||
status:
|
||||
released: 已發布
|
||||
draft: 草稿
|
||||
base: 基礎
|
||||
title: 文章版本歷史
|
||||
page_snapshots:
|
||||
operations:
|
||||
|
@ -1600,7 +1607,14 @@ core:
|
|||
delete:
|
||||
title: 刪除快照
|
||||
description: 確定要刪除該快照嗎?此操作無法恢復。
|
||||
cleanup:
|
||||
button: 清理
|
||||
title: 清理快照
|
||||
description: 確定要清理所有不再使用的快照嗎?只會保留已發佈、基礎和草稿版本。
|
||||
toast_empty: 沒有需要清理的快照
|
||||
toast_success: 清理完成
|
||||
status:
|
||||
released: 已發布
|
||||
draft: 草稿
|
||||
base: 基礎
|
||||
title: 頁面版本歷史
|
||||
|
|
Loading…
Reference in New Issue