mirror of https://github.com/halo-dev/halo-admin
refactor: use tanstack query to refactor attachments-related fetching (#878)
#### What type of PR is this? /kind improvement #### What this PR does / why we need it: 使用 [TanStack Query](https://github.com/TanStack/query) 重构附件相关数据请求的相关逻辑。 #### Which issue(s) this PR fixes: Ref https://github.com/halo-dev/halo/issues/3360 #### Special notes for your reviewer: 测试方式: 1. 测试附件管理页面的筛选、存储策略、分组等业务。 2. 测试附件选择模态框组件。 #### Does this PR introduce a user-facing change? ```release-note None ```pull/879/head
parent
43c5effcd0
commit
0f8e5fad80
|
@ -339,7 +339,7 @@ const editor = useEditor({
|
||||||
});
|
});
|
||||||
|
|
||||||
// image drag and paste upload
|
// image drag and paste upload
|
||||||
const { policies } = useFetchAttachmentPolicy({ fetchOnMounted: true });
|
const { policies } = useFetchAttachmentPolicy();
|
||||||
|
|
||||||
type Task = {
|
type Task = {
|
||||||
file: File;
|
file: File;
|
||||||
|
@ -349,7 +349,7 @@ type Task = {
|
||||||
const uploadQueue: queueAsPromised<Task> = fastq.promise(asyncWorker, 1);
|
const uploadQueue: queueAsPromised<Task> = fastq.promise(asyncWorker, 1);
|
||||||
|
|
||||||
async function asyncWorker(arg: Task): Promise<void> {
|
async function asyncWorker(arg: Task): Promise<void> {
|
||||||
if (!policies.value.length) {
|
if (!policies.value?.length) {
|
||||||
Toast.warning("目前没有可用的存储策略");
|
Toast.warning("目前没有可用的存储策略");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,10 +51,8 @@ const policyVisible = ref(false);
|
||||||
const uploadVisible = ref(false);
|
const uploadVisible = ref(false);
|
||||||
const detailVisible = ref(false);
|
const detailVisible = ref(false);
|
||||||
|
|
||||||
const { policies } = useFetchAttachmentPolicy({ fetchOnMounted: true });
|
const { policies } = useFetchAttachmentPolicy();
|
||||||
const { groups, handleFetchGroups } = useFetchAttachmentGroup({
|
const { groups, handleFetchGroups } = useFetchAttachmentGroup();
|
||||||
fetchOnMounted: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const selectedGroup = ref<Group>();
|
const selectedGroup = ref<Group>();
|
||||||
|
|
||||||
|
@ -85,26 +83,24 @@ const SortItems: SortItem[] = [
|
||||||
|
|
||||||
const selectedPolicy = ref<Policy>();
|
const selectedPolicy = ref<Policy>();
|
||||||
const selectedUser = ref<User>();
|
const selectedUser = ref<User>();
|
||||||
const keyword = ref<string>("");
|
|
||||||
const selectedSortItem = ref<SortItem>();
|
const selectedSortItem = ref<SortItem>();
|
||||||
|
|
||||||
const selectedSortItemValue = computed(() => {
|
const selectedSortItemValue = computed(() => {
|
||||||
return selectedSortItem.value?.value;
|
return selectedSortItem.value?.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
function handleSelectPolicy(policy: Policy | undefined) {
|
function handleSelectPolicy(policy: Policy | undefined) {
|
||||||
selectedPolicy.value = policy;
|
selectedPolicy.value = policy;
|
||||||
handleFetchAttachments({ page: 1 });
|
page.value = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSelectUser(user: User | undefined) {
|
function handleSelectUser(user: User | undefined) {
|
||||||
selectedUser.value = user;
|
selectedUser.value = user;
|
||||||
handleFetchAttachments({ page: 1 });
|
page.value = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSortItemChange(sortItem?: SortItem) {
|
function handleSortItemChange(sortItem?: SortItem) {
|
||||||
selectedSortItem.value = sortItem;
|
selectedSortItem.value = sortItem;
|
||||||
handleFetchAttachments({ page: 1 });
|
page.value = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleKeywordChange() {
|
function handleKeywordChange() {
|
||||||
|
@ -112,12 +108,12 @@ function handleKeywordChange() {
|
||||||
if (keywordNode) {
|
if (keywordNode) {
|
||||||
keyword.value = keywordNode._value as string;
|
keyword.value = keywordNode._value as string;
|
||||||
}
|
}
|
||||||
handleFetchAttachments({ page: 1 });
|
page.value = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleClearKeyword() {
|
function handleClearKeyword() {
|
||||||
keyword.value = "";
|
keyword.value = "";
|
||||||
handleFetchAttachments({ page: 1 });
|
page.value = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasFilters = computed(() => {
|
const hasFilters = computed(() => {
|
||||||
|
@ -134,19 +130,24 @@ function handleClearFilters() {
|
||||||
selectedUser.value = undefined;
|
selectedUser.value = undefined;
|
||||||
selectedSortItem.value = undefined;
|
selectedSortItem.value = undefined;
|
||||||
keyword.value = "";
|
keyword.value = "";
|
||||||
handleFetchAttachments({ page: 1 });
|
page.value = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const keyword = ref<string>("");
|
||||||
|
const page = ref<number>(1);
|
||||||
|
const size = ref<number>(20);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
attachments,
|
attachments,
|
||||||
selectedAttachment,
|
selectedAttachment,
|
||||||
selectedAttachments,
|
selectedAttachments,
|
||||||
checkedAll,
|
checkedAll,
|
||||||
loading,
|
isLoading,
|
||||||
|
isFetching,
|
||||||
|
total,
|
||||||
handleFetchAttachments,
|
handleFetchAttachments,
|
||||||
handleSelectNext,
|
handleSelectNext,
|
||||||
handleSelectPrevious,
|
handleSelectPrevious,
|
||||||
handlePaginationChange,
|
|
||||||
handleDelete,
|
handleDelete,
|
||||||
handleDeleteInBatch,
|
handleDeleteInBatch,
|
||||||
handleCheckAll,
|
handleCheckAll,
|
||||||
|
@ -159,6 +160,8 @@ const {
|
||||||
user: selectedUser,
|
user: selectedUser,
|
||||||
keyword: keyword,
|
keyword: keyword,
|
||||||
sort: selectedSortItemValue,
|
sort: selectedSortItemValue,
|
||||||
|
page: page,
|
||||||
|
size: size,
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleMove = async (group: Group) => {
|
const handleMove = async (group: Group) => {
|
||||||
|
@ -209,21 +212,16 @@ const onDetailModalClose = () => {
|
||||||
selectedAttachment.value = undefined;
|
selectedAttachment.value = undefined;
|
||||||
nameQuery.value = undefined;
|
nameQuery.value = undefined;
|
||||||
nameQueryAttachment.value = undefined;
|
nameQueryAttachment.value = undefined;
|
||||||
handleFetchAttachments({ mute: true });
|
handleFetchAttachments();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onUploadModalClose = () => {
|
const onUploadModalClose = () => {
|
||||||
routeQueryAction.value = undefined;
|
routeQueryAction.value = undefined;
|
||||||
handleFetchAttachments({ mute: true });
|
|
||||||
};
|
|
||||||
|
|
||||||
const onGroupChange = () => {
|
|
||||||
handleReset();
|
|
||||||
handleFetchAttachments();
|
handleFetchAttachments();
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPolicyName = (name: string | undefined) => {
|
const getPolicyName = (name: string | undefined) => {
|
||||||
const policy = policies.value.find((p) => p.metadata.name === name);
|
const policy = policies.value?.find((p) => p.metadata.name === name);
|
||||||
return policy?.spec.displayName;
|
return policy?.spec.displayName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -548,7 +546,7 @@ onMounted(() => {
|
||||||
>
|
>
|
||||||
<IconRefreshLine
|
<IconRefreshLine
|
||||||
v-tooltip="`刷新`"
|
v-tooltip="`刷新`"
|
||||||
:class="{ 'animate-spin text-gray-900': loading }"
|
:class="{ 'animate-spin text-gray-900': isFetching }"
|
||||||
class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
|
class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -562,15 +560,15 @@ onMounted(() => {
|
||||||
<div :style="`${viewType === 'list' ? 'padding:12px 16px 0' : ''}`">
|
<div :style="`${viewType === 'list' ? 'padding:12px 16px 0' : ''}`">
|
||||||
<AttachmentGroupList
|
<AttachmentGroupList
|
||||||
v-model:selected-group="selectedGroup"
|
v-model:selected-group="selectedGroup"
|
||||||
@select="onGroupChange"
|
@select="handleReset"
|
||||||
@update="handleFetchGroups"
|
@update="handleFetchGroups"
|
||||||
@reload-attachments="handleFetchAttachments"
|
@reload-attachments="handleFetchAttachments"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<VLoading v-if="loading" />
|
<VLoading v-if="isLoading" />
|
||||||
|
|
||||||
<Transition v-else-if="!attachments.total" appear name="fade">
|
<Transition v-else-if="!attachments?.length" appear name="fade">
|
||||||
<VEmpty
|
<VEmpty
|
||||||
message="当前分组没有附件,你可以尝试刷新或者上传附件"
|
message="当前分组没有附件,你可以尝试刷新或者上传附件"
|
||||||
title="当前分组没有附件"
|
title="当前分组没有附件"
|
||||||
|
@ -600,7 +598,7 @@ onMounted(() => {
|
||||||
role="list"
|
role="list"
|
||||||
>
|
>
|
||||||
<VCard
|
<VCard
|
||||||
v-for="(attachment, index) in attachments.items"
|
v-for="(attachment, index) in attachments"
|
||||||
:key="index"
|
:key="index"
|
||||||
:body-class="['!p-0']"
|
:body-class="['!p-0']"
|
||||||
:class="{
|
:class="{
|
||||||
|
@ -680,10 +678,7 @@ onMounted(() => {
|
||||||
class="box-border h-full w-full divide-y divide-gray-100"
|
class="box-border h-full w-full divide-y divide-gray-100"
|
||||||
role="list"
|
role="list"
|
||||||
>
|
>
|
||||||
<li
|
<li v-for="(attachment, index) in attachments" :key="index">
|
||||||
v-for="(attachment, index) in attachments.items"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
<VEntity :is-selected="isChecked(attachment)">
|
<VEntity :is-selected="isChecked(attachment)">
|
||||||
<template
|
<template
|
||||||
v-if="
|
v-if="
|
||||||
|
@ -797,11 +792,10 @@ onMounted(() => {
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="bg-white sm:flex sm:items-center sm:justify-end">
|
<div class="bg-white sm:flex sm:items-center sm:justify-end">
|
||||||
<VPagination
|
<VPagination
|
||||||
:page="attachments.page"
|
v-model:page="page"
|
||||||
:size="attachments.size"
|
v-model:size="size"
|
||||||
:total="attachments.total"
|
:total="total"
|
||||||
:size-options="[60, 120, 200]"
|
:size-options="[60, 120, 200]"
|
||||||
@change="handlePaginationChange"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { VButton, VModal, VSpace, VTag } from "@halo-dev/components";
|
import { VButton, VModal, VSpace, VTag } from "@halo-dev/components";
|
||||||
import LazyImage from "@/components/image/LazyImage.vue";
|
import LazyImage from "@/components/image/LazyImage.vue";
|
||||||
import type { Attachment, Policy } from "@halo-dev/api-client";
|
import type { Attachment } from "@halo-dev/api-client";
|
||||||
import prettyBytes from "pretty-bytes";
|
import prettyBytes from "pretty-bytes";
|
||||||
import { ref, watch, watchEffect } from "vue";
|
import { computed, ref } from "vue";
|
||||||
import { apiClient } from "@/utils/api-client";
|
import { apiClient } from "@/utils/api-client";
|
||||||
import { isImage } from "@/utils/image";
|
import { isImage } from "@/utils/image";
|
||||||
import { formatDatetime } from "@/utils/date";
|
import { formatDatetime } from "@/utils/date";
|
||||||
import { useFetchAttachmentGroup } from "../composables/use-attachment-group";
|
import { useFetchAttachmentGroup } from "../composables/use-attachment-group";
|
||||||
|
import { useQuery } from "@tanstack/vue-query";
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
@ -27,43 +28,40 @@ const emit = defineEmits<{
|
||||||
(event: "close"): void;
|
(event: "close"): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { groups, handleFetchGroups } = useFetchAttachmentGroup();
|
const { groups } = useFetchAttachmentGroup();
|
||||||
|
|
||||||
const policy = ref<Policy>();
|
|
||||||
const onlyPreview = ref(false);
|
const onlyPreview = ref(false);
|
||||||
|
|
||||||
watchEffect(async () => {
|
const policyName = computed(() => {
|
||||||
if (props.attachment) {
|
return props.attachment?.spec.policyName;
|
||||||
const { policyName } = props.attachment.spec;
|
});
|
||||||
if (!policyName) {
|
|
||||||
|
const { data: policy } = useQuery({
|
||||||
|
queryKey: ["attachment-policy", policyName],
|
||||||
|
queryFn: async () => {
|
||||||
|
if (!policyName.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data } =
|
const { data } =
|
||||||
await apiClient.extension.storage.policy.getstorageHaloRunV1alpha1Policy({
|
await apiClient.extension.storage.policy.getstorageHaloRunV1alpha1Policy({
|
||||||
name: policyName,
|
name: policyName.value,
|
||||||
});
|
|
||||||
policy.value = data;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
return data;
|
||||||
() => props.visible,
|
},
|
||||||
(newValue) => {
|
refetchOnWindowFocus: false,
|
||||||
if (newValue) {
|
enabled: computed(() => !!policyName.value),
|
||||||
handleFetchGroups();
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const getGroupName = (name: string | undefined) => {
|
const getGroupName = (name: string | undefined) => {
|
||||||
const group = groups.value.find((group) => group.metadata.name === name);
|
const group = groups.value?.find((group) => group.metadata.name === name);
|
||||||
return group?.spec.displayName || name;
|
return group?.spec.displayName || name;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onVisibleChange = (visible: boolean) => {
|
const onVisibleChange = (visible: boolean) => {
|
||||||
emit("update:visible", visible);
|
emit("update:visible", visible);
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
policy.value = undefined;
|
|
||||||
onlyPreview.value = false;
|
onlyPreview.value = false;
|
||||||
emit("close");
|
emit("close");
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,9 +163,9 @@ const handleDeleteWithAttachments = (group: Group) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => groups.value.length,
|
() => groups.value?.length,
|
||||||
() => {
|
() => {
|
||||||
const allGroups = [...defaultGroups, ...groups.value];
|
const allGroups = [...defaultGroups, ...(groups.value || [])];
|
||||||
const groupIndex = allGroups.findIndex(
|
const groupIndex = allGroups.findIndex(
|
||||||
(group) => group.metadata.name === routeQuery.value
|
(group) => group.metadata.name === routeQuery.value
|
||||||
);
|
);
|
||||||
|
@ -178,9 +178,8 @@ watch(
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await handleFetchGroups();
|
await handleFetchGroups();
|
||||||
|
|
||||||
if (routeQuery.value && !props.readonly) {
|
if (routeQuery.value && !props.readonly) {
|
||||||
const allGroups = [...defaultGroups, ...groups.value];
|
const allGroups = [...defaultGroups, ...(groups.value || [])];
|
||||||
const group = allGroups.find(
|
const group = allGroups.find(
|
||||||
(group) => group.metadata.name === routeQuery.value
|
(group) => group.metadata.name === routeQuery.value
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {
|
||||||
Toast,
|
Toast,
|
||||||
} from "@halo-dev/components";
|
} from "@halo-dev/components";
|
||||||
import AttachmentPolicyEditingModal from "./AttachmentPolicyEditingModal.vue";
|
import AttachmentPolicyEditingModal from "./AttachmentPolicyEditingModal.vue";
|
||||||
import { ref, watch } from "vue";
|
import { ref } from "vue";
|
||||||
import type { Policy, PolicyTemplate } from "@halo-dev/api-client";
|
import type { Policy, PolicyTemplate } from "@halo-dev/api-client";
|
||||||
import { formatDatetime } from "@/utils/date";
|
import { formatDatetime } from "@/utils/date";
|
||||||
import {
|
import {
|
||||||
|
@ -21,7 +21,7 @@ import {
|
||||||
} from "../composables/use-attachment-policy";
|
} from "../composables/use-attachment-policy";
|
||||||
import { apiClient } from "@/utils/api-client";
|
import { apiClient } from "@/utils/api-client";
|
||||||
|
|
||||||
const props = withDefaults(
|
withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
}>(),
|
}>(),
|
||||||
|
@ -35,11 +35,8 @@ const emit = defineEmits<{
|
||||||
(event: "close"): void;
|
(event: "close"): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { policies, loading, handleFetchPolicies } = useFetchAttachmentPolicy();
|
const { policies, isLoading, handleFetchPolicies } = useFetchAttachmentPolicy();
|
||||||
const { policyTemplates, handleFetchPolicyTemplates } =
|
const { policyTemplates } = useFetchAttachmentPolicyTemplate();
|
||||||
useFetchAttachmentPolicyTemplate({
|
|
||||||
fetchOnMounted: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const selectedPolicy = ref<Policy>();
|
const selectedPolicy = ref<Policy>();
|
||||||
|
|
||||||
|
@ -105,16 +102,6 @@ const onEditingModalClose = () => {
|
||||||
selectedPolicy.value = undefined;
|
selectedPolicy.value = undefined;
|
||||||
handleFetchPolicies();
|
handleFetchPolicies();
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(visible) => {
|
|
||||||
if (visible) {
|
|
||||||
handleFetchPolicyTemplates();
|
|
||||||
handleFetchPolicies();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VModal
|
<VModal
|
||||||
|
@ -150,7 +137,7 @@ watch(
|
||||||
</FloatingDropdown>
|
</FloatingDropdown>
|
||||||
</template>
|
</template>
|
||||||
<VEmpty
|
<VEmpty
|
||||||
v-if="!policies.length && !loading"
|
v-if="!policies?.length && !isLoading"
|
||||||
message="当前没有可用的存储策略,你可以尝试刷新或者新建策略"
|
message="当前没有可用的存储策略,你可以尝试刷新或者新建策略"
|
||||||
title="当前没有可用的存储策略"
|
title="当前没有可用的存储策略"
|
||||||
>
|
>
|
||||||
|
|
|
@ -25,14 +25,9 @@ const emit = defineEmits<{
|
||||||
(event: "close"): void;
|
(event: "close"): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { groups, handleFetchGroups } = useFetchAttachmentGroup({
|
const { groups } = useFetchAttachmentGroup();
|
||||||
fetchOnMounted: false,
|
const { policies, handleFetchPolicies } = useFetchAttachmentPolicy();
|
||||||
});
|
const { policyTemplates } = useFetchAttachmentPolicyTemplate();
|
||||||
const { policies, handleFetchPolicies } = useFetchAttachmentPolicy({
|
|
||||||
fetchOnMounted: false,
|
|
||||||
});
|
|
||||||
const { policyTemplates, handleFetchPolicyTemplates } =
|
|
||||||
useFetchAttachmentPolicyTemplate();
|
|
||||||
|
|
||||||
const selectedGroupName = useLocalStorage("attachment-upload-group", "");
|
const selectedGroupName = useLocalStorage("attachment-upload-group", "");
|
||||||
const selectedPolicyName = useLocalStorage("attachment-upload-policy", "");
|
const selectedPolicyName = useLocalStorage("attachment-upload-policy", "");
|
||||||
|
@ -45,12 +40,13 @@ watch(
|
||||||
() => {
|
() => {
|
||||||
if (selectedGroupName.value === "") return;
|
if (selectedGroupName.value === "") return;
|
||||||
|
|
||||||
const group = groups.value.find(
|
const group = groups.value?.find(
|
||||||
(group) => group.metadata.name === selectedGroupName.value
|
(group) => group.metadata.name === selectedGroupName.value
|
||||||
);
|
);
|
||||||
if (!group) {
|
if (!group) {
|
||||||
selectedGroupName.value =
|
selectedGroupName.value = groups.value?.length
|
||||||
groups.value.length > 0 ? groups.value[0].metadata.name : "";
|
? groups.value[0].metadata.name
|
||||||
|
: "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -58,12 +54,13 @@ watch(
|
||||||
watch(
|
watch(
|
||||||
() => policies.value,
|
() => policies.value,
|
||||||
() => {
|
() => {
|
||||||
const policy = policies.value.find(
|
const policy = policies.value?.find(
|
||||||
(policy) => policy.metadata.name === selectedPolicyName.value
|
(policy) => policy.metadata.name === selectedPolicyName.value
|
||||||
);
|
);
|
||||||
if (!policy) {
|
if (!policy) {
|
||||||
selectedPolicyName.value =
|
selectedPolicyName.value = policies.value?.length
|
||||||
policies.value.length > 0 ? policies.value[0].metadata.name : "";
|
? policies.value[0].metadata.name
|
||||||
|
: "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -87,7 +84,7 @@ const handleOpenCreateNewPolicyModal = (policyTemplate: PolicyTemplate) => {
|
||||||
|
|
||||||
const onEditingModalClose = async () => {
|
const onEditingModalClose = async () => {
|
||||||
await handleFetchPolicies();
|
await handleFetchPolicies();
|
||||||
policyToCreate.value = policies.value[0];
|
policyToCreate.value = policies.value?.[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
const onVisibleChange = (visible: boolean) => {
|
const onVisibleChange = (visible: boolean) => {
|
||||||
|
@ -102,9 +99,6 @@ watch(
|
||||||
() => props.visible,
|
() => props.visible,
|
||||||
(newValue) => {
|
(newValue) => {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
handleFetchGroups();
|
|
||||||
handleFetchPolicies();
|
|
||||||
handleFetchPolicyTemplates();
|
|
||||||
uploadVisible.value = true;
|
uploadVisible.value = true;
|
||||||
} else {
|
} else {
|
||||||
const uploadVisibleTimer = setTimeout(() => {
|
const uploadVisibleTimer = setTimeout(() => {
|
||||||
|
@ -131,7 +125,7 @@ watch(
|
||||||
<div
|
<div
|
||||||
v-for="(group, index) in [
|
v-for="(group, index) in [
|
||||||
{ metadata: { name: '' }, spec: { displayName: '未分组' } },
|
{ metadata: { name: '' }, spec: { displayName: '未分组' } },
|
||||||
...groups,
|
...(groups || []),
|
||||||
]"
|
]"
|
||||||
:key="index"
|
:key="index"
|
||||||
:class="{
|
:class="{
|
||||||
|
@ -200,7 +194,7 @@ watch(
|
||||||
</template>
|
</template>
|
||||||
</FloatingDropdown>
|
</FloatingDropdown>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="policies.length <= 0" class="mb-3">
|
<div v-if="!policies?.length" class="mb-3">
|
||||||
<VAlert
|
<VAlert
|
||||||
title="没有存储策略"
|
title="没有存储策略"
|
||||||
description="在上传之前,需要新建一个存储策略"
|
description="在上传之前,需要新建一个存储策略"
|
||||||
|
|
|
@ -38,20 +38,22 @@ const emit = defineEmits<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const selectedGroup = ref<Group>();
|
const selectedGroup = ref<Group>();
|
||||||
|
const page = ref(1);
|
||||||
|
const size = ref(60);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
attachments,
|
attachments,
|
||||||
loading,
|
isLoading,
|
||||||
|
total,
|
||||||
selectedAttachment,
|
selectedAttachment,
|
||||||
selectedAttachments,
|
selectedAttachments,
|
||||||
handleFetchAttachments,
|
handleFetchAttachments,
|
||||||
handlePaginationChange,
|
|
||||||
handleSelect,
|
handleSelect,
|
||||||
handleSelectPrevious,
|
handleSelectPrevious,
|
||||||
handleSelectNext,
|
handleSelectNext,
|
||||||
handleReset,
|
handleReset,
|
||||||
isChecked,
|
isChecked,
|
||||||
} = useAttachmentControl({ group: selectedGroup });
|
} = useAttachmentControl({ group: selectedGroup, page, size });
|
||||||
|
|
||||||
const uploadVisible = ref(false);
|
const uploadVisible = ref(false);
|
||||||
const detailVisible = ref(false);
|
const detailVisible = ref(false);
|
||||||
|
@ -64,21 +66,14 @@ const handleOpenDetail = (attachment: Attachment) => {
|
||||||
selectedAttachment.value = attachment;
|
selectedAttachment.value = attachment;
|
||||||
detailVisible.value = true;
|
detailVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onGroupChange = () => {
|
|
||||||
handleReset();
|
|
||||||
handleFetchAttachments();
|
|
||||||
};
|
|
||||||
|
|
||||||
await handleFetchAttachments();
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<AttachmentGroupList
|
<AttachmentGroupList
|
||||||
v-model:selected-group="selectedGroup"
|
v-model:selected-group="selectedGroup"
|
||||||
readonly
|
readonly
|
||||||
@select="onGroupChange"
|
@select="handleReset"
|
||||||
/>
|
/>
|
||||||
<div v-if="attachments.total > 0" class="mb-5">
|
<div v-if="attachments?.length" class="mb-5">
|
||||||
<VButton @click="uploadVisible = true">
|
<VButton @click="uploadVisible = true">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<IconUpload class="h-full w-full" />
|
<IconUpload class="h-full w-full" />
|
||||||
|
@ -87,7 +82,7 @@ await handleFetchAttachments();
|
||||||
</VButton>
|
</VButton>
|
||||||
</div>
|
</div>
|
||||||
<VEmpty
|
<VEmpty
|
||||||
v-if="!attachments.total && !loading"
|
v-if="!attachments?.length && !isLoading"
|
||||||
message="当前没有附件,你可以尝试刷新或者上传附件"
|
message="当前没有附件,你可以尝试刷新或者上传附件"
|
||||||
title="当前没有附件"
|
title="当前没有附件"
|
||||||
>
|
>
|
||||||
|
@ -109,7 +104,7 @@ await handleFetchAttachments();
|
||||||
role="list"
|
role="list"
|
||||||
>
|
>
|
||||||
<VCard
|
<VCard
|
||||||
v-for="(attachment, index) in attachments.items"
|
v-for="(attachment, index) in attachments"
|
||||||
:key="index"
|
:key="index"
|
||||||
:body-class="['!p-0']"
|
:body-class="['!p-0']"
|
||||||
:class="{
|
:class="{
|
||||||
|
@ -171,11 +166,10 @@ await handleFetchAttachments();
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4 bg-white sm:flex sm:items-center sm:justify-end">
|
<div class="mt-4 bg-white sm:flex sm:items-center sm:justify-end">
|
||||||
<VPagination
|
<VPagination
|
||||||
:page="attachments.page"
|
v-model:page="page"
|
||||||
:size="attachments.size"
|
v-model:size="size"
|
||||||
:total="attachments.total"
|
:total="total"
|
||||||
:size-options="[60, 120, 200]"
|
:size-options="[60, 120, 200]"
|
||||||
@change="handlePaginationChange"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<AttachmentUploadModal
|
<AttachmentUploadModal
|
||||||
|
|
|
@ -1,58 +1,35 @@
|
||||||
import { onMounted, onUnmounted, ref, type Ref } from "vue";
|
import type { Ref } from "vue";
|
||||||
import type { Group } from "@halo-dev/api-client";
|
import type { Group } from "@halo-dev/api-client";
|
||||||
import { apiClient } from "@/utils/api-client";
|
import { apiClient } from "@/utils/api-client";
|
||||||
|
import { useQuery } from "@tanstack/vue-query";
|
||||||
|
|
||||||
interface useFetchAttachmentGroupReturn {
|
interface useFetchAttachmentGroupReturn {
|
||||||
groups: Ref<Group[]>;
|
groups: Ref<Group[] | undefined>;
|
||||||
loading: Ref<boolean>;
|
isLoading: Ref<boolean>;
|
||||||
handleFetchGroups: () => void;
|
handleFetchGroups: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useFetchAttachmentGroup(options?: {
|
export function useFetchAttachmentGroup(): useFetchAttachmentGroupReturn {
|
||||||
fetchOnMounted: boolean;
|
const { data, isLoading, refetch } = useQuery<Group[]>({
|
||||||
}): useFetchAttachmentGroupReturn {
|
queryKey: ["attachment-groups"],
|
||||||
const { fetchOnMounted } = options || {};
|
queryFn: async () => {
|
||||||
|
|
||||||
const groups = ref<Group[]>([] as Group[]);
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
const refreshInterval = ref();
|
|
||||||
|
|
||||||
const handleFetchGroups = async () => {
|
|
||||||
try {
|
|
||||||
clearInterval(refreshInterval.value);
|
|
||||||
|
|
||||||
loading.value = true;
|
|
||||||
const { data } =
|
const { data } =
|
||||||
await apiClient.extension.storage.group.liststorageHaloRunV1alpha1Group();
|
await apiClient.extension.storage.group.liststorageHaloRunV1alpha1Group();
|
||||||
groups.value = data.items;
|
return data.items;
|
||||||
|
},
|
||||||
const deletedGroups = groups.value.filter(
|
refetchInterval(data) {
|
||||||
|
const deletingGroups = data?.filter(
|
||||||
(group) => !!group.metadata.deletionTimestamp
|
(group) => !!group.metadata.deletionTimestamp
|
||||||
);
|
);
|
||||||
|
|
||||||
if (deletedGroups.length) {
|
return deletingGroups?.length ? 1000 : false;
|
||||||
refreshInterval.value = setInterval(() => {
|
},
|
||||||
handleFetchGroups();
|
refetchOnWindowFocus: false,
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Failed to fetch attachment groups", e);
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
fetchOnMounted && handleFetchGroups();
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
clearInterval(refreshInterval.value);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
groups,
|
groups: data,
|
||||||
loading,
|
isLoading,
|
||||||
handleFetchGroups,
|
handleFetchGroups: refetch,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,97 +1,58 @@
|
||||||
import { onMounted, onUnmounted, ref } from "vue";
|
|
||||||
import type { Ref } from "vue";
|
import type { Ref } from "vue";
|
||||||
import type { Policy, PolicyTemplate } from "@halo-dev/api-client";
|
import type { Policy, PolicyTemplate } from "@halo-dev/api-client";
|
||||||
import { apiClient } from "@/utils/api-client";
|
import { apiClient } from "@/utils/api-client";
|
||||||
|
import { useQuery } from "@tanstack/vue-query";
|
||||||
|
|
||||||
interface useFetchAttachmentPolicyReturn {
|
interface useFetchAttachmentPolicyReturn {
|
||||||
policies: Ref<Policy[]>;
|
policies: Ref<Policy[] | undefined>;
|
||||||
loading: Ref<boolean>;
|
isLoading: Ref<boolean>;
|
||||||
handleFetchPolicies: () => void;
|
handleFetchPolicies: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface useFetchAttachmentPolicyTemplatesReturn {
|
interface useFetchAttachmentPolicyTemplatesReturn {
|
||||||
policyTemplates: Ref<PolicyTemplate[]>;
|
policyTemplates: Ref<PolicyTemplate[] | undefined>;
|
||||||
loading: Ref<boolean>;
|
isLoading: Ref<boolean>;
|
||||||
handleFetchPolicyTemplates: () => void;
|
handleFetchPolicyTemplates: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useFetchAttachmentPolicy(options?: {
|
export function useFetchAttachmentPolicy(): useFetchAttachmentPolicyReturn {
|
||||||
fetchOnMounted: boolean;
|
const { data, isLoading, refetch } = useQuery<Policy[]>({
|
||||||
}): useFetchAttachmentPolicyReturn {
|
queryKey: ["attachment-policies"],
|
||||||
const { fetchOnMounted } = options || {};
|
queryFn: async () => {
|
||||||
|
|
||||||
const policies = ref<Policy[]>([] as Policy[]);
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
const refreshInterval = ref();
|
|
||||||
|
|
||||||
const handleFetchPolicies = async () => {
|
|
||||||
try {
|
|
||||||
clearInterval(refreshInterval.value);
|
|
||||||
|
|
||||||
loading.value = true;
|
|
||||||
const { data } =
|
const { data } =
|
||||||
await apiClient.extension.storage.policy.liststorageHaloRunV1alpha1Policy();
|
await apiClient.extension.storage.policy.liststorageHaloRunV1alpha1Policy();
|
||||||
policies.value = data.items;
|
return data.items;
|
||||||
|
},
|
||||||
const deletedPolicies = policies.value.filter(
|
refetchInterval(data) {
|
||||||
|
const deletingPolicies = data?.filter(
|
||||||
(policy) => !!policy.metadata.deletionTimestamp
|
(policy) => !!policy.metadata.deletionTimestamp
|
||||||
);
|
);
|
||||||
|
return deletingPolicies?.length ? 1000 : false;
|
||||||
if (deletedPolicies.length) {
|
},
|
||||||
refreshInterval.value = setInterval(() => {
|
refetchOnWindowFocus: false,
|
||||||
handleFetchPolicies();
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Failed to fetch attachment policies", e);
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
fetchOnMounted && handleFetchPolicies();
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
clearInterval(refreshInterval.value);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
policies,
|
policies: data,
|
||||||
loading,
|
isLoading,
|
||||||
handleFetchPolicies,
|
handleFetchPolicies: refetch,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useFetchAttachmentPolicyTemplate(options?: {
|
export function useFetchAttachmentPolicyTemplate(): useFetchAttachmentPolicyTemplatesReturn {
|
||||||
fetchOnMounted: boolean;
|
const { data, isLoading, refetch } = useQuery<PolicyTemplate[]>({
|
||||||
}): useFetchAttachmentPolicyTemplatesReturn {
|
queryKey: ["attachment-policy-templates"],
|
||||||
const { fetchOnMounted } = options || {};
|
queryFn: async () => {
|
||||||
|
|
||||||
const policyTemplates = ref<PolicyTemplate[]>([] as PolicyTemplate[]);
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
|
|
||||||
const handleFetchPolicyTemplates = async () => {
|
|
||||||
try {
|
|
||||||
loading.value = true;
|
|
||||||
const { data } =
|
const { data } =
|
||||||
await apiClient.extension.storage.policyTemplate.liststorageHaloRunV1alpha1PolicyTemplate();
|
await apiClient.extension.storage.policyTemplate.liststorageHaloRunV1alpha1PolicyTemplate();
|
||||||
policyTemplates.value = data.items;
|
return data.items;
|
||||||
} catch (e) {
|
},
|
||||||
console.error("Failed to fetch attachment policy templates", e);
|
refetchOnWindowFocus: false,
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
fetchOnMounted && handleFetchPolicyTemplates();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
policyTemplates,
|
policyTemplates: data,
|
||||||
loading,
|
isLoading,
|
||||||
handleFetchPolicyTemplates,
|
handleFetchPolicyTemplates: refetch,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +1,21 @@
|
||||||
import type {
|
import type { Attachment, Group, Policy, User } from "@halo-dev/api-client";
|
||||||
Attachment,
|
|
||||||
AttachmentList,
|
|
||||||
Group,
|
|
||||||
Policy,
|
|
||||||
User,
|
|
||||||
} from "@halo-dev/api-client";
|
|
||||||
import type { Ref } from "vue";
|
import type { Ref } from "vue";
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import type { AttachmentLike } from "@halo-dev/console-shared";
|
import type { AttachmentLike } from "@halo-dev/console-shared";
|
||||||
import { apiClient } from "@/utils/api-client";
|
import { apiClient } from "@/utils/api-client";
|
||||||
import { Dialog, Toast } from "@halo-dev/components";
|
import { Dialog, Toast } from "@halo-dev/components";
|
||||||
import type { Content, Editor } from "@halo-dev/richtext-editor";
|
import type { Content, Editor } from "@halo-dev/richtext-editor";
|
||||||
import { onBeforeRouteLeave } from "vue-router";
|
import { useQuery } from "@tanstack/vue-query";
|
||||||
|
|
||||||
interface useAttachmentControlReturn {
|
interface useAttachmentControlReturn {
|
||||||
attachments: Ref<AttachmentList>;
|
attachments: Ref<Attachment[] | undefined>;
|
||||||
loading: Ref<boolean>;
|
isLoading: Ref<boolean>;
|
||||||
|
isFetching: Ref<boolean>;
|
||||||
selectedAttachment: Ref<Attachment | undefined>;
|
selectedAttachment: Ref<Attachment | undefined>;
|
||||||
selectedAttachments: Ref<Set<Attachment>>;
|
selectedAttachments: Ref<Set<Attachment>>;
|
||||||
checkedAll: Ref<boolean>;
|
checkedAll: Ref<boolean>;
|
||||||
handleFetchAttachments: (options?: { mute?: boolean; page?: number }) => void;
|
total: Ref<number>;
|
||||||
handlePaginationChange: ({
|
handleFetchAttachments: () => void;
|
||||||
page,
|
|
||||||
size,
|
|
||||||
}: {
|
|
||||||
page: number;
|
|
||||||
size: number;
|
|
||||||
}) => void;
|
|
||||||
handleSelectPrevious: () => void;
|
handleSelectPrevious: () => void;
|
||||||
handleSelectNext: () => void;
|
handleSelectNext: () => void;
|
||||||
handleDelete: (attachment: Attachment) => void;
|
handleDelete: (attachment: Attachment) => void;
|
||||||
|
@ -41,124 +30,95 @@ interface useAttachmentSelectReturn {
|
||||||
onAttachmentSelect: (attachments: AttachmentLike[]) => void;
|
onAttachmentSelect: (attachments: AttachmentLike[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useAttachmentControl(filterOptions?: {
|
export function useAttachmentControl(filterOptions: {
|
||||||
policy?: Ref<Policy | undefined>;
|
policy?: Ref<Policy | undefined>;
|
||||||
group?: Ref<Group | undefined>;
|
group?: Ref<Group | undefined>;
|
||||||
user?: Ref<User | undefined>;
|
user?: Ref<User | undefined>;
|
||||||
keyword?: Ref<string | undefined>;
|
keyword?: Ref<string | undefined>;
|
||||||
sort?: Ref<string | undefined>;
|
sort?: Ref<string | undefined>;
|
||||||
|
page: Ref<number>;
|
||||||
|
size: Ref<number>;
|
||||||
}): useAttachmentControlReturn {
|
}): useAttachmentControlReturn {
|
||||||
const { user, policy, group, keyword, sort } = filterOptions || {};
|
const { user, policy, group, keyword, sort, page, size } = filterOptions;
|
||||||
|
|
||||||
const attachments = ref<AttachmentList>({
|
|
||||||
page: 1,
|
|
||||||
size: 60,
|
|
||||||
total: 0,
|
|
||||||
items: [],
|
|
||||||
first: true,
|
|
||||||
last: false,
|
|
||||||
hasNext: false,
|
|
||||||
hasPrevious: false,
|
|
||||||
totalPages: 0,
|
|
||||||
});
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
|
|
||||||
const selectedAttachment = ref<Attachment>();
|
const selectedAttachment = ref<Attachment>();
|
||||||
const selectedAttachments = ref<Set<Attachment>>(new Set<Attachment>());
|
const selectedAttachments = ref<Set<Attachment>>(new Set<Attachment>());
|
||||||
const checkedAll = ref(false);
|
const checkedAll = ref(false);
|
||||||
const refreshInterval = ref();
|
|
||||||
|
|
||||||
const handleFetchAttachments = async (options?: {
|
const total = ref(0);
|
||||||
mute?: boolean;
|
const hasPrevious = ref(false);
|
||||||
page?: number;
|
const hasNext = ref(false);
|
||||||
}) => {
|
|
||||||
try {
|
|
||||||
clearInterval(refreshInterval.value);
|
|
||||||
|
|
||||||
if (!options?.mute) {
|
|
||||||
loading.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options?.page) {
|
|
||||||
attachments.value.page = options.page;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const { data, isLoading, isFetching, refetch } = useQuery<Attachment[]>({
|
||||||
|
queryKey: ["attachments", policy, keyword, group, user, page, size, sort],
|
||||||
|
queryFn: async () => {
|
||||||
const { data } = await apiClient.attachment.searchAttachments({
|
const { data } = await apiClient.attachment.searchAttachments({
|
||||||
policy: policy?.value?.metadata.name,
|
policy: policy?.value?.metadata.name,
|
||||||
displayName: keyword?.value,
|
displayName: keyword?.value,
|
||||||
group: group?.value?.metadata.name,
|
group: group?.value?.metadata.name,
|
||||||
ungrouped: group?.value?.metadata.name === "ungrouped",
|
ungrouped: group?.value?.metadata.name === "ungrouped",
|
||||||
uploadedBy: user?.value?.metadata.name,
|
uploadedBy: user?.value?.metadata.name,
|
||||||
page: attachments.value.page,
|
page: page?.value,
|
||||||
size: attachments.value.size,
|
size: size?.value,
|
||||||
sort: [sort?.value as string].filter(Boolean),
|
sort: [sort?.value as string].filter(Boolean),
|
||||||
});
|
});
|
||||||
attachments.value = data;
|
|
||||||
|
|
||||||
const deletedAttachments = attachments.value.items.filter(
|
total.value = data.total;
|
||||||
|
hasPrevious.value = data.hasPrevious;
|
||||||
|
hasNext.value = data.hasNext;
|
||||||
|
|
||||||
|
return data.items;
|
||||||
|
},
|
||||||
|
refetchInterval(data) {
|
||||||
|
const deletingAttachments = data?.filter(
|
||||||
(attachment) => !!attachment.metadata.deletionTimestamp
|
(attachment) => !!attachment.metadata.deletionTimestamp
|
||||||
);
|
);
|
||||||
|
return deletingAttachments?.length ? 3000 : false;
|
||||||
if (deletedAttachments.length) {
|
},
|
||||||
refreshInterval.value = setInterval(() => {
|
refetchOnWindowFocus: false,
|
||||||
handleFetchAttachments({ mute: true });
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Failed to fetch attachments", e);
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onBeforeRouteLeave(() => {
|
|
||||||
clearInterval(refreshInterval.value);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const handlePaginationChange = async ({
|
|
||||||
page,
|
|
||||||
size,
|
|
||||||
}: {
|
|
||||||
page: number;
|
|
||||||
size: number;
|
|
||||||
}) => {
|
|
||||||
attachments.value.page = page;
|
|
||||||
attachments.value.size = size;
|
|
||||||
await handleFetchAttachments();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSelectPrevious = async () => {
|
const handleSelectPrevious = async () => {
|
||||||
const { items, hasPrevious } = attachments.value;
|
if (!data.value) return;
|
||||||
const index = items.findIndex(
|
|
||||||
|
const index = data.value?.findIndex(
|
||||||
(attachment) =>
|
(attachment) =>
|
||||||
attachment.metadata.name === selectedAttachment.value?.metadata.name
|
attachment.metadata.name === selectedAttachment.value?.metadata.name
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (index === undefined) return;
|
||||||
|
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
selectedAttachment.value = items[index - 1];
|
selectedAttachment.value = data.value[index - 1];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index === 0 && hasPrevious) {
|
if (index === 0 && hasPrevious) {
|
||||||
attachments.value.page--;
|
page.value--;
|
||||||
await handleFetchAttachments();
|
await refetch();
|
||||||
selectedAttachment.value =
|
selectedAttachment.value = data.value[data.value.length - 1];
|
||||||
attachments.value.items[attachments.value.items.length - 1];
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectNext = async () => {
|
const handleSelectNext = async () => {
|
||||||
const { items, hasNext } = attachments.value;
|
if (!data.value) return;
|
||||||
const index = items.findIndex(
|
|
||||||
|
const index = data.value?.findIndex(
|
||||||
(attachment) =>
|
(attachment) =>
|
||||||
attachment.metadata.name === selectedAttachment.value?.metadata.name
|
attachment.metadata.name === selectedAttachment.value?.metadata.name
|
||||||
);
|
);
|
||||||
if (index < items.length - 1) {
|
|
||||||
selectedAttachment.value = items[index + 1];
|
if (index === undefined) return;
|
||||||
|
|
||||||
|
if (index < data.value?.length - 1) {
|
||||||
|
selectedAttachment.value = data.value[index + 1];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (index === items.length - 1 && hasNext) {
|
|
||||||
attachments.value.page++;
|
if (index === data.value.length - 1 && hasNext) {
|
||||||
await handleFetchAttachments();
|
page.value++;
|
||||||
selectedAttachment.value = attachments.value.items[0];
|
await refetch();
|
||||||
|
selectedAttachment.value = data.value[0];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -185,7 +145,7 @@ export function useAttachmentControl(filterOptions?: {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Failed to delete attachment", e);
|
console.error("Failed to delete attachment", e);
|
||||||
} finally {
|
} finally {
|
||||||
await handleFetchAttachments();
|
await refetch();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -214,7 +174,7 @@ export function useAttachmentControl(filterOptions?: {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Failed to delete attachments", e);
|
console.error("Failed to delete attachments", e);
|
||||||
} finally {
|
} finally {
|
||||||
await handleFetchAttachments();
|
await refetch();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -222,7 +182,7 @@ export function useAttachmentControl(filterOptions?: {
|
||||||
|
|
||||||
const handleCheckAll = (checkAll: boolean) => {
|
const handleCheckAll = (checkAll: boolean) => {
|
||||||
if (checkAll) {
|
if (checkAll) {
|
||||||
attachments.value.items.forEach((attachment) => {
|
data.value?.forEach((attachment) => {
|
||||||
selectedAttachments.value.add(attachment);
|
selectedAttachments.value.add(attachment);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -242,7 +202,7 @@ export function useAttachmentControl(filterOptions?: {
|
||||||
watch(
|
watch(
|
||||||
() => selectedAttachments.value.size,
|
() => selectedAttachments.value.size,
|
||||||
(newValue) => {
|
(newValue) => {
|
||||||
checkedAll.value = newValue === attachments.value.items?.length;
|
checkedAll.value = newValue === data.value?.length;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -256,20 +216,21 @@ export function useAttachmentControl(filterOptions?: {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
attachments.value.page = 1;
|
page.value = 1;
|
||||||
selectedAttachment.value = undefined;
|
selectedAttachment.value = undefined;
|
||||||
selectedAttachments.value.clear();
|
selectedAttachments.value.clear();
|
||||||
checkedAll.value = false;
|
checkedAll.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
attachments,
|
attachments: data,
|
||||||
loading,
|
isLoading,
|
||||||
|
isFetching,
|
||||||
selectedAttachment,
|
selectedAttachment,
|
||||||
selectedAttachments,
|
selectedAttachments,
|
||||||
checkedAll,
|
checkedAll,
|
||||||
handleFetchAttachments,
|
total,
|
||||||
handlePaginationChange,
|
handleFetchAttachments: refetch,
|
||||||
handleSelectPrevious,
|
handleSelectPrevious,
|
||||||
handleSelectNext,
|
handleSelectNext,
|
||||||
handleDelete,
|
handleDelete,
|
||||||
|
|
Loading…
Reference in New Issue