Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add restore by backup record supports #4511

Merged
merged 7 commits into from Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions console/src/locales/en.yaml
Expand Up @@ -1003,6 +1003,9 @@ core:
toast_success: Requested to restart
remote_download:
button: Download and restore
restore_by_backup:
button: Restore
title: Are you sure you want to restore from this backup?
list:
phases:
pending: Pending
Expand All @@ -1025,6 +1028,8 @@ core:
label: Remote
fields:
url: Remote URL
backup:
label: Restore from backup
exception:
not_found:
message: Page not found
Expand Down
5 changes: 5 additions & 0 deletions console/src/locales/zh-CN.yaml
Expand Up @@ -1003,6 +1003,9 @@ core:
toast_success: 已请求重启
remote_download:
button: 下载并恢复
restore_by_backup:
button: 恢复
title: 确认要从此备份进行恢复吗?
list:
phases:
pending: 准备中
Expand All @@ -1025,6 +1028,8 @@ core:
label: 远程恢复
fields:
url: 下载地址
backup:
label: 从备份恢复
exception:
not_found:
message: 没有找到该页面
Expand Down
9 changes: 7 additions & 2 deletions console/src/locales/zh-TW.yaml
Expand Up @@ -1003,6 +1003,9 @@ core:
toast_success: 已請求重啟
remote_download:
button: 下載並還原
restore_by_backup:
button: 還原
title: 確認要從此備份進行還原嗎?
list:
phases:
pending: 準備中
Expand All @@ -1016,15 +1019,17 @@ core:
first: 1. 還原過程可能需要較長時間,期間請勿重新整理頁面。
second: 2. 在還原過程中,雖然已有的資料不會被清除,但若有衝突的資料將被覆蓋。
third: 3. 還原完成後需要重新啟動 Halo 才能正常載入系統資源。
complete: 恢復完成,等待重啟...
complete: 還原完成,等待重啟...
start: 開始還原
tabs:
local:
label: 上傳
remote:
label: 遠程恢復
label: 遠程還原
fields:
url: 下載地址
backup:
label: 從備份還原
exception:
not_found:
message: 沒有找到該頁面
Expand Down
15 changes: 11 additions & 4 deletions console/src/modules/system/backup/components/BackupListItem.vue
Expand Up @@ -23,9 +23,15 @@ import type { OperationItem } from "packages/shared/dist";
const queryClient = useQueryClient();
const { t } = useI18n();

const props = defineProps<{
backup: Backup;
}>();
const props = withDefaults(
defineProps<{
backup: Backup;
showOperations: boolean;
}>(),
{
showOperations: true,
}
);

const { backup } = toRefs(props);

