add roles input on resource and make spacing more consistent

This commit is contained in:
Milo Schwartz
2024-11-15 18:25:27 -05:00
parent 8e64b5e0e9
commit 28bae40390
36 changed files with 1235 additions and 724 deletions

View File

@@ -110,52 +110,58 @@ export default function AccessControlsPage() {
return (
<>
<SettingsSectionTitle
title="Access Controls"
description="Manage what this user can access and do in the organization"
size="1xl"
/>
<div className="space-y-6">
<SettingsSectionTitle
title="Access Controls"
description="Manage what this user can access and do in the organization"
size="1xl"
/>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-4"
>
<FormField
control={form.control}
name="roleId"
render={({ field }) => (
<FormItem>
<FormLabel>Role</FormLabel>
<Select
onValueChange={field.onChange}
value={field.value}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select role" />
</SelectTrigger>
</FormControl>
<SelectContent>
{roles.map((role) => (
<SelectItem
key={role.roleId}
value={role.roleId.toString()}
>
{role.name}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" loading={loading} disabled={loading}>
Save Changes
</Button>
</form>
</Form>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-6"
>
<FormField
control={form.control}
name="roleId"
render={({ field }) => (
<FormItem>
<FormLabel>Role</FormLabel>
<Select
onValueChange={field.onChange}
value={field.value}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select role" />
</SelectTrigger>
</FormControl>
<SelectContent>
{roles.map((role) => (
<SelectItem
key={role.roleId}
value={role.roleId.toString()}
>
{role.name}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<Button
type="submit"
loading={loading}
disabled={loading}
>
Save Changes
</Button>
</form>
</Form>
</div>
</>
);
}

View File

@@ -171,125 +171,135 @@ export default function InviteUserForm({ open, setOpen }: InviteUserFormProps) {
</CredenzaDescription>
</CredenzaHeader>
<CredenzaBody>
{!inviteLink && (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-4"
id="invite-user-form"
>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input
placeholder="Enter an email"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="roleId"
render={({ field }) => (
<FormItem>
<FormLabel>Role</FormLabel>
<Select
onValueChange={
field.onChange
}
>
<div className="space-y-6">
{!inviteLink && (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-4"
id="invite-user-form"
>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select role" />
</SelectTrigger>
<Input
placeholder="Enter an email"
{...field}
/>
</FormControl>
<SelectContent>
{roles.map((role) => (
<SelectItem
key={
role.roleId
}
value={role.roleId.toString()}
>
{role.name}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="validForHours"
render={({ field }) => (
<FormItem>
<FormLabel>Valid For</FormLabel>
<Select
onValueChange={
field.onChange
}
defaultValue={field.value.toString()}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select duration" />
</SelectTrigger>
</FormControl>
<SelectContent>
{validFor.map(
(option) => (
<SelectItem
key={
option.hours
}
value={option.hours.toString()}
>
{
option.name
}
</SelectItem>
)
)}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
)}
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="roleId"
render={({ field }) => (
<FormItem>
<FormLabel>Role</FormLabel>
<Select
onValueChange={
field.onChange
}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select role" />
</SelectTrigger>
</FormControl>
<SelectContent>
{roles.map(
(role) => (
<SelectItem
key={
role.roleId
}
value={role.roleId.toString()}
>
{
role.name
}
</SelectItem>
)
)}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="validForHours"
render={({ field }) => (
<FormItem>
<FormLabel>
Valid For
</FormLabel>
<Select
onValueChange={
field.onChange
}
defaultValue={field.value.toString()}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select duration" />
</SelectTrigger>
</FormControl>
<SelectContent>
{validFor.map(
(option) => (
<SelectItem
key={
option.hours
}
value={option.hours.toString()}
>
{
option.name
}
</SelectItem>
)
)}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
)}
{inviteLink && (
<div className="max-w-md">
<p className="mb-4">
The user has been successfully invited. They
must access the link below to accept the
invitation.
</p>
<p className="mb-4">
The invite will expire in{" "}
<b>
{expiresInDays}{" "}
{expiresInDays === 1 ? "day" : "days"}
</b>
.
</p>
<CopyTextBox
text={inviteLink}
wrapText={false}
/>
</div>
)}
{inviteLink && (
<div className="max-w-md space-y-4">
<p>
The user has been successfully invited.
They must access the link below to
accept the invitation.
</p>
<p>
The invite will expire in{" "}
<b>
{expiresInDays}{" "}
{expiresInDays === 1
? "day"
: "days"}
</b>
.
</p>
<CopyTextBox
text={inviteLink}
wrapText={false}
/>
</div>
)}
</div>
</CredenzaBody>
<CredenzaFooter>
<Button

View File

@@ -8,7 +8,7 @@ import {
DropdownMenuTrigger,
} from "@app/components/ui/dropdown-menu";
import { Button } from "@app/components/ui/button";
import { ArrowUpDown, Crown, MoreHorizontal } from "lucide-react";
import { ArrowRight, ArrowUpDown, Crown, MoreHorizontal } from "lucide-react";
import { UsersDataTable } from "./UsersDataTable";
import { useState } from "react";
import InviteUserForm from "./InviteUserForm";
@@ -112,43 +112,63 @@ export default function UsersTable({ users: u }: UsersTableProps) {
return (
<>
{!userRow.isOwner && (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
className="h-8 w-8 p-0"
>
<span className="sr-only">
Open menu
</span>
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem>
<Link
href={`/${org?.org.orgId}/settings/access/users/${userRow.id}`}
>
Manage User
</Link>
</DropdownMenuItem>
{userRow.email !== user?.email && (
<DropdownMenuItem>
<button
className="text-red-600 hover:text-red-800"
onClick={() => {
setIsDeleteModalOpen(true);
setSelectedUser(userRow);
}}
<div className="flex items-center justify-end">
{!userRow.isOwner && (
<>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
className="h-8 w-8 p-0"
>
Remove User
</button>
</DropdownMenuItem>
)}
</DropdownMenuContent>
</DropdownMenu>
)}
<span className="sr-only">
Open menu
</span>
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem>
<Link
href={`/${org?.org.orgId}/settings/access/users/${userRow.id}`}
>
Manage User
</Link>
</DropdownMenuItem>
{userRow.email !== user?.email && (
<DropdownMenuItem>
<button
className="text-red-600 hover:text-red-800"
onClick={() => {
setIsDeleteModalOpen(
true
);
setSelectedUser(
userRow
);
}}
>
Remove User
</button>
</DropdownMenuItem>
)}
</DropdownMenuContent>
</DropdownMenu>
<Button
variant={"gray"}
className="ml-2"
onClick={() =>
router.push(
`/${org?.org.orgId}/settings/access/users/${userRow.id}`
)
}
>
Manage{" "}
<ArrowRight className="ml-2 w-4 h-4" />
</Button>
</>
)}
</div>
</>
);
},
@@ -194,13 +214,13 @@ export default function UsersTable({ users: u }: UsersTableProps) {
setSelectedUser(null);
}}
dialog={
<div>
<p className="mb-2">
<div className="space-y-4">
<p>
Are you sure you want to remove{" "}
<b>{selectedUser?.email}</b> from the organization?
</p>
<p className="mb-2">
<p>
Once removed, this user will no longer have access
to the organization. You can always re-invite them
later, but they will need to accept the invitation
@@ -213,10 +233,10 @@ export default function UsersTable({ users: u }: UsersTableProps) {
</p>
</div>
}
buttonText="Confirm remove user"
buttonText="Confirm Remove User"
onConfirm={removeUser}
string={selectedUser?.email ?? ""}
title="Remove user from organization"
title="Remove User from Organization"
/>
<InviteUserForm