Skip to content

Commit

Permalink
feat: show the startup status of the plugin (#5520)
Browse files Browse the repository at this point in the history
#### What type of PR is this?

/area ui
/kind feature
/milestone 2.14.x

#### What this PR does / why we need it:

Show the startup status of the plugin

<img width="444" alt="image" src="https://github.com/halo-dev/halo/assets/21301288/0f5d47c2-9d81-4cb7-b114-6b2eebe753c5">


#### Which issue(s) this PR fixes:

Fixes #5254

#### Does this PR introduce a user-facing change?

```release-note
插件支持显示启动中的状态。
```
  • Loading branch information
ruibaby authored Apr 25, 2024
1 parent a635881 commit 5a0f735
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 82 deletions.
21 changes: 18 additions & 3 deletions ui/console-src/modules/system/plugins/PluginList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ 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 { PluginStatusPhaseEnum, type Plugin } from "@halo-dev/api-client";
import { useI18n } from "vue-i18n";
import { useRouteQuery } from "@vueuse/router";
import { usePluginBatchOperations } from "./composables/use-plugin";
Expand Down Expand Up @@ -63,11 +63,26 @@ const { data, isLoading, isFetching, refetch } = useQuery<Plugin[]>({
},
keepPreviousData: true,
refetchInterval: (data) => {
const deletingPlugins = data?.filter(
const hasDeletingData = data?.some(
(plugin) => !!plugin.metadata.deletionTimestamp
);
return deletingPlugins?.length ? 2000 : false;
if (hasDeletingData) {
return 1000;
}
const hasStartingData = data?.some(
(plugin) =>
plugin.spec.enabled &&
plugin.status?.phase !==
(PluginStatusPhaseEnum.Started || PluginStatusPhaseEnum.Failed)
);
if (hasStartingData) {
return 3000;
}
return false;
},
});
Expand Down
165 changes: 92 additions & 73 deletions ui/console-src/modules/system/plugins/components/PluginListItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import type { Ref } from "vue";
import { computed, inject, markRaw, ref, toRefs } from "vue";
import { usePluginLifeCycle } from "../composables/use-plugin";
import type { Plugin } from "@halo-dev/api-client";
import { type Plugin, PluginStatusPhaseEnum } from "@halo-dev/api-client";
import { formatDatetime } from "@/utils/date";
import { usePermission } from "@/utils/permission";
import { apiClient } from "@/utils/api-client";
Expand Down Expand Up @@ -43,7 +43,7 @@ const { plugin } = toRefs(props);
const selectedNames = inject<Ref<string[]>>("selectedNames", ref([]));
const { getFailedMessage, uninstall } = usePluginLifeCycle(plugin);
const { getStatusMessage, uninstall } = usePluginLifeCycle(plugin);
const pluginUpgradeModalVisible = ref(false);
Expand Down Expand Up @@ -146,86 +146,105 @@ const { operationItems } = useOperationItemExtensionPoint<Plugin>(
const { startFields, endFields } = useEntityFieldItemExtensionPoint<Plugin>(
"plugin:list-item:field:create",
plugin,
computed((): EntityFieldItem[] => [
{
position: "start",
priority: 10,
component: markRaw(LogoField),
props: {
plugin: props.plugin,
computed((): EntityFieldItem[] => {
const { enabled } = props.plugin.spec || {};
const { phase } = props.plugin.status || {};
const shouldHideStatusDot =
!enabled || (enabled && phase === PluginStatusPhaseEnum.Started);
const getStatusDotState = () => {
if (
enabled &&
phase !==
(PluginStatusPhaseEnum.Started || PluginStatusPhaseEnum.Failed)
) {
return "default";
}
return "error";
};
return [
{
position: "start",
priority: 10,
component: markRaw(LogoField),
props: {
plugin: props.plugin,
},
},
},
{
position: "start",
priority: 20,
component: markRaw(VEntityField),
props: {
title: props.plugin.spec.displayName,
description: props.plugin.spec.description,
route: {
name: "PluginDetail",
params: { name: props.plugin.metadata.name },
{
position: "start",
priority: 20,
component: markRaw(VEntityField),
props: {
title: props.plugin.spec.displayName,
description: props.plugin.spec.description,
route: {
name: "PluginDetail",
params: { name: props.plugin.metadata.name },
},
},
},
},
{
position: "end",
priority: 10,
component: markRaw(StatusDotField),
props: {
tooltip: getFailedMessage(),
state: "error",
animate: true,
{
position: "end",
priority: 10,
component: markRaw(StatusDotField),
props: {
tooltip: getStatusMessage(),
state: getStatusDotState(),
animate: true,
},
hidden: shouldHideStatusDot,
},
hidden: props.plugin.status?.phase !== "FAILED",
},
{
position: "end",
priority: 20,
component: markRaw(StatusDotField),
props: {
tooltip: t("core.common.status.deleting"),
state: "warning",
animate: true,
{
position: "end",
priority: 20,
component: markRaw(StatusDotField),
props: {
tooltip: t("core.common.status.deleting"),
state: "warning",
animate: true,
},
hidden: !props.plugin.metadata.deletionTimestamp,
},
hidden: !props.plugin.metadata.deletionTimestamp,
},
{
position: "end",
priority: 30,
component: markRaw(AuthorField),
props: {
plugin: props.plugin,
{
position: "end",
priority: 30,
component: markRaw(AuthorField),
props: {
plugin: props.plugin,
},
hidden: !props.plugin.spec.author,
},
hidden: !props.plugin.spec.author,
},
{
position: "end",
priority: 40,
component: markRaw(VEntityField),
props: {
description: props.plugin.spec.version,
{
position: "end",
priority: 40,
component: markRaw(VEntityField),
props: {
description: props.plugin.spec.version,
},
},
},
{
position: "end",
priority: 50,
component: markRaw(VEntityField),
props: {
description: formatDatetime(props.plugin.metadata.creationTimestamp),
{
position: "end",
priority: 50,
component: markRaw(VEntityField),
props: {
description: formatDatetime(props.plugin.metadata.creationTimestamp),
},
hidden: !props.plugin.metadata.creationTimestamp,
},
hidden: !props.plugin.metadata.creationTimestamp,
},
{
position: "end",
priority: 60,
component: markRaw(SwitchField),
props: {
plugin: props.plugin,
{
position: "end",
priority: 60,
component: markRaw(SwitchField),
props: {
plugin: props.plugin,
},
permissions: ["system:plugins:manage"],
},
permissions: ["system:plugins:manage"],
},
])
];
})
);
</script>
<template>
Expand Down
27 changes: 21 additions & 6 deletions ui/console-src/modules/system/plugins/composables/use-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ComputedRef, Ref } from "vue";
import { computed } from "vue";
import { type Plugin } from "@halo-dev/api-client";
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";
Expand All @@ -9,7 +9,7 @@ import { useMutation } from "@tanstack/vue-query";

interface usePluginLifeCycleReturn {
isStarted: ComputedRef<boolean | undefined>;
getFailedMessage: () => string | undefined;
getStatusMessage: () => string | undefined;
changeStatus: () => void;
changingStatus: Ref<boolean>;
uninstall: (deleteExtensions?: boolean) => void;
Expand All @@ -22,18 +22,33 @@ export function usePluginLifeCycle(

const isStarted = computed(() => {
return (
plugin?.value?.status?.phase === "STARTED" && plugin.value?.spec.enabled
plugin?.value?.status?.phase === PluginStatusPhaseEnum.Started &&
plugin.value?.spec.enabled
);
});

const getFailedMessage = () => {
const getStatusMessage = () => {
if (!plugin?.value) return;

const { enabled } = plugin.value.spec || {};
const { phase } = plugin.value.status || {};

// Starting up
if (
enabled &&
phase !== (PluginStatusPhaseEnum.Started || PluginStatusPhaseEnum.Failed)
) {
return t("core.common.status.starting_up");
}

// Starting failed
if (!isStarted.value) {
const lastCondition = plugin.value.status?.conditions?.[0];

return (
[lastCondition?.reason, lastCondition?.message].join(":") || "Unknown"
[lastCondition?.reason, lastCondition?.message]
.filter(Boolean)
.join(":") || "Unknown"
);
}
};
Expand Down Expand Up @@ -138,7 +153,7 @@ export function usePluginLifeCycle(

return {
isStarted,
getFailedMessage,
getStatusMessage,
changeStatus,
changingStatus,
uninstall,
Expand Down
1 change: 1 addition & 0 deletions ui/src/locales/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1607,6 +1607,7 @@ core:
not_activated: Not activated
installed: Installed
not_installed: Not installed
starting_up: Starting
text:
none: None
tip: Tip
Expand Down
1 change: 1 addition & 0 deletions ui/src/locales/zh-CN.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1551,6 +1551,7 @@ core:
not_activated: 未启用
installed: 已安装
not_installed: 未安装
starting_up: 启动中
text:
none:
tip: 提示
Expand Down
1 change: 1 addition & 0 deletions ui/src/locales/zh-TW.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1509,6 +1509,7 @@ core:
not_activated: 未啟用
installed: 已安裝
not_installed: 未安裝
starting_up: 启动中
text:
none:
tip: 提示
Expand Down

0 comments on commit 5a0f735

Please sign in to comment.