mirror of https://github.com/halo-dev/halo
Add external URL editing capability to overview page
Signed-off-by: Ryan Wang <i@ryanc.cc>pull/7459/head
parent
254bb9b225
commit
42c374dba5
|
@ -1,8 +1,9 @@
|
|||
<script lang="ts" setup>
|
||||
import H2WarningAlert from "@/components/alerts/H2WarningAlert.vue";
|
||||
import type { GlobalInfo, Info, Startup } from "@/types";
|
||||
import type { Info, Startup } from "@/types";
|
||||
import { formatDatetime } from "@/utils/date";
|
||||
import { usePermission } from "@/utils/permission";
|
||||
import { useGlobalInfoFetch } from "@console/composables/use-global-info";
|
||||
import { useThemeStore } from "@console/stores/theme";
|
||||
import type { Plugin } from "@halo-dev/api-client";
|
||||
import { consoleApiClient } from "@halo-dev/api-client";
|
||||
|
@ -10,7 +11,6 @@ import {
|
|||
IconClipboardLine,
|
||||
IconTerminalBoxLine,
|
||||
Toast,
|
||||
VAlert,
|
||||
VButton,
|
||||
VCard,
|
||||
VDescription,
|
||||
|
@ -24,6 +24,7 @@ import { useClipboard } from "@vueuse/core";
|
|||
import axios from "axios";
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import ExternalUrlItem from "./components/ExternalUrlItem.vue";
|
||||
|
||||
const { t } = useI18n();
|
||||
const themeStore = useThemeStore();
|
||||
|
@ -40,16 +41,7 @@ const { data: info } = useQuery<Info>({
|
|||
retry: 0,
|
||||
});
|
||||
|
||||
const { data: globalInfo } = useQuery<GlobalInfo>({
|
||||
queryKey: ["system-global-info"],
|
||||
queryFn: async () => {
|
||||
const { data } = await axios.get<GlobalInfo>(`/actuator/globalinfo`, {
|
||||
withCredentials: true,
|
||||
});
|
||||
return data;
|
||||
},
|
||||
retry: 0,
|
||||
});
|
||||
const { globalInfo } = useGlobalInfoFetch();
|
||||
|
||||
const { data: startup } = useQuery<Startup>({
|
||||
queryKey: ["system-startup-info"],
|
||||
|
@ -76,20 +68,6 @@ const { data: plugins, isLoading: isPluginsLoading } = useQuery<Plugin[]>({
|
|||
enabled: computed(() => currentUserHasPermission(["system:plugins:view"])),
|
||||
});
|
||||
|
||||
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;
|
||||
});
|
||||
|
||||
// copy system information to clipboard
|
||||
const { copy, isSupported } = useClipboard({ legacy: true });
|
||||
|
||||
|
@ -243,25 +221,7 @@ const handleDownloadLogfile = () => {
|
|||
</div>
|
||||
<div class="border-t border-gray-200">
|
||||
<VDescription>
|
||||
<VDescriptionItem :label="$t('core.overview.fields.external_url')">
|
||||
<span v-if="globalInfo?.externalUrl">
|
||||
{{ globalInfo?.externalUrl }}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ $t("core.overview.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.overview.alert.external_url_invalid") }}
|
||||
</template>
|
||||
</VAlert>
|
||||
</VDescriptionItem>
|
||||
<ExternalUrlItem />
|
||||
<VDescriptionItem
|
||||
v-if="startup?.timeline.startTime"
|
||||
:label="$t('core.overview.fields.start_time')"
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
<script setup lang="ts">
|
||||
import { setFocus } from "@/formkit/utils/focus";
|
||||
import { useGlobalInfoFetch } from "@console/composables/use-global-info";
|
||||
import { coreApiClient } from "@halo-dev/api-client";
|
||||
import { Dialog, Toast, VButton, VLoading, VSpace } from "@halo-dev/components";
|
||||
import { useQuery } from "@tanstack/vue-query";
|
||||
import axios from "axios";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
const { globalInfo } = useGlobalInfoFetch();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: "close"): void;
|
||||
}>();
|
||||
|
||||
const isRestarting = ref(false);
|
||||
|
||||
function onSubmit({ externalUrl }: { externalUrl: string }) {
|
||||
Dialog.warning({
|
||||
title: t("core.overview.external_url_form.operations.save.title"),
|
||||
description: t(
|
||||
"core.overview.external_url_form.operations.save.description"
|
||||
),
|
||||
confirmType: "danger",
|
||||
confirmText: t("core.common.buttons.confirm"),
|
||||
cancelText: t("core.common.buttons.cancel"),
|
||||
onConfirm: async () => {
|
||||
const { data: configMap } = await coreApiClient.configMap.getConfigMap({
|
||||
name: "system",
|
||||
});
|
||||
|
||||
const basicConfig = JSON.parse(configMap.data?.["basic"] || "{}");
|
||||
|
||||
basicConfig.externalUrl = externalUrl.trim();
|
||||
|
||||
await coreApiClient.configMap.patchConfigMap({
|
||||
name: "system",
|
||||
jsonPatchInner: [
|
||||
{
|
||||
op: "add",
|
||||
path: "/data/basic",
|
||||
value: JSON.stringify(basicConfig),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await axios.post(`/actuator/restart`);
|
||||
|
||||
isRestarting.value = true;
|
||||
|
||||
Toast.success(t("core.common.toast.save_success"));
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setFocus("externalUrl");
|
||||
});
|
||||
|
||||
useQuery({
|
||||
queryKey: ["check-health"],
|
||||
queryFn: async () => {
|
||||
const { data } = await axios.get("/actuator/health");
|
||||
return data;
|
||||
},
|
||||
onSuccess(data) {
|
||||
if (data.status === "UP") {
|
||||
window.location.reload();
|
||||
}
|
||||
},
|
||||
retry: true,
|
||||
retryDelay: 2000,
|
||||
enabled: computed(() => isRestarting.value),
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<template v-if="!isRestarting">
|
||||
<FormKit
|
||||
id="external-url-form"
|
||||
type="form"
|
||||
name="external-url-form"
|
||||
@submit="onSubmit"
|
||||
>
|
||||
<FormKit
|
||||
id="externalUrl"
|
||||
:model-value="globalInfo?.externalUrl"
|
||||
type="url"
|
||||
name="externalUrl"
|
||||
validation="url|required"
|
||||
:validation-label="$t('core.overview.fields.external_url')"
|
||||
:classes="{ outer: '!pb-0' }"
|
||||
></FormKit>
|
||||
</FormKit>
|
||||
<VSpace class="mt-4">
|
||||
<VButton type="secondary" @click="$formkit.submit('external-url-form')">
|
||||
{{ $t("core.common.buttons.save") }}
|
||||
</VButton>
|
||||
<VButton @click="emit('close')">
|
||||
{{ $t("core.common.buttons.cancel") }}
|
||||
</VButton>
|
||||
</VSpace>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="flex items-center gap-2">
|
||||
<VLoading class="!inline-flex !py-0" />
|
||||
<div class="text-xs text-gray-600">
|
||||
{{ $t("core.overview.external_url_form.tips.restarting") }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
|
@ -0,0 +1,53 @@
|
|||
<script setup lang="ts">
|
||||
import { useGlobalInfoFetch } from "@console/composables/use-global-info";
|
||||
import {
|
||||
IconRiPencilFill,
|
||||
VAlert,
|
||||
VDescriptionItem,
|
||||
} from "@halo-dev/components";
|
||||
import { computed, ref } from "vue";
|
||||
import ExternalUrlForm from "./ExternalUrlForm.vue";
|
||||
|
||||
const { globalInfo } = useGlobalInfoFetch();
|
||||
|
||||
const isExternalUrlValid = computed(() => {
|
||||
if (!globalInfo.value?.externalUrl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const url = new URL(globalInfo.value.externalUrl);
|
||||
const { host: currentHost, protocol: currentProtocol } = window.location;
|
||||
return url.host === currentHost && url.protocol === currentProtocol;
|
||||
});
|
||||
|
||||
const showExternalUrlForm = ref(false);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VDescriptionItem :label="$t('core.overview.fields.external_url')">
|
||||
<div v-if="!showExternalUrlForm" class="flex items-center gap-3">
|
||||
<span v-if="globalInfo?.externalUrl">
|
||||
{{ globalInfo?.externalUrl }}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ $t("core.overview.fields_values.external_url.not_setup") }}
|
||||
</span>
|
||||
<IconRiPencilFill
|
||||
class="cursor-pointer text-sm text-gray-600 hover:text-gray-900"
|
||||
@click="showExternalUrlForm = true"
|
||||
/>
|
||||
</div>
|
||||
<ExternalUrlForm v-else @close="showExternalUrlForm = false" />
|
||||
<VAlert
|
||||
v-if="!isExternalUrlValid && !showExternalUrlForm"
|
||||
class="mt-3"
|
||||
type="warning"
|
||||
:title="$t('core.common.text.warning')"
|
||||
:closable="false"
|
||||
>
|
||||
<template #description>
|
||||
{{ $t("core.overview.alert.external_url_invalid") }}
|
||||
</template>
|
||||
</VAlert>
|
||||
</VDescriptionItem>
|
||||
</template>
|
|
@ -1458,6 +1458,16 @@ core:
|
|||
The external access url detected is inconsistent with the current access
|
||||
url, which may cause some links to fail to redirect properly. Please
|
||||
check the external access url settings.
|
||||
external_url_form:
|
||||
operations:
|
||||
save:
|
||||
title: Modify external url
|
||||
description: >-
|
||||
Modifying the external access address requires restarting the Halo
|
||||
service. It will automatically restart after the modification is
|
||||
completed. Do you want to continue?
|
||||
tips:
|
||||
restarting: Modification completed, waiting for restart...
|
||||
backup:
|
||||
title: Backup and Restore
|
||||
tabs:
|
||||
|
|
|
@ -1356,6 +1356,13 @@ core:
|
|||
os: 操作系统:{os}
|
||||
alert:
|
||||
external_url_invalid: 检测到外部访问地址与当前访问地址不一致,可能会导致部分链接无法正常跳转,请检查外部访问地址设置。
|
||||
external_url_form:
|
||||
operations:
|
||||
save:
|
||||
title: 修改外部访问地址
|
||||
description: 修改外部访问地址需要重启 Halo 服务,修改完成之后会自动进行重启,是否继续?
|
||||
tips:
|
||||
restarting: 修改完成,等待重启...
|
||||
backup:
|
||||
title: 备份与恢复
|
||||
tabs:
|
||||
|
|
|
@ -1341,6 +1341,13 @@ core:
|
|||
os: 操作系統:{os}
|
||||
alert:
|
||||
external_url_invalid: 檢測到外部訪問地址與當前訪問地址不一致,可能會導致部分連結無法正常跳轉,請檢查外部訪問地址設置。
|
||||
external_url_form:
|
||||
operations:
|
||||
save:
|
||||
title: 修改外部訪問地址
|
||||
description: 修改外部訪問地址需要重啟 Halo 服務,修改完成之後會自動進行重啟,是否繼續?
|
||||
tips:
|
||||
restarting: 修改完成,等待重啟...
|
||||
backup:
|
||||
title: 備份與還原
|
||||
tabs:
|
||||
|
|
Loading…
Reference in New Issue