Refactor Supabase server client and improve team management features
Refactored Supabase server component client to improve type safety. Improved team account management by adjusting role data providers to consider account IDs, and adjusted invite member functionality to use account IDs and slugs. Enhanced invitation update dialog by adding account parameter. Fixed database webhook URLs in seed.sql. Overall, these changes enhance the robustness and usability of the team management functionalities.
This commit is contained in:
@@ -197,6 +197,7 @@ function ActionsDropdown({
|
||||
<UpdateInvitationDialog
|
||||
isOpen
|
||||
setIsOpen={setIsUpdatingRole}
|
||||
account={invitation.account_id}
|
||||
invitationId={invitation.id}
|
||||
userRole={invitation.role}
|
||||
userRoleHierarchy={permissions.currentUserRoleHierarchy}
|
||||
|
||||
@@ -36,9 +36,17 @@ export const UpdateInvitationDialog: React.FC<{
|
||||
isOpen: boolean;
|
||||
setIsOpen: (isOpen: boolean) => void;
|
||||
invitationId: number;
|
||||
account: string;
|
||||
userRole: Role;
|
||||
userRoleHierarchy: number;
|
||||
}> = ({ isOpen, setIsOpen, invitationId, userRole, userRoleHierarchy }) => {
|
||||
}> = ({
|
||||
isOpen,
|
||||
setIsOpen,
|
||||
invitationId,
|
||||
userRole,
|
||||
userRoleHierarchy,
|
||||
account,
|
||||
}) => {
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||
<DialogContent>
|
||||
@@ -52,9 +60,13 @@ export const UpdateInvitationDialog: React.FC<{
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<RolesDataProvider maxRoleHierarchy={userRoleHierarchy}>
|
||||
<RolesDataProvider
|
||||
accountId={account}
|
||||
maxRoleHierarchy={userRoleHierarchy}
|
||||
>
|
||||
{(roles) => (
|
||||
<UpdateInvitationForm
|
||||
account={account}
|
||||
invitationId={invitationId}
|
||||
userRole={userRole}
|
||||
userRoleHierarchy={roles.length}
|
||||
@@ -68,11 +80,13 @@ export const UpdateInvitationDialog: React.FC<{
|
||||
};
|
||||
|
||||
function UpdateInvitationForm({
|
||||
account,
|
||||
invitationId,
|
||||
userRole,
|
||||
userRoleHierarchy,
|
||||
setIsOpen,
|
||||
}: React.PropsWithChildren<{
|
||||
account: string;
|
||||
invitationId: number;
|
||||
userRole: Role;
|
||||
userRoleHierarchy: number;
|
||||
@@ -136,7 +150,10 @@ function UpdateInvitationForm({
|
||||
</FormLabel>
|
||||
|
||||
<FormControl>
|
||||
<RolesDataProvider maxRoleHierarchy={userRoleHierarchy}>
|
||||
<RolesDataProvider
|
||||
accountId={account}
|
||||
maxRoleHierarchy={userRoleHierarchy}
|
||||
>
|
||||
{(roles) => (
|
||||
<MembershipRoleSelector
|
||||
roles={roles}
|
||||
|
||||
@@ -42,11 +42,13 @@ type InviteModel = ReturnType<typeof createEmptyInviteModel>;
|
||||
type Role = string;
|
||||
|
||||
export function InviteMembersDialogContainer({
|
||||
account,
|
||||
accountSlug,
|
||||
accountId,
|
||||
userRoleHierarchy,
|
||||
children,
|
||||
}: React.PropsWithChildren<{
|
||||
account: string;
|
||||
accountSlug: string;
|
||||
accountId: string;
|
||||
userRoleHierarchy: number;
|
||||
}>) {
|
||||
const [pending, startTransition] = useTransition();
|
||||
@@ -67,7 +69,10 @@ export function InviteMembersDialogContainer({
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<RolesDataProvider maxRoleHierarchy={userRoleHierarchy}>
|
||||
<RolesDataProvider
|
||||
accountId={accountId}
|
||||
maxRoleHierarchy={userRoleHierarchy}
|
||||
>
|
||||
{(roles) => (
|
||||
<InviteMembersForm
|
||||
pending={pending}
|
||||
@@ -75,7 +80,7 @@ export function InviteMembersDialogContainer({
|
||||
onSubmit={(data) => {
|
||||
startTransition(async () => {
|
||||
await createInvitationsAction({
|
||||
account,
|
||||
accountSlug,
|
||||
invitations: data.invitations,
|
||||
});
|
||||
|
||||
|
||||
@@ -5,17 +5,15 @@ import { LoadingOverlay } from '@kit/ui/loading-overlay';
|
||||
|
||||
export function RolesDataProvider(props: {
|
||||
maxRoleHierarchy: number;
|
||||
accountId: string;
|
||||
children: (roles: string[]) => React.ReactNode;
|
||||
}) {
|
||||
const rolesQuery = useFetchRoles({
|
||||
maxRoleHierarchy: props.maxRoleHierarchy,
|
||||
});
|
||||
const rolesQuery = useFetchRoles(props);
|
||||
|
||||
if (rolesQuery.isLoading) {
|
||||
return <LoadingOverlay fullPage={false} />;
|
||||
}
|
||||
|
||||
// TODO handle error
|
||||
if (rolesQuery.isError) {
|
||||
return null;
|
||||
}
|
||||
@@ -23,7 +21,7 @@ export function RolesDataProvider(props: {
|
||||
return <>{props.children(rolesQuery.data ?? [])}</>;
|
||||
}
|
||||
|
||||
function useFetchRoles(props: { maxRoleHierarchy: number }) {
|
||||
function useFetchRoles(props: { maxRoleHierarchy: number; accountId: string }) {
|
||||
const supabase = useSupabase();
|
||||
|
||||
return useQuery({
|
||||
@@ -33,6 +31,7 @@ function useFetchRoles(props: { maxRoleHierarchy: number }) {
|
||||
.from('roles')
|
||||
.select('name')
|
||||
.gte('hierarchy_level', props.maxRoleHierarchy)
|
||||
.or(`account_id.eq.${props.accountId}, account_id.is.null`)
|
||||
.order('hierarchy_level', { ascending: true });
|
||||
|
||||
if (error) {
|
||||
|
||||
@@ -60,7 +60,10 @@ export const UpdateMemberRoleDialog: React.FC<{
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<RolesDataProvider maxRoleHierarchy={userRoleHierarchy}>
|
||||
<RolesDataProvider
|
||||
accountId={accountId}
|
||||
maxRoleHierarchy={userRoleHierarchy}
|
||||
>
|
||||
{(data) => (
|
||||
<UpdateMemberForm
|
||||
setIsOpen={setIsOpen}
|
||||
|
||||
@@ -22,7 +22,7 @@ import { AccountInvitationsService } from '../services/account-invitations.servi
|
||||
* Creates invitations for inviting members.
|
||||
*/
|
||||
export async function createInvitationsAction(params: {
|
||||
account: string;
|
||||
accountSlug: string;
|
||||
invitations: z.infer<typeof InviteMembersSchema>['invitations'];
|
||||
}) {
|
||||
const client = getSupabaseServerActionClient();
|
||||
@@ -35,7 +35,10 @@ export async function createInvitationsAction(params: {
|
||||
|
||||
const service = new AccountInvitationsService(client);
|
||||
|
||||
await service.sendInvitations({ invitations, account: params.account });
|
||||
await service.sendInvitations({
|
||||
invitations,
|
||||
accountSlug: params.accountSlug,
|
||||
});
|
||||
|
||||
revalidateMemberPage();
|
||||
|
||||
|
||||
@@ -69,21 +69,21 @@ export class AccountInvitationsService {
|
||||
}
|
||||
|
||||
async sendInvitations({
|
||||
account,
|
||||
accountSlug,
|
||||
invitations,
|
||||
}: {
|
||||
invitations: z.infer<typeof InviteMembersSchema>['invitations'];
|
||||
account: string;
|
||||
accountSlug: string;
|
||||
}) {
|
||||
Logger.info(
|
||||
{ account, invitations, name: this.namespace },
|
||||
{ account: accountSlug, invitations, name: this.namespace },
|
||||
'Storing invitations',
|
||||
);
|
||||
|
||||
const accountResponse = await this.client
|
||||
.from('accounts')
|
||||
.select('name')
|
||||
.eq('slug', account)
|
||||
.eq('slug', accountSlug)
|
||||
.single();
|
||||
|
||||
if (!accountResponse.data) {
|
||||
@@ -92,7 +92,7 @@ export class AccountInvitationsService {
|
||||
|
||||
const response = await this.client.rpc('add_invitations_to_account', {
|
||||
invitations,
|
||||
account_slug: account,
|
||||
account_slug: accountSlug,
|
||||
});
|
||||
|
||||
if (response.error) {
|
||||
@@ -105,7 +105,7 @@ export class AccountInvitationsService {
|
||||
|
||||
Logger.info(
|
||||
{
|
||||
account,
|
||||
account: accountSlug,
|
||||
count: responseInvitations.length,
|
||||
name: this.namespace,
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ import { getSupabaseClientKeys } from '../get-supabase-client-keys';
|
||||
* @name getSupabaseServerComponentClient
|
||||
* @description Get a Supabase client for use in the Server Components
|
||||
*/
|
||||
export const getSupabaseServerComponentClient = <GenericSchema = Database>(
|
||||
export const getSupabaseServerComponentClient = (
|
||||
params = {
|
||||
admin: false,
|
||||
},
|
||||
@@ -30,7 +30,7 @@ export const getSupabaseServerComponentClient = <GenericSchema = Database>(
|
||||
throw new Error('Supabase Service Role Key not provided');
|
||||
}
|
||||
|
||||
return createServerClient<GenericSchema>(keys.url, serviceRoleKey, {
|
||||
return createServerClient<Database>(keys.url, serviceRoleKey, {
|
||||
auth: {
|
||||
persistSession: false,
|
||||
},
|
||||
@@ -38,7 +38,7 @@ export const getSupabaseServerComponentClient = <GenericSchema = Database>(
|
||||
});
|
||||
}
|
||||
|
||||
return createServerClient<GenericSchema>(keys.url, keys.anonKey, {
|
||||
return createServerClient<Database>(keys.url, keys.anonKey, {
|
||||
cookies: getCookiesStrategy(),
|
||||
});
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user