halo/ui/console-src/modules/system/plugins/PluginList.vue

309 lines
9.5 KiB
Vue
Raw Normal View History

<script lang="ts" setup>
import {
Dialog,
IconAddCircle,
IconPlug,
IconRefreshLine,
VButton,
VCard,
VDropdown,
VDropdownItem,
VEmpty,
VLoading,
VPageHeader,
VSpace,
} from "@halo-dev/components";
import PluginListItem from "./components/PluginListItem.vue";
import PluginInstallationModal from "./components/PluginInstallationModal.vue";
import type { Ref } from "vue";
import { computed, onMounted, provide, ref, watch } from "vue";
import { apiClient } from "@/utils/api-client";
import { usePermission } from "@/utils/permission";
import { useQuery } from "@tanstack/vue-query";
import type { Plugin } from "@halo-dev/api-client";
import { useI18n } from "vue-i18n";
import { useRouteQuery } from "@vueuse/router";
import { usePluginBatchOperations } from "./composables/use-plugin";
const { t } = useI18n();
const { currentUserHasPermission } = usePermission();
const pluginInstallationModalVisible = ref(false);
const keyword = ref("");
const selectedEnabledValue = ref();
const selectedSortValue = ref();
const hasFilters = computed(() => {
return selectedEnabledValue.value !== undefined || selectedSortValue.value;
});
function handleClearFilters() {
selectedSortValue.value = undefined;
selectedEnabledValue.value = undefined;
}
const total = ref(0);
const { data, isLoading, isFetching, refetch } = useQuery<Plugin[]>({
queryKey: ["plugins", keyword, selectedEnabledValue, selectedSortValue],
queryFn: async () => {
const { data } = await apiClient.plugin.listPlugins({
page: 0,
size: 0,
keyword: keyword.value,
enabled: selectedEnabledValue.value,
sort: [selectedSortValue.value].filter(Boolean) as string[],
});
total.value = data.total;
return data.items;
},
keepPreviousData: true,
refetchInterval: (data) => {
const deletingPlugins = data?.filter(
(plugin) => !!plugin.metadata.deletionTimestamp
);
return deletingPlugins?.length ? 2000 : false;
},
});
// selection
const selectedNames = ref<string[]>([]);
provide<Ref<string[]>>("selectedNames", selectedNames);
const checkedAll = ref(false);
watch(
() => selectedNames.value,
(value) => {
checkedAll.value = value.length === data.value?.length;
}
);
const handleCheckAllChange = (e: Event) => {
const { checked } = e.target as HTMLInputElement;
if (checked) {
selectedNames.value =
data.value?.map((plugin) => {
return plugin.metadata.name;
}) || [];
} else {
selectedNames.value.length = 0;
}
};
const { handleChangeStatusInBatch, handleUninstallInBatch } =
usePluginBatchOperations(selectedNames);
// handle remote download url from route
const routeRemoteDownloadUrl = useRouteQuery<string | null>(
"remote-download-url"
);
onMounted(() => {
if (routeRemoteDownloadUrl.value) {
Dialog.warning({
title: t("core.plugin.operations.remote_download.title"),
description: t("core.plugin.operations.remote_download.description", {
url: routeRemoteDownloadUrl.value,
}),
confirmText: t("core.common.buttons.download"),
cancelText: t("core.common.buttons.cancel"),
onConfirm() {
pluginInstallationModalVisible.value = true;
},
onCancel() {
routeRemoteDownloadUrl.value = null;
},
});
}
});
</script>
<template>
<PluginInstallationModal
v-if="
pluginInstallationModalVisible &&
currentUserHasPermission(['system:plugins:manage'])
"
@close="pluginInstallationModalVisible = false"
feat: add support for uploading plugins (halo-dev/console#590) Signed-off-by: Ryan Wang <i@ryanc.cc> <!-- Thanks for sending a pull request! Here are some tips for you: 1. 如果这是你的第一次,请阅读我们的贡献指南:<https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>。 1. If this is your first time, please read our contributor guidelines: <https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>. 2. 请根据你解决问题的类型为 Pull Request 添加合适的标签。 2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. 3. 请确保你已经添加并运行了适当的测试。 3. Ensure you have added or ran the appropriate tests for your PR. --> #### What type of PR is this? <!-- 添加其中一个类别: Add one of the following kinds: /kind bug /kind cleanup /kind documentation /kind feature /kind optimization 适当添加其中一个或多个类别(可选): Optionally add one or more of the following kinds if applicable: /kind api-change /kind deprecation /kind failing-test /kind flake /kind regression --> /kind feature /milestone 2.0 #### What this PR does / why we need it: 添加上传插件的支持。 see https://github.com/halo-dev/halo/pull/2271 #### Which issue(s) this PR fixes: <!-- PR 合并时自动关闭 issue。 Automatically closes linked issue when PR is merged. 用法:`Fixes #<issue 号>`,或者 `Fixes (粘贴 issue 完整链接)` Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`. --> None #### Screenshots: <img width="1156" alt="image" src="https://user-images.githubusercontent.com/21301288/180416186-49c56971-c0b9-4761-ae9e-8531e433a9c0.png"> <img width="1156" alt="image" src="https://user-images.githubusercontent.com/21301288/180416203-e4b35266-3645-497b-9d08-d6407b2dd7f7.png"> <!-- 如果此 PR 有 UI 的改动,最好截图说明这个 PR 的改动。 If there are UI changes to this PR, it is best to take a screenshot to illustrate the changes to this PR. eg. Before: ![screenshot-before](https://user-images.githubusercontent.com/screenshot.png) After: ![screenshot-after](https://user-images.githubusercontent.com/screenshot.png) --> #### Special notes for your reviewer: 可以使用以下插件仓库中 Actions 构建的 JAR 测试: - https://github.com/halo-sigs/plugin-links/actions - https://github.com/halo-sigs/plugin-meilisearch/actions - https://github.com/halo-sigs/plugin-template/actions /cc @halo-dev/sig-halo-admin /cc @halo-dev/sig-halo #### Does this PR introduce a user-facing change? <!-- 如果当前 Pull Request 的修改不会造成用户侧的任何变更,在 `release-note` 代码块儿中填写 `NONE`。 否则请填写用户侧能够理解的 Release Note。如果当前 Pull Request 包含破坏性更新(Break Change), Release Note 需要以 `action required` 开头。 If no, just write "NONE" in the release-note block below. If yes, a release note is required: Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required". --> ```release-note None ```
2022-07-23 12:42:13 +00:00
/>
<VPageHeader :title="$t('core.plugin.title')">
<template #icon>
<IconPlug class="mr-2 self-center" />
</template>
<template #actions>
feat: add support for uploading plugins (halo-dev/console#590) Signed-off-by: Ryan Wang <i@ryanc.cc> <!-- Thanks for sending a pull request! Here are some tips for you: 1. 如果这是你的第一次,请阅读我们的贡献指南:<https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>。 1. If this is your first time, please read our contributor guidelines: <https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>. 2. 请根据你解决问题的类型为 Pull Request 添加合适的标签。 2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. 3. 请确保你已经添加并运行了适当的测试。 3. Ensure you have added or ran the appropriate tests for your PR. --> #### What type of PR is this? <!-- 添加其中一个类别: Add one of the following kinds: /kind bug /kind cleanup /kind documentation /kind feature /kind optimization 适当添加其中一个或多个类别(可选): Optionally add one or more of the following kinds if applicable: /kind api-change /kind deprecation /kind failing-test /kind flake /kind regression --> /kind feature /milestone 2.0 #### What this PR does / why we need it: 添加上传插件的支持。 see https://github.com/halo-dev/halo/pull/2271 #### Which issue(s) this PR fixes: <!-- PR 合并时自动关闭 issue。 Automatically closes linked issue when PR is merged. 用法:`Fixes #<issue 号>`,或者 `Fixes (粘贴 issue 完整链接)` Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`. --> None #### Screenshots: <img width="1156" alt="image" src="https://user-images.githubusercontent.com/21301288/180416186-49c56971-c0b9-4761-ae9e-8531e433a9c0.png"> <img width="1156" alt="image" src="https://user-images.githubusercontent.com/21301288/180416203-e4b35266-3645-497b-9d08-d6407b2dd7f7.png"> <!-- 如果此 PR 有 UI 的改动,最好截图说明这个 PR 的改动。 If there are UI changes to this PR, it is best to take a screenshot to illustrate the changes to this PR. eg. Before: ![screenshot-before](https://user-images.githubusercontent.com/screenshot.png) After: ![screenshot-after](https://user-images.githubusercontent.com/screenshot.png) --> #### Special notes for your reviewer: 可以使用以下插件仓库中 Actions 构建的 JAR 测试: - https://github.com/halo-sigs/plugin-links/actions - https://github.com/halo-sigs/plugin-meilisearch/actions - https://github.com/halo-sigs/plugin-template/actions /cc @halo-dev/sig-halo-admin /cc @halo-dev/sig-halo #### Does this PR introduce a user-facing change? <!-- 如果当前 Pull Request 的修改不会造成用户侧的任何变更,在 `release-note` 代码块儿中填写 `NONE`。 否则请填写用户侧能够理解的 Release Note。如果当前 Pull Request 包含破坏性更新(Break Change), Release Note 需要以 `action required` 开头。 If no, just write "NONE" in the release-note block below. If yes, a release note is required: Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required". --> ```release-note None ```
2022-07-23 12:42:13 +00:00
<VButton
v-permission="['system:plugins:manage']"
type="secondary"
@click="pluginInstallationModalVisible = true"
feat: add support for uploading plugins (halo-dev/console#590) Signed-off-by: Ryan Wang <i@ryanc.cc> <!-- Thanks for sending a pull request! Here are some tips for you: 1. 如果这是你的第一次,请阅读我们的贡献指南:<https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>。 1. If this is your first time, please read our contributor guidelines: <https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>. 2. 请根据你解决问题的类型为 Pull Request 添加合适的标签。 2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. 3. 请确保你已经添加并运行了适当的测试。 3. Ensure you have added or ran the appropriate tests for your PR. --> #### What type of PR is this? <!-- 添加其中一个类别: Add one of the following kinds: /kind bug /kind cleanup /kind documentation /kind feature /kind optimization 适当添加其中一个或多个类别(可选): Optionally add one or more of the following kinds if applicable: /kind api-change /kind deprecation /kind failing-test /kind flake /kind regression --> /kind feature /milestone 2.0 #### What this PR does / why we need it: 添加上传插件的支持。 see https://github.com/halo-dev/halo/pull/2271 #### Which issue(s) this PR fixes: <!-- PR 合并时自动关闭 issue。 Automatically closes linked issue when PR is merged. 用法:`Fixes #<issue 号>`,或者 `Fixes (粘贴 issue 完整链接)` Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`. --> None #### Screenshots: <img width="1156" alt="image" src="https://user-images.githubusercontent.com/21301288/180416186-49c56971-c0b9-4761-ae9e-8531e433a9c0.png"> <img width="1156" alt="image" src="https://user-images.githubusercontent.com/21301288/180416203-e4b35266-3645-497b-9d08-d6407b2dd7f7.png"> <!-- 如果此 PR 有 UI 的改动,最好截图说明这个 PR 的改动。 If there are UI changes to this PR, it is best to take a screenshot to illustrate the changes to this PR. eg. Before: ![screenshot-before](https://user-images.githubusercontent.com/screenshot.png) After: ![screenshot-after](https://user-images.githubusercontent.com/screenshot.png) --> #### Special notes for your reviewer: 可以使用以下插件仓库中 Actions 构建的 JAR 测试: - https://github.com/halo-sigs/plugin-links/actions - https://github.com/halo-sigs/plugin-meilisearch/actions - https://github.com/halo-sigs/plugin-template/actions /cc @halo-dev/sig-halo-admin /cc @halo-dev/sig-halo #### Does this PR introduce a user-facing change? <!-- 如果当前 Pull Request 的修改不会造成用户侧的任何变更,在 `release-note` 代码块儿中填写 `NONE`。 否则请填写用户侧能够理解的 Release Note。如果当前 Pull Request 包含破坏性更新(Break Change), Release Note 需要以 `action required` 开头。 If no, just write "NONE" in the release-note block below. If yes, a release note is required: Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required". --> ```release-note None ```
2022-07-23 12:42:13 +00:00
>
<template #icon>
<IconAddCircle class="h-full w-full" />
</template>
{{ $t("core.common.buttons.install") }}
</VButton>
</template>
</VPageHeader>
<div class="m-0 md:m-4">
<VCard :body-class="['!p-0']">
<template #header>
<div class="block w-full bg-gray-50 px-4 py-3">
<div
class="relative flex flex-col flex-wrap items-start gap-4 sm:flex-row sm:items-center"
>
<div
v-permission="['system:posts:manage']"
class="hidden items-center sm:flex"
>
<input
v-model="checkedAll"
type="checkbox"
@change="handleCheckAllChange"
/>
</div>
<div class="flex w-full flex-1 items-center gap-2 sm:w-auto">
<SearchInput v-if="!selectedNames.length" v-model="keyword" />
<VSpace v-else>
<VButton @click="handleChangeStatusInBatch(true)">
{{ $t("core.common.buttons.activate") }}
</VButton>
<VButton @click="handleChangeStatusInBatch(false)">
{{ $t("core.common.buttons.inactivate") }}
</VButton>
<VDropdown>
<VButton type="danger">
{{ $t("core.common.buttons.uninstall") }}
</VButton>
<template #popper>
<VDropdownItem
type="danger"
@click="handleUninstallInBatch(false)"
>
{{ $t("core.common.buttons.uninstall") }}
</VDropdownItem>
<VDropdownItem
type="danger"
@click="handleUninstallInBatch(true)"
>
{{
$t(
"core.plugin.operations.uninstall_and_delete_config.button"
)
}}
</VDropdownItem>
</template>
</VDropdown>
</VSpace>
</div>
<VSpace spacing="lg" class="flex-wrap">
<FilterCleanButton
v-if="hasFilters"
@click="handleClearFilters"
/>
<FilterDropdown
v-model="selectedEnabledValue"
:label="$t('core.common.filters.labels.status')"
:items="[
{
label: t('core.common.filters.item_labels.all'),
},
{
label: t('core.plugin.filters.status.items.active'),
value: true,
},
{
label: t('core.plugin.filters.status.items.inactive'),
value: false,
},
]"
/>
<FilterDropdown
v-model="selectedSortValue"
:label="$t('core.common.filters.labels.sort')"
:items="[
{
label: t('core.common.filters.item_labels.default'),
},
{
label: t('core.plugin.filters.sort.items.create_time_desc'),
value: 'creationTimestamp,desc',
},
{
label: t('core.plugin.filters.sort.items.create_time_asc'),
value: 'creationTimestamp,asc',
},
]"
/>
<div class="flex flex-row gap-2">
<div
class="group cursor-pointer rounded p-1 hover:bg-gray-200"
@click="refetch()"
>
<IconRefreshLine
v-tooltip="$t('core.common.buttons.refresh')"
:class="{ 'animate-spin text-gray-900': isFetching }"
class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
/>
</div>
</div>
</VSpace>
</div>
</div>
</template>
<VLoading v-if="isLoading" />
<Transition v-else-if="!data?.length" appear name="fade">
<VEmpty
:message="$t('core.plugin.empty.message')"
:title="$t('core.plugin.empty.title')"
>
<template #actions>
<VSpace>
<VButton :loading="isFetching" @click="refetch()">
{{ $t("core.common.buttons.refresh") }}
</VButton>
<VButton
v-permission="['system:plugins:manage']"
type="secondary"
@click="pluginInstallationModalVisible = true"
>
<template #icon>
<IconAddCircle class="h-full w-full" />
</template>
{{ $t("core.plugin.empty.actions.install") }}
</VButton>
</VSpace>
</template>
</VEmpty>
</Transition>
<Transition v-else appear name="fade">
<ul
class="box-border h-full w-full divide-y divide-gray-100"
role="list"
>
fix: solve logo render error of plugin list (#3888) 解决删除某个插件项导致其他插件项渲染失败的问题 <!-- Thanks for sending a pull request! Here are some tips for you: 1. 如果这是你的第一次,请阅读我们的贡献指南:<https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>。 1. If this is your first time, please read our contributor guidelines: <https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>. 2. 请根据你解决问题的类型为 Pull Request 添加合适的标签。 2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. 3. 请确保你已经添加并运行了适当的测试。 3. Ensure you have added or ran the appropriate tests for your PR. --> #### What type of PR is this? /kind bug <!-- 添加其中一个类别: Add one of the following kinds: /kind bug /kind cleanup /kind documentation /kind feature /kind improvement 适当添加其中一个或多个类别(可选): Optionally add one or more of the following kinds if applicable: /kind api-change /kind deprecation /kind failing-test /kind flake /kind regression --> #### What this PR does / why we need it: 解决插件列表渲染问题 #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/3866 <!-- PR 合并时自动关闭 issue。 Automatically closes linked issue when PR is merged. 用法:`Fixes #<issue 号>`,或者 `Fixes (粘贴 issue 完整链接)` Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`. --> #### Special notes for your reviewer: https://user-images.githubusercontent.com/106857035/235871211-ee469964-d7b3-41d3-ac9b-6997872ac507.mp4 #### Does this PR introduce a user-facing change? <!-- 如果当前 Pull Request 的修改不会造成用户侧的任何变更,在 `release-note` 代码块儿中填写 `NONE`。 否则请填写用户侧能够理解的 Release Note。如果当前 Pull Request 包含破坏性更新(Break Change), Release Note 需要以 `action required` 开头。 If no, just write "NONE" in the release-note block below. If yes, a release note is required: Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required". --> ```release-note NONE ```
2023-05-03 15:56:33 +00:00
<li v-for="plugin in data" :key="plugin.metadata.name">
<PluginListItem
:plugin="plugin"
:is-selected="selectedNames.includes(plugin.metadata.name)"
/>
</li>
</ul>
</Transition>
<template #footer>
<div class="flex h-8 items-center">
<span class="text-sm text-gray-500">
{{ $t("core.components.pagination.total_label", { total: total }) }}
</span>
</div>
</template>
</VCard>
</div>
</template>