halo/ui/console-src/modules/system/plugins/composables/use-plugin.ts

256 lines
7.2 KiB
TypeScript
Raw Normal View History

import type { ComputedRef, Ref } from "vue";
import { computed } from "vue";
import { type Plugin, PluginStatusPhaseEnum } from "@halo-dev/api-client";
import { cloneDeep } from "lodash-es";
import { apiClient } from "@/utils/api-client";
import { Dialog, Toast } from "@halo-dev/components";
import { useI18n } from "vue-i18n";
import { useMutation } from "@tanstack/vue-query";
interface usePluginLifeCycleReturn {
isStarted: ComputedRef<boolean | undefined>;
getStatusMessage: () => string | undefined;
changeStatus: () => void;
changingStatus: Ref<boolean>;
uninstall: (deleteExtensions?: boolean) => void;
}
export function usePluginLifeCycle(
plugin?: Ref<Plugin | undefined>
): usePluginLifeCycleReturn {
const { t } = useI18n();
const isStarted = computed(() => {
return (
plugin?.value?.status?.phase === PluginStatusPhaseEnum.Started &&
plugin.value?.spec.enabled
);
});
const getStatusMessage = () => {
if (!plugin?.value) return;
const { enabled } = plugin.value.spec || {};
const { phase } = plugin.value.status || {};
// Starting failed
if (enabled && phase === PluginStatusPhaseEnum.Failed) {
const lastCondition = plugin.value.status?.conditions?.[0];
return (
[lastCondition?.reason, lastCondition?.message]
.filter(Boolean)
.join(":") || "Unknown"
);
}
// Starting up
if (
enabled &&
phase !== (PluginStatusPhaseEnum.Started || PluginStatusPhaseEnum.Failed)
) {
return t("core.common.status.starting_up");
}
};
const { isLoading: changingStatus, mutate: changeStatus } = useMutation({
mutationKey: ["change-plugin-status"],
mutationFn: async () => {
if (!plugin?.value) return;
const { enabled } = plugin.value.spec;
return await apiClient.plugin.changePluginRunningState({
name: plugin.value.metadata.name,
pluginRunningStateRequest: {
enable: !enabled,
},
});
},
retry: 3,
retryDelay: 1000,
onSuccess() {
window.location.reload();
},
});
const uninstall = (deleteExtensions?: boolean) => {
if (!plugin?.value) return;
const { enabled } = plugin.value.spec;
Dialog.warning({
title: `${
deleteExtensions
? t("core.plugin.operations.uninstall_and_delete_config.title")
: t("core.plugin.operations.uninstall.title")
}`,
description: `${
enabled
? t("core.plugin.operations.uninstall_when_enabled.description")
: t("core.common.dialog.descriptions.cannot_be_recovered")
}`,
confirmType: "danger",
confirmText: `${
enabled
? t("core.plugin.operations.uninstall_when_enabled.confirm_text")
: t("core.common.buttons.uninstall")
}`,
cancelText: t("core.common.buttons.cancel"),
onConfirm: async () => {
if (!plugin.value) return;
try {
if (enabled) {
const pluginToUpdate = cloneDeep(plugin.value);
pluginToUpdate.spec.enabled = false;
refactor: method parameters of api client (halo-dev/console#605) <!-- 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 improvement /milestone 2.0 <!-- 添加其中一个类别: 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 --> #### What this PR does / why we need it: 修改 api-client 的请求参数结构,改为所有参数由一个对象包裹,而不是将各个参数作为方法的参数,防止因为后端参数结构发生改变,或者生成 api-client 时参数顺序发生改变导致请求异常。如: ```diff await apiClient.extension.storage.group.updatestorageHaloRunV1alpha1Group( - formState.value.metadata.name, - formState.value + { + name: formState.value.metadata.name, + group: formState.value, + } ); ``` #### 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: <!-- 如果此 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) --> None #### Special notes for your reviewer: /cc @halo-dev/sig-halo-admin #### 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-09-06 02:26:11 +00:00
await apiClient.extension.plugin.updatepluginHaloRunV1alpha1Plugin({
name: pluginToUpdate.metadata.name,
plugin: pluginToUpdate,
});
}
refactor: method parameters of api client (halo-dev/console#605) <!-- 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 improvement /milestone 2.0 <!-- 添加其中一个类别: 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 --> #### What this PR does / why we need it: 修改 api-client 的请求参数结构,改为所有参数由一个对象包裹,而不是将各个参数作为方法的参数,防止因为后端参数结构发生改变,或者生成 api-client 时参数顺序发生改变导致请求异常。如: ```diff await apiClient.extension.storage.group.updatestorageHaloRunV1alpha1Group( - formState.value.metadata.name, - formState.value + { + name: formState.value.metadata.name, + group: formState.value, + } ); ``` #### 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: <!-- 如果此 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) --> None #### Special notes for your reviewer: /cc @halo-dev/sig-halo-admin #### 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-09-06 02:26:11 +00:00
await apiClient.extension.plugin.deletepluginHaloRunV1alpha1Plugin({
name: plugin.value.metadata.name,
});
// delete plugin setting and configMap
if (deleteExtensions) {
const { settingName, configMapName } = plugin.value.spec;
if (settingName) {
await apiClient.extension.setting.deletev1alpha1Setting(
{
name: settingName,
},
{
mute: true,
}
);
}
if (configMapName) {
await apiClient.extension.configMap.deletev1alpha1ConfigMap(
{
name: configMapName,
},
{
mute: true,
}
);
}
}
Toast.success(t("core.common.toast.uninstall_success"));
} catch (e) {
console.error("Failed to uninstall plugin", e);
} finally {
window.location.reload();
}
},
});
};
return {
isStarted,
getStatusMessage,
changeStatus,
changingStatus,
uninstall,
};
}
export function usePluginBatchOperations(names: Ref<string[]>) {
const { t } = useI18n();
function handleUninstallInBatch(deleteExtensions: boolean) {
Dialog.warning({
title: `${
deleteExtensions
? t(
"core.plugin.operations.uninstall_and_delete_config_in_batch.title"
)
: t("core.plugin.operations.uninstall_in_batch.title")
}`,
description: t("core.common.dialog.descriptions.cannot_be_recovered"),
confirmType: "danger",
confirmText: t("core.common.buttons.uninstall"),
cancelText: t("core.common.buttons.cancel"),
onConfirm: async () => {
try {
for (let i = 0; i < names.value.length; i++) {
await apiClient.extension.plugin.deletepluginHaloRunV1alpha1Plugin({
name: names.value[i],
});
if (deleteExtensions) {
const { data: plugin } =
await apiClient.extension.plugin.getpluginHaloRunV1alpha1Plugin(
{
name: names.value[i],
}
);
const { settingName, configMapName } = plugin.spec;
if (settingName) {
await apiClient.extension.setting.deletev1alpha1Setting(
{
name: settingName,
},
{
mute: true,
}
);
}
if (configMapName) {
await apiClient.extension.configMap.deletev1alpha1ConfigMap(
{
name: configMapName,
},
{
mute: true,
}
);
}
}
}
window.location.reload();
} catch (e) {
console.error("Failed to uninstall plugin in batch", e);
}
},
});
}
function handleChangeStatusInBatch(enabled: boolean) {
Dialog.info({
title: enabled
? t("core.plugin.operations.change_status_in_batch.activate_title")
: t("core.plugin.operations.change_status_in_batch.inactivate_title"),
confirmText: t("core.common.buttons.confirm"),
cancelText: t("core.common.buttons.cancel"),
onConfirm: async () => {
try {
for (let i = 0; i < names.value.length; i++) {
await apiClient.plugin.changePluginRunningState({
name: names.value[i],
pluginRunningStateRequest: {
enable: enabled,
},
});
}
window.location.reload();
} catch (e) {
console.error("Failed to change plugin status in batch", e);
}
},
});
}
return { handleUninstallInBatch, handleChangeStatusInBatch };
}