More user form tweaks
This commit is contained in:
@@ -3,6 +3,7 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
||||||
import { Info } from "lucide-react";
|
import { Info } from "lucide-react";
|
||||||
|
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||||
|
|
||||||
interface Permission {
|
interface Permission {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -21,13 +22,15 @@ interface PermissionSelectorProps {
|
|||||||
selectedPermissions: number[];
|
selectedPermissions: number[];
|
||||||
onChange: (selectedPermissions: number[]) => void;
|
onChange: (selectedPermissions: number[]) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
isAdmin?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PermissionSelector({
|
export function PermissionSelector({
|
||||||
permissionsByCategory,
|
permissionsByCategory,
|
||||||
selectedPermissions,
|
selectedPermissions,
|
||||||
onChange,
|
onChange,
|
||||||
disabled = false
|
disabled = false,
|
||||||
|
isAdmin = false
|
||||||
}: PermissionSelectorProps) {
|
}: PermissionSelectorProps) {
|
||||||
// Handle permission checkbox change
|
// Handle permission checkbox change
|
||||||
const handlePermissionChange = (permissionId: number) => {
|
const handlePermissionChange = (permissionId: number) => {
|
||||||
@@ -68,7 +71,13 @@ export function PermissionSelector({
|
|||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h3 className="text-lg font-medium">Permissions</h3>
|
<h3 className="text-lg font-medium">Permissions</h3>
|
||||||
|
{isAdmin && (
|
||||||
|
<Alert variant="destructive">
|
||||||
|
<AlertDescription>
|
||||||
|
Administrators have access to all permissions by default. Individual permissions cannot be edited for admin users.
|
||||||
|
</AlertDescription>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
{permissionsByCategory.map(category => (
|
{permissionsByCategory.map(category => (
|
||||||
<Card key={category.category} className="mb-4">
|
<Card key={category.category} className="mb-4">
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ const userFormSchema = z.object({
|
|||||||
password: z.string().min(6, { message: "Password must be at least 6 characters" }).optional().or(z.literal("")),
|
password: z.string().min(6, { message: "Password must be at least 6 characters" }).optional().or(z.literal("")),
|
||||||
is_admin: z.boolean().default(false),
|
is_admin: z.boolean().default(false),
|
||||||
is_active: z.boolean().default(true),
|
is_active: z.boolean().default(true),
|
||||||
rocket_chat_user_id: z.string().optional(),
|
rocket_chat_user_id: z.string().default("none"),
|
||||||
});
|
});
|
||||||
|
|
||||||
type FormValues = z.infer<typeof userFormSchema>;
|
type FormValues = z.infer<typeof userFormSchema>;
|
||||||
@@ -136,20 +136,24 @@ export function UserForm({ user, permissions, onSave, onCancel }: UserFormProps)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Ensure rocket_chat_user_id is set to "none" initially if not set
|
||||||
|
if (!form.getValues().rocket_chat_user_id) {
|
||||||
|
form.setValue('rocket_chat_user_id', 'none');
|
||||||
|
}
|
||||||
|
|
||||||
fetchRocketChatUsers();
|
fetchRocketChatUsers();
|
||||||
}, []);
|
}, [form]);
|
||||||
|
|
||||||
// Initialize selected permissions and form values
|
// Initialize selected permissions and form values
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("User permissions:", user?.permissions);
|
|
||||||
|
|
||||||
if (user?.permissions && Array.isArray(user.permissions) && user.permissions.length > 0) {
|
if (user?.permissions && Array.isArray(user.permissions) && user.permissions.length > 0) {
|
||||||
// Extract IDs from the permissions
|
// Extract IDs from the permissions
|
||||||
const permissionIds = user.permissions.map(p => p.id);
|
const permissionIds = user.permissions.map(p => p.id);
|
||||||
console.log("Setting selected permissions:", permissionIds);
|
|
||||||
setSelectedPermissions(permissionIds);
|
setSelectedPermissions(permissionIds);
|
||||||
} else {
|
} else {
|
||||||
console.log("No permissions found or empty permissions array");
|
|
||||||
setSelectedPermissions([]);
|
setSelectedPermissions([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,6 +167,16 @@ export function UserForm({ user, permissions, onSave, onCancel }: UserFormProps)
|
|||||||
is_active: user.is_active !== false,
|
is_active: user.is_active !== false,
|
||||||
rocket_chat_user_id: user.rocket_chat_user_id || "none",
|
rocket_chat_user_id: user.rocket_chat_user_id || "none",
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
// For new users, ensure rocket_chat_user_id defaults to "none"
|
||||||
|
form.reset({
|
||||||
|
username: "",
|
||||||
|
email: "",
|
||||||
|
password: "",
|
||||||
|
is_admin: false,
|
||||||
|
is_active: true,
|
||||||
|
rocket_chat_user_id: "none",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, [user, form]);
|
}, [user, form]);
|
||||||
|
|
||||||
@@ -170,7 +184,7 @@ export function UserForm({ user, permissions, onSave, onCancel }: UserFormProps)
|
|||||||
const onSubmit = (data: FormValues) => {
|
const onSubmit = (data: FormValues) => {
|
||||||
try {
|
try {
|
||||||
setFormError(null);
|
setFormError(null);
|
||||||
console.log("Form submitted with permissions:", selectedPermissions);
|
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!user && !data.password) {
|
if (!user && !data.password) {
|
||||||
@@ -214,7 +228,7 @@ export function UserForm({ user, permissions, onSave, onCancel }: UserFormProps)
|
|||||||
userData.permissions = [];
|
userData.permissions = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Saving user data:", userData);
|
|
||||||
onSave(userData);
|
onSave(userData);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorMessage = error instanceof Error ? error.message : "An error occurred";
|
const errorMessage = error instanceof Error ? error.message : "An error occurred";
|
||||||
@@ -222,12 +236,6 @@ export function UserForm({ user, permissions, onSave, onCancel }: UserFormProps)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// For debugging
|
|
||||||
console.log("Current form state:", form.getValues());
|
|
||||||
console.log("Available permissions categories:", permissions);
|
|
||||||
console.log("Selected permissions:", selectedPermissions);
|
|
||||||
console.log("Is admin:", form.watch("is_admin"));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
@@ -242,6 +250,8 @@ export function UserForm({ user, permissions, onSave, onCancel }: UserFormProps)
|
|||||||
|
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
|
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
|
||||||
|
{/* Basic Information Section */}
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="username"
|
name="username"
|
||||||
@@ -270,6 +280,25 @@ export function UserForm({ user, permissions, onSave, onCancel }: UserFormProps)
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="password"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{user ? "New Password" : "Password"}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
type="password"
|
||||||
|
{...field}
|
||||||
|
placeholder={user ? "Leave blank to keep current password" : ""}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="rocket_chat_user_id"
|
name="rocket_chat_user_id"
|
||||||
@@ -278,13 +307,13 @@ export function UserForm({ user, permissions, onSave, onCancel }: UserFormProps)
|
|||||||
<FormLabel>Rocket Chat User</FormLabel>
|
<FormLabel>Rocket Chat User</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
{form.watch("is_admin") ? (
|
{form.watch("is_admin") ? (
|
||||||
<div className="flex items-center gap-2 p-2 border rounded-md bg-muted">
|
<div className="flex items-center gap-2 p-2 border text-sm rounded-md bg-muted">
|
||||||
<span className="text-muted-foreground">
|
<span className="text-muted-foreground">
|
||||||
Admin users have access to all chat rooms by default
|
Admin users have access to all chat rooms by default
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Select value={field.value} onValueChange={field.onChange}>
|
<Select value={field.value || "none"} onValueChange={field.onChange}>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue placeholder={loadingRocketChatUsers ? "Loading..." : "Select Rocket Chat user..."} />
|
<SelectValue placeholder={loadingRocketChatUsers ? "Loading..." : "Select Rocket Chat user..."} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
@@ -321,26 +350,9 @@ export function UserForm({ user, permissions, onSave, onCancel }: UserFormProps)
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<FormField
|
{/* Status Switches - Two Columns */}
|
||||||
control={form.control}
|
|
||||||
name="password"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>{user ? "New Password" : "Password"}</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="password"
|
|
||||||
{...field}
|
|
||||||
placeholder={user ? "Leave blank to keep current password" : ""}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
@@ -385,31 +397,18 @@ export function UserForm({ user, permissions, onSave, onCancel }: UserFormProps)
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Permissions Section */}
|
||||||
{permissions && permissions.length > 0 && (
|
{permissions && permissions.length > 0 && (
|
||||||
<>
|
<>
|
||||||
{form.watch("is_admin") ? (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<Alert variant="destructive">
|
|
||||||
<AlertDescription>
|
|
||||||
Administrators have access to all permissions by default. Individual permissions cannot be edited for admin users.
|
|
||||||
</AlertDescription>
|
|
||||||
</Alert>
|
|
||||||
<PermissionSelector
|
<PermissionSelector
|
||||||
permissionsByCategory={permissions}
|
permissionsByCategory={permissions}
|
||||||
selectedPermissions={getAllPermissionIds(permissions)}
|
selectedPermissions={form.watch("is_admin") ? getAllPermissionIds(permissions) : selectedPermissions}
|
||||||
onChange={() => {}}
|
|
||||||
disabled={true}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<PermissionSelector
|
|
||||||
permissionsByCategory={permissions}
|
|
||||||
selectedPermissions={selectedPermissions}
|
|
||||||
onChange={setSelectedPermissions}
|
onChange={setSelectedPermissions}
|
||||||
|
disabled={form.watch("is_admin")}
|
||||||
|
isAdmin={form.watch("is_admin")}
|
||||||
/>
|
/>
|
||||||
{selectedPermissions.length === 0 && (
|
{!form.watch("is_admin") && selectedPermissions.length === 0 && (
|
||||||
<Alert>
|
<Alert variant="destructive">
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
Warning: This user has no permissions selected. They won't be able to access anything.
|
Warning: This user has no permissions selected. They won't be able to access anything.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
@@ -417,8 +416,6 @@ export function UserForm({ user, permissions, onSave, onCancel }: UserFormProps)
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="flex justify-end space-x-4">
|
<div className="flex justify-end space-x-4">
|
||||||
<Button type="button" variant="outline" onClick={onCancel}>
|
<Button type="button" variant="outline" onClick={onCancel}>
|
||||||
|
|||||||
Reference in New Issue
Block a user