Expand Down Expand Up @@ -185,8 +191,9 @@ const { operationItems } = useOperationItemExtensionPoint<Backup>(
</span>
</template>
</VEntityField>
<slot name="end"></slot>
</template>
<template #dropdownItems>
<template v-if="showOperations" #dropdownItems>
<EntityDropdownItems :dropdown-items="operationItems" :item="backup" />
</template>
</VEntity>
Expand Down
38 changes: 37 additions & 1 deletion console/src/modules/system/backup/composables/use-backup.ts
@@ -1,9 +1,45 @@
import { apiClient } from "@/utils/api-client";
import { Dialog, Toast } from "@halo-dev/components";
import { useQueryClient } from "@tanstack/vue-query";
import { useQuery, useQueryClient } from "@tanstack/vue-query";
import dayjs from "dayjs";
import { BackupStatusPhaseEnum } from "@halo-dev/api-client";
import { useI18n } from "vue-i18n";

export function useBackupFetch() {
return useQuery({
queryKey: ["backups"],
queryFn: async () => {
const { data } =
await apiClient.extension.backup.listmigrationHaloRunV1alpha1Backup({
sort: ["metadata.creationTimestamp,desc"],
});
return data;
},
refetchInterval(data) {
const deletingBackups = data?.items.filter((backup) => {
return !!backup.metadata.deletionTimestamp;
});

if (deletingBackups?.length) {
return 1000;
}

const pendingBackups = data?.items.filter((backup) => {
return (
backup.status?.phase === BackupStatusPhaseEnum.Pending ||
backup.status?.phase === BackupStatusPhaseEnum.Running
);
});

if (pendingBackups?.length) {
return 3000;
}

return false;
},
});
}

export function useBackup() {
const { t } = useI18n();
const queryClient = useQueryClient();
Expand Down
42 changes: 2 additions & 40 deletions console/src/modules/system/backup/tabs/List.vue
@@ -1,47 +1,9 @@
<script lang="ts" setup>
import { apiClient } from "@/utils/api-client";
import { useQuery } from "@tanstack/vue-query";
import { BackupStatusPhaseEnum } from "@halo-dev/api-client";
import { VButton, VEmpty, VLoading } from "@halo-dev/components";
import BackupListItem from "../components/BackupListItem.vue";
import { useBackupFetch } from "../composables/use-backup";

const {
data: backups,
isLoading,
isFetching,
refetch,
} = useQuery({
queryKey: ["backups"],
queryFn: async () => {
const { data } =
await apiClient.extension.backup.listmigrationHaloRunV1alpha1Backup({
sort: ["metadata.creationTimestamp,desc"],
});
return data;
},
refetchInterval(data) {
const deletingBackups = data?.items.filter((backup) => {
return !!backup.metadata.deletionTimestamp;
});

if (deletingBackups?.length) {
return 1000;
}

const pendingBackups = data?.items.filter((backup) => {
return (
backup.status?.phase === BackupStatusPhaseEnum.Pending ||
backup.status?.phase === BackupStatusPhaseEnum.Running
);
});

if (pendingBackups?.length) {
return 3000;
}

return false;
},
});
const { data: backups, isLoading, isFetching, refetch } = useBackupFetch();
</script>

<template>
Expand Down
55 changes: 55 additions & 0 deletions console/src/modules/system/backup/tabs/Restore.vue
Expand Up @@ -6,6 +6,7 @@ import {
Toast,
VAlert,
VButton,
VEntityField,
VLoading,
VTabItem,
VTabs,
Expand All @@ -15,8 +16,18 @@ import axios from "axios";
import { computed } from "vue";
import { ref } from "vue";
import { useI18n } from "vue-i18n";
import { useBackupFetch } from "../composables/use-backup";
import BackupListItem from "../components/BackupListItem.vue";
import type { Backup } from "packages/api-client/dist";

const { t } = useI18n();
const { data: backups } = useBackupFetch();

const normalBackups = computed(() => {
return backups.value?.items.filter((item) => {
return item.status?.phase === "SUCCEEDED";
});
});

const complete = ref(false);
const showUploader = ref(false);
Expand Down Expand Up @@ -58,6 +69,22 @@ const { isLoading: downloading, mutate: handleRemoteDownload } = useMutation({
},
});

function handleRestoreFromBackup(backup: Backup) {
Dialog.info({
title: t("core.backup.operations.restore_by_backup.title"),
confirmText: t("core.common.buttons.confirm"),
showCancel: false,
async onConfirm() {
await apiClient.migration.restoreBackup({
backupName: backup.metadata.name,
});
setTimeout(() => {
onProcessCompleted();
}, 200);
},
});
}

useQuery({
queryKey: ["check-health"],
queryFn: async () => {
Expand Down Expand Up @@ -142,6 +169,34 @@ useQuery({
</VButton>
</div>
</VTabItem>
<VTabItem
id="backups"
:label="$t('core.backup.restore.tabs.backup.label')"
>
<ul
class="box-border h-full w-full divide-y divide-gray-100 overflow-hidden rounded-base"
role="list"
>
<li v-for="(backup, index) in normalBackups" :key="index">
<BackupListItem :show-operations="false" :backup="backup">
<template #end>
<VEntityField v-permission="['system:themes:manage']">
<template #description>
<VButton
size="sm"
@click="handleRestoreFromBackup(backup)"
>
{{
$t("core.backup.operations.restore_by_backup.button")
}}
</VButton>
</template>
</VEntityField>
</template>
</BackupListItem>
</li>
</ul>
</VTabItem>
</VTabs>
</div>
</div>
Expand Down