mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
feat(elements): add logto-user-email element (#6726)
This commit is contained in:
parent
6ef19b3e73
commit
20a714c94d
5 changed files with 113 additions and 1 deletions
|
@ -0,0 +1,65 @@
|
||||||
|
import { assert, fixture, html, waitUntil } from '@open-wc/testing';
|
||||||
|
|
||||||
|
import { createMockAccountApi } from '../__mocks__/account-api.js';
|
||||||
|
import { type LogtoAccountProvider } from '../providers/logto-account-provider.js';
|
||||||
|
|
||||||
|
import { LogtoUserEmail } from './logto-user-email.js';
|
||||||
|
|
||||||
|
suite('logto-user-email', () => {
|
||||||
|
test('is defined', () => {
|
||||||
|
const element = document.createElement(LogtoUserEmail.tagName);
|
||||||
|
assert.instanceOf(element, LogtoUserEmail);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render error message when account context is not available', async () => {
|
||||||
|
const element = await fixture<LogtoUserEmail>(html`<logto-user-email></logto-user-email>`);
|
||||||
|
await element.updateComplete;
|
||||||
|
|
||||||
|
assert.equal(element.shadowRoot?.textContent, 'Unable to retrieve account context.');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render email if the user has permission to view email information', async () => {
|
||||||
|
const mockAccountApi = createMockAccountApi({
|
||||||
|
fetchUserProfile: async () => ({
|
||||||
|
primaryEmail: 'user@example.com',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const provider = await fixture<LogtoAccountProvider>(
|
||||||
|
html`<logto-account-provider .accountApi=${mockAccountApi}>
|
||||||
|
<logto-user-email></logto-user-email>
|
||||||
|
</logto-account-provider>`
|
||||||
|
);
|
||||||
|
|
||||||
|
await provider.updateComplete;
|
||||||
|
|
||||||
|
const logtoUserEmail = provider.querySelector<LogtoUserEmail>(LogtoUserEmail.tagName);
|
||||||
|
|
||||||
|
await waitUntil(
|
||||||
|
() =>
|
||||||
|
logtoUserEmail?.shadowRoot?.querySelector('div[slot="content"]')?.textContent ===
|
||||||
|
'user@example.com',
|
||||||
|
'Unable to get email from account context'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render nothing if the user lacks permission to view email information', async () => {
|
||||||
|
const mockAccountApi = createMockAccountApi({
|
||||||
|
fetchUserProfile: async () => ({
|
||||||
|
primaryEmail: undefined,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const provider = await fixture<LogtoAccountProvider>(
|
||||||
|
html`<logto-account-provider .accountApi=${mockAccountApi}>
|
||||||
|
<logto-user-email></logto-user-email>
|
||||||
|
</logto-account-provider>`
|
||||||
|
);
|
||||||
|
|
||||||
|
await provider.updateComplete;
|
||||||
|
const logtoUserEmail = provider.querySelector<LogtoUserEmail>(LogtoUserEmail.tagName);
|
||||||
|
|
||||||
|
await logtoUserEmail?.updateComplete;
|
||||||
|
assert.equal(logtoUserEmail?.shadowRoot?.children.length, 0);
|
||||||
|
});
|
||||||
|
});
|
38
packages/elements/src/account/elements/logto-user-email.ts
Normal file
38
packages/elements/src/account/elements/logto-user-email.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import { html, type TemplateResult } from 'lit';
|
||||||
|
import { customElement } from 'lit/decorators.js';
|
||||||
|
import { when } from 'lit/directives/when.js';
|
||||||
|
|
||||||
|
import emailIcon from '../icons/email.svg';
|
||||||
|
|
||||||
|
import { LogtoProfileItemElement } from './LogtoProfileItemElement.js';
|
||||||
|
|
||||||
|
const tagName = 'logto-user-email';
|
||||||
|
|
||||||
|
@customElement(tagName)
|
||||||
|
export class LogtoUserEmail extends LogtoProfileItemElement {
|
||||||
|
static tagName = tagName;
|
||||||
|
|
||||||
|
protected isAccessible(): boolean {
|
||||||
|
return this.accountContext?.userProfile.primaryEmail !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getItemLabelInfo() {
|
||||||
|
return {
|
||||||
|
icon: emailIcon,
|
||||||
|
label: 'Email address',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected renderContent(): TemplateResult {
|
||||||
|
const { primaryEmail } = this.accountContext?.userProfile ?? {};
|
||||||
|
|
||||||
|
return when(primaryEmail, (email) => html`<div slot="content">${email}</div>`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
[tagName]: LogtoUserEmail;
|
||||||
|
}
|
||||||
|
}
|
3
packages/elements/src/account/icons/email.svg
Normal file
3
packages/elements/src/account/icons/email.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M15.8334 3.33331H4.16675C3.50371 3.33331 2.86782 3.59671 2.39898 4.06555C1.93014 4.53439 1.66675 5.17027 1.66675 5.83331V14.1666C1.66675 14.8297 1.93014 15.4656 2.39898 15.9344C2.86782 16.4033 3.50371 16.6666 4.16675 16.6666H15.8334C16.4965 16.6666 17.1323 16.4033 17.6012 15.9344C18.07 15.4656 18.3334 14.8297 18.3334 14.1666V5.83331C18.3334 5.17027 18.07 4.53439 17.6012 4.06555C17.1323 3.59671 16.4965 3.33331 15.8334 3.33331ZM4.16675 4.99998H15.8334C16.0544 4.99998 16.2664 5.08778 16.4227 5.24406C16.579 5.40034 16.6667 5.6123 16.6667 5.83331L10.0001 9.89998L3.33341 5.83331C3.33341 5.6123 3.42121 5.40034 3.57749 5.24406C3.73377 5.08778 3.94573 4.99998 4.16675 4.99998ZM16.6667 14.1666C16.6667 14.3877 16.579 14.5996 16.4227 14.7559C16.2664 14.9122 16.0544 15 15.8334 15H4.16675C3.94573 15 3.73377 14.9122 3.57749 14.7559C3.42121 14.5996 3.33341 14.3877 3.33341 14.1666V7.73331L9.56675 11.5416C9.69343 11.6148 9.83713 11.6533 9.98341 11.6533C10.1297 11.6533 10.2734 11.6148 10.4001 11.5416L16.6667 7.73331V14.1666Z" fill="currentColor"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -6,3 +6,4 @@ export * from './components/logto-profile-item.js';
|
||||||
export * from './providers/logto-account-provider.js';
|
export * from './providers/logto-account-provider.js';
|
||||||
|
|
||||||
export * from './elements/logto-username.js';
|
export * from './elements/logto-username.js';
|
||||||
|
export * from './elements/logto-user-email.js';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { createComponent } from '@lit/react';
|
import { createComponent } from '@lit/react';
|
||||||
|
|
||||||
import { LogtoUsername } from './elements/logto-username.js';
|
import { LogtoUsername } from './elements/logto-username.js';
|
||||||
import { LogtoAccountProvider } from './index.js';
|
import { LogtoAccountProvider, LogtoUserEmail } from './index.js';
|
||||||
|
|
||||||
export * from './api/index.js';
|
export * from './api/index.js';
|
||||||
|
|
||||||
|
@ -17,5 +17,10 @@ export const createReactComponents = (react: Parameters<typeof createComponent>[
|
||||||
elementClass: LogtoUsername,
|
elementClass: LogtoUsername,
|
||||||
react,
|
react,
|
||||||
}),
|
}),
|
||||||
|
LogtoUserEmail: createComponent({
|
||||||
|
tagName: LogtoUserEmail.tagName,
|
||||||
|
elementClass: LogtoUserEmail,
|
||||||
|
react,
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue