mirror of
https://github.com/andwati/dokploy.git
synced 2026-10-29 00:02:16 +00:00
feat(organization): allow setting a default role for new members
This commit is contained in:
@@ -106,6 +106,7 @@ export const AddInvitation = () => {
|
||||
const { mutateAsync: createUserWithCredentials, isPending: isCreating } =
|
||||
api.user.createUserWithCredentials.useMutation();
|
||||
const { data: customRoles } = api.customRole.all.useQuery();
|
||||
const { data: activeOrganization } = api.organization.active.useQuery();
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const form = useForm<AddInvitation>({
|
||||
@@ -132,6 +133,16 @@ export const AddInvitation = () => {
|
||||
}
|
||||
}, [form, isCloud]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
activeOrganization?.defaultRole &&
|
||||
activeOrganization.defaultRole !== "owner" &&
|
||||
!form.formState.dirtyFields.role
|
||||
) {
|
||||
form.setValue("role", activeOrganization.defaultRole);
|
||||
}
|
||||
}, [form, activeOrganization?.defaultRole]);
|
||||
|
||||
const onSubmit = async (data: AddInvitation) => {
|
||||
setError(null);
|
||||
|
||||
@@ -267,10 +278,7 @@ export const AddInvitation = () => {
|
||||
return (
|
||||
<FormItem>
|
||||
<FormLabel>Role</FormLabel>
|
||||
<Select
|
||||
onValueChange={field.onChange}
|
||||
defaultValue={field.value}
|
||||
>
|
||||
<Select onValueChange={field.onChange} value={field.value}>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select a role" />
|
||||
|
||||
@@ -45,6 +45,13 @@ import {
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { api } from "@/utils/api";
|
||||
|
||||
@@ -780,6 +787,78 @@ function HandleCustomRole({
|
||||
);
|
||||
}
|
||||
|
||||
const DefaultRoleSection = ({ customRoles }: { customRoles: string[] }) => {
|
||||
const utils = api.useUtils();
|
||||
const { data: auth } = api.user.get.useQuery();
|
||||
const { data: activeOrganization } = api.organization.active.useQuery();
|
||||
const { mutateAsync: updateOrganization, isPending: isUpdating } =
|
||||
api.organization.update.useMutation();
|
||||
const [selectedRole, setSelectedRole] = useState<string>();
|
||||
|
||||
if (auth?.role !== "owner" || !activeOrganization) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const currentRole = activeOrganization.defaultRole ?? "member";
|
||||
const value = selectedRole ?? currentRole;
|
||||
|
||||
const onSave = async () => {
|
||||
await updateOrganization({
|
||||
organizationId: activeOrganization.id,
|
||||
name: activeOrganization.name,
|
||||
logo: activeOrganization.logo ?? undefined,
|
||||
defaultRole: value,
|
||||
})
|
||||
.then(() => {
|
||||
toast.success("Default role updated");
|
||||
utils.organization.active.invalidate();
|
||||
})
|
||||
.catch((error) => {
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Error updating default role",
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-3 rounded-lg border bg-muted/20 p-4">
|
||||
<div className="space-y-0.5">
|
||||
<p className="text-sm font-medium">Default role for new members</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Assigned automatically to users joining through SSO and preselected
|
||||
when creating invitations.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Select value={value} onValueChange={setSelectedRole}>
|
||||
<SelectTrigger className="w-40">
|
||||
<SelectValue placeholder="Select a role" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="member">Member</SelectItem>
|
||||
<SelectItem value="admin">Admin</SelectItem>
|
||||
{customRoles.map((role) => (
|
||||
<SelectItem key={role} value={role}>
|
||||
{role}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Button
|
||||
size="sm"
|
||||
isLoading={isUpdating}
|
||||
disabled={value === currentRole}
|
||||
onClick={onSave}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const CustomRolesContent = () => {
|
||||
const {
|
||||
data: customRoles,
|
||||
@@ -821,6 +900,9 @@ const CustomRolesContent = () => {
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<DefaultRoleSection
|
||||
customRoles={customRoles?.map((role) => role.role) ?? []}
|
||||
/>
|
||||
<div className="flex justify-end">
|
||||
<HandleCustomRole onSuccess={refetch} />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user