Skip to content

Commit e0e4eb8

Browse files
committed
fix(foxy-user-invitation-form): fix when selfrevoked event is emitted
1 parent f8f0d4a commit e0e4eb8

3 files changed

Lines changed: 96 additions & 11 deletions

File tree

src/elements/public/UserInvitationForm/UserInvitationForm.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ describe('UserInvitationForm', () => {
5454
});
5555
});
5656

57+
it('has a reactive property "currentStore"', () => {
58+
expect(new Form()).to.have.property('currentStore', null);
59+
expect(Form).to.have.deep.nested.property('properties.currentStore', {
60+
attribute: 'current-store',
61+
});
62+
});
63+
5764
it('has a reactive property "currentUser"', () => {
5865
expect(new Form()).to.have.property('currentUser', null);
5966
expect(Form).to.have.deep.nested.property('properties.currentUser', {
@@ -414,6 +421,7 @@ describe('UserInvitationForm', () => {
414421
const router = createRouter();
415422
const form = await fixture<Form>(html`
416423
<foxy-user-invitation-form
424+
current-store="https://demo.api/hapi/stores/0"
417425
current-user="https://demo.api/hapi/users/0"
418426
layout="admin"
419427
href="https://demo.api/hapi/user_invitations/0"
@@ -440,6 +448,37 @@ describe('UserInvitationForm', () => {
440448
expect(await selfrevokedEvent).to.exist;
441449
});
442450

451+
it("renders a special async action for revoking current user's access in snapshot user layout", async () => {
452+
const router = createRouter();
453+
const form = await fixture<Form>(html`
454+
<foxy-user-invitation-form
455+
current-store="https://demo.api/hapi/stores/0"
456+
current-user="https://demo.api/hapi/users/0"
457+
layout="user"
458+
href="https://demo.api/hapi/user_invitations/0"
459+
@fetch=${(evt: FetchEvent) => router.handleEvent(evt)}
460+
>
461+
</foxy-user-invitation-form>
462+
`);
463+
464+
await waitUntil(() => !!form.data, undefined, { timeout: 5000 });
465+
const action = form.renderRoot.querySelector(
466+
'foxy-internal-post-action-control[infer="leave"]'
467+
);
468+
469+
expect(action).to.exist;
470+
expect(action).to.have.attribute('href', form.data!._links['fx:revoke'].href);
471+
expect(action).to.have.attribute('theme', 'error');
472+
expect(action).to.have.attribute(
473+
'message-options',
474+
JSON.stringify({ store_domain: 'example', store_name: 'Example Store' })
475+
);
476+
477+
const selfrevokedEvent = oneEvent(form, 'selfrevoked');
478+
action!.dispatchEvent(new Event('success'));
479+
expect(await selfrevokedEvent).to.exist;
480+
});
481+
443482
it('renders async action for resending invitation in snapshot admin layout', async () => {
444483
const router = createRouter();
445484
const form = await fixture<Form>(html`

src/elements/public/UserInvitationForm/UserInvitationForm.ts

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export class UserInvitationForm extends Base<Data> {
2121
...super.properties,
2222
getStorePageHref: { attribute: false },
2323
defaultDomain: { attribute: 'default-domain' },
24+
currentStore: { attribute: 'current-store' },
2425
currentUser: { attribute: 'current-user' },
2526
layout: {},
2627
};
@@ -63,7 +64,10 @@ export class UserInvitationForm extends Base<Data> {
6364
/** Default host domain for stores that don't use a custom domain name, e.g. `foxycart.com`. */
6465
defaultDomain: string | null = null;
6566

66-
/** Currently logged in user resource URL. Used to display a warning when revoking access. */
67+
/** Currently viewed store URL. Used for determining when to emit `selfrevoked` event. */
68+
currentStore: string | null = null;
69+
70+
/** Currently logged in user resource URL. Used for determining when to emit `selfrevoked` event. */
6771
currentUser: string | null = null;
6872

6973
/** Admin layout will display user info, user layout (default) will display store info. */
@@ -179,6 +183,14 @@ export class UserInvitationForm extends Base<Data> {
179183
const status = this.data?.status;
180184
const hidden = this.hiddenSelector;
181185

186+
const isOwnInvitationForCurrentStore =
187+
this.currentStore &&
188+
this.currentUser &&
189+
_links?.['fx:store'] &&
190+
_links?.['fx:user'] &&
191+
this.currentStore === _links?.['fx:store'].href &&
192+
this.currentUser === _links?.['fx:user'].href;
193+
182194
return html`
183195
<div style="padding-top: 3.5rem">
184196
<div class="relative">
@@ -241,7 +253,7 @@ export class UserInvitationForm extends Base<Data> {
241253
hidden.matches('resend', true) &&
242254
hidden.matches('delete', true)}
243255
>
244-
${this.currentUser && _links['fx:user'] && this.currentUser === _links['fx:user'].href
256+
${isOwnInvitationForCurrentStore
245257
? html`
246258
<foxy-internal-post-action-control
247259
message-options=${JSON.stringify({
@@ -291,6 +303,14 @@ export class UserInvitationForm extends Base<Data> {
291303
'text-error': status === 'rejected',
292304
};
293305

306+
const isOwnInvitationForCurrentStore =
307+
this.currentStore &&
308+
this.currentUser &&
309+
links?.['fx:store'] &&
310+
links?.['fx:user'] &&
311+
this.currentStore === links?.['fx:store'].href &&
312+
this.currentUser === links?.['fx:user'].href;
313+
294314
return html`
295315
<div class=${classMap({ 'flex items-center gap-m': true, ...textColorMap })}>
296316
<div class="border-t flex-1"></div>
@@ -339,13 +359,30 @@ export class UserInvitationForm extends Base<Data> {
339359
>
340360
</foxy-i18n>
341361
342-
<foxy-internal-user-invitation-form-async-action
343-
theme="error"
344-
class="flex-1"
345-
infer="leave"
346-
href=${ifDefined(links?.['fx:revoke']?.href ?? links?.['fx:reject']?.href)}
347-
>
348-
</foxy-internal-user-invitation-form-async-action>
362+
${isOwnInvitationForCurrentStore
363+
? html`
364+
<foxy-internal-post-action-control
365+
message-options=${JSON.stringify({
366+
store_domain: this.__storeDomainGetValue(),
367+
store_name,
368+
})}
369+
infer="leave"
370+
class="flex-1"
371+
theme="error"
372+
href=${ifDefined(links?.['fx:revoke']?.href ?? links?.['fx:reject']?.href)}
373+
@success=${() => this.dispatchEvent(new CustomEvent('selfrevoked'))}
374+
>
375+
</foxy-internal-post-action-control>
376+
`
377+
: html`
378+
<foxy-internal-user-invitation-form-async-action
379+
theme="error"
380+
class="flex-1"
381+
infer="leave"
382+
href=${ifDefined(links?.['fx:revoke']?.href ?? links?.['fx:reject']?.href)}
383+
>
384+
</foxy-internal-user-invitation-form-async-action>
385+
`}
349386
350387
<div
351388
class="grid grid-cols-2 gap-m"

src/static/translations/user-invitation-form/en.json

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,16 @@
2727
"leave": {
2828
"idle": "Leave this store",
2929
"busy": "Leaving...",
30-
"fail": "Failed to leave"
30+
"fail": "Failed to leave",
31+
"message_idle": "You are about to remove your own access to {{ store_name }} ({{ store_domain }}). Are you sure you want to proceed? If you need access to this store again in the future, you will need to be re-invited by another user of the store.",
32+
"message_fail": "Failed to revoke access. If you'd like to retry, close this dialog and click the revoke button again.",
33+
"message_done": "Your access was revoked successfully. Close this dialog to continue.",
34+
"button_close": "Close",
35+
"button_confirm": "Leave this store",
36+
"button_cancel": "Cancel",
37+
"loading_busy": "Processing",
38+
"header": "Confirmation Required",
39+
"button": "Leave this store"
3140
},
3241
"revoke": {
3342
"idle": "Revoke access",
@@ -104,4 +113,4 @@
104113
"loading_busy": "Loading",
105114
"loading_error": "Unknown error"
106115
}
107-
}
116+
}

0 commit comments

Comments
 (0)