Skip to content

Commit a6deedf

Browse files
feat(swingset): add live user profile panels and API keys pages (#10188)
1 parent 65b8c02 commit a6deedf

7 files changed

Lines changed: 162 additions & 9 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
---
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use client';
2+
3+
import { UserProfileProfilePanel } from '@clerk/mosaic/features/user-profile/user-profile-profile-panel';
4+
import { MosaicProvider } from '@clerk/mosaic/mosaic-provider';
5+
import { useUser } from '@clerk/nextjs';
6+
import Link from 'next/link';
7+
8+
export default function AccountLivePage() {
9+
const { isLoaded, isSignedIn } = useUser();
10+
11+
return (
12+
<MosaicProvider>
13+
<div className='mx-auto flex w-full max-w-3xl flex-col gap-6 p-3 sm:p-8'>
14+
<div className='flex flex-col gap-1'>
15+
<h1 className='text-xl font-semibold'>Account</h1>
16+
<p className='text-muted-foreground text-sm'>
17+
The user profile account panel, with every live section the signed-in account has enabled.
18+
</p>
19+
</div>
20+
{!isLoaded ? <p className='text-muted-foreground text-sm'>Loading…</p> : null}
21+
{isLoaded && !isSignedIn ? (
22+
<p className='text-muted-foreground text-sm'>
23+
<Link
24+
href='/sign-in'
25+
className='text-foreground underline underline-offset-4'
26+
>
27+
Sign in
28+
</Link>{' '}
29+
to use the live harness.
30+
</p>
31+
) : null}
32+
{isLoaded && isSignedIn ? <UserProfileProfilePanel /> : null}
33+
</div>
34+
</MosaicProvider>
35+
);
36+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
'use client';
2+
3+
import { APIKeysTable } from '@clerk/mosaic/features/api-keys/api-keys-table';
4+
import { MosaicProvider } from '@clerk/mosaic/mosaic-provider';
5+
import { useOrganization, useUser } from '@clerk/nextjs';
6+
import Link from 'next/link';
7+
8+
export default function APIKeysTableLivePage() {
9+
const { isLoaded, isSignedIn, user } = useUser();
10+
const { organization } = useOrganization();
11+
12+
return (
13+
<MosaicProvider>
14+
<div className='mx-auto flex w-full max-w-3xl flex-col gap-6 p-3 sm:p-8'>
15+
<div className='flex flex-col gap-1'>
16+
<h1 className='text-xl font-semibold'>API keys table</h1>
17+
<p className='text-muted-foreground text-sm'>
18+
The API keys table for the signed-in user and their active organization, listing, creating, and revoking
19+
real API keys. API keys must be enabled for the application.
20+
</p>
21+
</div>
22+
{!isLoaded ? <p className='text-muted-foreground text-sm'>Loading…</p> : null}
23+
{isLoaded && !isSignedIn ? (
24+
<p className='text-muted-foreground text-sm'>
25+
<Link
26+
href='/sign-in'
27+
className='text-foreground underline underline-offset-4'
28+
>
29+
Sign in
30+
</Link>{' '}
31+
to use the live harness.
32+
</p>
33+
) : null}
34+
{user ? <APIKeysTable subject={user.id} /> : null}
35+
{organization ? <APIKeysTable subject={organization.id} /> : null}
36+
</div>
37+
</MosaicProvider>
38+
);
39+
}

‎packages/swingset/src/app/(clerk)/live/api-keys/page.tsx‎

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use client';
22

3-
import { OrganizationProfileApiKeysPanel } from '@clerk/mosaic/features/organization-profile/organization-profile-api-keys-panel';
43
import { UserProfileApiKeysPanel } from '@clerk/mosaic/features/user-profile/user-profile-api-keys-panel';
54
import { MosaicProvider } from '@clerk/mosaic/mosaic-provider';
65
import { useUser } from '@clerk/nextjs';
@@ -15,8 +14,8 @@ export default function ApiKeysLivePage() {
1514
<div className='flex flex-col gap-1'>
1615
<h1 className='text-xl font-semibold'>API keys</h1>
1716
<p className='text-muted-foreground text-sm'>
18-
The user and organization profile API keys panels, listing, creating, and revoking real API keys for the
19-
signed-in user and their active organization. API keys must be enabled for the application.
17+
The user profile API keys panel, listing, creating, and revoking real API keys for the signed-in user. API
18+
keys must be enabled for the application.
2019
</p>
2120
</div>
2221
{!isLoaded ? <p className='text-muted-foreground text-sm'>Loading…</p> : null}
@@ -31,12 +30,7 @@ export default function ApiKeysLivePage() {
3130
to use the live harness.
3231
</p>
3332
) : null}
34-
{isLoaded && isSignedIn ? (
35-
<>
36-
<UserProfileApiKeysPanel />
37-
<OrganizationProfileApiKeysPanel />
38-
</>
39-
) : null}
33+
{isLoaded && isSignedIn ? <UserProfileApiKeysPanel /> : null}
4034
</div>
4135
</MosaicProvider>
4236
);
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'use client';
2+
3+
import { OrganizationProfileApiKeysPanel } from '@clerk/mosaic/features/organization-profile/organization-profile-api-keys-panel';
4+
import { MosaicProvider } from '@clerk/mosaic/mosaic-provider';
5+
import { useOrganization, useUser } from '@clerk/nextjs';
6+
import Link from 'next/link';
7+
8+
export default function OrganizationApiKeysLivePage() {
9+
const { isLoaded, isSignedIn } = useUser();
10+
const { organization } = useOrganization();
11+
12+
return (
13+
<MosaicProvider>
14+
<div className='mx-auto flex w-full max-w-3xl flex-col gap-6 p-3 sm:p-8'>
15+
<div className='flex flex-col gap-1'>
16+
<h1 className='text-xl font-semibold'>Organization API keys</h1>
17+
<p className='text-muted-foreground text-sm'>
18+
The organization profile API keys panel, listing, creating, and revoking real API keys for the active
19+
organization. API keys must be enabled for the application.
20+
</p>
21+
</div>
22+
{!isLoaded ? <p className='text-muted-foreground text-sm'>Loading…</p> : null}
23+
{isLoaded && !isSignedIn ? (
24+
<p className='text-muted-foreground text-sm'>
25+
<Link
26+
href='/sign-in'
27+
className='text-foreground underline underline-offset-4'
28+
>
29+
Sign in
30+
</Link>{' '}
31+
and pick an active organization.
32+
</p>
33+
) : null}
34+
{isLoaded && isSignedIn && !organization ? (
35+
<p className='text-muted-foreground text-sm'>Pick an active organization to see its API keys panel.</p>
36+
) : null}
37+
{isLoaded && isSignedIn ? <OrganizationProfileApiKeysPanel /> : null}
38+
</div>
39+
</MosaicProvider>
40+
);
41+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
'use client';
2+
3+
import { UserProfileSecurityPanel } from '@clerk/mosaic/features/user-profile/user-profile-security-panel';
4+
import { MosaicProvider } from '@clerk/mosaic/mosaic-provider';
5+
import { useUser } from '@clerk/nextjs';
6+
import Link from 'next/link';
7+
8+
export default function SecurityLivePage() {
9+
const { isLoaded, isSignedIn } = useUser();
10+
11+
return (
12+
<MosaicProvider>
13+
<div className='mx-auto flex w-full max-w-3xl flex-col gap-6 p-3 sm:p-8'>
14+
<div className='flex flex-col gap-1'>
15+
<h1 className='text-xl font-semibold'>Security</h1>
16+
<p className='text-muted-foreground text-sm'>
17+
The user profile security panel, with the password, passkeys, 2-step verification, and active devices
18+
sections for the signed-in account.
19+
</p>
20+
</div>
21+
{!isLoaded ? <p className='text-muted-foreground text-sm'>Loading…</p> : null}
22+
{isLoaded && !isSignedIn ? (
23+
<p className='text-muted-foreground text-sm'>
24+
<Link
25+
href='/sign-in'
26+
className='text-foreground underline underline-offset-4'
27+
>
28+
Sign in
29+
</Link>{' '}
30+
to use the live harness.
31+
</p>
32+
) : null}
33+
{isLoaded && isSignedIn ? <UserProfileSecurityPanel /> : null}
34+
</div>
35+
</MosaicProvider>
36+
);
37+
}

‎packages/swingset/src/lib/live-navigation.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ type LiveSidebarGroup = {
1010
};
1111

1212
const liveRoutes = new Map([
13+
['/user-profile/user-profile-profile-panel', '/live/account'],
14+
['/user-profile/user-profile-security-panel', '/live/security'],
1315
['/user-profile/user-profile-api-keys-panel', '/live/api-keys'],
1416
['/user-profile/user-profile-profile-section', '/live/profile'],
1517
['/user-profile/user-profile-email-section', '/live/email'],
@@ -22,9 +24,11 @@ const liveRoutes = new Map([
2224
['/user-profile/user-profile-danger-section', '/live/user-danger'],
2325
['/organization-profile/organization-profile-general-panel', '/live/organization-general'],
2426
['/organization-profile/organization-profile-members-panel', '/live/organization-members'],
27+
['/organization-profile/organization-profile-api-keys-panel', '/live/organization-api-keys'],
2528
['/organization-profile/organization-profile-danger-section', '/live/organization-danger'],
2629
['/user-profile/user-profile-passkeys-section', '/live/passkeys'],
2730
['/user-profile/user-profile-web3wallets-section', '/live/web3-wallets'],
31+
['/api-keys/api-keys-table', '/live/api-keys-table'],
2832
['/reverification/reverification', '/live/reverification'],
2933
]);
3034

0 commit comments

Comments
 (0)