Skip to content

Commit

Permalink
feat(clerk-js): Function or string literals in afterSelectPersonalUrl…
Browse files Browse the repository at this point in the history
… and afterSelectOrganizationUrl
  • Loading branch information
panteliselef committed Jul 20, 2023
1 parent a6363a3 commit 440127a
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 22 deletions.
19 changes: 19 additions & 0 deletions .changeset/strange-owls-behave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
'@clerk/clerk-js': patch
'@clerk/types': patch
---

Construct urls based on context in <OrganizationSwitcher/>
- Deprecate `afterSwitchOrganizationUrl`
- Introduce `afterSelectOrganizationUrl` & `afterSelectPersonalUrl`

`afterSelectOrganizationUrl` accepts
- Full URL -> 'https://clerk.com/'
- relative path -> '/organizations'
- relative path -> with param '/organizations/:id'
- function that returns a string -> (org) => `/org/${org.slug}`
`afterSelectPersonalUrl` accepts
- Full URL -> 'https://clerk.com/'
- relative path -> '/users'
- relative path -> with param '/users/:username'
- function that returns a string -> (user) => `/users/${user.id}`
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,24 @@ export const OrganizationSwitcherPopover = React.forwardRef<HTMLDivElement, Orga
}

const handleOrganizationClicked = (organization: OrganizationResource) => {
return card.runAsync(() => setActive({ organization, beforeEmit: navigateAfterSwitchOrganization })).then(close);
return card
.runAsync(() =>
setActive({
organization,
beforeEmit: () =>
navigateAfterSwitchOrganization({
organization: organization,
}),
}),
)
.then(close);
};

const handlePersonalWorkspaceClicked = () => {
return card
.runAsync(() => setActive({ organization: null, beforeEmit: navigateAfterSwitchOrganization }))
.runAsync(() =>
setActive({ organization: null, beforeEmit: () => navigateAfterSwitchOrganization({ user: user }) }),
)
.then(close);
};

Expand Down
77 changes: 57 additions & 20 deletions packages/clerk-js/src/ui/contexts/ClerkUIComponentsContext.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { OrganizationResource } from '@clerk/types';
import type { OrganizationResource, UserResource } from '@clerk/types';
import React from 'react';

import { buildAuthQueryString, buildURL, pickRedirectionProp } from '../../utils';
Expand All @@ -16,6 +16,23 @@ import type {
UserProfileCtx,
} from '../types';

const createDynamicParamParser =
({ regex }: { regex: RegExp }) =>
<T extends Record<any, any>>({ urlWithParam, entity }: { urlWithParam: string; entity: T }) => {
const match = regex.exec(urlWithParam);

if (match) {
const key = match[1];
if (key in entity) {
const value = entity[key] as string;
return urlWithParam.replace(match[0], value);
}
}
return urlWithParam;
};

const parse = createDynamicParamParser({ regex: /:(\w+)/ });

export const ComponentContext = React.createContext<AvailableComponentCtx | null>(null);

export type SignUpContextType = SignUpCtx & {
Expand Down Expand Up @@ -231,8 +248,45 @@ export const useOrganizationSwitcherContext = () => {
const navigateCreateOrganization = () => navigate(ctx.createOrganizationUrl || displayConfig.createOrganizationUrl);
const navigateOrganizationProfile = () =>
navigate(ctx.organizationProfileUrl || displayConfig.organizationProfileUrl);
const navigateAfterSwitchOrganization = () =>
ctx.afterSwitchOrganizationUrl ? navigate(ctx.afterSwitchOrganizationUrl) : Promise.resolve();

const navigateAfterSwitchOrganization = ({
organization,
user,
}: {
organization?: OrganizationResource;
user?: UserResource;
}) => {
// Continue to support afterSwitchOrganizationUrl
if (ctx.afterSwitchOrganizationUrl) {
return navigate(ctx.afterSwitchOrganizationUrl);
}

if (typeof ctx.afterSelectPersonalUrl === 'function' && user) {
return navigate(ctx.afterSelectPersonalUrl(user));
}

if (typeof ctx.afterSelectOrganizationUrl === 'function' && organization) {
return navigate(ctx.afterSelectOrganizationUrl(organization));
}

if (ctx.afterSelectPersonalUrl && user) {
const parsedUrl = parse({
urlWithParam: ctx.afterSelectPersonalUrl as string,
entity: user,
});
return navigate(parsedUrl);
}

if (ctx.afterSelectOrganizationUrl && organization) {
const parsedUrl = parse({
urlWithParam: ctx.afterSelectOrganizationUrl as string,
entity: organization,
});
return navigate(parsedUrl);
}

return Promise.resolve();
};

return {
...ctx,
Expand Down Expand Up @@ -267,21 +321,6 @@ export const useOrganizationProfileContext = () => {
};
};

const createDynamicParamParser =
({ regex }: { regex: RegExp }) =>
<T extends Record<any, any>>({ urlWithParam, entity }: { urlWithParam: string; entity: T }) => {
const match = regex.exec(urlWithParam);

if (match) {
const key = match[1];
if (key in entity) {
const value = entity[key] as string;
return urlWithParam.replace(match[0], value);
}
}
return urlWithParam;
};

export const useCreateOrganizationContext = () => {
const { componentName, ...ctx } = (React.useContext(ComponentContext) || {}) as CreateOrganizationCtx;
const { navigate } = useRouter();
Expand All @@ -296,8 +335,6 @@ export const useCreateOrganizationContext = () => {
return navigate(ctx.afterCreateOrganizationUrl(organization));
}

const parse = createDynamicParamParser({ regex: /:(\w+)/ });

if (ctx.afterCreateOrganizationUrl) {
const parsedUrl = parse({
urlWithParam: ctx.afterCreateOrganizationUrl,
Expand Down

0 comments on commit 440127a

Please sign in to comment.