diff --git a/apps/studio/components/interfaces/Account/AccessTokens/Scoped/Form/Permissions/PermissionResourceSelector.tsx b/apps/studio/components/interfaces/Account/AccessTokens/Scoped/Form/Permissions/PermissionResourceSelector.tsx index e0d823e77ee..79955c9ebce 100644 --- a/apps/studio/components/interfaces/Account/AccessTokens/Scoped/Form/Permissions/PermissionResourceSelector.tsx +++ b/apps/studio/components/interfaces/Account/AccessTokens/Scoped/Form/Permissions/PermissionResourceSelector.tsx @@ -1,5 +1,4 @@ import { Key, Plus } from 'lucide-react' -import { Path, PathValue } from 'react-hook-form' import { Button, Checkbox, @@ -14,30 +13,16 @@ import { PopoverTrigger, } from 'ui' -import { - PermissionResource, - PermissionResourceSelectorProps, - PermissionRow, - PermissionsFormValues, -} from './Permissions.types' -import { togglePermissionResource } from './Permissions.utils' +import { PermissionResourceSelectorProps, PermissionRow } from './Permissions.types' import { ACCESS_TOKEN_RESOURCES } from '@/components/interfaces/Account/AccessTokens/AccessToken.constants' -export const PermissionResourceSelector = ({ +export const PermissionResourceSelector = ({ open, onOpenChange, + onResourceToggled, permissionRows, - setValue, align = 'center', -}: PermissionResourceSelectorProps) => { - const handleToggleResource = (resource: PermissionResource) => { - const newRows = togglePermissionResource(permissionRows, resource) - setValue( - 'permissionRows' as Path, - newRows as PathValue> - ) - } - +}: PermissionResourceSelectorProps) => { return ( @@ -61,13 +46,13 @@ export const PermissionResourceSelector = handleToggleResource(resource)} + onSelect={() => onResourceToggled(resource)} className="text-foreground" >
handleToggleResource(resource)} + onCheckedChange={() => onResourceToggled(resource)} onClick={(e) => e.stopPropagation()} /> diff --git a/apps/studio/components/interfaces/Account/AccessTokens/Scoped/Form/Permissions/Permissions.tsx b/apps/studio/components/interfaces/Account/AccessTokens/Scoped/Form/Permissions/Permissions.tsx index f22efce175d..1860d289d08 100644 --- a/apps/studio/components/interfaces/Account/AccessTokens/Scoped/Form/Permissions/Permissions.tsx +++ b/apps/studio/components/interfaces/Account/AccessTokens/Scoped/Form/Permissions/Permissions.tsx @@ -1,21 +1,39 @@ import { ChevronDown, RotateCcw, X } from 'lucide-react' -import { Path, PathValue } from 'react-hook-form' -import { Button, Checkbox, Popover, PopoverContent, PopoverTrigger, WarningIcon } from 'ui' +import { useFieldArray, useFormState } from 'react-hook-form' +import { + Button, + Checkbox, + FormControl, + FormField, + FormMessage, + Popover, + PopoverContent, + PopoverTrigger, + WarningIcon, +} from 'ui' +import { TokenFormValues } from '../../../AccessToken.schemas' import { PermissionResourceSelector } from './PermissionResourceSelector' -import { PermissionRow, PermissionsFormValues, PermissionsProps } from './Permissions.types' +import { PermissionsProps } from './Permissions.types' import { sortActions } from './Permissions.utils' import { ACCESS_TOKEN_RESOURCES } from '@/components/interfaces/Account/AccessTokens/AccessToken.constants' import { formatAccessText } from '@/components/interfaces/Account/AccessTokens/AccessToken.utils' import { ButtonTooltip } from '@/components/ui/ButtonTooltip' -export const Permissions = ({ - setValue, - watch, +export const Permissions = ({ + control, resourceSearchOpen, setResourceSearchOpen, -}: PermissionsProps) => { - const permissionRows = (watch('permissionRows' as Path) || []) as PermissionRow[] +}: PermissionsProps) => { + const { + fields: permissionRows, + append, + remove, + } = useFieldArray({ + name: 'permissionRows', + control, + }) + const { errors } = useFormState({ control, name: 'permissionRows' }) return (
@@ -28,12 +46,7 @@ export const Permissions = { - setValue( - 'permissionRows' as Path, - [] as PathValue> - ) - }} + onClick={() => remove()} icon={} tooltip={{ content: { @@ -49,7 +62,13 @@ export const Permissions = { + const index = permissionRows.findIndex((p) => p.resource === resource.resource) + if (index > -1) { + return remove(index) + } + append(resource) + }} align="end" />
@@ -66,88 +85,101 @@ export const Permissions = r.resource === row.resource ) return ( -
-
-
-
-
- - {selectedResource?.title} - -
-
-
-
- {selectedResource && ( - - - - - -
- {sortActions(selectedResource.actions).map((action) => ( - - ))} + { + const fieldValue = field.value || [] + + return ( +
+
+
+
+
+ + {selectedResource?.title} + +
- - - )} -
-
- {index < permissionRows.length - 1 &&
} -
+
+
+ {selectedResource && ( + + + + + + + +
+ {sortActions(selectedResource.actions).map((action) => ( + + ))} +
+
+
+ )} +
+
+
+ +
+ {index < permissionRows.length - 1 && ( +
+ )} +
+ ) + }} + /> ) })}
@@ -160,6 +192,11 @@ export const Permissions =
+ {errors.permissionRows?.message || errors.permissionRows?.root?.message ? ( +

+ {errors.permissionRows?.message || errors.permissionRows?.root?.message} +

+ ) : null}
) } diff --git a/apps/studio/components/interfaces/Account/AccessTokens/Scoped/Form/Permissions/Permissions.types.ts b/apps/studio/components/interfaces/Account/AccessTokens/Scoped/Form/Permissions/Permissions.types.ts index ffb26fe487a..8b3c4a5d439 100644 --- a/apps/studio/components/interfaces/Account/AccessTokens/Scoped/Form/Permissions/Permissions.types.ts +++ b/apps/studio/components/interfaces/Account/AccessTokens/Scoped/Form/Permissions/Permissions.types.ts @@ -1,4 +1,6 @@ -import { FieldValues, UseFormSetValue, UseFormWatch } from 'react-hook-form' +import { Control, FieldValues } from 'react-hook-form' + +import { TokenFormValues } from '../../../AccessToken.schemas' export interface PermissionResource { resource: string @@ -15,19 +17,16 @@ export interface PermissionsFormValues extends FieldValues { permissionRows?: PermissionRow[] } -export interface PermissionsProps< - TFormValues extends PermissionsFormValues = PermissionsFormValues, -> { - setValue: UseFormSetValue - watch: UseFormWatch +export interface PermissionsProps { + control: Control resourceSearchOpen: boolean setResourceSearchOpen: (open: boolean) => void } -export interface PermissionResourceSelectorProps { +export interface PermissionResourceSelectorProps { open: boolean onOpenChange: (open: boolean) => void permissionRows: PermissionRow[] - setValue: UseFormSetValue + onResourceToggled: (resource: PermissionResource) => void align?: 'center' | 'end' | 'start' } diff --git a/apps/studio/components/interfaces/Account/AccessTokens/Scoped/NewScopedTokenSheet.tsx b/apps/studio/components/interfaces/Account/AccessTokens/Scoped/NewScopedTokenSheet.tsx index 21cd176dbcd..31efd63cd9b 100644 --- a/apps/studio/components/interfaces/Account/AccessTokens/Scoped/NewScopedTokenSheet.tsx +++ b/apps/studio/components/interfaces/Account/AccessTokens/Scoped/NewScopedTokenSheet.tsx @@ -66,6 +66,7 @@ export const NewScopedTokenSheet = ({ }, mode: 'onChange', }) + const track = useTrack() const { mutate: createAccessToken, isPending } = useAccessTokenCreateMutation() @@ -303,8 +304,7 @@ export const NewScopedTokenSheet = ({ />