mirror of https://github.com/halo-dev/halo
266 lines
8.1 KiB
Vue
266 lines
8.1 KiB
Vue
<script lang="ts" setup>
|
||
import {
|
||
IconTerminalBoxLine,
|
||
IconClipboardLine,
|
||
VAlert,
|
||
VPageHeader,
|
||
VCard,
|
||
VButton,
|
||
Toast,
|
||
VDescription,
|
||
VDescriptionItem,
|
||
} from "@halo-dev/components";
|
||
import { computed, onMounted, ref } 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";
|
||
|
||
const { t } = useI18n();
|
||
|
||
const info = ref<Info>();
|
||
const globalInfo = ref<GlobalInfo>();
|
||
const startup = ref<Startup>();
|
||
|
||
const handleFetchActuatorInfo = async () => {
|
||
const { data } = await axios.get(
|
||
`${import.meta.env.VITE_API_URL}/actuator/info`,
|
||
{
|
||
withCredentials: true,
|
||
}
|
||
);
|
||
info.value = data;
|
||
};
|
||
|
||
const handleFetchActuatorGlobalInfo = async () => {
|
||
const { data } = await axios.get(
|
||
`${import.meta.env.VITE_API_URL}/actuator/globalinfo`,
|
||
{
|
||
withCredentials: true,
|
||
}
|
||
);
|
||
globalInfo.value = data;
|
||
};
|
||
|
||
const handleFetchActuatorStartup = async () => {
|
||
const { data } = await axios.get(
|
||
`${import.meta.env.VITE_API_URL}/actuator/startup`,
|
||
{
|
||
withCredentials: true,
|
||
}
|
||
);
|
||
startup.value = data;
|
||
};
|
||
|
||
const isExternalUrlValid = computed(() => {
|
||
if (!globalInfo.value?.useAbsolutePermalink) {
|
||
return true;
|
||
}
|
||
|
||
if (!globalInfo.value?.externalUrl) {
|
||
return true;
|
||
}
|
||
|
||
const url = new URL(globalInfo.value.externalUrl);
|
||
const { host: currentHost, protocol: currentProtocol } = window.location;
|
||
return url.host === currentHost && url.protocol === currentProtocol;
|
||
});
|
||
|
||
onMounted(() => {
|
||
handleFetchActuatorInfo();
|
||
handleFetchActuatorGlobalInfo();
|
||
handleFetchActuatorStartup();
|
||
});
|
||
|
||
// copy system information to clipboard
|
||
const { copy, isSupported } = useClipboard({ legacy: true });
|
||
|
||
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(" / "),
|
||
})}
|
||
`;
|
||
|
||
copy(text);
|
||
|
||
Toast.success(t("core.common.toast.copy_success"));
|
||
};
|
||
|
||
const handleDownloadLogfile = () => {
|
||
axios
|
||
.get(`${import.meta.env.VITE_API_URL}/actuator/logfile`)
|
||
.then((response) => {
|
||
const blob = new Blob([response.data]);
|
||
const downloadElement = document.createElement("a");
|
||
const href = window.URL.createObjectURL(blob);
|
||
downloadElement.href = href;
|
||
downloadElement.download = `halo-log-${formatDatetime(new Date())}.log`;
|
||
document.body.appendChild(downloadElement);
|
||
downloadElement.click();
|
||
document.body.removeChild(downloadElement);
|
||
window.URL.revokeObjectURL(href);
|
||
|
||
Toast.success(t("core.common.toast.download_success"));
|
||
})
|
||
.catch((e) => {
|
||
Toast.error(t("core.common.toast.download_failed"));
|
||
console.log("Failed to download log file.", e);
|
||
});
|
||
};
|
||
</script>
|
||
|
||
<template>
|
||
<VPageHeader :title="$t('core.actuator.title')">
|
||
<template #icon>
|
||
<IconTerminalBoxLine class="mr-2 self-center" />
|
||
</template>
|
||
<template #actions>
|
||
<VButton size="sm" @click="handleCopy">
|
||
<template #icon>
|
||
<IconClipboardLine class="h-full w-full" />
|
||
</template>
|
||
{{ $t("core.common.buttons.copy") }}
|
||
</VButton>
|
||
</template>
|
||
</VPageHeader>
|
||
|
||
<div class="m-0 flex flex-col gap-4 md:m-4">
|
||
<VCard :body-class="['!p-0']">
|
||
<div class="bg-white">
|
||
<div
|
||
class="flex items-center justify-between bg-white px-4 py-4 sm:px-6"
|
||
>
|
||
<div>
|
||
<h3 class="text-lg font-medium leading-6 text-gray-900">
|
||
{{ $t("core.actuator.header.titles.general") }}
|
||
</h3>
|
||
</div>
|
||
</div>
|
||
<div class="border-t border-gray-200">
|
||
<VDescription>
|
||
<VDescriptionItem :label="$t('core.actuator.fields.external_url')">
|
||
<span v-if="globalInfo?.externalUrl">
|
||
{{ globalInfo?.externalUrl }}
|
||
</span>
|
||
<span v-else>
|
||
{{ $t("core.actuator.fields_values.external_url.not_setup") }}
|
||
</span>
|
||
<VAlert
|
||
v-if="!isExternalUrlValid"
|
||
class="mt-3"
|
||
type="warning"
|
||
:title="$t('core.common.text.warning')"
|
||
:closable="false"
|
||
>
|
||
<template #description>
|
||
{{ $t("core.actuator.alert.external_url_invalid") }}
|
||
</template>
|
||
</VAlert>
|
||
</VDescriptionItem>
|
||
<VDescriptionItem
|
||
:label="$t('core.actuator.fields.start_time')"
|
||
:content="formatDatetime(startup?.timeline.startTime)"
|
||
/>
|
||
<VDescriptionItem
|
||
:label="$t('core.actuator.fields.timezone')"
|
||
:content="globalInfo?.timeZone"
|
||
/>
|
||
<VDescriptionItem
|
||
:label="$t('core.actuator.fields.locale')"
|
||
:content="globalInfo?.locale"
|
||
/>
|
||
</VDescription>
|
||
</div>
|
||
</div>
|
||
</VCard>
|
||
<VCard v-if="info" :body-class="['!p-0']">
|
||
<div class="bg-white">
|
||
<div
|
||
class="flex items-center justify-between bg-white px-4 py-4 sm:px-6"
|
||
>
|
||
<div>
|
||
<h3 class="text-lg font-medium leading-6 text-gray-900">
|
||
{{ $t("core.actuator.header.titles.environment") }}
|
||
</h3>
|
||
</div>
|
||
</div>
|
||
<div class="border-t border-gray-200">
|
||
<VDescription>
|
||
<VDescriptionItem
|
||
v-if="info.build"
|
||
:label="$t('core.actuator.fields.version')"
|
||
>
|
||
<a
|
||
:href="`https://github.com/halo-dev/halo/releases/tag/v${info.build.version}`"
|
||
class="hover:text-gray-600"
|
||
target="_blank"
|
||
>
|
||
{{ info.build.version }}
|
||
</a>
|
||
</VDescriptionItem>
|
||
<VDescriptionItem
|
||
v-if="info.build"
|
||
:label="$t('core.actuator.fields.build_time')"
|
||
:content="formatDatetime(info.build.time)"
|
||
/>
|
||
<VDescriptionItem v-if="info.git" label="Git Commit">
|
||
<a
|
||
:href="`https://github.com/halo-dev/halo/commit/${info.git.commit.id}`"
|
||
class="hover:text-gray-600"
|
||
target="_blank"
|
||
>
|
||
{{ info.git.commit.id }}
|
||
</a>
|
||
</VDescriptionItem>
|
||
<VDescriptionItem
|
||
label="Java"
|
||
:content="
|
||
[info.java.runtime.name, info.java.runtime.version].join(' / ')
|
||
"
|
||
/>
|
||
<VDescriptionItem
|
||
:label="$t('core.actuator.fields.database')"
|
||
:content="[info.database.name, info.database.version].join(' / ')"
|
||
/>
|
||
<VDescriptionItem :label="$t('core.actuator.fields.os')">
|
||
{{ info.os.name }} {{ info.os.version }} / {{ info.os.arch }}
|
||
</VDescriptionItem>
|
||
<VDescriptionItem
|
||
:label="$t('core.actuator.fields.log')"
|
||
vertical-center
|
||
>
|
||
<VButton size="sm" @click="handleDownloadLogfile()">
|
||
{{ $t("core.common.buttons.download") }}
|
||
</VButton>
|
||
</VDescriptionItem>
|
||
</VDescription>
|
||
</div>
|
||
</div>
|
||
</VCard>
|
||
</div>
|
||
</template>
|