fix: make settings controls editable
This commit is contained in:
@@ -1 +1,28 @@
|
|||||||
export { Input, Textarea, type InputProps, type InputAreaProps as TextareaProps } from "@cloudflare/kumo/components/input";
|
"use client";
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
import {
|
||||||
|
Input as KumoInput,
|
||||||
|
Textarea as KumoTextarea,
|
||||||
|
type InputAreaProps as KumoTextareaProps,
|
||||||
|
type InputProps as KumoInputProps,
|
||||||
|
} from "@cloudflare/kumo/components/input";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
export type InputProps = KumoInputProps;
|
||||||
|
export type TextareaProps = KumoTextareaProps;
|
||||||
|
|
||||||
|
export const Input = React.forwardRef<HTMLInputElement, InputProps>(function Input(
|
||||||
|
{ className, ...props },
|
||||||
|
ref,
|
||||||
|
): React.ReactElement {
|
||||||
|
return <KumoInput ref={ref} className={cn("w-full", className)} {...props} />;
|
||||||
|
});
|
||||||
|
|
||||||
|
export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(function Textarea(
|
||||||
|
{ className, ...props },
|
||||||
|
ref,
|
||||||
|
): React.ReactElement {
|
||||||
|
return <KumoTextarea ref={ref} className={cn("min-h-24 w-full", className)} {...props} />;
|
||||||
|
});
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Select as KumoSelect } from "@cloudflare/kumo/components/select";
|
import { Select as KumoSelect } from "@cloudflare/kumo/components/select";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
export type SelectOption = {
|
export type SelectOption = {
|
||||||
value: string;
|
value: string;
|
||||||
label: React.ReactNode;
|
label: React.ReactNode;
|
||||||
@@ -24,6 +26,7 @@ type SelectProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function Select({
|
export function Select({
|
||||||
|
className,
|
||||||
onValueChange,
|
onValueChange,
|
||||||
options,
|
options,
|
||||||
placeholder,
|
placeholder,
|
||||||
@@ -33,6 +36,7 @@ export function Select({
|
|||||||
}: SelectProps): React.ReactElement {
|
}: SelectProps): React.ReactElement {
|
||||||
return (
|
return (
|
||||||
<KumoSelect<string>
|
<KumoSelect<string>
|
||||||
|
className={cn("w-full", className)}
|
||||||
defaultValue={defaultValue}
|
defaultValue={defaultValue}
|
||||||
onValueChange={(nextValue) => onValueChange?.(String(nextValue))}
|
onValueChange={(nextValue) => onValueChange?.(String(nextValue))}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
|||||||
@@ -65,29 +65,47 @@ export function GlobalSettingsClient({ settings }: GlobalSettingsClientProps): R
|
|||||||
<CardDescription>控制全站公开注册能力和 OIDC 登录入口总开关。</CardDescription>
|
<CardDescription>控制全站公开注册能力和 OIDC 登录入口总开关。</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="grid gap-4">
|
<CardContent className="grid gap-4">
|
||||||
<label className="flex items-center justify-between gap-4 rounded-md border p-3 text-sm">
|
<div className="rounded-md border p-3 text-sm">
|
||||||
<span>
|
<Checkbox
|
||||||
<span className="block font-medium">开放公开注册</span>
|
controlFirst={false}
|
||||||
<span className="block text-xs text-muted-foreground">关闭后普通注册不可用;邀请链接仍可使用。</span>
|
defaultChecked={settings.registrationEnabled}
|
||||||
</span>
|
label={
|
||||||
<Checkbox aria-label="开放公开注册" defaultChecked={settings.registrationEnabled} name="registrationEnabled" />
|
<span className="min-w-0">
|
||||||
</label>
|
<span className="block font-medium">开放公开注册</span>
|
||||||
|
<span className="block text-xs text-muted-foreground">关闭后普通注册不可用;邀请链接仍可使用。</span>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
name="registrationEnabled"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label className="flex items-center justify-between gap-4 rounded-md border p-3 text-sm">
|
<div className="rounded-md border p-3 text-sm">
|
||||||
<span>
|
<Checkbox
|
||||||
<span className="block font-medium">启用 OIDC 登录</span>
|
controlFirst={false}
|
||||||
<span className="block text-xs text-muted-foreground">作为平台级总开关,机构级 OIDC 配置仍可单独管理。</span>
|
defaultChecked={settings.oidcEnabled}
|
||||||
</span>
|
label={
|
||||||
<Checkbox aria-label="启用 OIDC 登录" defaultChecked={settings.oidcEnabled} name="oidcEnabled" />
|
<span className="min-w-0">
|
||||||
</label>
|
<span className="block font-medium">启用 OIDC 登录</span>
|
||||||
|
<span className="block text-xs text-muted-foreground">作为平台级总开关,机构级 OIDC 配置仍可单独管理。</span>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
name="oidcEnabled"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label className="flex items-center justify-between gap-4 rounded-md border p-3 text-sm">
|
<div className="rounded-md border p-3 text-sm">
|
||||||
<span>
|
<Checkbox
|
||||||
<span className="block font-medium">OIDC 自动开户</span>
|
controlFirst={false}
|
||||||
<span className="block text-xs text-muted-foreground">首次 OIDC 登录时按声明信息创建账号,默认进入等待分配。</span>
|
defaultChecked={settings.oidcAutoProvision}
|
||||||
</span>
|
label={
|
||||||
<Checkbox aria-label="OIDC 自动开户" defaultChecked={settings.oidcAutoProvision} name="oidcAutoProvision" />
|
<span className="min-w-0">
|
||||||
</label>
|
<span className="block font-medium">OIDC 自动开户</span>
|
||||||
|
<span className="block text-xs text-muted-foreground">首次 OIDC 登录时按声明信息创建账号,默认进入等待分配。</span>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
name="oidcAutoProvision"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
@@ -101,40 +119,33 @@ export function GlobalSettingsClient({ settings }: GlobalSettingsClientProps): R
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="grid gap-4">
|
<CardContent className="grid gap-4">
|
||||||
<div className="grid gap-3 md:grid-cols-2">
|
<div className="grid gap-3 md:grid-cols-2">
|
||||||
<label className="grid gap-2 text-sm">
|
<Input
|
||||||
<span className="font-medium">Issuer URL</span>
|
defaultValue={settings.oidcIssuerUrl}
|
||||||
<Input defaultValue={settings.oidcIssuerUrl} name="oidcIssuerUrl" placeholder="https://idp.example.com" />
|
label="Issuer URL"
|
||||||
</label>
|
name="oidcIssuerUrl"
|
||||||
<label className="grid gap-2 text-sm">
|
placeholder="https://idp.example.com"
|
||||||
<span className="font-medium">Client ID</span>
|
/>
|
||||||
<Input defaultValue={settings.oidcClientId} name="oidcClientId" />
|
<Input defaultValue={settings.oidcClientId} label="Client ID" name="oidcClientId" />
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label className="grid gap-2 text-sm">
|
<Input
|
||||||
<span className="font-medium">Client Secret</span>
|
label="Client Secret"
|
||||||
<Input
|
name="oidcClientSecret"
|
||||||
name="oidcClientSecret"
|
placeholder={settings.oidcHasClientSecret ? "已配置,留空则不修改" : "未配置"}
|
||||||
placeholder={settings.oidcHasClientSecret ? "已配置,留空则不修改" : "未配置"}
|
type="password"
|
||||||
type="password"
|
/>
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div className="grid gap-3 md:grid-cols-2">
|
<div className="grid gap-3 md:grid-cols-2">
|
||||||
<label className="grid gap-2 text-sm">
|
<Input defaultValue={settings.oidcScopes} label="Scopes" name="oidcScopes" placeholder="openid profile email" />
|
||||||
<span className="font-medium">Scopes</span>
|
<Input
|
||||||
<Input defaultValue={settings.oidcScopes} name="oidcScopes" placeholder="openid profile email" />
|
defaultValue={settings.oidcRedirectUri}
|
||||||
</label>
|
label="Redirect URI"
|
||||||
<label className="grid gap-2 text-sm">
|
name="oidcRedirectUri"
|
||||||
<span className="font-medium">Redirect URI</span>
|
placeholder="/api/auth/oidc/callback"
|
||||||
<Input defaultValue={settings.oidcRedirectUri} name="oidcRedirectUri" placeholder="/api/auth/oidc/callback" />
|
/>
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label className="grid gap-2 text-sm">
|
<Input defaultValue={settings.oidcAvatarClaim} label="Avatar Claim" name="oidcAvatarClaim" placeholder="picture" />
|
||||||
<span className="font-medium">Avatar Claim</span>
|
|
||||||
<Input defaultValue={settings.oidcAvatarClaim} name="oidcAvatarClaim" placeholder="picture" />
|
|
||||||
</label>
|
|
||||||
|
|
||||||
{message ? (
|
{message ? (
|
||||||
<p className="rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status">
|
<p className="rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status">
|
||||||
|
|||||||
@@ -71,73 +71,86 @@ export function OrganizationDetailClient({
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<form className="grid gap-4" onSubmit={handleSettingsSubmit}>
|
<form className="grid gap-4" onSubmit={handleSettingsSubmit}>
|
||||||
<label className="flex items-center justify-between gap-4 rounded-md border p-3 text-sm">
|
<div className="rounded-md border p-3 text-sm">
|
||||||
<span>
|
|
||||||
<span className="block font-medium">开放公开注册</span>
|
|
||||||
<span className="block text-xs text-muted-foreground">关闭后,注册页不再展示该机构;邀请链接仍可使用。</span>
|
|
||||||
</span>
|
|
||||||
<Checkbox
|
<Checkbox
|
||||||
aria-label="开放公开注册"
|
controlFirst={false}
|
||||||
defaultChecked={organization.registrationEnabled}
|
defaultChecked={organization.registrationEnabled}
|
||||||
|
label={
|
||||||
|
<span className="min-w-0">
|
||||||
|
<span className="block font-medium">开放公开注册</span>
|
||||||
|
<span className="block text-xs text-muted-foreground">关闭后,注册页不再展示该机构;邀请链接仍可使用。</span>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
name="registrationEnabled"
|
name="registrationEnabled"
|
||||||
/>
|
/>
|
||||||
</label>
|
|
||||||
|
|
||||||
<label className="flex items-center justify-between gap-4 rounded-md border p-3 text-sm">
|
|
||||||
<span>
|
|
||||||
<span className="block font-medium">启用 OIDC 登录</span>
|
|
||||||
<span className="block text-xs text-muted-foreground">保存标准 OIDC 配置,后续登录入口按该开关展示。</span>
|
|
||||||
</span>
|
|
||||||
<Checkbox aria-label="启用 OIDC 登录" defaultChecked={organization.oidcEnabled} name="oidcEnabled" />
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div className="grid gap-3 md:grid-cols-2">
|
|
||||||
<label className="grid gap-2 text-sm">
|
|
||||||
<span className="font-medium">Issuer URL</span>
|
|
||||||
<Input defaultValue={organization.oidcIssuerUrl} name="oidcIssuerUrl" placeholder="https://idp.example.com" />
|
|
||||||
</label>
|
|
||||||
<label className="grid gap-2 text-sm">
|
|
||||||
<span className="font-medium">Client ID</span>
|
|
||||||
<Input defaultValue={organization.oidcClientId} name="oidcClientId" />
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label className="grid gap-2 text-sm">
|
<div className="rounded-md border p-3 text-sm">
|
||||||
<span className="font-medium">Client Secret</span>
|
|
||||||
<Input
|
|
||||||
name="oidcClientSecret"
|
|
||||||
placeholder={organization.oidcHasClientSecret ? "已配置,留空则不修改" : "未配置"}
|
|
||||||
type="password"
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div className="grid gap-3 md:grid-cols-2">
|
|
||||||
<label className="grid gap-2 text-sm">
|
|
||||||
<span className="font-medium">Scopes</span>
|
|
||||||
<Input defaultValue={organization.oidcScopes} name="oidcScopes" placeholder="openid profile email" />
|
|
||||||
</label>
|
|
||||||
<label className="grid gap-2 text-sm">
|
|
||||||
<span className="font-medium">Redirect URI</span>
|
|
||||||
<Input defaultValue={organization.oidcRedirectUri} name="oidcRedirectUri" placeholder="/api/auth/oidc/callback" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<label className="grid gap-2 text-sm">
|
|
||||||
<span className="font-medium">Avatar Claim</span>
|
|
||||||
<Input defaultValue={organization.oidcAvatarClaim} name="oidcAvatarClaim" placeholder="picture" />
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label className="flex items-center justify-between gap-4 rounded-md border p-3 text-sm">
|
|
||||||
<span>
|
|
||||||
<span className="block font-medium">OIDC 自动开户</span>
|
|
||||||
<span className="block text-xs text-muted-foreground">首次 OIDC 登录时自动创建账号并进入本机构。</span>
|
|
||||||
</span>
|
|
||||||
<Checkbox
|
<Checkbox
|
||||||
aria-label="OIDC 自动开户"
|
controlFirst={false}
|
||||||
|
defaultChecked={organization.oidcEnabled}
|
||||||
|
label={
|
||||||
|
<span className="min-w-0">
|
||||||
|
<span className="block font-medium">启用 OIDC 登录</span>
|
||||||
|
<span className="block text-xs text-muted-foreground">保存标准 OIDC 配置,后续登录入口按该开关展示。</span>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
name="oidcEnabled"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid gap-3 md:grid-cols-2">
|
||||||
|
<Input
|
||||||
|
defaultValue={organization.oidcIssuerUrl}
|
||||||
|
label="Issuer URL"
|
||||||
|
name="oidcIssuerUrl"
|
||||||
|
placeholder="https://idp.example.com"
|
||||||
|
/>
|
||||||
|
<Input defaultValue={organization.oidcClientId} label="Client ID" name="oidcClientId" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
label="Client Secret"
|
||||||
|
name="oidcClientSecret"
|
||||||
|
placeholder={organization.oidcHasClientSecret ? "已配置,留空则不修改" : "未配置"}
|
||||||
|
type="password"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="grid gap-3 md:grid-cols-2">
|
||||||
|
<Input
|
||||||
|
defaultValue={organization.oidcScopes}
|
||||||
|
label="Scopes"
|
||||||
|
name="oidcScopes"
|
||||||
|
placeholder="openid profile email"
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
defaultValue={organization.oidcRedirectUri}
|
||||||
|
label="Redirect URI"
|
||||||
|
name="oidcRedirectUri"
|
||||||
|
placeholder="/api/auth/oidc/callback"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
defaultValue={organization.oidcAvatarClaim}
|
||||||
|
label="Avatar Claim"
|
||||||
|
name="oidcAvatarClaim"
|
||||||
|
placeholder="picture"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="rounded-md border p-3 text-sm">
|
||||||
|
<Checkbox
|
||||||
|
controlFirst={false}
|
||||||
defaultChecked={organization.oidcAutoProvision}
|
defaultChecked={organization.oidcAutoProvision}
|
||||||
|
label={
|
||||||
|
<span className="min-w-0">
|
||||||
|
<span className="block font-medium">OIDC 自动开户</span>
|
||||||
|
<span className="block text-xs text-muted-foreground">首次 OIDC 登录时自动创建账号并进入本机构。</span>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
name="oidcAutoProvision"
|
name="oidcAutoProvision"
|
||||||
/>
|
/>
|
||||||
</label>
|
</div>
|
||||||
|
|
||||||
{settingsMessage ? (
|
{settingsMessage ? (
|
||||||
<p className="rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status">
|
<p className="rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status">
|
||||||
|
|||||||
@@ -101,40 +101,41 @@ function PermissionTree({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="rounded-md border bg-card" key={group.category}>
|
<div className="rounded-md border bg-card" key={group.category}>
|
||||||
<label className="flex items-center justify-between gap-3 border-b px-3 py-3 text-sm">
|
<div className="flex items-center justify-between gap-3 border-b px-3 py-3 text-sm">
|
||||||
<span className="flex min-w-0 items-center gap-3">
|
<span className="flex min-w-0 items-center gap-3">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
aria-label={`切换 ${group.category} 权限`}
|
|
||||||
checked={isAllSelected}
|
checked={isAllSelected}
|
||||||
|
label={
|
||||||
|
<span className="min-w-0">
|
||||||
|
<span className="block font-medium">{group.category}</span>
|
||||||
|
<span className="block text-xs text-muted-foreground">
|
||||||
|
已选 {selectedCount} / {group.permissions.length}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
onCheckedChange={(checked) => toggleCategory(group.permissions, checked)}
|
onCheckedChange={(checked) => toggleCategory(group.permissions, checked)}
|
||||||
/>
|
/>
|
||||||
<span>
|
|
||||||
<span className="block font-medium">{group.category}</span>
|
|
||||||
<span className="block text-xs text-muted-foreground">
|
|
||||||
已选 {selectedCount} / {group.permissions.length}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
<Badge variant={selectedCount > 0 ? "success" : "secondary"}>{selectedCount}</Badge>
|
<Badge variant={selectedCount > 0 ? "success" : "secondary"}>{selectedCount}</Badge>
|
||||||
</label>
|
</div>
|
||||||
<div className="grid gap-2 bg-secondary/15 p-3 md:grid-cols-2">
|
<div className="grid gap-2 bg-secondary/15 p-3 md:grid-cols-2">
|
||||||
{group.permissions.map((permission) => (
|
{group.permissions.map((permission) => (
|
||||||
<label
|
<div
|
||||||
className="flex min-h-16 items-start gap-3 rounded-md border bg-background p-3 text-sm transition-colors hover:bg-secondary/50"
|
className="flex min-h-16 items-start gap-3 rounded-md border bg-background p-3 text-sm transition-colors hover:bg-secondary/50"
|
||||||
key={permission.id}
|
key={permission.id}
|
||||||
>
|
>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
aria-label={`切换 ${permission.label}`}
|
|
||||||
checked={selectedSet.has(permission.id)}
|
checked={selectedSet.has(permission.id)}
|
||||||
className="mt-1"
|
label={
|
||||||
|
<span className="min-w-0">
|
||||||
|
<span className="block font-medium">{permission.label}</span>
|
||||||
|
<span className="block break-all text-xs text-muted-foreground">{permission.id}</span>
|
||||||
|
<span className="mt-1 block text-xs text-muted-foreground">{permission.description}</span>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
onCheckedChange={(checked) => togglePermission(permission.id, checked)}
|
onCheckedChange={(checked) => togglePermission(permission.id, checked)}
|
||||||
/>
|
/>
|
||||||
<span className="min-w-0">
|
</div>
|
||||||
<span className="block font-medium">{permission.label}</span>
|
|
||||||
<span className="block break-all text-xs text-muted-foreground">{permission.id}</span>
|
|
||||||
<span className="mt-1 block text-xs text-muted-foreground">{permission.description}</span>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -211,9 +212,9 @@ export function RoleManagementClient({ permissions }: RoleManagementClientProps)
|
|||||||
>
|
>
|
||||||
<form className="grid gap-4" onSubmit={handleSubmit}>
|
<form className="grid gap-4" onSubmit={handleSubmit}>
|
||||||
<div className="grid gap-3 md:grid-cols-3">
|
<div className="grid gap-3 md:grid-cols-3">
|
||||||
<Input name="label" placeholder="角色名称" required />
|
<Input label="角色名称" name="label" placeholder="角色名称" required />
|
||||||
<Input name="key" placeholder="角色标识,可留空" />
|
<Input label="角色标识" name="key" placeholder="可留空" />
|
||||||
<Input name="description" placeholder="角色说明" />
|
<Input label="角色说明" name="description" placeholder="角色说明" />
|
||||||
</div>
|
</div>
|
||||||
<PermissionTree
|
<PermissionTree
|
||||||
onChange={setSelectedPermissions}
|
onChange={setSelectedPermissions}
|
||||||
@@ -352,31 +353,19 @@ export function RoleRowActions({ permissions, role }: RoleRowActionsProps): Reac
|
|||||||
>
|
>
|
||||||
<form className="grid gap-4" onSubmit={handleSubmit}>
|
<form className="grid gap-4" onSubmit={handleSubmit}>
|
||||||
<div className="grid gap-3 md:grid-cols-2">
|
<div className="grid gap-3 md:grid-cols-2">
|
||||||
<label className="grid gap-2 text-sm">
|
<Input defaultValue={role.label} label="角色名称" name="label" required />
|
||||||
<span className="font-medium">角色名称</span>
|
<Input defaultValue={role.key} label="角色标识" name="key" required />
|
||||||
<Input defaultValue={role.label} name="label" required />
|
|
||||||
</label>
|
|
||||||
<label className="grid gap-2 text-sm">
|
|
||||||
<span className="font-medium">角色标识</span>
|
|
||||||
<Input defaultValue={role.key} name="key" required />
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
<label className="grid gap-2 text-sm">
|
<Input defaultValue={role.description} label="角色说明" name="description" />
|
||||||
<span className="font-medium">角色说明</span>
|
<Select
|
||||||
<Input defaultValue={role.description} name="description" />
|
defaultValue={String(role.isEnabled)}
|
||||||
</label>
|
label="状态"
|
||||||
<label className="grid gap-2 text-sm">
|
name="isEnabled"
|
||||||
<span className="font-medium">状态</span>
|
options={[
|
||||||
<Select
|
{ value: "true", label: "启用" },
|
||||||
aria-label="角色状态"
|
{ value: "false", label: "停用" },
|
||||||
defaultValue={String(role.isEnabled)}
|
]}
|
||||||
name="isEnabled"
|
/>
|
||||||
options={[
|
|
||||||
{ value: "true", label: "启用" },
|
|
||||||
{ value: "false", label: "停用" },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
<PermissionTree
|
<PermissionTree
|
||||||
onChange={setSelectedPermissions}
|
onChange={setSelectedPermissions}
|
||||||
permissions={permissions}
|
permissions={permissions}
|
||||||
|
|||||||
Reference in New Issue
Block a user