Skip to content

Commit b2296d6

Browse files
authored
feat(clerk-js): Delete pending invitations when updating enrolment mode of domain (#1632)
* feat(clerk-js): Delete pending invitations when updating enrollment mode of domain * chore(clerk-js): Remove BlockWithAction as it unused * chore(clerk-js): Add changeset
1 parent 9f32fd7 commit b2296d6

File tree

11 files changed

+174
-253
lines changed

11 files changed

+174
-253
lines changed

.changeset/shy-readers-visit.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@clerk/localizations': patch
3+
'@clerk/clerk-js': patch
4+
'@clerk/types': patch
5+
---
6+
7+
When updating enrollment mode of a domain uses can now delete any pending invitations or suggestions.

packages/clerk-js/src/ui/components/OrganizationProfile/VerifiedDomainPage.tsx

+50-41
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,27 @@
11
import type { OrganizationEnrollmentMode } from '@clerk/types';
22

33
import { useCoreOrganization, useEnvironment } from '../../contexts';
4-
import { Col, descriptors, Flex, localizationKeys, Spinner } from '../../customizables';
5-
import {
6-
BlockWithAction,
7-
ContentPage,
8-
Form,
9-
FormButtons,
10-
Header,
11-
useCardState,
12-
withCardStateProvider,
13-
} from '../../elements';
14-
import { useFetch } from '../../hooks';
4+
import { Col, Flex, localizationKeys, Spinner } from '../../customizables';
5+
import { ContentPage, Form, FormButtons, Header, useCardState, withCardStateProvider } from '../../elements';
6+
import { useFetch, useNavigateToFlowStart } from '../../hooks';
157
import { useRouter } from '../../router';
168
import { handleError, useFormControl } from '../../utils';
17-
import { EnrollmentBadge } from './EnrollmentBadge';
189
import { OrganizationProfileBreadcrumbs } from './OrganizationProfileNavbar';
1910

2011
export const VerifiedDomainPage = withCardStateProvider(() => {
2112
const card = useCardState();
2213
const { organizationSettings } = useEnvironment();
2314
const { organization } = useCoreOrganization();
24-
const { params, navigate } = useRouter();
15+
const { domains } = useCoreOrganization({
16+
domains: {
17+
infinite: true,
18+
},
19+
});
20+
const { navigateToFlowStart } = useNavigateToFlowStart();
21+
const { params, navigate, queryParams } = useRouter();
22+
const mode = (queryParams.mode ?? 'edit') as 'select' | 'edit';
2523

26-
const title = localizationKeys('organizationProfile.verifiedDomainPage.title');
24+
const allowsEdit = mode === 'edit';
2725

2826
const enrollmentMode = useFormControl('enrollmentMode', '', {
2927
type: 'radio',
@@ -32,9 +30,11 @@ export const VerifiedDomainPage = withCardStateProvider(() => {
3230
? [
3331
{
3432
value: 'manual_invitation',
35-
label: localizationKeys('organizationProfile.verifiedDomainPage.manualInvitationOption__label'),
33+
label: localizationKeys(
34+
'organizationProfile.verifiedDomainPage.enrollmentTab.manualInvitationOption__label',
35+
),
3636
description: localizationKeys(
37-
'organizationProfile.verifiedDomainPage.manualInvitationOption__description',
37+
'organizationProfile.verifiedDomainPage.enrollmentTab.manualInvitationOption__description',
3838
),
3939
},
4040
]
@@ -43,9 +43,11 @@ export const VerifiedDomainPage = withCardStateProvider(() => {
4343
? [
4444
{
4545
value: 'automatic_invitation',
46-
label: localizationKeys('organizationProfile.verifiedDomainPage.automaticInvitationOption__label'),
46+
label: localizationKeys(
47+
'organizationProfile.verifiedDomainPage.enrollmentTab.automaticInvitationOption__label',
48+
),
4749
description: localizationKeys(
48-
'organizationProfile.verifiedDomainPage.automaticInvitationOption__description',
50+
'organizationProfile.verifiedDomainPage.enrollmentTab.automaticInvitationOption__description',
4951
),
5052
},
5153
]
@@ -54,16 +56,23 @@ export const VerifiedDomainPage = withCardStateProvider(() => {
5456
? [
5557
{
5658
value: 'automatic_suggestion',
57-
label: localizationKeys('organizationProfile.verifiedDomainPage.automaticSuggestionOption__label'),
59+
label: localizationKeys(
60+
'organizationProfile.verifiedDomainPage.enrollmentTab.automaticSuggestionOption__label',
61+
),
5862
description: localizationKeys(
59-
'organizationProfile.verifiedDomainPage.automaticSuggestionOption__description',
63+
'organizationProfile.verifiedDomainPage.enrollmentTab.automaticSuggestionOption__description',
6064
),
6165
},
6266
]
6367
: []),
6468
],
6569
});
6670

71+
const deletePending = useFormControl('deleteExistingInvitationsSuggestions', '', {
72+
label: localizationKeys('formFieldLabel__organizationDomainDeletePending'),
73+
type: 'checkbox',
74+
});
75+
6776
const { data: domain, status: domainStatus } = useFetch(
6877
organization?.getDomain,
6978
{
@@ -76,6 +85,7 @@ export const VerifiedDomainPage = withCardStateProvider(() => {
7685
},
7786
);
7887

88+
const isFormDirty = deletePending.checked || domain?.enrollmentMode !== enrollmentMode.value;
7989
const updateEnrollmentMode = async () => {
8090
if (!domain || !organization) {
8191
return;
@@ -84,8 +94,11 @@ export const VerifiedDomainPage = withCardStateProvider(() => {
8494
try {
8595
await domain.updateEnrollmentMode({
8696
enrollmentMode: enrollmentMode.value as OrganizationEnrollmentMode,
97+
deletePending: deletePending.checked,
8798
});
8899

100+
await (domains as any).unstable__mutate();
101+
89102
await navigate('../../');
90103
} catch (e) {
91104
handleError(e, [enrollmentMode], card.setError);
@@ -115,36 +128,23 @@ export const VerifiedDomainPage = withCardStateProvider(() => {
115128
);
116129
}
117130

131+
if (!(domain.verification && domain.verification.status === 'verified')) {
132+
void navigateToFlowStart();
133+
}
118134
return (
119135
<ContentPage
120-
headerTitle={title}
136+
headerTitle={domain.name}
137+
gap={4}
121138
Breadcrumbs={OrganizationProfileBreadcrumbs}
122139
>
123-
<BlockWithAction
124-
elementDescriptor={descriptors.accordionTriggerButton}
125-
badge={<EnrollmentBadge organizationDomain={domain} />}
126-
sx={t => ({
127-
backgroundColor: t.colors.$blackAlpha50,
128-
padding: `${t.space.$3} ${t.space.$4}`,
129-
minHeight: t.sizes.$10,
130-
})}
131-
actionSx={t => ({
132-
color: t.colors.$danger500,
133-
})}
134-
actionLabel={localizationKeys('organizationProfile.verifiedDomainPage.actionLabel__remove')}
135-
onActionClick={() => navigate(`../../domain/${domain.id}/remove`)}
136-
>
137-
{domain.name}
138-
</BlockWithAction>
139-
140140
<Col gap={2}>
141141
<Header.Root>
142142
<Header.Title
143-
localizationKey={localizationKeys('organizationProfile.verifiedDomainPage.formTitle')}
143+
localizationKey={localizationKeys('organizationProfile.verifiedDomainPage.start.headerTitle__enrollment')}
144144
textVariant='largeMedium'
145145
/>
146146
<Header.Subtitle
147-
localizationKey={localizationKeys('organizationProfile.verifiedDomainPage.formSubtitle')}
147+
localizationKey={localizationKeys('organizationProfile.verifiedDomainPage.enrollmentTab.subtitle')}
148148
variant='regularRegular'
149149
/>
150150
</Header.Root>
@@ -154,7 +154,16 @@ export const VerifiedDomainPage = withCardStateProvider(() => {
154154
<Form.Control {...enrollmentMode.props} />
155155
</Form.ControlRow>
156156

157-
<FormButtons isDisabled={domainStatus.isLoading || !domain} />
157+
{allowsEdit && (
158+
<Form.ControlRow elementId={deletePending.id}>
159+
<Form.Control {...deletePending.props} />
160+
</Form.ControlRow>
161+
)}
162+
163+
<FormButtons
164+
localizationKey={localizationKeys('organizationProfile.verifiedDomainPage.enrollmentTab.formButton__save')}
165+
isDisabled={domainStatus.isLoading || !domain || !isFormDirty}
166+
/>
158167
</Form.Root>
159168
</Col>
160169
</ContentPage>

packages/clerk-js/src/ui/components/OrganizationProfile/VerifyDomainPage.tsx

+1-20
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { useCoreOrganization, useEnvironment } from '../../contexts';
55
import { Button, descriptors, Flex, localizationKeys, Spinner } from '../../customizables';
66
import type { VerificationCodeCardProps } from '../../elements';
77
import {
8-
BlockWithAction,
98
ContentPage,
109
Form,
1110
FormButtonContainer,
@@ -18,14 +17,13 @@ import { CodeForm } from '../../elements/CodeForm';
1817
import { useFetch, useLoadingStatus, useNavigateToFlowStart } from '../../hooks';
1918
import { useRouter } from '../../router';
2019
import { handleError, sleep, useFormControl } from '../../utils';
21-
import { EnrollmentBadge } from './EnrollmentBadge';
2220
import { OrganizationProfileBreadcrumbs } from './OrganizationProfileNavbar';
2321

2422
export const VerifyDomainPage = withCardStateProvider(() => {
2523
const card = useCardState();
2624
const { organizationSettings } = useEnvironment();
2725
const { organization } = useCoreOrganization();
28-
const { params, navigate } = useRouter();
26+
const { params } = useRouter();
2927
const { navigateToFlowStart } = useNavigateToFlowStart();
3028

3129
const [success, setSuccess] = React.useState(false);
@@ -134,23 +132,6 @@ export const VerifyDomainPage = withCardStateProvider(() => {
134132
headerSubtitle={subtitle}
135133
Breadcrumbs={OrganizationProfileBreadcrumbs}
136134
>
137-
<BlockWithAction
138-
elementDescriptor={descriptors.accordionTriggerButton}
139-
badge={<EnrollmentBadge organizationDomain={domain} />}
140-
sx={t => ({
141-
backgroundColor: t.colors.$blackAlpha50,
142-
padding: `${t.space.$3} ${t.space.$4}`,
143-
minHeight: t.sizes.$10,
144-
})}
145-
actionLabel={localizationKeys('organizationProfile.verifyDomainPage.actionLabel__remove')}
146-
onActionClick={() => navigate(`../../../domain/${domain.id}/remove`)}
147-
actionSx={t => ({
148-
color: t.colors.$danger500,
149-
})}
150-
>
151-
{domain.name}
152-
</BlockWithAction>
153-
154135
<Form.Root onSubmit={onSubmitPrepare}>
155136
<Form.ControlRow elementId={emailField.id}>
156137
<Form.Control

packages/clerk-js/src/ui/elements/BlockWithAction.tsx

-164
This file was deleted.

0 commit comments

Comments
 (0)