From da021658c82322488f72484d072c24767e24f4ef Mon Sep 17 00:00:00 2001 From: Ryan Wang Date: Sun, 8 Oct 2023 17:58:37 +0800 Subject: [PATCH] feat: make attachment list item operations extendable (#4689) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #### What type of PR is this? /area console /kind feature /milestone 2.10.x #### What this PR does / why we need it: 附件管理列表项的操作按钮支持被插件扩展。 image #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/4667 #### Special notes for your reviewer: 需要测试附件的关于列表的已有功能是否正常。 如果需要测试扩展点是否有效,可以使用此插件测试:[plugin-s3-1.5.0-SNAPSHOT.jar.zip](https://github.com/halo-dev/halo/files/12839986/plugin-s3-1.5.0-SNAPSHOT.jar.zip) ```diff export default definePlugin({ components: {}, routes: [], extensionPoints: { "plugin:self:tabs:create": (): PluginTab[] => { return [ { id: "s3-link", label: "关联S3文件", component: markRaw(HomeView), permissions: [], }, ]; }, + "attachment:list-item:operation:create": (attachment: Ref) => { + return [ + { + priority: 21, + component: markRaw(VDropdownDivider), + }, + { + priority: 22, + component: markRaw(VDropdownItem), + props: { + type: "danger", + }, + label: "解除 S3 关联", + permissions: ["system:attachments:manage"], + action: () => { + console.log(attachment); + }, + }, + ]; + }, }, }); ``` #### Does this PR introduce a user-facing change? ```release-note Console 附件管理列表项的操作按钮支持被插件扩展。 ``` --- .../entity-listitem-operation.md | 1 + console/packages/shared/src/types/plugin.ts | 12 +- .../contents/attachments/AttachmentList.vue | 144 ++---------- .../components/AttachmentListItem.vue | 205 ++++++++++++++++++ .../attachments/composables/use-attachment.ts | 33 --- 5 files changed, 234 insertions(+), 161 deletions(-) create mode 100644 console/src/modules/contents/attachments/components/AttachmentListItem.vue diff --git a/console/docs/extension-points/entity-listitem-operation.md b/console/docs/extension-points/entity-listitem-operation.md index fb2588b13..3458b6c5e 100644 --- a/console/docs/extension-points/entity-listitem-operation.md +++ b/console/docs/extension-points/entity-listitem-operation.md @@ -12,6 +12,7 @@ - 插件:`"plugin:list-item:operation:create"?: (plugin: Ref) => | OperationItem[] | Promise[]>` - 备份:`"backup:list-item:operation:create"?: (backup: Ref) => | OperationItem[] | Promise[]>` - 主题:`"theme:list-item:operation:create"?: (theme: Ref) => | OperationItem[] | Promise[]>` +- 附件:`"attachment:list-item:operation:create"?: (attachment: Ref) => | OperationItem[] | Promise[]>` 示例: diff --git a/console/packages/shared/src/types/plugin.ts b/console/packages/shared/src/types/plugin.ts index b5793225b..deee315f8 100644 --- a/console/packages/shared/src/types/plugin.ts +++ b/console/packages/shared/src/types/plugin.ts @@ -10,7 +10,13 @@ import type { PluginInstallationTab } from "@/states/plugin-installation-tabs"; import type { EntityFieldItem } from "@/states/entity"; import type { OperationItem } from "@/states/operation"; import type { ThemeListTab } from "@/states/theme-list-tabs"; -import type { Backup, ListedPost, Plugin, Theme } from "@halo-dev/api-client"; +import type { + Attachment, + Backup, + ListedPost, + Plugin, + Theme, +} from "@halo-dev/api-client"; export interface RouteRecordAppend { parentName: RouteRecordName; @@ -53,6 +59,10 @@ export interface ExtensionPoint { backup: Ref ) => OperationItem[] | Promise[]>; + "attachment:list-item:operation:create"?: ( + attachment: Ref + ) => OperationItem[] | Promise[]>; + "plugin:list-item:field:create"?: ( plugin: Ref ) => EntityFieldItem[] | Promise; diff --git a/console/src/modules/contents/attachments/AttachmentList.vue b/console/src/modules/contents/attachments/AttachmentList.vue index 47f2a5f00..c4842a39c 100644 --- a/console/src/modules/contents/attachments/AttachmentList.vue +++ b/console/src/modules/contents/attachments/AttachmentList.vue @@ -15,9 +15,6 @@ import { VSpace, VEmpty, IconFolder, - VStatusDot, - VEntity, - VEntityField, VLoading, Toast, VDropdown, @@ -30,8 +27,6 @@ import AttachmentPoliciesModal from "./components/AttachmentPoliciesModal.vue"; import AttachmentGroupList from "./components/AttachmentGroupList.vue"; import { computed, onMounted, ref, watch } from "vue"; import type { Attachment, Group } from "@halo-dev/api-client"; -import { formatDatetime } from "@/utils/date"; -import prettyBytes from "pretty-bytes"; import { useFetchAttachmentPolicy } from "./composables/use-attachment-policy"; import { useAttachmentControl } from "./composables/use-attachment"; import { apiClient } from "@/utils/api-client"; @@ -39,12 +34,13 @@ import cloneDeep from "lodash.clonedeep"; import { isImage } from "@/utils/image"; import { useRouteQuery } from "@vueuse/router"; import { useFetchAttachmentGroup } from "./composables/use-attachment-group"; -import { usePermission } from "@/utils/permission"; import { useI18n } from "vue-i18n"; import { useLocalStorage } from "@vueuse/core"; import UserFilterDropdown from "@/components/filter/UserFilterDropdown.vue"; +import { provide } from "vue"; +import type { Ref } from "vue"; +import AttachmentListItem from "./components/AttachmentListItem.vue"; -const { currentUserHasPermission } = usePermission(); const { t } = useI18n(); const policyVisible = ref(false); @@ -101,7 +97,6 @@ const { handleFetchAttachments, handleSelectNext, handleSelectPrevious, - handleDelete, handleDeleteInBatch, handleCheckAll, handleSelect, @@ -121,6 +116,8 @@ const { size: size, }); +provide>>("selectedAttachments", selectedAttachments); + const handleMove = async (group: Group) => { try { const promises = Array.from(selectedAttachments.value).map((attachment) => { @@ -177,11 +174,6 @@ const onUploadModalClose = () => { handleFetchAttachments(); }; -const getPolicyName = (name: string | undefined) => { - const policy = policies.value?.find((p) => p.metadata.name === name); - return policy?.spec.displayName; -}; - // View type const viewTypes = [ { @@ -468,8 +460,8 @@ onMounted(() => { role="list" > -
  • - - - - - - +
  • +
  • diff --git a/console/src/modules/contents/attachments/components/AttachmentListItem.vue b/console/src/modules/contents/attachments/components/AttachmentListItem.vue new file mode 100644 index 000000000..3109f2ac3 --- /dev/null +++ b/console/src/modules/contents/attachments/components/AttachmentListItem.vue @@ -0,0 +1,205 @@ + + + diff --git a/console/src/modules/contents/attachments/composables/use-attachment.ts b/console/src/modules/contents/attachments/composables/use-attachment.ts index 0e14d886f..63a16f6dc 100644 --- a/console/src/modules/contents/attachments/composables/use-attachment.ts +++ b/console/src/modules/contents/attachments/composables/use-attachment.ts @@ -21,7 +21,6 @@ interface useAttachmentControlReturn { handleFetchAttachments: () => void; handleSelectPrevious: () => void; handleSelectNext: () => void; - handleDelete: (attachment: Attachment) => void; handleDeleteInBatch: () => void; handleCheckAll: (checkAll: boolean) => void; handleSelect: (attachment: Attachment | undefined) => void; @@ -128,37 +127,6 @@ export function useAttachmentControl(filterOptions: { } }; - const handleDelete = (attachment: Attachment) => { - Dialog.warning({ - title: t("core.attachment.operations.delete.title"), - description: t("core.common.dialog.descriptions.cannot_be_recovered"), - confirmType: "danger", - confirmText: t("core.common.buttons.confirm"), - cancelText: t("core.common.buttons.cancel"), - onConfirm: async () => { - try { - await apiClient.extension.storage.attachment.deletestorageHaloRunV1alpha1Attachment( - { - name: attachment.metadata.name, - } - ); - if ( - selectedAttachment.value?.metadata.name === attachment.metadata.name - ) { - selectedAttachment.value = undefined; - } - selectedAttachments.value.delete(attachment); - - Toast.success(t("core.common.toast.delete_success")); - } catch (e) { - console.error("Failed to delete attachment", e); - } finally { - await refetch(); - } - }, - }); - }; - const handleDeleteInBatch = () => { Dialog.warning({ title: t("core.attachment.operations.delete_in_batch.title"), @@ -243,7 +211,6 @@ export function useAttachmentControl(filterOptions: { handleFetchAttachments: refetch, handleSelectPrevious, handleSelectNext, - handleDelete, handleDeleteInBatch, handleCheckAll, handleSelect,