halo/ui/console-src/modules/contents/attachments/components/AttachmentPoliciesModal.vue

237 lines
7.0 KiB
Vue

<script lang="ts" setup>
import { SYSTEM_PROTECTION } from "@/constants/finalizers";
import { formatDatetime } from "@/utils/date";
import type { Policy, PolicyTemplate } from "@halo-dev/api-client";
import { consoleApiClient, coreApiClient } from "@halo-dev/api-client";
import {
Dialog,
IconAddCircle,
Toast,
VButton,
VDropdown,
VDropdownItem,
VEmpty,
VEntity,
VEntityField,
VModal,
VSpace,
VStatusDot,
VTag,
} from "@halo-dev/components";
import { ref } from "vue";
import { useI18n } from "vue-i18n";
import {
useFetchAttachmentPolicy,
useFetchAttachmentPolicyTemplate,
} from "../composables/use-attachment-policy";
import AttachmentPolicyEditingModal from "./AttachmentPolicyEditingModal.vue";
const emit = defineEmits<{
(event: "close"): void;
}>();
const { t } = useI18n();
const { policies, isLoading, handleFetchPolicies } = useFetchAttachmentPolicy();
const { policyTemplates } = useFetchAttachmentPolicyTemplate();
const modal = ref<InstanceType<typeof VModal> | null>(null);
const selectedPolicy = ref<Policy>();
const selectedTemplateName = ref();
const policyEditingModal = ref(false);
const handleOpenEditingModal = (policy: Policy) => {
selectedPolicy.value = policy;
policyEditingModal.value = true;
};
const handleOpenCreateNewPolicyModal = (policyTemplate: PolicyTemplate) => {
selectedTemplateName.value = policyTemplate.metadata.name;
policyEditingModal.value = true;
};
const handleDelete = async (policy: Policy) => {
const { data } = await consoleApiClient.storage.attachment.searchAttachments({
fieldSelector: [`spec.policyName=${policy.metadata.name}`],
});
if (data.total > 0) {
Dialog.warning({
title: t(
"core.attachment.policies_modal.operations.can_not_delete.title"
),
description: t(
"core.attachment.policies_modal.operations.can_not_delete.description"
),
confirmText: t("core.common.buttons.confirm"),
showCancel: false,
});
return;
}
Dialog.warning({
title: t("core.attachment.policies_modal.operations.delete.title"),
description: t(
"core.attachment.policies_modal.operations.delete.description"
),
confirmText: t("core.common.buttons.confirm"),
cancelText: t("core.common.buttons.cancel"),
onConfirm: async () => {
await coreApiClient.storage.policy.deletePolicy({
name: policy.metadata.name,
});
Toast.success(t("core.common.toast.delete_success"));
handleFetchPolicies();
},
});
};
const onEditingModalClose = () => {
selectedPolicy.value = undefined;
selectedTemplateName.value = undefined;
handleFetchPolicies();
policyEditingModal.value = false;
};
function getPolicyTemplateDisplayName(templateName: string) {
const policyTemplate = policyTemplates.value?.find(
(template) => template.metadata.name === templateName
);
return policyTemplate?.spec?.displayName || "--";
}
</script>
<template>
<VModal
ref="modal"
:width="750"
:title="$t('core.attachment.policies_modal.title')"
:body-class="['!p-0']"
:layer-closable="true"
@close="emit('close')"
>
<template #actions>
<VDropdown>
<span v-tooltip="$t('core.common.buttons.new')">
<IconAddCircle />
</span>
<template #popper>
<VDropdownItem
v-for="policyTemplate in policyTemplates"
:key="policyTemplate.metadata.name"
@click="handleOpenCreateNewPolicyModal(policyTemplate)"
>
{{ policyTemplate.spec?.displayName }}
</VDropdownItem>
</template>
</VDropdown>
</template>
<VEmpty
v-if="!policies?.length && !isLoading"
:message="$t('core.attachment.policies_modal.empty.message')"
:title="$t('core.attachment.policies_modal.empty.title')"
>
<template #actions>
<VSpace>
<VButton @click="handleFetchPolicies">
{{ $t("core.common.buttons.refresh") }}
</VButton>
<VDropdown>
<VButton type="secondary">
<template #icon>
<IconAddCircle class="h-full w-full" />
</template>
{{ $t("core.common.buttons.new") }}
</VButton>
<template #popper>
<VDropdownItem
v-for="(policyTemplate, index) in policyTemplates"
:key="index"
@click="handleOpenCreateNewPolicyModal(policyTemplate)"
>
{{ policyTemplate.spec?.displayName }}
</VDropdownItem>
</template>
</VDropdown>
</VSpace>
</template>
</VEmpty>
<ul
v-else
class="box-border h-full w-full divide-y divide-gray-100"
role="list"
>
<li v-for="(policy, index) in policies" :key="index">
<VEntity>
<template #start>
<VEntityField
:title="policy.spec.displayName"
:description="
getPolicyTemplateDisplayName(policy.spec.templateName)
"
></VEntityField>
</template>
<template #end>
<VEntityField>
<template
v-if="policy.metadata.finalizers?.includes(SYSTEM_PROTECTION)"
#description
>
<VTag>{{ $t("core.common.text.system_protection") }}</VTag>
</template>
</VEntityField>
<VEntityField v-if="policy.metadata.deletionTimestamp">
<template #description>
<VStatusDot
v-tooltip="$t('core.common.status.deleting')"
state="warning"
animate
/>
</template>
</VEntityField>
<VEntityField>
<template #description>
<span class="truncate text-xs tabular-nums text-gray-500">
{{ formatDatetime(policy.metadata.creationTimestamp) }}
</span>
</template>
</VEntityField>
</template>
<template #dropdownItems>
<VDropdownItem
:disabled="
policy.metadata.finalizers?.includes(SYSTEM_PROTECTION)
"
@click="handleOpenEditingModal(policy)"
>
{{ $t("core.common.buttons.edit") }}
</VDropdownItem>
<VDropdownItem
:disabled="
policy.metadata.finalizers?.includes(SYSTEM_PROTECTION)
"
type="danger"
@click="handleDelete(policy)"
>
{{ $t("core.common.buttons.delete") }}
</VDropdownItem>
</template>
</VEntity>
</li>
</ul>
<template #footer>
<VButton @click="modal?.close()">
{{ $t("core.common.buttons.close_and_shortcut") }}
</VButton>
</template>
</VModal>
<AttachmentPolicyEditingModal
v-if="policyEditingModal"
:policy="selectedPolicy"
:template-name="selectedTemplateName"
@close="onEditingModalClose"
/>
</template>