Update database types and relationships
The commit removes semicolons at the ends of lines and makes updates to the Database object in the `database.types.ts` file. This better aligns the syntax with TypeScript norms. It also affects many database relationships, including but not limited to `Accounts`, `Roles`, and `Subscriptions`.
This commit is contained in:
@@ -20,7 +20,7 @@ import pathsConfig from '~/config/paths.config';
|
|||||||
export const loadTeamWorkspace = cache(async (accountSlug: string) => {
|
export const loadTeamWorkspace = cache(async (accountSlug: string) => {
|
||||||
const client = getSupabaseServerComponentClient();
|
const client = getSupabaseServerComponentClient();
|
||||||
|
|
||||||
const accountPromise = client.rpc('organization_account_workspace', {
|
const accountPromise = client.rpc('team_account_workspace', {
|
||||||
account_slug: accountSlug,
|
account_slug: accountSlug,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { loadUserWorkspace } from '../_lib/load-user-workspace';
|
|||||||
|
|
||||||
export function HomeSidebar() {
|
export function HomeSidebar() {
|
||||||
const collapsed = getSidebarCollapsed();
|
const collapsed = getSidebarCollapsed();
|
||||||
const { accounts, user } = use(loadUserWorkspace());
|
const { accounts, user, workspace } = use(loadUserWorkspace());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sidebar collapsed={collapsed}>
|
<Sidebar collapsed={collapsed}>
|
||||||
@@ -38,7 +38,11 @@ export function HomeSidebar() {
|
|||||||
|
|
||||||
<div className={'absolute bottom-4 left-0 w-full'}>
|
<div className={'absolute bottom-4 left-0 w-full'}>
|
||||||
<SidebarContent>
|
<SidebarContent>
|
||||||
<ProfileAccountDropdownContainer collapsed={collapsed} user={user} />
|
<ProfileAccountDropdownContainer
|
||||||
|
collapsed={collapsed}
|
||||||
|
user={user}
|
||||||
|
account={workspace}
|
||||||
|
/>
|
||||||
</SidebarContent>
|
</SidebarContent>
|
||||||
</div>
|
</div>
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
|
|||||||
@@ -9,27 +9,37 @@ import { useUser } from '@kit/supabase/hooks/use-user';
|
|||||||
import featuresFlagConfig from '~/config/feature-flags.config';
|
import featuresFlagConfig from '~/config/feature-flags.config';
|
||||||
import pathsConfig from '~/config/paths.config';
|
import pathsConfig from '~/config/paths.config';
|
||||||
|
|
||||||
|
const paths = {
|
||||||
|
home: pathsConfig.app.home,
|
||||||
|
};
|
||||||
|
|
||||||
|
const features = {
|
||||||
|
enableThemeToggle: featuresFlagConfig.enableThemeToggle,
|
||||||
|
};
|
||||||
|
|
||||||
export function ProfileAccountDropdownContainer(props: {
|
export function ProfileAccountDropdownContainer(props: {
|
||||||
collapsed: boolean;
|
collapsed: boolean;
|
||||||
user: User | null;
|
user: User | null;
|
||||||
|
|
||||||
|
account?: {
|
||||||
|
id: string | null;
|
||||||
|
name: string | null;
|
||||||
|
picture_url: string | null;
|
||||||
|
};
|
||||||
}) {
|
}) {
|
||||||
const signOut = useSignOut();
|
const signOut = useSignOut();
|
||||||
const user = useUser(props.user);
|
const user = useUser(props.user);
|
||||||
|
|
||||||
const userData = user.data ?? props.user ?? null;
|
const userData = user.data ?? props.user ?? null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={props.collapsed ? '' : 'w-full animate-in fade-in-90'}>
|
<div className={props.collapsed ? '' : 'w-full'}>
|
||||||
<PersonalAccountDropdown
|
<PersonalAccountDropdown
|
||||||
paths={{
|
|
||||||
home: pathsConfig.app.home,
|
|
||||||
}}
|
|
||||||
features={{
|
|
||||||
enableThemeToggle: featuresFlagConfig.enableThemeToggle,
|
|
||||||
}}
|
|
||||||
className={'w-full'}
|
className={'w-full'}
|
||||||
|
paths={paths}
|
||||||
|
features={features}
|
||||||
showProfileName={!props.collapsed}
|
showProfileName={!props.collapsed}
|
||||||
user={userData}
|
user={userData}
|
||||||
|
account={props.account}
|
||||||
signOutRequested={() => signOut.mutateAsync()}
|
signOutRequested={() => signOut.mutateAsync()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,26 +1,62 @@
|
|||||||
import { cache } from 'react';
|
import { cache } from 'react';
|
||||||
|
|
||||||
|
import { SupabaseClient } from '@supabase/supabase-js';
|
||||||
|
|
||||||
import { getSupabaseServerComponentClient } from '@kit/supabase/server-component-client';
|
import { getSupabaseServerComponentClient } from '@kit/supabase/server-component-client';
|
||||||
|
|
||||||
import featureFlagsConfig from '~/config/feature-flags.config';
|
import featureFlagsConfig from '~/config/feature-flags.config';
|
||||||
import { Database } from '~/lib/database.types';
|
import { Database } from '~/lib/database.types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name loadUserWorkspace
|
||||||
|
* @description
|
||||||
|
* Load the user workspace data. It's a cached per-request function that fetches the user workspace data.
|
||||||
|
* It can be used across the server components to load the user workspace data.
|
||||||
|
*/
|
||||||
export const loadUserWorkspace = cache(async () => {
|
export const loadUserWorkspace = cache(async () => {
|
||||||
const client = getSupabaseServerComponentClient();
|
const client = getSupabaseServerComponentClient();
|
||||||
const loadAccounts = featureFlagsConfig.enableTeamAccounts;
|
const loadAccounts = featureFlagsConfig.enableTeamAccounts;
|
||||||
|
|
||||||
const accounts = loadAccounts ? await loadUserAccounts(client) : [];
|
const accountsPromise = loadAccounts
|
||||||
const { data } = await client.auth.getUser();
|
? loadUserAccounts(client)
|
||||||
|
: Promise.resolve([]);
|
||||||
|
|
||||||
|
const workspacePromise = loadUserAccountWorkspace(client);
|
||||||
|
const userPromise = client.auth.getUser();
|
||||||
|
|
||||||
|
const [accounts, workspace, userResult] = await Promise.all([
|
||||||
|
accountsPromise,
|
||||||
|
workspacePromise,
|
||||||
|
userPromise,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const user = userResult.data.user;
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
throw new Error('User is not logged in');
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
accounts,
|
accounts,
|
||||||
user: data.user,
|
workspace,
|
||||||
|
user,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
async function loadUserAccounts(
|
async function loadUserAccountWorkspace(client: SupabaseClient<Database>) {
|
||||||
client: ReturnType<typeof getSupabaseServerComponentClient<Database>>,
|
const { data, error } = await client
|
||||||
) {
|
.from('user_account_workspace')
|
||||||
|
.select(`*`)
|
||||||
|
.single();
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadUserAccounts(client: SupabaseClient<Database>) {
|
||||||
const { data: accounts, error } = await client
|
const { data: accounts, error } = await client
|
||||||
.from('user_accounts')
|
.from('user_accounts')
|
||||||
.select(`name, slug, picture_url`);
|
.select(`name, slug, picture_url`);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 92 KiB |
@@ -1781,19 +1781,21 @@ language plpgsql;
|
|||||||
--
|
--
|
||||||
-- VIEW "user_account_workspace":
|
-- VIEW "user_account_workspace":
|
||||||
-- we create a view to load the general app data for the authenticated
|
-- we create a view to load the general app data for the authenticated
|
||||||
-- user which includes the user's accounts, memberships, and roles, and relative subscription status
|
-- user which includes the user accounts and memberships
|
||||||
create or replace view public.user_account_workspace as
|
create or replace view public.user_account_workspace as
|
||||||
select
|
select
|
||||||
accounts.id as id,
|
accounts.id as id,
|
||||||
accounts.name as name,
|
accounts.name as name,
|
||||||
accounts.picture_url as picture_url,
|
accounts.picture_url as picture_url,
|
||||||
|
accounts.public_data as public_data,
|
||||||
subscriptions.status as subscription_status
|
subscriptions.status as subscription_status
|
||||||
from
|
from
|
||||||
public.accounts
|
public.accounts
|
||||||
left join public.subscriptions on accounts.id = subscriptions.account_id
|
left join public.subscriptions on accounts.id = subscriptions.account_id
|
||||||
where
|
where
|
||||||
primary_owner_user_id = auth.uid()
|
primary_owner_user_id = auth.uid()
|
||||||
and accounts.is_personal_account = true;
|
and accounts.is_personal_account = true
|
||||||
|
limit 1;
|
||||||
|
|
||||||
grant select on public.user_account_workspace to authenticated, service_role;
|
grant select on public.user_account_workspace to authenticated, service_role;
|
||||||
|
|
||||||
@@ -1822,7 +1824,7 @@ grant select on public.user_accounts to authenticated, service_role;
|
|||||||
-- Function: get the account workspace for an organization account
|
-- Function: get the account workspace for an organization account
|
||||||
-- to load all the required data for the authenticated user within the account scope
|
-- to load all the required data for the authenticated user within the account scope
|
||||||
create or replace function
|
create or replace function
|
||||||
public.organization_account_workspace(account_slug text)
|
public.team_account_workspace(account_slug text)
|
||||||
returns table(
|
returns table(
|
||||||
id uuid,
|
id uuid,
|
||||||
name varchar(255),
|
name varchar(255),
|
||||||
@@ -1869,7 +1871,7 @@ end;
|
|||||||
$$
|
$$
|
||||||
language plpgsql;
|
language plpgsql;
|
||||||
|
|
||||||
grant execute on function public.organization_account_workspace(text)
|
grant execute on function public.team_account_workspace(text)
|
||||||
to authenticated, service_role;
|
to authenticated, service_role;
|
||||||
|
|
||||||
-- Functions: get account members
|
-- Functions: get account members
|
||||||
|
|||||||
@@ -36,19 +36,29 @@ export function PersonalAccountDropdown({
|
|||||||
showProfileName,
|
showProfileName,
|
||||||
paths,
|
paths,
|
||||||
features,
|
features,
|
||||||
|
account,
|
||||||
}: {
|
}: {
|
||||||
className?: string;
|
className?: string;
|
||||||
user: User | null;
|
user: User | null;
|
||||||
|
|
||||||
|
account?: {
|
||||||
|
id: string | null;
|
||||||
|
name: string | null;
|
||||||
|
picture_url: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
signOutRequested: () => unknown;
|
signOutRequested: () => unknown;
|
||||||
showProfileName?: boolean;
|
showProfileName?: boolean;
|
||||||
|
|
||||||
paths: {
|
paths: {
|
||||||
home: string;
|
home: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
features: {
|
features: {
|
||||||
enableThemeToggle: boolean;
|
enableThemeToggle: boolean;
|
||||||
};
|
};
|
||||||
}) {
|
}) {
|
||||||
const { data: personalAccountData } = usePersonalAccountData();
|
const { data: personalAccountData } = usePersonalAccountData(account);
|
||||||
|
|
||||||
const signedInAsLabel = useMemo(() => {
|
const signedInAsLabel = useMemo(() => {
|
||||||
const email = user?.email ?? undefined;
|
const email = user?.email ?? undefined;
|
||||||
@@ -57,7 +67,8 @@ export function PersonalAccountDropdown({
|
|||||||
return email ?? phone;
|
return email ?? phone;
|
||||||
}, [user?.email, user?.phone]);
|
}, [user?.email, user?.phone]);
|
||||||
|
|
||||||
const displayName = personalAccountData?.name ?? user?.email ?? '';
|
const displayName =
|
||||||
|
account?.name ?? personalAccountData?.name ?? user?.email ?? '';
|
||||||
|
|
||||||
const isSuperAdmin = useMemo(() => {
|
const isSuperAdmin = useMemo(() => {
|
||||||
return user?.app_metadata.role === 'super-admin';
|
return user?.app_metadata.role === 'super-admin';
|
||||||
|
|||||||
@@ -5,7 +5,15 @@ import { useQuery, useQueryClient } from '@tanstack/react-query';
|
|||||||
import { useSupabase } from '@kit/supabase/hooks/use-supabase';
|
import { useSupabase } from '@kit/supabase/hooks/use-supabase';
|
||||||
import { useUser } from '@kit/supabase/hooks/use-user';
|
import { useUser } from '@kit/supabase/hooks/use-user';
|
||||||
|
|
||||||
export function usePersonalAccountData() {
|
export function usePersonalAccountData(
|
||||||
|
partialAccount?:
|
||||||
|
| {
|
||||||
|
id: string | null;
|
||||||
|
name: string | null;
|
||||||
|
picture_url: string | null;
|
||||||
|
}
|
||||||
|
| undefined,
|
||||||
|
) {
|
||||||
const client = useSupabase();
|
const client = useSupabase();
|
||||||
const user = useUser();
|
const user = useUser();
|
||||||
const userId = user.data?.id;
|
const userId = user.data?.id;
|
||||||
@@ -43,6 +51,7 @@ export function usePersonalAccountData() {
|
|||||||
enabled: !!userId,
|
enabled: !!userId,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
refetchOnMount: false,
|
refetchOnMount: false,
|
||||||
|
initialData: partialAccount,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user