Skip to content

Commit

Permalink
feat: add support for displaying enabled plugins on actuator page (#4897
Browse files Browse the repository at this point in the history
)
  • Loading branch information
ruibaby committed Nov 27, 2023
1 parent 03a9fc5 commit 3306b1f
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 71 deletions.
265 changes: 200 additions & 65 deletions console/console-src/modules/system/actuator/Actuator.vue
Expand Up @@ -9,49 +9,80 @@ import {
Toast,
VDescription,
VDescriptionItem,
VTag,
VLoading,
} from "@halo-dev/components";
import { computed, onMounted, ref } from "vue";
import { computed } from "vue";
import type { Info, GlobalInfo, Startup } from "@/types";
import axios from "axios";
import { formatDatetime } from "@/utils/date";
import { useClipboard } from "@vueuse/core";
import { useI18n } from "vue-i18n";
import { useThemeStore } from "@console/stores/theme";
import type { Plugin } from "@halo-dev/api-client";
import { apiClient } from "@/utils/api-client";
import { useQuery } from "@tanstack/vue-query";
import { usePermission } from "@/utils/permission";
const { t } = useI18n();
const themeStore = useThemeStore();
const { currentUserHasPermission } = usePermission();
const info = ref<Info>();
const globalInfo = ref<GlobalInfo>();
const startup = ref<Startup>();
const { data: info } = useQuery<Info>({
queryKey: ["system-info"],
queryFn: async () => {
const { data } = await axios.get<Info>(
`${import.meta.env.VITE_API_URL}/actuator/info`,
{
withCredentials: true,
}
);
return data;
},
retry: 0,
});
const handleFetchActuatorInfo = async () => {
const { data } = await axios.get(
`${import.meta.env.VITE_API_URL}/actuator/info`,
{
withCredentials: true,
}
);
info.value = data;
};
const { data: globalInfo } = useQuery<GlobalInfo>({
queryKey: ["system-global-info"],
queryFn: async () => {
const { data } = await axios.get<GlobalInfo>(
`${import.meta.env.VITE_API_URL}/actuator/globalinfo`,
{
withCredentials: true,
}
);
return data;
},
retry: 0,
});
const handleFetchActuatorGlobalInfo = async () => {
const { data } = await axios.get(
`${import.meta.env.VITE_API_URL}/actuator/globalinfo`,
{
withCredentials: true,
}
);
globalInfo.value = data;
};
const { data: startup } = useQuery<Startup>({
queryKey: ["system-startup-info"],
queryFn: async () => {
const { data } = await axios.get<Startup>(
`${import.meta.env.VITE_API_URL}/actuator/startup`,
{
withCredentials: true,
}
);
return data;
},
retry: 0,
});
const handleFetchActuatorStartup = async () => {
const { data } = await axios.get(
`${import.meta.env.VITE_API_URL}/actuator/startup`,
{
withCredentials: true,
}
);
startup.value = data;
};
const { data: plugins, isLoading: isPluginsLoading } = useQuery<Plugin[]>({
queryKey: ["enabled-plugins"],
queryFn: async () => {
const { data } = await apiClient.plugin.listPlugins({
page: 0,
size: 0,
enabled: true,
});
return data.items;
},
enabled: computed(() => currentUserHasPermission(["system:plugins:view"])),
});
const isExternalUrlValid = computed(() => {
if (!globalInfo.value?.useAbsolutePermalink) {
Expand All @@ -67,43 +98,101 @@ const isExternalUrlValid = computed(() => {
return url.host === currentHost && url.protocol === currentProtocol;
});
onMounted(() => {
handleFetchActuatorInfo();
handleFetchActuatorGlobalInfo();
handleFetchActuatorStartup();
});
// copy system information to clipboard
const { copy, isSupported } = useClipboard({ legacy: true });
interface CopyItem {
label: string;
value?: string;
href?: string;
children?: CopyItem[];
}
const handleCopy = () => {
if (!isSupported.value) {
Toast.warning(t("core.actuator.actions.copy.toast_browser_not_supported"));
return;
}
const text = `
- ${t("core.actuator.copy_results.external_url", {
external_url: globalInfo.value?.externalUrl,
})}
- ${t("core.actuator.copy_results.start_time", {
start_time: formatDatetime(startup.value?.timeline.startTime),
})}
- ${t("core.actuator.fields.version", { version: info.value?.build?.version })}
- ${t("core.actuator.copy_results.build_time", {
build_time: formatDatetime(info.value?.build?.time),
})}
- Git Commit:${info.value?.git?.commit.id}
- Java:${info.value?.java.runtime.name} / ${info.value?.java.runtime.version}
- ${t("core.actuator.copy_results.database", {
database: [info.value?.database.name, info.value?.database.version].join(
" / "
),
})}
- ${t("core.actuator.copy_results.os", {
os: [info.value?.os.name, info.value?.os.version].join(" / "),
})}
`;
const copyItems: CopyItem[] = [
{
label: t("core.actuator.fields.external_url"),
value: globalInfo.value?.externalUrl || "",
},
{
label: t("core.actuator.fields.start_time"),
value: formatDatetime(startup.value?.timeline.startTime) || "",
},
{
label: t("core.actuator.fields.version"),
value: info.value?.build?.version || "",
},
{
label: t("core.actuator.fields.build_time"),
value: formatDatetime(info.value?.build?.time) || "",
},
{
label: "Git Commit",
value: info.value?.git?.commit.id || "",
},
{
label: "Java",
value:
[info.value?.java.runtime.name, info.value?.java.runtime.version]
.filter(Boolean)
.join(" / ")
.trim() || "",
},
{
label: t("core.actuator.fields.database"),
value:
[info.value?.database.name, info.value?.database.version]
.filter(Boolean)
.join(" / ") || "",
},
{
label: t("core.actuator.fields.os"),
value:
[info.value?.os.name, info.value?.os.version]
.filter(Boolean)
.join(" / ") || "",
},
{
label: t("core.actuator.fields.activated_theme"),
value: themeStore.activatedTheme?.spec.displayName || "",
href:
themeStore.activatedTheme?.spec.repo ||
themeStore.activatedTheme?.spec.homepage,
},
{
label: t("core.actuator.fields.enabled_plugins"),
children: plugins.value?.map((plugin) => ({
value: plugin.spec.displayName,
href: plugin.spec.repo || plugin.spec.homepage,
})) as CopyItem[],
},
];
const text = copyItems
.map((item) => {
if (item.children?.length) {
const childrenText = item.children
.map(
(child) =>
` - ${
child.href ? `[${child.value}](${child.href})` : child.value
}`
)
.filter(Boolean)
.join("\n");
return `- ${item.label}:\n${childrenText}`;
} else {
return `- ${item.label}: ${
item.href ? `[${item.value}](${item.href})` : item.value || ""
}`;
}
})
.join("\n");
copy(text);
Expand Down Expand Up @@ -182,17 +271,55 @@ const handleDownloadLogfile = () => {
</VAlert>
</VDescriptionItem>
<VDescriptionItem
v-if="startup?.timeline.startTime"
:label="$t('core.actuator.fields.start_time')"
:content="formatDatetime(startup?.timeline.startTime)"
/>
<VDescriptionItem
:label="$t('core.actuator.fields.timezone')"
:content="globalInfo?.timeZone"
/>
v-if="themeStore.activatedTheme"
:label="$t('core.actuator.fields.activated_theme')"
>
<VTag @click="$router.push({ name: 'ThemeDetail' })">
<template v-if="themeStore.activatedTheme.spec.logo" #leftIcon>
<img
class="h-3.5 w-3.5 rounded-sm"
:src="themeStore.activatedTheme.spec.logo"
:alt="themeStore.activatedTheme.spec.displayName"
/>
</template>
{{ themeStore.activatedTheme.spec.displayName }}
</VTag>
</VDescriptionItem>
<VDescriptionItem
:label="$t('core.actuator.fields.locale')"
:content="globalInfo?.locale"
/>
v-permission="['system:plugins:view']"
:label="$t('core.actuator.fields.enabled_plugins')"
>
<VLoading v-if="isPluginsLoading" />
<span v-else-if="!plugins?.length">
{{ $t("core.common.text.none") }}
</span>
<div v-else class="flex flex-wrap gap-1.5">
<VTag
v-for="plugin in plugins"
:key="plugin.metadata.name"
@click="
$router.push({
name: 'PluginDetail',
params: { name: plugin.metadata.name },
})
"
>
<template v-if="plugin.status?.logo" #leftIcon>
<img
class="h-3.5 w-3.5 rounded-sm"
:src="plugin.status?.logo"
:alt="plugin.spec.displayName"
/>
</template>
{{ plugin.spec.displayName }}
</VTag>
</div>
</VDescriptionItem>
</VDescription>
</div>
</div>
Expand Down Expand Up @@ -249,6 +376,14 @@ const handleDownloadLogfile = () => {
<VDescriptionItem :label="$t('core.actuator.fields.os')">
{{ info.os.name }} {{ info.os.version }} / {{ info.os.arch }}
</VDescriptionItem>
<VDescriptionItem
:label="$t('core.actuator.fields.timezone')"
:content="globalInfo?.timeZone"
/>
<VDescriptionItem
:label="$t('core.actuator.fields.locale')"
:content="globalInfo?.locale"
/>
<VDescriptionItem
:label="$t('core.actuator.fields.log')"
vertical-center
Expand Down
6 changes: 4 additions & 2 deletions console/src/locales/en.yaml
Expand Up @@ -1019,13 +1019,15 @@ core:
fields:
external_url: External url
start_time: Start time
timezone: Timezone
locale: Locale
timezone: System Timezone
locale: System Locale
version: Version
build_time: Build time
database: Database
os: Operating system
log: System log
activated_theme: Activated theme
enabled_plugins: Enabled plugins
fields_values:
external_url:
not_setup: Not setup
Expand Down
6 changes: 4 additions & 2 deletions console/src/locales/zh-CN.yaml
Expand Up @@ -1019,13 +1019,15 @@ core:
fields:
external_url: 外部访问地址
start_time: 启动时间
timezone: 时区
locale: 语言
timezone: 系统时区
locale: 系统语言
version: 版本
build_time: 构建时间
database: 数据库
os: 操作系统
log: 运行日志
activated_theme: 已激活主题
enabled_plugins: 已启动插件
fields_values:
external_url:
not_setup: 未设置
Expand Down
6 changes: 4 additions & 2 deletions console/src/locales/zh-TW.yaml
Expand Up @@ -1019,13 +1019,15 @@ core:
fields:
external_url: 外部訪問地址
start_time: 啟動時間
timezone: 時區
locale: 語言
timezone: 系統時區
locale: 系統語言
version: 版本
build_time: 構建時間
database: 資料庫
os: 操作系統
log: 運行日誌
activated_theme: 已啟動主題
enabled_plugins: 已啟動插件
fields_values:
external_url:
not_setup: 未設置
Expand Down

0 comments on commit 3306b1f

Please sign in to comment.