mirror of https://github.com/halo-dev/halo
feat: add description component (#3792)
#### What type of PR is this? /kind feature /area console /milestone 2.5.0 #### What this PR does / why we need it: 为 Console 端添加 Description 组件。 #### Which issue(s) this PR fixes: Fixes #3790 #### Special notes for your reviewer: 测试方式: 1. 检查主题管理、插件详情、认证方式详情页面的样式是否异常即可。 #### Does this PR introduce a user-facing change? ```release-note 为 Console 端添加 Description 组件。 ```pull/3822/head
parent
676df239ea
commit
eec1d0758e
|
@ -19,3 +19,4 @@ export * from "./components/toast";
|
||||||
export * from "./components/loading";
|
export * from "./components/loading";
|
||||||
export * from "./components/dropdown";
|
export * from "./components/dropdown";
|
||||||
export * from "./components/tooltip";
|
export * from "./components/tooltip";
|
||||||
|
export * from "./components/description";
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<script lang="ts" setup></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<dl class="description-wrapper">
|
||||||
|
<slot />
|
||||||
|
</dl>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.description-wrapper {
|
||||||
|
@apply divide-y divide-gray-100;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,42 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
label: string;
|
||||||
|
content?: string;
|
||||||
|
verticalCenter?: boolean;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
content: undefined,
|
||||||
|
verticalCenter: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="description-item-wrapper"
|
||||||
|
:class="{ 'items-center': verticalCenter }"
|
||||||
|
>
|
||||||
|
<dt class="description-item__label">{{ label }}</dt>
|
||||||
|
<dd class="description-item__content">
|
||||||
|
<slot v-if="$slots.default" />
|
||||||
|
<template v-else>
|
||||||
|
{{ content }}
|
||||||
|
</template>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.description-item-wrapper {
|
||||||
|
@apply bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6;
|
||||||
|
|
||||||
|
.description-item__label {
|
||||||
|
@apply text-sm font-medium text-gray-900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description-item__content {
|
||||||
|
@apply mt-1 text-sm text-gray-900 sm:col-span-6 md:col-span-5 lg:col-span-3 sm:mt-0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,2 @@
|
||||||
|
export { default as VDescription } from "./Description.vue";
|
||||||
|
export { default as VDescriptionItem } from "./DescriptionItem.vue";
|
|
@ -1,5 +1,11 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { VButton, VModal, VSpace } from "@halo-dev/components";
|
import {
|
||||||
|
VButton,
|
||||||
|
VDescription,
|
||||||
|
VDescriptionItem,
|
||||||
|
VModal,
|
||||||
|
VSpace,
|
||||||
|
} from "@halo-dev/components";
|
||||||
import LazyImage from "@/components/image/LazyImage.vue";
|
import LazyImage from "@/components/image/LazyImage.vue";
|
||||||
import type { Attachment } from "@halo-dev/api-client";
|
import type { Attachment } from "@halo-dev/api-client";
|
||||||
import prettyBytes from "pretty-bytes";
|
import prettyBytes from "pretty-bytes";
|
||||||
|
@ -79,6 +85,7 @@ const onVisibleChange = (visible: boolean) => {
|
||||||
:mount-to-body="mountToBody"
|
:mount-to-body="mountToBody"
|
||||||
:layer-closable="true"
|
:layer-closable="true"
|
||||||
height="calc(100vh - 20px)"
|
height="calc(100vh - 20px)"
|
||||||
|
:body-class="['!p-0']"
|
||||||
@update:visible="onVisibleChange"
|
@update:visible="onVisibleChange"
|
||||||
>
|
>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
|
@ -87,7 +94,7 @@ const onVisibleChange = (visible: boolean) => {
|
||||||
<div class="overflow-hidden bg-white">
|
<div class="overflow-hidden bg-white">
|
||||||
<div
|
<div
|
||||||
v-if="onlyPreview && isImage(attachment?.spec.mediaType)"
|
v-if="onlyPreview && isImage(attachment?.spec.mediaType)"
|
||||||
class="flex justify-center"
|
class="flex justify-center p-4"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
v-tooltip.bottom="
|
v-tooltip.bottom="
|
||||||
|
@ -99,14 +106,11 @@ const onVisibleChange = (visible: boolean) => {
|
||||||
@click="onlyPreview = !onlyPreview"
|
@click="onlyPreview = !onlyPreview"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<dl v-else>
|
<div v-else>
|
||||||
<div
|
<VDescription>
|
||||||
class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
<VDescriptionItem
|
||||||
>
|
:label="$t('core.attachment.detail_modal.fields.preview')"
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
>
|
||||||
{{ $t("core.attachment.detail_modal.fields.preview") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
<div
|
<div
|
||||||
v-if="isImage(attachment?.spec.mediaType)"
|
v-if="isImage(attachment?.spec.mediaType)"
|
||||||
@click="onlyPreview = !onlyPreview"
|
@click="onlyPreview = !onlyPreview"
|
||||||
|
@ -149,80 +153,47 @@ const onVisibleChange = (visible: boolean) => {
|
||||||
<span v-else>
|
<span v-else>
|
||||||
{{ $t("core.attachment.detail_modal.preview.not_support") }}
|
{{ $t("core.attachment.detail_modal.preview.not_support") }}
|
||||||
</span>
|
</span>
|
||||||
</dd>
|
</VDescriptionItem>
|
||||||
</div>
|
<VDescriptionItem
|
||||||
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
:label="$t('core.attachment.detail_modal.fields.storage_policy')"
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
:content="policy?.spec.displayName"
|
||||||
{{ $t("core.attachment.detail_modal.fields.storage_policy") }}
|
></VDescriptionItem>
|
||||||
</dt>
|
<VDescriptionItem
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
:label="$t('core.attachment.detail_modal.fields.group')"
|
||||||
{{ policy?.spec.displayName }}
|
:content="
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.attachment.detail_modal.fields.group") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
{{
|
|
||||||
getGroupName(attachment?.spec.groupName) ||
|
getGroupName(attachment?.spec.groupName) ||
|
||||||
$t("core.attachment.common.text.ungrouped")
|
$t('core.attachment.common.text.ungrouped')
|
||||||
}}
|
"
|
||||||
</dd>
|
/>
|
||||||
</div>
|
<VDescriptionItem
|
||||||
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
:label="$t('core.attachment.detail_modal.fields.display_name')"
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
:content="attachment?.spec.displayName"
|
||||||
{{ $t("core.attachment.detail_modal.fields.display_name") }}
|
/>
|
||||||
</dt>
|
<VDescriptionItem
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
:label="$t('core.attachment.detail_modal.fields.media_type')"
|
||||||
{{ attachment?.spec.displayName }}
|
:content="attachment?.spec.mediaType"
|
||||||
</dd>
|
/>
|
||||||
</div>
|
<VDescriptionItem
|
||||||
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
:label="$t('core.attachment.detail_modal.fields.size')"
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
:content="prettyBytes(attachment?.spec.size || 0)"
|
||||||
{{ $t("core.attachment.detail_modal.fields.media_type") }}
|
/>
|
||||||
</dt>
|
<VDescriptionItem
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
:label="$t('core.attachment.detail_modal.fields.owner')"
|
||||||
{{ attachment?.spec.mediaType }}
|
:content="attachment?.spec.ownerName"
|
||||||
</dd>
|
/>
|
||||||
</div>
|
<VDescriptionItem
|
||||||
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
:label="$t('core.attachment.detail_modal.fields.creation_time')"
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
:content="formatDatetime(attachment?.metadata.creationTimestamp)"
|
||||||
{{ $t("core.attachment.detail_modal.fields.size") }}
|
/>
|
||||||
</dt>
|
<VDescriptionItem
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
:label="$t('core.attachment.detail_modal.fields.permalink')"
|
||||||
{{ prettyBytes(attachment?.spec.size || 0) }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.attachment.detail_modal.fields.owner") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
{{ attachment?.spec.ownerName }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.attachment.detail_modal.fields.creation_time") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
{{ formatDatetime(attachment?.metadata.creationTimestamp) }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.attachment.detail_modal.fields.permalink") }}
|
|
||||||
</dt>
|
|
||||||
<dd
|
|
||||||
class="mt-1 text-sm text-gray-900 hover:text-blue-600 sm:col-span-2 sm:mt-0"
|
|
||||||
>
|
>
|
||||||
<a target="_blank" :href="attachment?.status?.permalink">
|
<a target="_blank" :href="attachment?.status?.permalink">
|
||||||
{{ attachment?.status?.permalink }}
|
{{ attachment?.status?.permalink }}
|
||||||
</a>
|
</a>
|
||||||
</dd>
|
</VDescriptionItem>
|
||||||
</div>
|
</VDescription>
|
||||||
</dl>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<VSpace>
|
<VSpace>
|
||||||
|
|
|
@ -17,6 +17,8 @@ import {
|
||||||
VDropdown,
|
VDropdown,
|
||||||
VDropdownItem,
|
VDropdownItem,
|
||||||
VDropdownDivider,
|
VDropdownDivider,
|
||||||
|
VDescription,
|
||||||
|
VDescriptionItem,
|
||||||
} from "@halo-dev/components";
|
} from "@halo-dev/components";
|
||||||
import ThemeUploadModal from "./components/ThemeUploadModal.vue";
|
import ThemeUploadModal from "./components/ThemeUploadModal.vue";
|
||||||
|
|
||||||
|
@ -126,141 +128,46 @@ const onUpgradeModalClose = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-t border-gray-200">
|
<div class="border-t border-gray-200">
|
||||||
<dl class="divide-y divide-gray-100">
|
<VDescription>
|
||||||
<div
|
<VDescriptionItem
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
label="ID"
|
||||||
>
|
:content="selectedTheme?.metadata.name"
|
||||||
<dt class="text-sm font-medium text-gray-900">ID</dt>
|
/>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
<VDescriptionItem
|
||||||
{{ selectedTheme?.metadata.name }}
|
:label="$t('core.theme.detail.fields.author')"
|
||||||
</dd>
|
:content="selectedTheme?.spec.author.name"
|
||||||
</div>
|
/>
|
||||||
<div
|
<VDescriptionItem :label="$t('core.theme.detail.fields.website')">
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
<a
|
||||||
>
|
:href="selectedTheme?.spec.website"
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
class="hover:text-gray-600"
|
||||||
{{ $t("core.theme.detail.fields.author") }}
|
target="_blank"
|
||||||
</dt>
|
>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
{{ selectedTheme?.spec.website }}
|
||||||
{{ selectedTheme?.spec.author.name }}
|
</a>
|
||||||
</dd>
|
</VDescriptionItem>
|
||||||
</div>
|
<VDescriptionItem :label="$t('core.theme.detail.fields.repo')">
|
||||||
<div
|
<a
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
:href="selectedTheme?.spec.repo"
|
||||||
>
|
class="hover:text-gray-600"
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
target="_blank"
|
||||||
{{ $t("core.theme.detail.fields.website") }}
|
>
|
||||||
</dt>
|
{{ selectedTheme?.spec.repo }}
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
</a>
|
||||||
<a
|
</VDescriptionItem>
|
||||||
:href="selectedTheme?.spec.website"
|
<VDescriptionItem
|
||||||
class="hover:text-gray-600"
|
:label="$t('core.theme.detail.fields.version')"
|
||||||
target="_blank"
|
:content="selectedTheme?.spec.version"
|
||||||
>
|
/>
|
||||||
{{ selectedTheme?.spec.website }}
|
<VDescriptionItem
|
||||||
</a>
|
:label="$t('core.theme.detail.fields.requires')"
|
||||||
</dd>
|
:content="selectedTheme?.spec.requires"
|
||||||
</div>
|
/>
|
||||||
<div
|
<VDescriptionItem
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
:label="$t('core.theme.detail.fields.storage_location')"
|
||||||
>
|
:content="selectedTheme?.status?.location"
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
/>
|
||||||
{{ $t("core.theme.detail.fields.repo") }}
|
</VDescription>
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
|
||||||
<a
|
|
||||||
:href="selectedTheme?.spec.repo"
|
|
||||||
class="hover:text-gray-600"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{{ selectedTheme?.spec.repo }}
|
|
||||||
</a>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.theme.detail.fields.version") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
|
||||||
{{ selectedTheme?.spec.version }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.theme.detail.fields.requires") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
|
||||||
{{ selectedTheme?.spec.requires }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.theme.detail.fields.storage_location") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
|
||||||
{{ selectedTheme?.status?.location }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<!-- TODO: add display required plugins support -->
|
|
||||||
<div
|
|
||||||
v-if="false"
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.theme.detail.fields.plugin_requires") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm sm:col-span-3 sm:mt-0">
|
|
||||||
<VAlert
|
|
||||||
description="当前有 1 个插件还未安装"
|
|
||||||
title="提示"
|
|
||||||
></VAlert>
|
|
||||||
<ul class="mt-2 space-y-2">
|
|
||||||
<li>
|
|
||||||
<div
|
|
||||||
class="inline-flex w-96 cursor-pointer flex-col gap-y-3 rounded border p-5 hover:border-primary"
|
|
||||||
>
|
|
||||||
<RouterLink
|
|
||||||
:to="{
|
|
||||||
name: 'PluginDetail',
|
|
||||||
params: { name: 'PluginLinks' },
|
|
||||||
}"
|
|
||||||
class="font-medium text-gray-900 hover:text-blue-400"
|
|
||||||
>
|
|
||||||
run.halo.plugins.links
|
|
||||||
</RouterLink>
|
|
||||||
<div class="text-xs">
|
|
||||||
<VSpace>
|
|
||||||
<VTag>{{ $t("core.common.status.installed") }}</VTag>
|
|
||||||
</VSpace>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div
|
|
||||||
class="inline-flex w-96 cursor-pointer flex-col gap-y-3 rounded border p-5 hover:border-primary"
|
|
||||||
>
|
|
||||||
<span class="font-medium hover:text-blue-400">
|
|
||||||
run.halo.plugins.photos
|
|
||||||
</span>
|
|
||||||
<div class="text-xs">
|
|
||||||
<VSpace>
|
|
||||||
<VTag>
|
|
||||||
{{ $t("core.common.status.not_installed") }}
|
|
||||||
</VTag>
|
|
||||||
</VSpace>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
</dl>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
|
@ -7,6 +7,8 @@ import {
|
||||||
VCard,
|
VCard,
|
||||||
VButton,
|
VButton,
|
||||||
Toast,
|
Toast,
|
||||||
|
VDescription,
|
||||||
|
VDescriptionItem,
|
||||||
} from "@halo-dev/components";
|
} from "@halo-dev/components";
|
||||||
import { computed, onMounted, ref } from "vue";
|
import { computed, onMounted, ref } from "vue";
|
||||||
import type { Info, GlobalInfo, Startup } from "./types";
|
import type { Info, GlobalInfo, Startup } from "./types";
|
||||||
|
@ -159,64 +161,39 @@ const handleDownloadLogfile = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-t border-gray-200">
|
<div class="border-t border-gray-200">
|
||||||
<dl class="divide-y divide-gray-100">
|
<VDescription>
|
||||||
<div
|
<VDescriptionItem :label="$t('core.actuator.fields.external_url')">
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
<span v-if="globalInfo?.externalUrl">
|
||||||
>
|
{{ globalInfo?.externalUrl }}
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
</span>
|
||||||
{{ $t("core.actuator.fields.external_url") }}
|
<span v-else>
|
||||||
</dt>
|
{{ $t("core.actuator.fields_values.external_url.not_setup") }}
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
</span>
|
||||||
<span v-if="globalInfo?.externalUrl">
|
<VAlert
|
||||||
{{ globalInfo?.externalUrl }}
|
v-if="!isExternalUrlValid"
|
||||||
</span>
|
class="mt-3"
|
||||||
<span v-else>
|
type="warning"
|
||||||
{{ $t("core.actuator.fields_values.external_url.not_setup") }}
|
:title="$t('core.common.text.warning')"
|
||||||
</span>
|
:closable="false"
|
||||||
<VAlert
|
>
|
||||||
v-if="!isExternalUrlValid"
|
<template #description>
|
||||||
class="mt-3"
|
{{ $t("core.actuator.alert.external_url_invalid") }}
|
||||||
type="warning"
|
</template>
|
||||||
:title="$t('core.common.text.warning')"
|
</VAlert>
|
||||||
:closable="false"
|
</VDescriptionItem>
|
||||||
>
|
<VDescriptionItem
|
||||||
<template #description>
|
:label="$t('core.actuator.fields.start_time')"
|
||||||
{{ $t("core.actuator.alert.external_url_invalid") }}
|
:content="formatDatetime(startup?.timeline.startTime)"
|
||||||
</template>
|
/>
|
||||||
</VAlert>
|
<VDescriptionItem
|
||||||
</dd>
|
:label="$t('core.actuator.fields.timezone')"
|
||||||
</div>
|
:content="globalInfo?.timeZone"
|
||||||
<div
|
/>
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
<VDescriptionItem
|
||||||
>
|
:label="$t('core.actuator.fields.locale')"
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
:content="globalInfo?.locale"
|
||||||
{{ $t("core.actuator.fields.start_time") }}
|
/>
|
||||||
</dt>
|
</VDescription>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
{{ formatDatetime(startup?.timeline.startTime) }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.actuator.fields.timezone") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
{{ globalInfo?.timeZone }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.actuator.fields.locale") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
{{ globalInfo?.locale }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
</dl>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
@ -232,91 +209,55 @@ const handleDownloadLogfile = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-t border-gray-200">
|
<div class="border-t border-gray-200">
|
||||||
<dl class="divide-y divide-gray-100">
|
<VDescription>
|
||||||
<div
|
<VDescriptionItem
|
||||||
v-if="info.build"
|
v-if="info.build"
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
:label="$t('core.actuator.fields.version')"
|
||||||
>
|
>
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
<a
|
||||||
{{ $t("core.actuator.fields.version") }}
|
:href="`https://github.com/halo-dev/halo/releases/tag/v${info.build.version}`"
|
||||||
</dt>
|
class="hover:text-gray-600"
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
target="_blank"
|
||||||
<a
|
>
|
||||||
:href="`https://github.com/halo-dev/halo/releases/tag/v${info.build.version}`"
|
{{ info.build.version }}
|
||||||
class="hover:text-gray-600"
|
</a>
|
||||||
target="_blank"
|
</VDescriptionItem>
|
||||||
>
|
<VDescriptionItem
|
||||||
{{ info.build.version }}
|
|
||||||
</a>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="info.build"
|
v-if="info.build"
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
: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
|
||||||
>
|
>
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
<VButton size="sm" @click="handleDownloadLogfile()">
|
||||||
{{ $t("core.actuator.fields.build_time") }}
|
{{ $t("core.common.buttons.download") }}
|
||||||
</dt>
|
</VButton>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
</VDescriptionItem>
|
||||||
{{ formatDatetime(info.build.time) }}
|
</VDescription>
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="info.git"
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">Git Commit</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
<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>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">Java</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
{{ info.java.runtime.name }} / {{ info.java.runtime.version }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.actuator.fields.database") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
{{ [info.database.name, info.database.version].join(" / ") }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.actuator.fields.os") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
{{ info.os.name }} {{ info.os.version }} / {{ info.os.arch }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="items-center bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.actuator.fields.log") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
<VButton size="sm" @click="handleDownloadLogfile()">
|
|
||||||
{{ $t("core.common.buttons.download") }}
|
|
||||||
</VButton>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
</dl>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
|
|
@ -9,6 +9,8 @@ import {
|
||||||
VAvatar,
|
VAvatar,
|
||||||
VButton,
|
VButton,
|
||||||
VCard,
|
VCard,
|
||||||
|
VDescription,
|
||||||
|
VDescriptionItem,
|
||||||
VPageHeader,
|
VPageHeader,
|
||||||
VTabbar,
|
VTabbar,
|
||||||
} from "@halo-dev/components";
|
} from "@halo-dev/components";
|
||||||
|
@ -167,82 +169,56 @@ const handleSaveConfigMap = async () => {
|
||||||
</template>
|
</template>
|
||||||
<div class="bg-white">
|
<div class="bg-white">
|
||||||
<div v-if="activeTab === 'detail'">
|
<div v-if="activeTab === 'detail'">
|
||||||
<dl class="divide-y divide-gray-100">
|
<VDescription>
|
||||||
<div
|
<VDescriptionItem
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
:label="
|
||||||
|
$t('core.identity_authentication.detail.fields.display_name')
|
||||||
|
"
|
||||||
|
:content="authProvider?.spec.displayName"
|
||||||
|
/>
|
||||||
|
<VDescriptionItem
|
||||||
|
:label="
|
||||||
|
$t('core.identity_authentication.detail.fields.description')
|
||||||
|
"
|
||||||
|
:content="authProvider?.spec.description"
|
||||||
|
/>
|
||||||
|
<VDescriptionItem
|
||||||
|
:label="$t('core.identity_authentication.detail.fields.website')"
|
||||||
>
|
>
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
<a
|
||||||
{{
|
v-if="authProvider?.spec.website"
|
||||||
$t("core.identity_authentication.detail.fields.display_name")
|
:href="authProvider?.spec.website"
|
||||||
}}
|
target="_blank"
|
||||||
</dt>
|
>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
{{ authProvider.spec.website }}
|
||||||
{{ authProvider?.spec.displayName }}
|
</a>
|
||||||
</dd>
|
<span v-else>
|
||||||
</div>
|
{{ $t("core.common.text.none") }}
|
||||||
<div
|
</span>
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
</VDescriptionItem>
|
||||||
|
<VDescriptionItem
|
||||||
|
:label="
|
||||||
|
$t('core.identity_authentication.detail.fields.help_page')
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
<a
|
||||||
{{
|
v-if="authProvider?.spec.helpPage"
|
||||||
$t("core.identity_authentication.detail.fields.description")
|
:href="authProvider?.spec.helpPage"
|
||||||
}}
|
target="_blank"
|
||||||
</dt>
|
>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
{{ authProvider.spec.helpPage }}
|
||||||
{{ authProvider?.spec.description }}
|
</a>
|
||||||
</dd>
|
<span v-else>{{ $t("core.common.text.none") }}</span>
|
||||||
</div>
|
</VDescriptionItem>
|
||||||
<div
|
<VDescriptionItem
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
:label="
|
||||||
>
|
$t(
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
'core.identity_authentication.detail.fields.authentication_url'
|
||||||
{{ $t("core.identity_authentication.detail.fields.website") }}
|
)
|
||||||
</dt>
|
"
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
:content="authProvider?.spec.authenticationUrl"
|
||||||
<a
|
/>
|
||||||
v-if="authProvider?.spec.website"
|
</VDescription>
|
||||||
:href="authProvider?.spec.website"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{{ authProvider.spec.website }}
|
|
||||||
</a>
|
|
||||||
<span v-else>
|
|
||||||
{{ $t("core.common.text.none") }}
|
|
||||||
</span>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.identity_authentication.detail.fields.help_page") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
|
||||||
<a
|
|
||||||
v-if="authProvider?.spec.helpPage"
|
|
||||||
:href="authProvider?.spec.helpPage"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{{ authProvider.spec.helpPage }}
|
|
||||||
</a>
|
|
||||||
<span v-else>{{ $t("core.common.text.none") }}</span>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{
|
|
||||||
$t(
|
|
||||||
"core.identity_authentication.detail.fields.authentication_url"
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
|
||||||
{{ authProvider?.spec.authenticationUrl }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
</dl>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="activeTab === 'setting'" class="bg-white p-4">
|
<div v-if="activeTab === 'setting'" class="bg-white p-4">
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { VSwitch, VTag } from "@halo-dev/components";
|
import {
|
||||||
|
VDescription,
|
||||||
|
VDescriptionItem,
|
||||||
|
VSwitch,
|
||||||
|
VTag,
|
||||||
|
} from "@halo-dev/components";
|
||||||
import type { Ref } from "vue";
|
import type { Ref } from "vue";
|
||||||
import { computed, inject } from "vue";
|
import { computed, inject } from "vue";
|
||||||
import { apiClient } from "@/utils/api-client";
|
import { apiClient } from "@/utils/api-client";
|
||||||
|
@ -83,183 +88,114 @@ const pluginRoleTemplateGroups = computed<RoleTemplateGroup[]>(() => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-t border-gray-200">
|
<div class="border-t border-gray-200">
|
||||||
<dl class="divide-y divide-gray-100">
|
<VDescription>
|
||||||
<div
|
<VDescriptionItem
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
:label="$t('core.plugin.detail.fields.display_name')"
|
||||||
>
|
:content="plugin?.spec.displayName"
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
/>
|
||||||
{{ $t("core.plugin.detail.fields.display_name") }}
|
<VDescriptionItem
|
||||||
</dt>
|
:label="$t('core.plugin.detail.fields.description')"
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
:content="plugin?.spec.description"
|
||||||
{{ plugin?.spec.displayName }}
|
/>
|
||||||
</dd>
|
<VDescriptionItem
|
||||||
</div>
|
:label="$t('core.plugin.detail.fields.version')"
|
||||||
<div
|
:content="plugin?.spec.version"
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
/>
|
||||||
>
|
<VDescriptionItem
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
:label="$t('core.plugin.detail.fields.requires')"
|
||||||
{{ $t("core.plugin.detail.fields.description") }}
|
:content="plugin?.spec.requires"
|
||||||
</dt>
|
/>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
<VDescriptionItem :label="$t('core.plugin.detail.fields.author')">
|
||||||
{{ plugin?.spec.description }}
|
<a
|
||||||
</dd>
|
v-if="plugin?.spec.author"
|
||||||
</div>
|
:href="plugin?.spec.author.website"
|
||||||
<div
|
target="_blank"
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.plugin.detail.fields.version") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
{{ plugin?.spec.version }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.plugin.detail.fields.requires") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
{{ plugin?.spec.requires }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.plugin.detail.fields.author") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
<a
|
|
||||||
v-if="plugin?.spec.author"
|
|
||||||
:href="plugin?.spec.author.website"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{{ plugin?.spec.author.name }}
|
|
||||||
</a>
|
|
||||||
<span v-else>
|
|
||||||
{{ $t("core.common.text.none") }}
|
|
||||||
</span>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.plugin.detail.fields.license") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
<ul
|
|
||||||
v-if="plugin?.spec.license && plugin?.spec.license.length"
|
|
||||||
class="list-inside"
|
|
||||||
:class="{ 'list-disc': plugin?.spec.license.length > 1 }"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
v-for="(license, index) in plugin.spec.license"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
<a v-if="license.url" :href="license.url" target="_blank">
|
|
||||||
{{ license.name }}
|
|
||||||
</a>
|
|
||||||
<span>
|
|
||||||
{{ license.name }}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<!-- TODO add display extensions support -->
|
|
||||||
<div
|
|
||||||
v-if="false"
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">模型定义</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
<span>
|
|
||||||
{{ $t("core.common.text.none") }}
|
|
||||||
</span>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
:class="`${
|
|
||||||
pluginRoleTemplateGroups.length ? 'bg-gray-50' : 'bg-white'
|
|
||||||
}`"
|
|
||||||
class="px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.plugin.detail.fields.role_templates") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-5 sm:mt-0">
|
|
||||||
<dl
|
|
||||||
v-if="pluginRoleTemplateGroups.length"
|
|
||||||
class="divide-y divide-gray-100"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-for="(group, groupIndex) in pluginRoleTemplateGroups"
|
|
||||||
:key="groupIndex"
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ group.module }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
<ul class="space-y-2">
|
|
||||||
<li v-for="(role, index) in group.roles" :key="index">
|
|
||||||
<div
|
|
||||||
class="inline-flex w-72 cursor-pointer flex-row items-center gap-4 rounded border p-5 hover:border-primary"
|
|
||||||
>
|
|
||||||
<div class="inline-flex flex-col gap-y-3">
|
|
||||||
<span class="font-medium text-gray-900">
|
|
||||||
{{
|
|
||||||
role.metadata.annotations?.[
|
|
||||||
rbacAnnotations.DISPLAY_NAME
|
|
||||||
]
|
|
||||||
}}
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
v-if="
|
|
||||||
role.metadata.annotations?.[
|
|
||||||
rbacAnnotations.DEPENDENCIES
|
|
||||||
]
|
|
||||||
"
|
|
||||||
class="text-xs text-gray-400"
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
$t("core.role.common.text.dependent_on", {
|
|
||||||
roles: JSON.parse(
|
|
||||||
role.metadata.annotations?.[
|
|
||||||
rbacAnnotations.DEPENDENCIES
|
|
||||||
]
|
|
||||||
).join(", "),
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
</dl>
|
|
||||||
<span v-else>
|
|
||||||
{{ $t("core.common.text.none") }}
|
|
||||||
</span>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.plugin.detail.fields.last_starttime") }}
|
|
||||||
</dt>
|
|
||||||
<dd
|
|
||||||
class="mt-1 text-sm tabular-nums text-gray-900 sm:col-span-2 sm:mt-0"
|
|
||||||
>
|
>
|
||||||
{{ formatDatetime(plugin?.status?.lastStartTime) }}
|
{{ plugin?.spec.author.name }}
|
||||||
</dd>
|
</a>
|
||||||
</div>
|
<span v-else>
|
||||||
</dl>
|
{{ $t("core.common.text.none") }}
|
||||||
|
</span>
|
||||||
|
</VDescriptionItem>
|
||||||
|
<VDescriptionItem :label="$t('core.plugin.detail.fields.license')">
|
||||||
|
<ul
|
||||||
|
v-if="plugin?.spec.license && plugin?.spec.license.length"
|
||||||
|
class="list-inside"
|
||||||
|
:class="{ 'list-disc': plugin?.spec.license.length > 1 }"
|
||||||
|
>
|
||||||
|
<li v-for="(license, index) in plugin.spec.license" :key="index">
|
||||||
|
<a v-if="license.url" :href="license.url" target="_blank">
|
||||||
|
{{ license.name }}
|
||||||
|
</a>
|
||||||
|
<span>
|
||||||
|
{{ license.name }}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</VDescriptionItem>
|
||||||
|
<VDescriptionItem
|
||||||
|
:label="$t('core.plugin.detail.fields.role_templates')"
|
||||||
|
>
|
||||||
|
<dl
|
||||||
|
v-if="pluginRoleTemplateGroups.length"
|
||||||
|
class="divide-y divide-gray-100"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(group, groupIndex) in pluginRoleTemplateGroups"
|
||||||
|
:key="groupIndex"
|
||||||
|
class="rounded bg-gray-50 px-4 py-5 hover:bg-gray-100 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
||||||
|
>
|
||||||
|
<dt class="text-sm font-medium text-gray-900">
|
||||||
|
{{ group.module }}
|
||||||
|
</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||||
|
<ul class="space-y-2">
|
||||||
|
<li v-for="(role, index) in group.roles" :key="index">
|
||||||
|
<div
|
||||||
|
class="inline-flex w-72 cursor-pointer flex-row items-center gap-4 rounded border p-5 hover:border-primary"
|
||||||
|
>
|
||||||
|
<div class="inline-flex flex-col gap-y-3">
|
||||||
|
<span class="font-medium text-gray-900">
|
||||||
|
{{
|
||||||
|
role.metadata.annotations?.[
|
||||||
|
rbacAnnotations.DISPLAY_NAME
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-if="
|
||||||
|
role.metadata.annotations?.[
|
||||||
|
rbacAnnotations.DEPENDENCIES
|
||||||
|
]
|
||||||
|
"
|
||||||
|
class="text-xs text-gray-400"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
$t("core.role.common.text.dependent_on", {
|
||||||
|
roles: JSON.parse(
|
||||||
|
role.metadata.annotations?.[
|
||||||
|
rbacAnnotations.DEPENDENCIES
|
||||||
|
]
|
||||||
|
).join(", "),
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
</dl>
|
||||||
|
<span v-else>
|
||||||
|
{{ $t("core.common.text.none") }}
|
||||||
|
</span>
|
||||||
|
</VDescriptionItem>
|
||||||
|
<VDescriptionItem
|
||||||
|
:label="$t('core.plugin.detail.fields.last_starttime')"
|
||||||
|
:content="formatDatetime(plugin?.status?.lastStartTime)"
|
||||||
|
/>
|
||||||
|
</VDescription>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
|
@ -9,6 +9,8 @@ import {
|
||||||
VTag,
|
VTag,
|
||||||
VAvatar,
|
VAvatar,
|
||||||
VAlert,
|
VAlert,
|
||||||
|
VDescription,
|
||||||
|
VDescriptionItem,
|
||||||
} from "@halo-dev/components";
|
} from "@halo-dev/components";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import { computed, onMounted, ref, watch } from "vue";
|
import { computed, onMounted, ref, watch } from "vue";
|
||||||
|
@ -19,7 +21,6 @@ import {
|
||||||
useRoleForm,
|
useRoleForm,
|
||||||
useRoleTemplateSelection,
|
useRoleTemplateSelection,
|
||||||
} from "@/modules/system/roles/composables/use-role";
|
} from "@/modules/system/roles/composables/use-role";
|
||||||
import { useUserFetch } from "@/modules/system/users/composables/use-user";
|
|
||||||
import { SUPER_ROLE_NAME } from "@/constants/constants";
|
import { SUPER_ROLE_NAME } from "@/constants/constants";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { formatDatetime } from "@/utils/date";
|
import { formatDatetime } from "@/utils/date";
|
||||||
|
@ -34,8 +35,6 @@ const { roleTemplateGroups, handleRoleTemplateSelect, selectedRoleTemplates } =
|
||||||
|
|
||||||
const { formState, saving, handleCreateOrUpdate } = useRoleForm();
|
const { formState, saving, handleCreateOrUpdate } = useRoleForm();
|
||||||
|
|
||||||
const { users } = useUserFetch({ fetchOnMounted: false });
|
|
||||||
|
|
||||||
const isSystemReserved = computed(() => {
|
const isSystemReserved = computed(() => {
|
||||||
return (
|
return (
|
||||||
formState.value.metadata.labels?.[roleLabels.SYSTEM_RESERVED] === "true"
|
formState.value.metadata.labels?.[roleLabels.SYSTEM_RESERVED] === "true"
|
||||||
|
@ -130,114 +129,34 @@ onMounted(() => {
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-t border-gray-200">
|
<div class="border-t border-gray-200">
|
||||||
<dl class="divide-y divide-gray-100">
|
<VDescription>
|
||||||
<div
|
<VDescriptionItem
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
:label="$t('core.role.detail.fields.display_name')"
|
||||||
>
|
>
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
{{
|
||||||
{{ $t("core.role.detail.fields.display_name") }}
|
formState.metadata?.annotations?.[
|
||||||
</dt>
|
rbacAnnotations.DISPLAY_NAME
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
] || formState.metadata?.name
|
||||||
|
}}
|
||||||
|
</VDescriptionItem>
|
||||||
|
<VDescriptionItem
|
||||||
|
:label="$t('core.role.detail.fields.name')"
|
||||||
|
:content="formState.metadata?.name"
|
||||||
|
/>
|
||||||
|
<VDescriptionItem :label="$t('core.role.detail.fields.type')">
|
||||||
|
<VTag>
|
||||||
{{
|
{{
|
||||||
formState.metadata?.annotations?.[
|
isSystemReserved
|
||||||
rbacAnnotations.DISPLAY_NAME
|
? t("core.role.common.text.system_reserved")
|
||||||
] || formState.metadata?.name
|
: t("core.role.common.text.custom")
|
||||||
}}
|
}}
|
||||||
</dd>
|
</VTag>
|
||||||
</div>
|
</VDescriptionItem>
|
||||||
<div
|
<VDescriptionItem
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
:label="$t('core.role.detail.fields.creation_time')"
|
||||||
>
|
:content="formatDatetime(formState.metadata.creationTimestamp)"
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
/>
|
||||||
{{ $t("core.role.detail.fields.name") }}
|
</VDescription>
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
{{ formState.metadata?.name }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.role.detail.fields.type") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
<VTag>
|
|
||||||
{{
|
|
||||||
isSystemReserved
|
|
||||||
? t("core.role.common.text.system_reserved")
|
|
||||||
: t("core.role.common.text.custom")
|
|
||||||
}}
|
|
||||||
</VTag>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.role.detail.fields.creation_time") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
{{ formatDatetime(formState.metadata.creationTimestamp) }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<!-- TODO: 支持通过当前角色查询用户 -->
|
|
||||||
<div
|
|
||||||
v-if="false"
|
|
||||||
class="bg-gray-50 px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">用户</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
|
||||||
<div
|
|
||||||
class="h-96 overflow-y-auto overflow-x-hidden rounded-sm bg-white shadow-sm transition-all hover:shadow"
|
|
||||||
>
|
|
||||||
<ul class="divide-y divide-gray-100" role="list">
|
|
||||||
<RouterLink
|
|
||||||
v-for="(user, index) in users"
|
|
||||||
:key="index"
|
|
||||||
:to="{
|
|
||||||
name: 'UserDetail',
|
|
||||||
params: { name: user.metadata.name },
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<li class="block cursor-pointer hover:bg-gray-50">
|
|
||||||
<div class="flex items-center px-4 py-4">
|
|
||||||
<div class="flex min-w-0 flex-1 items-center">
|
|
||||||
<div class="flex flex-shrink-0 items-center">
|
|
||||||
<VAvatar
|
|
||||||
:alt="user.spec.displayName"
|
|
||||||
:src="user.spec.avatar"
|
|
||||||
size="md"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="min-w-0 flex-1 px-4 md:grid md:grid-cols-2 md:gap-4"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<p
|
|
||||||
class="truncate text-sm font-medium text-gray-900"
|
|
||||||
>
|
|
||||||
{{ user.spec.displayName }}
|
|
||||||
</p>
|
|
||||||
<p class="mt-2 flex items-center">
|
|
||||||
<span class="text-xs text-gray-500">
|
|
||||||
{{ user.metadata.name }}
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<IconArrowRight />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</RouterLink>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
</dl>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Dialog, IconUserSettings, VButton, VTag } from "@halo-dev/components";
|
import {
|
||||||
|
Dialog,
|
||||||
|
IconUserSettings,
|
||||||
|
VButton,
|
||||||
|
VDescription,
|
||||||
|
VDescriptionItem,
|
||||||
|
VTag,
|
||||||
|
} from "@halo-dev/components";
|
||||||
import type { ComputedRef, Ref } from "vue";
|
import type { ComputedRef, Ref } from "vue";
|
||||||
import { inject, computed } from "vue";
|
import { inject, computed } from "vue";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
|
@ -64,144 +71,99 @@ const handleBindAuth = (authProvider: ListedAuthProvider) => {
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="border-t border-gray-100">
|
<div class="border-t border-gray-100">
|
||||||
<dl class="divide-y divide-gray-50">
|
<VDescription>
|
||||||
<div
|
<VDescriptionItem
|
||||||
class="bg-white px-2 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4"
|
:label="$t('core.user.detail.fields.display_name')"
|
||||||
|
:content="user?.user.spec.displayName"
|
||||||
|
class="!px-2"
|
||||||
|
/>
|
||||||
|
<VDescriptionItem
|
||||||
|
:label="$t('core.user.detail.fields.username')"
|
||||||
|
:content="user?.user.metadata.name"
|
||||||
|
class="!px-2"
|
||||||
|
/>
|
||||||
|
<VDescriptionItem
|
||||||
|
:label="$t('core.user.detail.fields.email')"
|
||||||
|
:content="user?.user.spec.email || $t('core.common.text.none')"
|
||||||
|
class="!px-2"
|
||||||
|
/>
|
||||||
|
<VDescriptionItem
|
||||||
|
:label="$t('core.user.detail.fields.roles')"
|
||||||
|
class="!px-2"
|
||||||
>
|
>
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
<VTag
|
||||||
{{ $t("core.user.detail.fields.display_name") }}
|
v-for="(role, index) in user?.roles"
|
||||||
</dt>
|
:key="index"
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
@click="
|
||||||
{{ user?.user.spec?.displayName }}
|
router.push({
|
||||||
</dd>
|
name: 'RoleDetail',
|
||||||
</div>
|
params: { name: role.metadata.name },
|
||||||
<div
|
})
|
||||||
class="bg-white px-2 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4"
|
"
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.user.detail.fields.username") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
|
||||||
{{ user?.user.metadata?.name }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-2 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.user.detail.fields.email") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
|
||||||
{{ user?.user.spec?.email || $t("core.common.text.none") }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-2 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.user.detail.fields.roles") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
|
||||||
<VTag
|
|
||||||
v-for="(role, index) in user?.roles"
|
|
||||||
:key="index"
|
|
||||||
@click="
|
|
||||||
router.push({
|
|
||||||
name: 'RoleDetail',
|
|
||||||
params: { name: role.metadata.name },
|
|
||||||
})
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<template #leftIcon>
|
|
||||||
<IconUserSettings />
|
|
||||||
</template>
|
|
||||||
{{
|
|
||||||
role.metadata.annotations?.[rbacAnnotations.DISPLAY_NAME] ||
|
|
||||||
role.metadata.name
|
|
||||||
}}
|
|
||||||
</VTag>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-2 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.user.detail.fields.bio") }}
|
|
||||||
</dt>
|
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
|
||||||
{{ user?.user.spec?.bio || $t("core.common.text.none") }}
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-white px-2 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4"
|
|
||||||
>
|
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
|
||||||
{{ $t("core.user.detail.fields.creation_time") }}
|
|
||||||
</dt>
|
|
||||||
<dd
|
|
||||||
class="mt-1 text-sm tabular-nums text-gray-900 sm:col-span-3 sm:mt-0"
|
|
||||||
>
|
>
|
||||||
{{ formatDatetime(user?.user.metadata?.creationTimestamp) }}
|
<template #leftIcon>
|
||||||
</dd>
|
<IconUserSettings />
|
||||||
</div>
|
</template>
|
||||||
<!-- TODO: add display last login time support -->
|
{{
|
||||||
<div
|
role.metadata.annotations?.[rbacAnnotations.DISPLAY_NAME] ||
|
||||||
v-if="false"
|
role.metadata.name
|
||||||
class="bg-white px-2 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4"
|
}}
|
||||||
>
|
</VTag>
|
||||||
<dt class="text-sm font-medium text-gray-900">最近登录时间</dt>
|
</VDescriptionItem>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
<VDescriptionItem
|
||||||
{{ user?.user.metadata?.creationTimestamp }}
|
:label="$t('core.user.detail.fields.bio')"
|
||||||
</dd>
|
:content="user?.user.spec?.bio || $t('core.common.text.none')"
|
||||||
</div>
|
class="!px-2"
|
||||||
<div
|
/>
|
||||||
|
<VDescriptionItem
|
||||||
|
:label="$t('core.user.detail.fields.creation_time')"
|
||||||
|
:content="formatDatetime(user?.user.metadata?.creationTimestamp)"
|
||||||
|
class="!px-2"
|
||||||
|
/>
|
||||||
|
<VDescriptionItem
|
||||||
v-if="!isFetching && isCurrentUser && availableAuthProviders?.length"
|
v-if="!isFetching && isCurrentUser && availableAuthProviders?.length"
|
||||||
class="bg-white px-2 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4"
|
:label="$t('core.user.detail.fields.identity_authentication')"
|
||||||
|
class="!px-2"
|
||||||
>
|
>
|
||||||
<dt class="text-sm font-medium text-gray-900">
|
<ul class="space-y-2">
|
||||||
{{ $t("core.user.detail.fields.identity_authentication") }}
|
<template v-for="(authProvider, index) in authProviders">
|
||||||
</dt>
|
<li
|
||||||
<dd class="mt-1 text-sm sm:col-span-3 sm:mt-0">
|
v-if="authProvider.supportsBinding && authProvider.enabled"
|
||||||
<ul class="space-y-2">
|
:key="index"
|
||||||
<template v-for="(authProvider, index) in authProviders">
|
>
|
||||||
<li
|
<div
|
||||||
v-if="authProvider.supportsBinding && authProvider.enabled"
|
class="flex w-full cursor-pointer flex-wrap justify-between gap-y-3 rounded border p-5 hover:border-primary sm:w-1/2"
|
||||||
:key="index"
|
|
||||||
>
|
>
|
||||||
<div
|
<div class="inline-flex items-center gap-3">
|
||||||
class="flex w-full cursor-pointer flex-wrap justify-between gap-y-3 rounded border p-5 hover:border-primary sm:w-1/2"
|
<div>
|
||||||
>
|
<img class="h-7 w-7 rounded" :src="authProvider.logo" />
|
||||||
<div class="inline-flex items-center gap-3">
|
|
||||||
<div>
|
|
||||||
<img class="h-7 w-7 rounded" :src="authProvider.logo" />
|
|
||||||
</div>
|
|
||||||
<div class="text-sm font-medium text-gray-900">
|
|
||||||
{{ authProvider.displayName }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="inline-flex items-center">
|
<div class="text-sm font-medium text-gray-900">
|
||||||
<VButton
|
{{ authProvider.displayName }}
|
||||||
v-if="authProvider.isBound"
|
|
||||||
size="sm"
|
|
||||||
@click="handleUnbindAuth(authProvider)"
|
|
||||||
>
|
|
||||||
{{ $t("core.user.detail.operations.unbind.button") }}
|
|
||||||
</VButton>
|
|
||||||
<VButton
|
|
||||||
v-else
|
|
||||||
size="sm"
|
|
||||||
type="secondary"
|
|
||||||
@click="handleBindAuth(authProvider)"
|
|
||||||
>
|
|
||||||
{{ $t("core.user.detail.operations.bind.button") }}
|
|
||||||
</VButton>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
<div class="inline-flex items-center">
|
||||||
</template>
|
<VButton
|
||||||
</ul>
|
v-if="authProvider.isBound"
|
||||||
</dd>
|
size="sm"
|
||||||
</div>
|
@click="handleUnbindAuth(authProvider)"
|
||||||
</dl>
|
>
|
||||||
|
{{ $t("core.user.detail.operations.unbind.button") }}
|
||||||
|
</VButton>
|
||||||
|
<VButton
|
||||||
|
v-else
|
||||||
|
size="sm"
|
||||||
|
type="secondary"
|
||||||
|
@click="handleBindAuth(authProvider)"
|
||||||
|
>
|
||||||
|
{{ $t("core.user.detail.operations.bind.button") }}
|
||||||
|
</VButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
</ul>
|
||||||
|
</VDescriptionItem>
|
||||||
|
</VDescription>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
Loading…
Reference in New Issue