mirror of https://github.com/halo-dev/halo
201 lines
5.4 KiB
Vue
201 lines
5.4 KiB
Vue
![]() |
<script lang="ts" setup>
|
||
|
import {
|
||
|
Dialog,
|
||
|
Toast,
|
||
|
VDropdownItem,
|
||
|
VEntity,
|
||
|
VEntityField,
|
||
|
VSpace,
|
||
|
VStatusDot,
|
||
|
} from "@halo-dev/components";
|
||
|
import type { Backup } from "@halo-dev/api-client";
|
||
|
import { relativeTimeTo, formatDatetime } from "@/utils/date";
|
||
![]() |
import { computed, markRaw } from "vue";
|
||
![]() |
import { apiClient } from "@/utils/api-client";
|
||
|
import { useQueryClient } from "@tanstack/vue-query";
|
||
|
import prettyBytes from "pretty-bytes";
|
||
|
import { useI18n } from "vue-i18n";
|
||
![]() |
import { useOperationItemExtensionPoint } from "@console/composables/use-operation-extension-points";
|
||
![]() |
import EntityDropdownItems from "@/components/entity/EntityDropdownItems.vue";
|
||
![]() |
import { toRefs } from "vue";
|
||
![]() |
import type { OperationItem } from "@halo-dev/console-shared";
|
||
![]() |
|
||
|
const queryClient = useQueryClient();
|
||
|
const { t } = useI18n();
|
||
|
|
||
![]() |
const props = withDefaults(
|
||
|
defineProps<{
|
||
|
backup: Backup;
|
||
![]() |
showOperations?: boolean;
|
||
![]() |
}>(),
|
||
|
{
|
||
|
showOperations: true,
|
||
|
}
|
||
|
);
|
||
![]() |
|
||
![]() |
const { backup } = toRefs(props);
|
||
|
|
||
![]() |
type Phase = {
|
||
|
text: string;
|
||
|
state: "default" | "warning" | "success" | "error";
|
||
|
animate: boolean;
|
||
|
value: "PENDING" | "RUNNING" | "SUCCEEDED" | "FAILED";
|
||
|
};
|
||
|
|
||
|
const phases: Phase[] = [
|
||
|
{
|
||
|
text: t("core.backup.list.phases.pending"),
|
||
|
state: "default",
|
||
|
animate: false,
|
||
|
value: "PENDING",
|
||
|
},
|
||
|
{
|
||
|
text: t("core.backup.list.phases.running"),
|
||
|
state: "warning",
|
||
|
animate: true,
|
||
|
value: "RUNNING",
|
||
|
},
|
||
|
{
|
||
|
text: t("core.backup.list.phases.succeeded"),
|
||
|
state: "success",
|
||
|
animate: false,
|
||
|
value: "SUCCEEDED",
|
||
|
},
|
||
|
{
|
||
|
text: t("core.backup.list.phases.failed"),
|
||
|
state: "error",
|
||
|
animate: false,
|
||
|
value: "FAILED",
|
||
|
},
|
||
|
];
|
||
|
|
||
|
const getPhase = computed(() => {
|
||
|
if (!props.backup.status?.phase) {
|
||
|
return undefined;
|
||
|
}
|
||
|
return phases.find((phase) => phase.value === props.backup.status?.phase);
|
||
|
});
|
||
|
|
||
|
const getFailureMessage = computed(() => {
|
||
|
const { phase, failureMessage } = props.backup.status || {};
|
||
|
return phase === "FAILED" ? failureMessage : undefined;
|
||
|
});
|
||
|
|
||
|
function handleDownload() {
|
||
|
window.open(
|
||
|
`/apis/api.console.migration.halo.run/v1alpha1/backups/${props.backup.metadata.name}/files/${props.backup.status?.filename}`,
|
||
|
"_blank"
|
||
|
);
|
||
|
}
|
||
|
|
||
|
function handleDelete() {
|
||
|
Dialog.warning({
|
||
|
title: t("core.backup.operations.delete.title"),
|
||
|
description: t("core.backup.operations.delete.description"),
|
||
|
confirmType: "danger",
|
||
|
confirmText: t("core.common.buttons.confirm"),
|
||
|
cancelText: t("core.common.buttons.cancel"),
|
||
|
async onConfirm() {
|
||
|
await apiClient.extension.backup.deletemigrationHaloRunV1alpha1Backup({
|
||
|
name: props.backup.metadata.name,
|
||
|
});
|
||
|
|
||
|
queryClient.invalidateQueries({ queryKey: ["backups"] });
|
||
|
|
||
|
Toast.success(t("core.common.toast.delete_success"));
|
||
|
},
|
||
|
});
|
||
|
}
|
||
![]() |
|
||
![]() |
const { operationItems } = useOperationItemExtensionPoint<Backup>(
|
||
![]() |
"backup:list-item:operation:create",
|
||
![]() |
backup,
|
||
![]() |
computed((): OperationItem<Backup>[] => [
|
||
![]() |
{
|
||
|
priority: 10,
|
||
|
component: markRaw(VDropdownItem),
|
||
|
label: t("core.common.buttons.download"),
|
||
![]() |
hidden: props.backup.status?.phase !== "SUCCEEDED",
|
||
![]() |
permissions: [],
|
||
|
action: () => handleDownload(),
|
||
|
},
|
||
|
{
|
||
|
priority: 20,
|
||
|
component: markRaw(VDropdownItem),
|
||
|
props: {
|
||
|
type: "danger",
|
||
|
},
|
||
|
label: t("core.common.buttons.delete"),
|
||
|
action: () => handleDelete(),
|
||
|
},
|
||
![]() |
])
|
||
![]() |
);
|
||
![]() |
</script>
|
||
|
|
||
|
<template>
|
||
|
<VEntity>
|
||
|
<template #start>
|
||
|
<VEntityField
|
||
|
:title="backup.metadata.name"
|
||
|
:description="backup.status?.filename"
|
||
|
>
|
||
|
<template v-if="backup.status?.filename" #description>
|
||
|
<VSpace class="flex-wrap">
|
||
|
<span class="text-xs text-gray-500">
|
||
|
{{ backup.status?.filename }}
|
||
|
</span>
|
||
|
<span class="text-xs text-gray-500">
|
||
|
{{ prettyBytes(backup.status?.size || 0) }}
|
||
|
</span>
|
||
|
</VSpace>
|
||
|
</template>
|
||
|
</VEntityField>
|
||
|
</template>
|
||
|
<template #end>
|
||
|
<VEntityField v-if="getPhase">
|
||
|
<template #description>
|
||
|
<VStatusDot
|
||
|
v-tooltip="{ content: getFailureMessage }"
|
||
|
:state="getPhase.state"
|
||
|
:text="getPhase.text"
|
||
|
:animate="getPhase.animate"
|
||
|
/>
|
||
|
</template>
|
||
|
</VEntityField>
|
||
|
<VEntityField v-if="backup.metadata.deletionTimestamp">
|
||
|
<template #description>
|
||
|
<VStatusDot
|
||
|
v-tooltip="$t('core.common.status.deleting')"
|
||
|
state="warning"
|
||
|
animate
|
||
|
/>
|
||
|
</template>
|
||
|
</VEntityField>
|
||
|
<VEntityField
|
||
|
v-if="backup.spec?.expiresAt && backup.status?.phase === 'SUCCEEDED'"
|
||
|
>
|
||
|
<template #description>
|
||
|
<span class="truncate text-xs tabular-nums text-gray-500">
|
||
|
{{
|
||
|
$t("core.backup.list.fields.expiresAt", {
|
||
|
expiresAt: relativeTimeTo(backup.spec?.expiresAt),
|
||
|
})
|
||
|
}}
|
||
|
</span>
|
||
|
</template>
|
||
|
</VEntityField>
|
||
|
<VEntityField v-if="backup.metadata.creationTimestamp">
|
||
|
<template #description>
|
||
|
<span class="truncate text-xs tabular-nums text-gray-500">
|
||
|
{{ formatDatetime(backup.metadata.creationTimestamp) }}
|
||
|
</span>
|
||
|
</template>
|
||
|
</VEntityField>
|
||
![]() |
<slot name="end"></slot>
|
||
![]() |
</template>
|
||
![]() |
<template v-if="showOperations" #dropdownItems>
|
||
![]() |
<EntityDropdownItems :dropdown-items="operationItems" :item="backup" />
|
||
![]() |
</template>
|
||
|
</VEntity>
|
||
|
</template>
|