mirror of https://github.com/halo-dev/halo-admin
refactor: logic for role creation form
Signed-off-by: Ryan Wang <i@ryanc.cc>pull/591/head
parent
05375a1a7b
commit
fad809fec2
|
@ -9,49 +9,43 @@ import {
|
||||||
VTabbar,
|
VTabbar,
|
||||||
VTag,
|
VTag,
|
||||||
} from "@halo-dev/components";
|
} from "@halo-dev/components";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref, watch } from "vue";
|
||||||
import { apiClient } from "@halo-dev/admin-shared";
|
import { apiClient } from "@halo-dev/admin-shared";
|
||||||
import type { Role, User } from "@halo-dev/api-client";
|
import type { User } from "@halo-dev/api-client";
|
||||||
import { pluginLabels } from "@/constants/labels";
|
import { pluginLabels } from "@/constants/labels";
|
||||||
import { rbacAnnotations } from "@/constants/annotations";
|
import { rbacAnnotations } from "@/constants/annotations";
|
||||||
import { useRoleTemplateSelection } from "@/modules/system/roles/composables/use-role";
|
import {
|
||||||
|
useRoleForm,
|
||||||
interface FormState {
|
useRoleTemplateSelection,
|
||||||
role: Role;
|
} from "@/modules/system/roles/composables/use-role";
|
||||||
saving: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
const users = ref<User[]>([]);
|
const users = ref<User[]>([]);
|
||||||
const roleActiveId = ref("detail");
|
const tabActiveId = ref("detail");
|
||||||
const formState = ref<FormState>({
|
|
||||||
role: {
|
|
||||||
apiVersion: "v1alpha1",
|
|
||||||
kind: "Role",
|
|
||||||
metadata: {
|
|
||||||
name: "",
|
|
||||||
labels: {},
|
|
||||||
annotations: {
|
|
||||||
[rbacAnnotations.DEPENDENCIES]: "",
|
|
||||||
[rbacAnnotations.DISPLAY_NAME]: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rules: [],
|
|
||||||
},
|
|
||||||
saving: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { roleTemplateGroups, handleRoleTemplateSelect, selectedRoleTemplates } =
|
const { roleTemplateGroups, handleRoleTemplateSelect, selectedRoleTemplates } =
|
||||||
useRoleTemplateSelection();
|
useRoleTemplateSelection();
|
||||||
|
|
||||||
|
const { formState, saving, handleCreateOrUpdate } = useRoleForm();
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => selectedRoleTemplates.value,
|
||||||
|
(newValue) => {
|
||||||
|
if (formState.value.metadata.annotations) {
|
||||||
|
formState.value.metadata.annotations[rbacAnnotations.DEPENDENCIES] =
|
||||||
|
JSON.stringify(Array.from(newValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const handleFetchRole = async () => {
|
const handleFetchRole = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await apiClient.extension.role.getv1alpha1Role(
|
const response = await apiClient.extension.role.getv1alpha1Role(
|
||||||
route.params.name as string
|
route.params.name as string
|
||||||
);
|
);
|
||||||
formState.value.role = response.data;
|
formState.value = response.data;
|
||||||
selectedRoleTemplates.value = new Set(
|
selectedRoleTemplates.value = new Set(
|
||||||
JSON.parse(
|
JSON.parse(
|
||||||
response.data.metadata.annotations?.[rbacAnnotations.DEPENDENCIES] ||
|
response.data.metadata.annotations?.[rbacAnnotations.DEPENDENCIES] ||
|
||||||
|
@ -73,28 +67,8 @@ const handleFetchUsers = async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpdateRole = async () => {
|
const handleUpdateRole = async () => {
|
||||||
try {
|
await handleCreateOrUpdate();
|
||||||
formState.value.saving = true;
|
await handleFetchRole();
|
||||||
if (formState.value.role.metadata.annotations) {
|
|
||||||
formState.value.role.metadata.annotations[rbacAnnotations.DEPENDENCIES] =
|
|
||||||
JSON.stringify(Array.from(selectedRoleTemplates.value));
|
|
||||||
}
|
|
||||||
await apiClient.extension.role.updatev1alpha1Role(
|
|
||||||
route.params.name as string,
|
|
||||||
formState.value.role
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
} finally {
|
|
||||||
formState.value.saving = false;
|
|
||||||
await handleFetchRole();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const handleRouteToUser = (name: string) => {
|
|
||||||
router.push({ name: "UserDetail", params: { name } });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
@ -105,8 +79,8 @@ onMounted(() => {
|
||||||
<template>
|
<template>
|
||||||
<VPageHeader
|
<VPageHeader
|
||||||
:title="`角色:${
|
:title="`角色:${
|
||||||
formState.role?.metadata?.annotations?.[rbacAnnotations.DISPLAY_NAME] ||
|
formState.metadata?.annotations?.[rbacAnnotations.DISPLAY_NAME] ||
|
||||||
formState.role?.metadata?.name
|
formState.metadata?.name
|
||||||
}`"
|
}`"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
|
@ -125,7 +99,7 @@ onMounted(() => {
|
||||||
<VCard :body-class="['!p-0']">
|
<VCard :body-class="['!p-0']">
|
||||||
<template #header>
|
<template #header>
|
||||||
<VTabbar
|
<VTabbar
|
||||||
v-model:active-id="roleActiveId"
|
v-model:active-id="tabActiveId"
|
||||||
:items="[
|
:items="[
|
||||||
{ id: 'detail', label: '详情' },
|
{ id: 'detail', label: '详情' },
|
||||||
{ id: 'permissions', label: '权限设置' },
|
{ id: 'permissions', label: '权限设置' },
|
||||||
|
@ -134,7 +108,7 @@ onMounted(() => {
|
||||||
type="outline"
|
type="outline"
|
||||||
></VTabbar>
|
></VTabbar>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="roleActiveId === 'detail'">
|
<div v-if="tabActiveId === 'detail'">
|
||||||
<div class="px-4 py-4 sm:px-6">
|
<div class="px-4 py-4 sm:px-6">
|
||||||
<h3 class="text-lg font-medium leading-6 text-gray-900">权限信息</h3>
|
<h3 class="text-lg font-medium leading-6 text-gray-900">权限信息</h3>
|
||||||
<p
|
<p
|
||||||
|
@ -144,7 +118,7 @@ onMounted(() => {
|
||||||
>包含
|
>包含
|
||||||
{{
|
{{
|
||||||
JSON.parse(
|
JSON.parse(
|
||||||
formState.role.metadata.annotations?.[
|
formState.metadata.annotations?.[
|
||||||
rbacAnnotations.DEPENDENCIES
|
rbacAnnotations.DEPENDENCIES
|
||||||
] || "[]"
|
] || "[]"
|
||||||
).length
|
).length
|
||||||
|
@ -161,9 +135,9 @@ onMounted(() => {
|
||||||
<dt class="text-sm font-medium text-gray-900">名称</dt>
|
<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">
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||||
{{
|
{{
|
||||||
formState.role?.metadata?.annotations?.[
|
formState.metadata?.annotations?.[
|
||||||
rbacAnnotations.DISPLAY_NAME
|
rbacAnnotations.DISPLAY_NAME
|
||||||
] || formState.role?.metadata?.name
|
] || formState.metadata?.name
|
||||||
}}
|
}}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
@ -172,7 +146,7 @@ onMounted(() => {
|
||||||
>
|
>
|
||||||
<dt class="text-sm font-medium text-gray-900">别名</dt>
|
<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">
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||||
{{ formState.role?.metadata?.name }}
|
{{ formState.metadata?.name }}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -196,7 +170,7 @@ onMounted(() => {
|
||||||
>
|
>
|
||||||
<dt class="text-sm font-medium text-gray-900">创建时间</dt>
|
<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">
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||||
{{ formState.role?.metadata?.creationTimestamp }}
|
{{ formState.metadata?.creationTimestamp }}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -208,49 +182,53 @@ onMounted(() => {
|
||||||
class="h-96 overflow-y-auto overflow-x-hidden rounded-sm bg-white shadow-sm transition-all hover:shadow"
|
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">
|
<ul class="divide-y divide-gray-100" role="list">
|
||||||
<li
|
<RouterLink
|
||||||
v-for="(user, index) in users"
|
v-for="(user, index) in users"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="block cursor-pointer hover:bg-gray-50"
|
:to="{
|
||||||
@click="handleRouteToUser(user.metadata.name)"
|
name: 'UserDetail',
|
||||||
|
params: { name: user.metadata.name },
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<div class="flex items-center px-4 py-4">
|
<li class="block cursor-pointer hover:bg-gray-50">
|
||||||
<div class="flex min-w-0 flex-1 items-center">
|
<div class="flex items-center px-4 py-4">
|
||||||
<div class="flex-shrink-0">
|
<div class="flex min-w-0 flex-1 items-center">
|
||||||
<div class="h-12 w-12">
|
<div class="flex-shrink-0">
|
||||||
<div
|
<div class="h-12 w-12">
|
||||||
class="overflow-hidden rounded border bg-white hover:shadow-sm"
|
<div
|
||||||
>
|
class="overflow-hidden rounded border bg-white hover:shadow-sm"
|
||||||
<img
|
>
|
||||||
:alt="user.spec.displayName"
|
<img
|
||||||
:src="user.spec.avatar"
|
:alt="user.spec.displayName"
|
||||||
class="h-full w-full"
|
:src="user.spec.avatar"
|
||||||
/>
|
class="h-full w-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</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>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div>
|
||||||
class="min-w-0 flex-1 px-4 md:grid md:grid-cols-2 md:gap-4"
|
<IconArrowRight />
|
||||||
>
|
|
||||||
<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>
|
</div>
|
||||||
<div>
|
</li>
|
||||||
<IconArrowRight />
|
</RouterLink>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</dd>
|
</dd>
|
||||||
|
@ -259,7 +237,7 @@ onMounted(() => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="roleActiveId === 'permissions'">
|
<div v-if="tabActiveId === 'permissions'">
|
||||||
<div>
|
<div>
|
||||||
<dl class="divide-y divide-gray-100">
|
<dl class="divide-y divide-gray-100">
|
||||||
<div
|
<div
|
||||||
|
@ -342,7 +320,7 @@ onMounted(() => {
|
||||||
</dl>
|
</dl>
|
||||||
<div v-permission="['system:roles:manage']" class="p-4">
|
<div v-permission="['system:roles:manage']" class="p-4">
|
||||||
<VButton
|
<VButton
|
||||||
:loading="formState.saving"
|
:loading="saving"
|
||||||
type="secondary"
|
type="secondary"
|
||||||
@click="handleUpdateRole"
|
@click="handleUpdateRole"
|
||||||
>保存
|
>保存
|
||||||
|
|
|
@ -12,15 +12,15 @@ import {
|
||||||
VTag,
|
VTag,
|
||||||
} from "@halo-dev/components";
|
} from "@halo-dev/components";
|
||||||
import RoleEditingModal from "./components/RoleEditingModal.vue";
|
import RoleEditingModal from "./components/RoleEditingModal.vue";
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import { computed, onMounted, ref } from "vue";
|
import { computed, onMounted, ref } from "vue";
|
||||||
import type { Role } from "@halo-dev/api-client";
|
import type { Role } from "@halo-dev/api-client";
|
||||||
import { apiClient } from "@halo-dev/admin-shared";
|
import { apiClient } from "@halo-dev/admin-shared";
|
||||||
import { roleLabels } from "@/constants/labels";
|
import { roleLabels } from "@/constants/labels";
|
||||||
import { pluginAnnotations, rbacAnnotations } from "@/constants/annotations";
|
import { rbacAnnotations } from "@/constants/annotations";
|
||||||
|
|
||||||
const createVisible = ref(false);
|
|
||||||
const roles = ref<Role[]>([]);
|
const roles = ref<Role[]>([]);
|
||||||
|
const editingModal = ref<boolean>(false);
|
||||||
|
const selectedRole = ref<Role | null>(null);
|
||||||
|
|
||||||
const basicRoles = computed(() => {
|
const basicRoles = computed(() => {
|
||||||
return roles.value.filter(
|
return roles.value.filter(
|
||||||
|
@ -28,19 +28,20 @@ const basicRoles = computed(() => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const handleFetchRoles = async () => {
|
const handleFetchRoles = async () => {
|
||||||
try {
|
try {
|
||||||
const { data } = await apiClient.extension.role.listv1alpha1Role();
|
const { data } = await apiClient.extension.role.listv1alpha1Role();
|
||||||
roles.value = data.items;
|
roles.value = data.items;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
} finally {
|
||||||
|
selectedRole.value = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRouteToDetail = (name: string) => {
|
const handleOpenEditingModal = (role: Role) => {
|
||||||
router.push({ name: "RoleDetail", params: { name } });
|
selectedRole.value = role;
|
||||||
|
editingModal.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
@ -48,7 +49,11 @@ onMounted(() => {
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<RoleEditingModal v-model:visible="createVisible" @close="handleFetchRoles" />
|
<RoleEditingModal
|
||||||
|
v-model:visible="editingModal"
|
||||||
|
:role="selectedRole"
|
||||||
|
@close="handleFetchRoles"
|
||||||
|
/>
|
||||||
|
|
||||||
<VPageHeader title="角色">
|
<VPageHeader title="角色">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
|
@ -58,7 +63,7 @@ onMounted(() => {
|
||||||
<VButton
|
<VButton
|
||||||
v-permission="['system:roles:manage']"
|
v-permission="['system:roles:manage']"
|
||||||
type="secondary"
|
type="secondary"
|
||||||
@click="createVisible = true"
|
@click="editingModal = true"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<IconAddCircle class="h-full w-full" />
|
<IconAddCircle class="h-full w-full" />
|
||||||
|
@ -164,24 +169,31 @@ onMounted(() => {
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<ul class="box-border h-full w-full divide-y divide-gray-100" role="list">
|
<ul class="box-border h-full w-full divide-y divide-gray-100" role="list">
|
||||||
<li
|
<li v-for="(role, index) in basicRoles" :key="index">
|
||||||
v-for="(role, index) in basicRoles"
|
|
||||||
:key="index"
|
|
||||||
@click="handleRouteToDetail(role.metadata.name)"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="relative block cursor-pointer px-4 py-3 transition-all hover:bg-gray-50"
|
class="relative block cursor-pointer px-4 py-3 transition-all hover:bg-gray-50"
|
||||||
>
|
>
|
||||||
<div class="relative flex flex-row items-center">
|
<div class="relative flex flex-row items-center">
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<div class="flex flex-row items-center">
|
<div class="flex flex-row items-center">
|
||||||
<span class="mr-2 truncate text-sm font-medium text-gray-900">
|
<RouterLink
|
||||||
{{
|
:to="{
|
||||||
role.metadata.annotations?.[
|
name: 'RoleDetail',
|
||||||
pluginAnnotations.DISPLAY_NAME
|
params: {
|
||||||
] || role.metadata.name
|
name: role.metadata.name,
|
||||||
}}
|
},
|
||||||
</span>
|
}"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="mr-2 truncate text-sm font-medium text-gray-900"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
role.metadata.annotations?.[
|
||||||
|
rbacAnnotations.DISPLAY_NAME
|
||||||
|
] || role.metadata.name
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2 flex">
|
<div class="mt-2 flex">
|
||||||
<span class="text-xs text-gray-500">
|
<span class="text-xs text-gray-500">
|
||||||
|
@ -208,14 +220,14 @@ onMounted(() => {
|
||||||
0 个用户
|
0 个用户
|
||||||
</a>
|
</a>
|
||||||
<VTag> 系统保留</VTag>
|
<VTag> 系统保留</VTag>
|
||||||
<time class="text-sm text-gray-500" datetime="2020-01-07">
|
<time class="text-sm text-gray-500">
|
||||||
2020-01-07
|
{{ role.metadata.creationTimestamp }}
|
||||||
</time>
|
</time>
|
||||||
<span
|
<span
|
||||||
v-permission="['system:roles:manage']"
|
v-permission="['system:roles:manage']"
|
||||||
class="cursor-pointer"
|
class="cursor-pointer"
|
||||||
>
|
>
|
||||||
<IconSettings />
|
<IconSettings @click="handleOpenEditingModal(role)" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,59 +1,59 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { VButton, VModal, VTabItem, VTabs } from "@halo-dev/components";
|
import { VButton, VModal, VTabItem, VTabs } from "@halo-dev/components";
|
||||||
import { ref } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { apiClient } from "@halo-dev/admin-shared";
|
import { ref, watch } from "vue";
|
||||||
import type { Role } from "@halo-dev/api-client";
|
|
||||||
import { rbacAnnotations } from "@/constants/annotations";
|
import { rbacAnnotations } from "@/constants/annotations";
|
||||||
import { useRoleTemplateSelection } from "@/modules/system/roles/composables/use-role";
|
import type { Role } from "@halo-dev/api-client";
|
||||||
|
import {
|
||||||
|
useRoleForm,
|
||||||
|
useRoleTemplateSelection,
|
||||||
|
} from "@/modules/system/roles/composables/use-role";
|
||||||
|
import cloneDeep from "lodash.clonedeep";
|
||||||
|
|
||||||
interface FormState {
|
const props = defineProps({
|
||||||
role: Role;
|
|
||||||
saving: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
defineProps({
|
|
||||||
visible: {
|
visible: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
role: {
|
||||||
|
type: Object as PropType<Role | null>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(["update:visible", "close"]);
|
const emit = defineEmits(["update:visible", "close"]);
|
||||||
|
|
||||||
const { roleTemplateGroups, handleRoleTemplateSelect, selectedRoleTemplates } =
|
const { roleTemplateGroups, handleRoleTemplateSelect, selectedRoleTemplates } =
|
||||||
useRoleTemplateSelection();
|
useRoleTemplateSelection();
|
||||||
|
const { formState, initialFormState, saving, handleCreateOrUpdate } =
|
||||||
|
useRoleForm();
|
||||||
|
|
||||||
const activeId = ref("general");
|
watch(
|
||||||
const formState = ref<FormState>({
|
() => selectedRoleTemplates.value,
|
||||||
role: {
|
(newValue) => {
|
||||||
apiVersion: "v1alpha1",
|
if (formState.value.metadata.annotations) {
|
||||||
kind: "Role",
|
formState.value.metadata.annotations[rbacAnnotations.DEPENDENCIES] =
|
||||||
metadata: {
|
JSON.stringify(Array.from(newValue));
|
||||||
name: "",
|
}
|
||||||
labels: {},
|
}
|
||||||
annotations: {
|
);
|
||||||
[rbacAnnotations.DEPENDENCIES]: "",
|
|
||||||
[rbacAnnotations.DISPLAY_NAME]: "",
|
watch(props, (newVal) => {
|
||||||
}!,
|
if (newVal.visible && props.role) {
|
||||||
},
|
formState.value = cloneDeep(props.role);
|
||||||
rules: [],
|
return;
|
||||||
},
|
}
|
||||||
saving: false,
|
formState.value = cloneDeep(initialFormState);
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleCreateRole = async () => {
|
const tabActiveId = ref("general");
|
||||||
|
|
||||||
|
const handleCreateOrUpdateRole = async () => {
|
||||||
try {
|
try {
|
||||||
formState.value.saving = true;
|
await handleCreateOrUpdate();
|
||||||
if (formState.value.role.metadata.annotations) {
|
|
||||||
formState.value.role.metadata.annotations[rbacAnnotations.DEPENDENCIES] =
|
|
||||||
JSON.stringify(Array.from(selectedRoleTemplates.value));
|
|
||||||
}
|
|
||||||
await apiClient.extension.role.createv1alpha1Role(formState.value.role);
|
|
||||||
handleVisibleChange(false);
|
handleVisibleChange(false);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
} finally {
|
|
||||||
formState.value.saving = false;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -71,25 +71,25 @@ const handleVisibleChange = (visible: boolean) => {
|
||||||
title="创建角色"
|
title="创建角色"
|
||||||
@update:visible="handleVisibleChange"
|
@update:visible="handleVisibleChange"
|
||||||
>
|
>
|
||||||
<VTabs v-model:active-id="activeId" type="outline">
|
<VTabs v-model:active-id="tabActiveId" type="outline">
|
||||||
<VTabItem id="general" label="基础信息">
|
<VTabItem id="general" label="基础信息">
|
||||||
<FormKit
|
<FormKit
|
||||||
v-if="formState.role.metadata.annotations"
|
v-if="formState.metadata.annotations"
|
||||||
id="role-form"
|
id="role-form"
|
||||||
:actions="false"
|
:actions="false"
|
||||||
type="form"
|
type="form"
|
||||||
@submit="handleCreateRole"
|
@submit="handleCreateOrUpdateRole"
|
||||||
>
|
>
|
||||||
<FormKit
|
<FormKit
|
||||||
v-model="
|
v-model="
|
||||||
formState.role.metadata.annotations[rbacAnnotations.DISPLAY_NAME]
|
formState.metadata.annotations[rbacAnnotations.DISPLAY_NAME]
|
||||||
"
|
"
|
||||||
label="名称"
|
label="名称"
|
||||||
type="text"
|
type="text"
|
||||||
validation="required"
|
validation="required"
|
||||||
></FormKit>
|
></FormKit>
|
||||||
<FormKit
|
<FormKit
|
||||||
v-model="formState.role.metadata.name"
|
v-model="formState.metadata.name"
|
||||||
help="角色别名,用于区分角色,不能重复,创建之后不能修改"
|
help="角色别名,用于区分角色,不能重复,创建之后不能修改"
|
||||||
label="别名"
|
label="别名"
|
||||||
type="text"
|
type="text"
|
||||||
|
@ -158,7 +158,7 @@ const handleVisibleChange = (visible: boolean) => {
|
||||||
</VTabs>
|
</VTabs>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<VButton
|
<VButton
|
||||||
:loading="formState.saving"
|
:loading="saving"
|
||||||
type="secondary"
|
type="secondary"
|
||||||
@click="$formkit.submit('role-form')"
|
@click="$formkit.submit('role-form')"
|
||||||
>创建
|
>创建
|
||||||
|
|
|
@ -9,6 +9,54 @@ interface RoleTemplateGroup {
|
||||||
roles: Role[];
|
roles: Role[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const initialFormState: Role = {
|
||||||
|
apiVersion: "v1alpha1",
|
||||||
|
kind: "Role",
|
||||||
|
metadata: {
|
||||||
|
name: "",
|
||||||
|
labels: {},
|
||||||
|
annotations: {
|
||||||
|
[rbacAnnotations.DEPENDENCIES]: "",
|
||||||
|
[rbacAnnotations.DISPLAY_NAME]: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useRoleForm() {
|
||||||
|
const formState = ref<Role>(initialFormState);
|
||||||
|
const saving = ref(false);
|
||||||
|
|
||||||
|
const isUpdateMode = computed(() => {
|
||||||
|
return !!formState.value.metadata.creationTimestamp;
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleCreateOrUpdate = async () => {
|
||||||
|
try {
|
||||||
|
saving.value = true;
|
||||||
|
if (isUpdateMode.value) {
|
||||||
|
await apiClient.extension.role.updatev1alpha1Role(
|
||||||
|
formState.value.metadata.name,
|
||||||
|
formState.value
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await apiClient.extension.role.createv1alpha1Role(formState.value);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
} finally {
|
||||||
|
saving.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
formState,
|
||||||
|
initialFormState,
|
||||||
|
saving,
|
||||||
|
handleCreateOrUpdate,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function useRoleTemplateSelection() {
|
export function useRoleTemplateSelection() {
|
||||||
const rawRoles = ref<Role[]>([] as Role[]);
|
const rawRoles = ref<Role[]>([] as Role[]);
|
||||||
const selectedRoleTemplates = ref<Set<string>>(new Set());
|
const selectedRoleTemplates = ref<Set<string>>(new Set());
|
||||||
|
|
Loading…
Reference in New Issue