import { useMemo, useEffect } from 'react' import { Formik, Form, Field, useFormikContext } from 'formik' import { ActionAccessLevel } from '@prisma/client' import { actionAccessLevelToString, pluralizeWithCount } from '~/utils/text' import { inferQueryOutput, inferMutationInput, trpc } from '~/utils/trpc' import IVButton from '~/components/IVButton' import IVInputField from '~/components/IVInputField' import IVRadio from '~/components/IVRadio' import IVSelect from '~/components/IVSelect' import { useOrgParams } from '~/utils/organization' import IVConstraintsIndicator from '~/components/IVConstraintsIndicator' import { useIsFeatureEnabled } from '~/utils/useIsFeatureEnabled' import useDashboard from '../DashboardContext' import { Link } from 'react-router-dom' import { SDK_PERMISSIONS_MIN_VERSION } from '~/utils/permissions' import IVAlert from '../IVAlert' import IconInfo from '~/icons/compiled/Info' function GroupAccessForm({ groups, groupPermissions, }: { groups: inferQueryOutput<'group.list'> groupPermissions: { groupId: string; level: ActionAccessLevel }[] }) { const { orgEnvSlug } = useOrgParams() const { setFieldValue, values } = useFormikContext['data']>() useEffect(() => { setFieldValue('groupPermissions', groupPermissions) }, [setFieldValue, groupPermissions]) if (!groups) return null return (
{groups.length > 0 ? (
    {groups.map(group => { const formValue = values.groupPermissions?.find( v => v.groupId === group.id ) return (
  • {group.name} {pluralizeWithCount(group._count.memberships, 'member')}
    ({ value: level, label: actionAccessLevelToString(level), }) )} onChange={event => { const { groupPermissions } = values if (!groupPermissions) return const idx = groupPermissions.findIndex( v => v.groupId === group.id ) if (idx < 0) return const level = event.target.value as ActionAccessLevel groupPermissions[idx].level = level || 'NONE' setFieldValue('groupPermissions', groupPermissions) }} />
    {formValue?.level === 'RUNNER' && ( To run the action, users on this team must also have{' '} a role with sufficient access . } id="admin-explanation" placement="right" /> )} {formValue?.level === 'ADMINISTRATOR' && (

    The Administrator permission enables running the action and configuring settings.

    To run the action, users on this team must also have{' '} a role with sufficient access .

    To configure action settings, users on this team must also have the{' '} Admin role .

    } id="admin-explanation" placement="right" />
    )}
  • ) })}
  • Everyone else
    No access
) : (

There aren't any teams yet. Please create one to configure team access.

)}
) } export default function ActionPermissionsSettings({ action, onSuccess, onError, isUsingCodeBasedPermissions, }: { action: inferQueryOutput<'action.one'> onSuccess: () => void onError: () => void refetch: () => void isUsingCodeBasedPermissions?: boolean }) { const { organization } = useDashboard() const groups = trpc.useQuery(['group.list', { actionId: action.id }], { refetchOnWindowFocus: false, }) const updateMeta = trpc.useMutation('action.permissions.update') const groupPermissions = useMemo( () => groups.data?.map(group => ({ groupId: group.id, level: group.actionAccesses[0]?.level ?? ('NONE' as ActionAccessLevel), })), [groups.data] ) if (!groups.data || !groupPermissions) { return null } if (isUsingCodeBasedPermissions) { return (

Starting with version {SDK_PERMISSIONS_MIN_VERSION} of the SDK, permissions must be configured via code.{' '} View documentation ›

) } return ( ['data']> initialValues={{ groupPermissions, availability: action.metadata?.availability ?? 'ORGANIZATION', }} validateOnBlur={false} validateOnChange={false} onSubmit={async data => { if (updateMeta.isLoading) return updateMeta.mutate( { actionId: action.id, data: { ...data, // before code-based permissions, this was the default behavior - organization = undefined. // this UI is not available for organizations using code-based permissions, so we'll // keep the previous behavior here. availability: data.availability === 'ORGANIZATION' ? null : data.availability, }, }, { onSuccess() { groups.refetch() onSuccess() }, onError, } ) }} > {({ values, isValid }) => (
{values.availability === 'GROUPS' && (
)}
)} ) }