2022-05-30 13:06:02 +00:00
|
|
|
<script lang="ts" setup>
|
2024-05-30 07:01:15 +00:00
|
|
|
import UserAvatar from "@/components/user-avatar/UserAvatar.vue";
|
|
|
|
import { usePluginModuleStore } from "@/stores/plugin";
|
|
|
|
import { useUserStore } from "@/stores/user";
|
2024-06-25 04:31:44 +00:00
|
|
|
import { consoleApiClient } from "@halo-dev/api-client";
|
2024-05-30 07:01:15 +00:00
|
|
|
import { usePermission } from "@/utils/permission";
|
2023-04-23 02:49:32 +00:00
|
|
|
import {
|
|
|
|
VButton,
|
2023-09-26 15:34:16 +00:00
|
|
|
VDropdown,
|
|
|
|
VDropdownItem,
|
2024-04-25 00:33:09 +00:00
|
|
|
VTabbar,
|
2023-04-23 02:49:32 +00:00
|
|
|
} from "@halo-dev/components";
|
2024-05-30 07:01:15 +00:00
|
|
|
import type { UserTab } from "@halo-dev/console-shared";
|
|
|
|
import { useQuery } from "@tanstack/vue-query";
|
|
|
|
import { useRouteQuery } from "@vueuse/router";
|
2024-04-25 00:33:09 +00:00
|
|
|
import {
|
|
|
|
computed,
|
|
|
|
markRaw,
|
|
|
|
onMounted,
|
|
|
|
provide,
|
|
|
|
ref,
|
|
|
|
toRaw,
|
2024-05-30 07:01:15 +00:00
|
|
|
type Ref,
|
2024-04-25 00:33:09 +00:00
|
|
|
} from "vue";
|
2024-05-30 07:01:15 +00:00
|
|
|
import { useI18n } from "vue-i18n";
|
2023-09-26 15:34:16 +00:00
|
|
|
import { useRoute } from "vue-router";
|
|
|
|
import UserEditingModal from "./components/UserEditingModal.vue";
|
|
|
|
import UserPasswordChangeModal from "./components/UserPasswordChangeModal.vue";
|
|
|
|
import DetailTab from "./tabs/Detail.vue";
|
2022-05-30 13:06:02 +00:00
|
|
|
|
2023-09-26 15:34:16 +00:00
|
|
|
const { currentUserHasPermission } = usePermission();
|
2023-03-23 08:54:33 +00:00
|
|
|
const { t } = useI18n();
|
2023-11-16 07:51:19 +00:00
|
|
|
const { currentUser } = useUserStore();
|
2023-03-21 03:54:28 +00:00
|
|
|
|
2023-09-26 15:34:16 +00:00
|
|
|
const editingModal = ref(false);
|
|
|
|
const passwordChangeModal = ref(false);
|
|
|
|
|
|
|
|
const { params } = useRoute();
|
|
|
|
|
|
|
|
const {
|
|
|
|
data: user,
|
|
|
|
isLoading,
|
|
|
|
refetch,
|
|
|
|
} = useQuery({
|
2023-11-13 08:56:08 +00:00
|
|
|
queryKey: ["user-detail", params.name],
|
2023-03-21 03:54:28 +00:00
|
|
|
queryFn: async () => {
|
2024-06-25 04:31:44 +00:00
|
|
|
const { data } = await consoleApiClient.user.getUserDetail({
|
2023-11-13 08:56:08 +00:00
|
|
|
name: params.name as string,
|
|
|
|
});
|
|
|
|
return data;
|
2023-09-26 15:34:16 +00:00
|
|
|
},
|
2023-11-13 08:56:08 +00:00
|
|
|
enabled: computed(() => !!params.name),
|
2023-03-29 13:30:14 +00:00
|
|
|
});
|
|
|
|
|
2024-04-25 00:33:09 +00:00
|
|
|
const tabs = ref<UserTab[]>([
|
2023-11-13 08:56:08 +00:00
|
|
|
{
|
|
|
|
id: "detail",
|
|
|
|
label: t("core.user.detail.tabs.detail"),
|
|
|
|
component: markRaw(DetailTab),
|
|
|
|
priority: 10,
|
|
|
|
},
|
2024-04-25 00:33:09 +00:00
|
|
|
]);
|
|
|
|
|
|
|
|
// Collect user:detail:tabs:create extension points
|
2024-05-30 07:01:15 +00:00
|
|
|
const { pluginModules } = usePluginModuleStore();
|
2024-04-25 00:33:09 +00:00
|
|
|
|
2024-05-30 07:01:15 +00:00
|
|
|
onMounted(async () => {
|
|
|
|
for (const pluginModule of pluginModules) {
|
|
|
|
try {
|
|
|
|
const callbackFunction =
|
|
|
|
pluginModule?.extensionPoints?.["user:detail:tabs:create"];
|
|
|
|
if (typeof callbackFunction !== "function") {
|
|
|
|
continue;
|
|
|
|
}
|
2024-04-25 00:33:09 +00:00
|
|
|
|
2024-05-30 07:01:15 +00:00
|
|
|
const providers = await callbackFunction();
|
2024-04-25 00:33:09 +00:00
|
|
|
|
2024-05-30 07:01:15 +00:00
|
|
|
tabs.value.push(...providers);
|
|
|
|
} catch (error) {
|
|
|
|
console.error(`Error processing plugin module:`, pluginModule, error);
|
|
|
|
}
|
|
|
|
}
|
2024-04-25 00:33:09 +00:00
|
|
|
});
|
2023-03-21 03:54:28 +00:00
|
|
|
|
2024-04-25 00:33:09 +00:00
|
|
|
const activeTab = useRouteQuery<string>("tab", tabs.value[0].id, {
|
2023-09-26 15:34:16 +00:00
|
|
|
mode: "push",
|
|
|
|
});
|
2023-11-13 08:56:08 +00:00
|
|
|
|
2023-09-26 15:34:16 +00:00
|
|
|
provide<Ref<string>>("activeTab", activeTab);
|
|
|
|
|
|
|
|
const tabbarItems = computed(() => {
|
2024-04-25 00:33:09 +00:00
|
|
|
return toRaw(tabs)
|
|
|
|
.value.sort((a, b) => a.priority - b.priority)
|
|
|
|
.map((tab) => ({
|
|
|
|
id: tab.id,
|
|
|
|
label: tab.label,
|
|
|
|
}));
|
2023-09-26 15:34:16 +00:00
|
|
|
});
|
2023-11-16 07:51:19 +00:00
|
|
|
|
|
|
|
function handleRouteToUC() {
|
|
|
|
window.location.href = "/uc";
|
|
|
|
}
|
2024-05-23 06:32:49 +00:00
|
|
|
|
|
|
|
function onPasswordChangeModalClose() {
|
|
|
|
passwordChangeModal.value = false;
|
|
|
|
refetch();
|
|
|
|
}
|
2022-05-30 13:06:02 +00:00
|
|
|
</script>
|
|
|
|
<template>
|
2024-05-23 06:32:49 +00:00
|
|
|
<UserEditingModal
|
|
|
|
v-if="editingModal && user?.user"
|
|
|
|
:user="user?.user"
|
|
|
|
@close="editingModal = false"
|
|
|
|
/>
|
2023-09-26 15:34:16 +00:00
|
|
|
|
|
|
|
<UserPasswordChangeModal
|
2024-05-23 06:32:49 +00:00
|
|
|
v-if="passwordChangeModal"
|
2023-09-26 15:34:16 +00:00
|
|
|
:user="user?.user"
|
2024-05-23 06:32:49 +00:00
|
|
|
@close="onPasswordChangeModalClose"
|
2023-09-26 15:34:16 +00:00
|
|
|
/>
|
|
|
|
|
|
|
|
<header class="bg-white">
|
|
|
|
<div class="p-4">
|
|
|
|
<div class="flex items-center justify-between">
|
|
|
|
<div class="flex flex-row items-center gap-5">
|
|
|
|
<div class="group relative h-20 w-20">
|
2024-01-29 08:06:02 +00:00
|
|
|
<UserAvatar :name="user?.user.metadata.name" />
|
2023-09-26 15:34:16 +00:00
|
|
|
</div>
|
|
|
|
<div class="block">
|
|
|
|
<h1 class="truncate text-lg font-bold text-gray-900">
|
|
|
|
{{ user?.user.spec.displayName }}
|
|
|
|
</h1>
|
|
|
|
<span v-if="!isLoading" class="text-sm text-gray-600">
|
|
|
|
@{{ user?.user.metadata.name }}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
2023-11-16 07:51:19 +00:00
|
|
|
<div class="inline-flex items-center gap-2">
|
|
|
|
<VButton
|
|
|
|
v-if="currentUser?.metadata.name === user?.user.metadata.name"
|
|
|
|
type="primary"
|
|
|
|
@click="handleRouteToUC"
|
|
|
|
>
|
2023-11-30 10:56:10 +00:00
|
|
|
{{ $t("core.user.detail.actions.profile.title") }}
|
2023-11-16 07:51:19 +00:00
|
|
|
</VButton>
|
|
|
|
<VDropdown v-if="currentUserHasPermission(['system:users:manage'])">
|
2023-09-26 15:34:16 +00:00
|
|
|
<VButton type="default">
|
|
|
|
{{ $t("core.common.buttons.edit") }}
|
|
|
|
</VButton>
|
|
|
|
<template #popper>
|
|
|
|
<VDropdownItem @click="editingModal = true">
|
|
|
|
{{ $t("core.user.detail.actions.update_profile.title") }}
|
|
|
|
</VDropdownItem>
|
|
|
|
<VDropdownItem @click="passwordChangeModal = true">
|
|
|
|
{{ $t("core.user.detail.actions.change_password.title") }}
|
|
|
|
</VDropdownItem>
|
|
|
|
</template>
|
|
|
|
</VDropdown>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</header>
|
|
|
|
<section class="bg-white p-4">
|
|
|
|
<VTabbar
|
|
|
|
v-model:active-id="activeTab"
|
|
|
|
:items="tabbarItems"
|
|
|
|
class="w-full"
|
|
|
|
type="outline"
|
|
|
|
></VTabbar>
|
|
|
|
<div class="mt-2">
|
|
|
|
<template v-for="tab in tabs" :key="tab.id">
|
|
|
|
<component
|
|
|
|
:is="tab.component"
|
2024-04-25 00:33:09 +00:00
|
|
|
v-if="activeTab === tab.id"
|
|
|
|
:user="user"
|
2023-09-26 15:34:16 +00:00
|
|
|
/>
|
|
|
|
</template>
|
|
|
|
</div>
|
|
|
|
</section>
|
2022-05-30 13:06:02 +00:00
|
|
|
</template>
|