import type { ComputedRef, Ref } from "vue"; import { computed } from "vue"; import { type Plugin, PluginStatusPhaseEnum, coreApiClient, consoleApiClient, } from "@halo-dev/api-client"; import { Dialog, Toast } from "@halo-dev/components"; import { useI18n } from "vue-i18n"; import { useMutation } from "@tanstack/vue-query"; interface usePluginLifeCycleReturn { isStarted: ComputedRef; getStatusDotState: () => string; getStatusMessage: () => string | undefined; changeStatus: () => void; changingStatus: Ref; uninstall: (deleteExtensions?: boolean) => void; } export function usePluginLifeCycle( plugin?: Ref ): usePluginLifeCycleReturn { const { t } = useI18n(); const isStarted = computed(() => { return ( plugin?.value?.status?.phase === PluginStatusPhaseEnum.Started && plugin.value?.spec.enabled ); }); const getStatusDotState = () => { const { phase } = plugin?.value?.status || {}; const { enabled } = plugin?.value?.spec || {}; if (enabled && phase === PluginStatusPhaseEnum.Failed) { return "error"; } if (phase === PluginStatusPhaseEnum.Disabling) { return "warning"; } return "default"; }; const getStatusMessage = () => { if (!plugin?.value) return; const { phase } = plugin.value.status || {}; if ( phase === PluginStatusPhaseEnum.Failed || phase === PluginStatusPhaseEnum.Disabling ) { const lastCondition = plugin.value.status?.conditions?.[0]; return ( [lastCondition?.reason, lastCondition?.message] .filter(Boolean) .join(": ") || "Unknown" ); } // Starting up if ( 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 consoleApiClient.plugin.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 { await consoleApiClient.plugin.plugin.changePluginRunningState({ name: plugin.value.metadata.name, pluginRunningStateRequest: { enable: false, }, }); await coreApiClient.plugin.plugin.deletePlugin({ name: plugin.value.metadata.name, }); // delete plugin setting and configMap if (deleteExtensions) { const { settingName, configMapName } = plugin.value.spec; if (settingName) { await coreApiClient.setting.deleteSetting( { name: settingName, }, { mute: true, } ); } if (configMapName) { await coreApiClient.configMap.deleteConfigMap( { 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, getStatusDotState, getStatusMessage, changeStatus, changingStatus, uninstall, }; } export function usePluginBatchOperations(names: Ref) { 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 coreApiClient.plugin.plugin.deletePlugin({ name: names.value[i], }); if (deleteExtensions) { const { data: plugin } = await coreApiClient.plugin.plugin.getPlugin({ name: names.value[i], }); const { settingName, configMapName } = plugin.spec; if (settingName) { await coreApiClient.setting.deleteSetting( { name: settingName, }, { mute: true, } ); } if (configMapName) { await coreApiClient.configMap.deleteConfigMap( { 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 consoleApiClient.plugin.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 }; }